11 * to license@zend.com so we can send you a copy immediately. |
11 * to license@zend.com so we can send you a copy immediately. |
12 * |
12 * |
13 * @category Zend |
13 * @category Zend |
14 * @package Zend_Cloud |
14 * @package Zend_Cloud |
15 * @subpackage StorageService |
15 * @subpackage StorageService |
16 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
16 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) |
17 * @license http://framework.zend.com/license/new-bsd New BSD License |
17 * @license http://framework.zend.com/license/new-bsd New BSD License |
18 */ |
18 */ |
19 |
19 |
20 require_once 'Zend/Cloud/StorageService/Adapter.php'; |
20 require_once 'Zend/Cloud/StorageService/Adapter.php'; |
21 require_once 'Zend/Service/WindowsAzure/Storage/Blob.php'; |
21 require_once 'Zend/Service/WindowsAzure/Storage/Blob.php'; |
22 require_once 'Zend/Cloud/StorageService/Exception.php'; |
22 require_once 'Zend/Cloud/StorageService/Exception.php'; |
23 |
23 |
24 /** |
24 /** |
25 * |
25 * |
26 * Windows Azure Blob Service abstraction |
26 * Windows Azure Blob Service abstraction |
27 * |
27 * |
28 * @category Zend |
28 * @category Zend |
29 * @package Zend_Cloud |
29 * @package Zend_Cloud |
30 * @subpackage StorageService |
30 * @subpackage StorageService |
31 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
31 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) |
32 * @license http://framework.zend.com/license/new-bsd New BSD License |
32 * @license http://framework.zend.com/license/new-bsd New BSD License |
33 */ |
33 */ |
34 class Zend_Cloud_StorageService_Adapter_WindowsAzure |
34 class Zend_Cloud_StorageService_Adapter_WindowsAzure |
35 implements Zend_Cloud_StorageService_Adapter |
35 implements Zend_Cloud_StorageService_Adapter |
36 { |
36 { |
37 const ACCOUNT_NAME = 'storage_accountname'; |
37 const ACCOUNT_NAME = 'storage_accountname'; |
38 const ACCOUNT_KEY = 'storage_accountkey'; |
38 const ACCOUNT_KEY = 'storage_accountkey'; |
39 const HOST = "storage_host"; |
39 const HOST = "storage_host"; |
42 const PROXY_CREDENTIALS = "storage_proxy_credentials"; |
42 const PROXY_CREDENTIALS = "storage_proxy_credentials"; |
43 const CONTAINER = "storage_container"; |
43 const CONTAINER = "storage_container"; |
44 const RETURN_TYPE = 'return_type'; |
44 const RETURN_TYPE = 'return_type'; |
45 const RETURN_PATHNAME = 'return_path'; |
45 const RETURN_PATHNAME = 'return_path'; |
46 const RETURN_OPENMODE = 'return_openmode'; |
46 const RETURN_OPENMODE = 'return_openmode'; |
47 |
47 |
48 /** return types for fetch */ |
48 /** return types for fetch */ |
49 const RETURN_PATH = 1; // return filename |
49 const RETURN_PATH = 1; // return filename |
50 const RETURN_STRING = 2; // return data as string |
50 const RETURN_STRING = 2; // return data as string |
51 const RETURN_STREAM = 3; // return PHP stream |
51 const RETURN_STREAM = 3; // return PHP stream |
52 |
52 |
53 /** return types for list */ |
53 /** return types for list */ |
54 const RETURN_LIST = 1; // return native list |
54 const RETURN_LIST = 1; // return native list |
55 const RETURN_NAMES = 2; // return only names |
55 const RETURN_NAMES = 2; // return only names |
56 |
56 |
57 const DEFAULT_HOST = Zend_Service_WindowsAzure_Storage::URL_CLOUD_BLOB; |
57 const DEFAULT_HOST = Zend_Service_WindowsAzure_Storage::URL_CLOUD_BLOB; |
58 |
58 |
59 /** |
59 /** |
60 * Storage container to operate on |
60 * Storage container to operate on |
61 * |
61 * |
62 * @var string |
62 * @var string |
63 */ |
63 */ |
64 protected $_container; |
64 protected $_container; |
65 |
65 |
66 /** |
66 /** |
67 * Storage client |
67 * Storage client |
68 * |
68 * |
69 * @var Zend_Service_WindowsAzure_Storage_Blob |
69 * @var Zend_Service_WindowsAzure_Storage_Blob |
70 */ |
70 */ |
71 protected $_storageClient = null; |
71 protected $_storageClient = null; |
72 |
72 |
73 /** |
73 /** |
74 * Creates a new Zend_Cloud_Storage_WindowsAzure instance |
74 * Creates a new Zend_Cloud_Storage_WindowsAzure instance |
75 * |
75 * |
76 * @param array|Zend_Config $options Options for the Zend_Cloud_Storage_WindowsAzure instance |
76 * @param array|Zend_Config $options Options for the Zend_Cloud_Storage_WindowsAzure instance |
77 */ |
77 */ |
78 public function __construct($options = array()) |
78 public function __construct($options = array()) |
79 { |
79 { |
80 if ($options instanceof Zend_Config) { |
80 if ($options instanceof Zend_Config) { |
89 if (!isset($options[self::HOST])) { |
89 if (!isset($options[self::HOST])) { |
90 $host = self::DEFAULT_HOST; |
90 $host = self::DEFAULT_HOST; |
91 } else { |
91 } else { |
92 $host = $options[self::HOST]; |
92 $host = $options[self::HOST]; |
93 } |
93 } |
94 |
94 |
95 if (!isset($options[self::ACCOUNT_NAME])) { |
95 if (!isset($options[self::ACCOUNT_NAME])) { |
96 throw new Zend_Cloud_StorageService_Exception('No Windows Azure account name provided.'); |
96 throw new Zend_Cloud_StorageService_Exception('No Windows Azure account name provided.'); |
97 } |
97 } |
98 if (!isset($options[self::ACCOUNT_KEY])) { |
98 if (!isset($options[self::ACCOUNT_KEY])) { |
99 throw new Zend_Cloud_StorageService_Exception('No Windows Azure account key provided.'); |
99 throw new Zend_Cloud_StorageService_Exception('No Windows Azure account key provided.'); |
100 } |
100 } |
101 |
101 |
102 $this->_storageClient = new Zend_Service_WindowsAzure_Storage_Blob($host, |
102 $this->_storageClient = new Zend_Service_WindowsAzure_Storage_Blob($host, |
103 $options[self::ACCOUNT_NAME], $options[self::ACCOUNT_KEY]); |
103 $options[self::ACCOUNT_NAME], $options[self::ACCOUNT_KEY]); |
104 |
104 |
105 // Parse other options |
105 // Parse other options |
106 if (!empty($options[self::PROXY_HOST])) { |
106 if (!empty($options[self::PROXY_HOST])) { |
107 $proxyHost = $options[self::PROXY_HOST]; |
107 $proxyHost = $options[self::PROXY_HOST]; |
108 $proxyPort = isset($options[self::PROXY_PORT]) ? $options[self::PROXY_PORT] : 8080; |
108 $proxyPort = isset($options[self::PROXY_PORT]) ? $options[self::PROXY_PORT] : 8080; |
109 $proxyCredentials = isset($options[self::PROXY_CREDENTIALS]) ? $options[self::PROXY_CREDENTIALS] : ''; |
109 $proxyCredentials = isset($options[self::PROXY_CREDENTIALS]) ? $options[self::PROXY_CREDENTIALS] : ''; |
110 |
110 |
111 $this->_storageClient->setProxy(true, $proxyHost, $proxyPort, $proxyCredentials); |
111 $this->_storageClient->setProxy(true, $proxyHost, $proxyPort, $proxyCredentials); |
112 } |
112 } |
113 |
113 |
114 if (isset($options[self::HTTP_ADAPTER])) { |
114 if (isset($options[self::HTTP_ADAPTER])) { |
115 $this->_storageClient->setHttpClientChannel($options[self::HTTP_ADAPTER]); |
115 $this->_storageClient->setHttpClientChannel($options[self::HTTP_ADAPTER]); |
116 } |
116 } |
117 |
117 |
118 // Set container |
118 // Set container |
119 $this->_container = $options[self::CONTAINER]; |
119 $this->_container = $options[self::CONTAINER]; |
120 |
120 |
121 // Make sure the container exists |
121 // Make sure the container exists |
122 if (!$this->_storageClient->containerExists($this->_container)) { |
122 if (!$this->_storageClient->containerExists($this->_container)) { |
123 $this->_storageClient->createContainer($this->_container); |
123 $this->_storageClient->createContainer($this->_container); |
124 } |
124 } |
125 } |
125 } |
126 |
126 |
127 /** |
127 /** |
128 * Get an item from the storage service. |
128 * Get an item from the storage service. |
129 * |
129 * |
130 * @param string $path |
130 * @param string $path |
131 * @param array $options |
131 * @param array $options |
132 * @return mixed |
132 * @return mixed |
133 */ |
133 */ |
134 public function fetchItem($path, $options = null) |
134 public function fetchItem($path, $options = null) |
135 { |
135 { |
136 // Options |
136 // Options |
137 $returnType = self::RETURN_STRING; |
137 $returnType = self::RETURN_STRING; |
138 $returnPath = tempnam('', 'azr'); |
138 $returnPath = tempnam('', 'azr'); |
139 $openMode = 'r'; |
139 $openMode = 'r'; |
140 |
140 |
141 // Parse options |
141 // Parse options |
142 if (is_array($options)) { |
142 if (is_array($options)) { |
143 if (isset($options[self::RETURN_TYPE])) { |
143 if (isset($options[self::RETURN_TYPE])) { |
144 $returnType = $options[self::RETURN_TYPE]; |
144 $returnType = $options[self::RETURN_TYPE]; |
145 } |
145 } |
146 |
146 |
147 if (isset($options[self::RETURN_PATHNAME])) { |
147 if (isset($options[self::RETURN_PATHNAME])) { |
148 $returnPath = $options[self::RETURN_PATHNAME]; |
148 $returnPath = $options[self::RETURN_PATHNAME]; |
149 } |
149 } |
150 |
150 |
151 if (isset($options[self::RETURN_OPENMODE])) { |
151 if (isset($options[self::RETURN_OPENMODE])) { |
152 $openMode = $options[self::RETURN_OPENMODE]; |
152 $openMode = $options[self::RETURN_OPENMODE]; |
153 } |
153 } |
154 } |
154 } |
155 |
155 |
156 // Fetch the blob |
156 // Fetch the blob |
157 try { |
157 try { |
158 $this->_storageClient->getBlob( |
158 $this->_storageClient->getBlob( |
159 $this->_container, |
159 $this->_container, |
160 $path, |
160 $path, |
176 } |
176 } |
177 if ($returnType == self::RETURN_STREAM) { |
177 if ($returnType == self::RETURN_STREAM) { |
178 return fopen($returnPath, $openMode); |
178 return fopen($returnPath, $openMode); |
179 } |
179 } |
180 } |
180 } |
181 |
181 |
182 /** |
182 /** |
183 * Store an item in the storage service. |
183 * Store an item in the storage service. |
184 * WARNING: This operation overwrites any item that is located at |
184 * WARNING: This operation overwrites any item that is located at |
185 * $destinationPath. |
185 * $destinationPath. |
186 * @param string $destinationPath |
186 * @param string $destinationPath |
187 * @param mixed $data |
187 * @param mixed $data |
188 * @param array $options |
188 * @param array $options |
189 * @return boolean |
189 * @return boolean |
190 */ |
190 */ |
191 public function storeItem($destinationPath, $data, $options = null) |
191 public function storeItem($destinationPath, $data, $options = null) |
192 { |
192 { |
193 // Create a temporary file that will be uploaded |
193 // Create a temporary file that will be uploaded |
194 $temporaryFilePath = ''; |
194 $temporaryFilePath = ''; |
195 $removeTemporaryFilePath = false; |
195 $removeTemporaryFilePath = false; |
196 |
196 |
201 $fpSource = $data; |
201 $fpSource = $data; |
202 rewind($fpSource); |
202 rewind($fpSource); |
203 while (!feof($fpSource)) { |
203 while (!feof($fpSource)) { |
204 fwrite($fpDestination, fread($fpSource, 8192)); |
204 fwrite($fpDestination, fread($fpSource, 8192)); |
205 } |
205 } |
206 |
206 |
207 fclose($fpDestination); |
207 fclose($fpDestination); |
208 |
208 |
209 $removeTemporaryFilePath = true; |
209 $removeTemporaryFilePath = true; |
210 } elseif (file_exists($data)) { |
210 } elseif (file_exists($data)) { |
211 $temporaryFilePath = $data; |
211 $temporaryFilePath = $data; |
212 $removeTemporaryFilePath = false; |
212 $removeTemporaryFilePath = false; |
213 } else { |
213 } else { |
214 $temporaryFilePath = tempnam('', 'azr'); |
214 $temporaryFilePath = tempnam('', 'azr'); |
215 file_put_contents($temporaryFilePath, $data); |
215 file_put_contents($temporaryFilePath, $data); |
216 $removeTemporaryFilePath = true; |
216 $removeTemporaryFilePath = true; |
217 } |
217 } |
218 |
218 |
219 try { |
219 try { |
220 // Upload data |
220 // Upload data |
221 $this->_storageClient->putBlob( |
221 $this->_storageClient->putBlob( |
222 $this->_container, |
222 $this->_container, |
223 $destinationPath, |
223 $destinationPath, |
224 $temporaryFilePath |
224 $temporaryFilePath |
225 ); |
225 ); |
226 } catch(Zend_Service_WindowsAzure_Exception $e) { |
226 } catch(Zend_Service_WindowsAzure_Exception $e) { |
227 @unlink($temporaryFilePath); |
227 @unlink($temporaryFilePath); |
228 throw new Zend_Cloud_StorageService_Exception('Error on store: '.$e->getMessage(), $e->getCode(), $e); |
228 throw new Zend_Cloud_StorageService_Exception('Error on store: '.$e->getMessage(), $e->getCode(), $e); |
229 } |
229 } |
230 if ($removeTemporaryFilePath) { |
230 if ($removeTemporaryFilePath) { |
231 @unlink($temporaryFilePath); |
231 @unlink($temporaryFilePath); |
232 } |
232 } |
233 } |
233 } |
234 |
234 |
235 /** |
235 /** |
236 * Delete an item in the storage service. |
236 * Delete an item in the storage service. |
237 * |
237 * |
238 * @param string $path |
238 * @param string $path |
239 * @param array $options |
239 * @param array $options |
327 */ |
327 */ |
328 public function listItems($path, $options = null) |
328 public function listItems($path, $options = null) |
329 { |
329 { |
330 // Options |
330 // Options |
331 $returnType = self::RETURN_NAMES; // 1: return list of paths, 2: return raw output from underlying provider |
331 $returnType = self::RETURN_NAMES; // 1: return list of paths, 2: return raw output from underlying provider |
332 |
332 |
333 // Parse options |
333 // Parse options |
334 if (is_array($options)&& isset($options[self::RETURN_TYPE])) { |
334 if (is_array($options)&& isset($options[self::RETURN_TYPE])) { |
335 $returnType = $options[self::RETURN_TYPE]; |
335 $returnType = $options[self::RETURN_TYPE]; |
336 } |
336 } |
337 |
337 |
338 try { |
338 try { |
339 // Fetch list |
339 // Fetch list |
340 $blobList = $this->_storageClient->listBlobs( |
340 $blobList = $this->_storageClient->listBlobs( |
341 $this->_container, |
341 $this->_container, |
342 $path |
342 $path |
343 ); |
343 ); |
344 } catch (Zend_Service_WindowsAzure_Exception $e) { |
344 } catch (Zend_Service_WindowsAzure_Exception $e) { |
345 throw new Zend_Cloud_StorageService_Exception('Error on list: '.$e->getMessage(), $e->getCode(), $e); |
345 throw new Zend_Cloud_StorageService_Exception('Error on list: '.$e->getMessage(), $e->getCode(), $e); |
346 } |
346 } |
347 |
347 |
348 // Return |
348 // Return |
349 if ($returnType == self::RETURN_LIST) { |
349 if ($returnType == self::RETURN_LIST) { |
350 return $blobList; |
350 return $blobList; |
351 } |
351 } |
352 |
352 |
353 $returnValue = array(); |
353 $returnValue = array(); |
354 foreach ($blobList as $blob) { |
354 foreach ($blobList as $blob) { |
355 $returnValue[] = $blob->Name; |
355 $returnValue[] = $blob->Name; |
356 } |
356 } |
357 |
357 |
358 return $returnValue; |
358 return $returnValue; |
359 } |
359 } |
360 |
360 |
361 /** |
361 /** |
362 * Get a key/value array of metadata for the given path. |
362 * Get a key/value array of metadata for the given path. |
415 if (strpos($e->getMessage(), "could not be accessed") === false) { |
415 if (strpos($e->getMessage(), "could not be accessed") === false) { |
416 throw new Zend_Cloud_StorageService_Exception('Error on delete metadata: '.$e->getMessage(), $e->getCode(), $e); |
416 throw new Zend_Cloud_StorageService_Exception('Error on delete metadata: '.$e->getMessage(), $e->getCode(), $e); |
417 } |
417 } |
418 } |
418 } |
419 } |
419 } |
420 |
420 |
421 /** |
421 /** |
422 * Delete container |
422 * Delete container |
423 * |
423 * |
424 * @return void |
424 * @return void |
425 */ |
425 */ |
426 public function deleteContainer() |
426 public function deleteContainer() |
427 { |
427 { |
428 try { |
428 try { |
429 $this->_storageClient->deleteContainer($this->_container); |
429 $this->_storageClient->deleteContainer($this->_container); |
430 } catch (Zend_Service_WindowsAzure_Exception $e) { |
430 } catch (Zend_Service_WindowsAzure_Exception $e) { |
431 throw new Zend_Cloud_StorageService_Exception('Error on delete: '.$e->getMessage(), $e->getCode(), $e); |
431 throw new Zend_Cloud_StorageService_Exception('Error on delete: '.$e->getMessage(), $e->getCode(), $e); |
432 } |
432 } |
433 } |
433 } |
434 |
434 |
435 /** |
435 /** |
436 * Get the concrete adapter. |
436 * Get the concrete adapter. |
437 * @return Zend_Service_Azure_Storage_Blob |
437 * @return Zend_Service_Azure_Storage_Blob |
438 */ |
438 */ |
439 public function getClient() |
439 public function getClient() |
440 { |
440 { |
441 return $this->_storageClient; |
441 return $this->_storageClient; |
442 } |
442 } |
443 } |
443 } |