/zf/library/Zend/Cloud/StorageService/Adapter/S3.php
PHP | 327 lines | 152 code | 25 blank | 150 comment | 14 complexity | 0c0a59c7b1b0670d51032c7ddf5e3d03 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, Apache-2.0, LGPL-2.1, LGPL-3.0, BSD-2-Clause
1<?php 2/** 3 * LICENSE 4 * 5 * This source file is subject to the new BSD license that is bundled 6 * with this package in the file LICENSE.txt. 7 * It is also available through the world-wide-web at this URL: 8 * http://framework.zend.com/license/new-bsd 9 * If you did not receive a copy of the license and are unable to 10 * obtain it through the world-wide-web, please send an email 11 * to license@zend.com so we can send you a copy immediately. 12 * 13 * @category Zend 14 * @package Zend_Cloud 15 * @subpackage StorageService 16 * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) 17 * @license http://framework.zend.com/license/new-bsd New BSD License 18 */ 19 20require_once 'Zend/Service/Amazon/S3.php'; 21require_once 'Zend/Cloud/StorageService/Adapter.php'; 22require_once 'Zend/Cloud/StorageService/Exception.php'; 23 24/** 25 * S3 adapter for unstructured cloud storage. 26 * 27 * @category Zend 28 * @package Zend_Cloud 29 * @subpackage StorageService 30 * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) 31 * @license http://framework.zend.com/license/new-bsd New BSD License 32 */ 33class Zend_Cloud_StorageService_Adapter_S3 34 implements Zend_Cloud_StorageService_Adapter 35{ 36 /* 37 * Options array keys for the S3 adapter. 38 */ 39 const BUCKET_NAME = 'bucket_name'; 40 const BUCKET_AS_DOMAIN = 'bucket_as_domain?'; 41 const FETCH_STREAM = 'fetch_stream'; 42 const METADATA = 'metadata'; 43 44 /** 45 * AWS constants 46 */ 47 const AWS_ACCESS_KEY = 'aws_accesskey'; 48 const AWS_SECRET_KEY = 'aws_secretkey'; 49 50 /** 51 * S3 service instance. 52 * @var Zend_Service_Amazon_S3 53 */ 54 protected $_s3; 55 protected $_defaultBucketName = null; 56 protected $_defaultBucketAsDomain = false; 57 58 /** 59 * Constructor 60 * 61 * @param array|Zend_Config $options 62 * @return void 63 */ 64 public function __construct($options = array()) 65 { 66 if ($options instanceof Zend_Config) { 67 $options = $options->toArray(); 68 } 69 70 if (!is_array($options)) { 71 throw new Zend_Cloud_StorageService_Exception('Invalid options provided'); 72 } 73 74 if (!isset($options[self::AWS_ACCESS_KEY]) || !isset($options[self::AWS_SECRET_KEY])) { 75 throw new Zend_Cloud_StorageService_Exception('AWS keys not specified!'); 76 } 77 78 try { 79 $this->_s3 = new Zend_Service_Amazon_S3($options[self::AWS_ACCESS_KEY], 80 $options[self::AWS_SECRET_KEY]); 81 } catch (Zend_Service_Amazon_S3_Exception $e) { 82 throw new Zend_Cloud_StorageService_Exception('Error on create: '.$e->getMessage(), $e->getCode(), $e); 83 } 84 85 if (isset($options[self::HTTP_ADAPTER])) { 86 $this->_s3->getHttpClient()->setAdapter($options[self::HTTP_ADAPTER]); 87 } 88 89 if (isset($options[self::BUCKET_NAME])) { 90 $this->_defaultBucketName = $options[self::BUCKET_NAME]; 91 } 92 93 if (isset($options[self::BUCKET_AS_DOMAIN])) { 94 $this->_defaultBucketAsDomain = $options[self::BUCKET_AS_DOMAIN]; 95 } 96 } 97 98 /** 99 * Get an item from the storage service. 100 * 101 * @TODO Support streams 102 * 103 * @param string $path 104 * @param array $options 105 * @return string 106 */ 107 public function fetchItem($path, $options = array()) 108 { 109 $fullPath = $this->_getFullPath($path, $options); 110 try { 111 if (!empty($options[self::FETCH_STREAM])) { 112 return $this->_s3->getObjectStream($fullPath, $options[self::FETCH_STREAM]); 113 } else { 114 return $this->_s3->getObject($fullPath); 115 } 116 } catch (Zend_Service_Amazon_S3_Exception $e) { 117 throw new Zend_Cloud_StorageService_Exception('Error on fetch: '.$e->getMessage(), $e->getCode(), $e); 118 } 119 } 120 121 /** 122 * Store an item in the storage service. 123 * 124 * WARNING: This operation overwrites any item that is located at 125 * $destinationPath. 126 * 127 * @TODO Support streams 128 * 129 * @param string $destinationPath 130 * @param string|resource $data 131 * @param array $options 132 * @return void 133 */ 134 public function storeItem($destinationPath, $data, $options = array()) 135 { 136 try { 137 $fullPath = $this->_getFullPath($destinationPath, $options); 138 return $this->_s3->putObject( 139 $fullPath, 140 $data, 141 empty($options[self::METADATA]) ? null : $options[self::METADATA] 142 ); 143 } catch (Zend_Service_Amazon_S3_Exception $e) { 144 throw new Zend_Cloud_StorageService_Exception('Error on store: '.$e->getMessage(), $e->getCode(), $e); 145 } 146 } 147 148 /** 149 * Delete an item in the storage service. 150 * 151 * @param string $path 152 * @param array $options 153 * @return void 154 */ 155 public function deleteItem($path, $options = array()) 156 { 157 try { 158 $this->_s3->removeObject($this->_getFullPath($path, $options)); 159 } catch (Zend_Service_Amazon_S3_Exception $e) { 160 throw new Zend_Cloud_StorageService_Exception('Error on delete: '.$e->getMessage(), $e->getCode(), $e); 161 } 162 } 163 164 /** 165 * Copy an item in the storage service to a given path. 166 * 167 * WARNING: This operation is *very* expensive for services that do not 168 * support copying an item natively. 169 * 170 * @TODO Support streams for those services that don't support natively 171 * 172 * @param string $sourcePath 173 * @param string $destination path 174 * @param array $options 175 * @return void 176 */ 177 public function copyItem($sourcePath, $destinationPath, $options = array()) 178 { 179 try { 180 // TODO We *really* need to add support for object copying in the S3 adapter 181 $item = $this->fetch($_getFullPath(sourcePath), $options); 182 $this->storeItem($item, $destinationPath, $options); 183 } catch (Zend_Service_Amazon_S3_Exception $e) { 184 throw new Zend_Cloud_StorageService_Exception('Error on copy: '.$e->getMessage(), $e->getCode(), $e); 185 } 186 } 187 188 /** 189 * Move an item in the storage service to a given path. 190 * 191 * @TODO Support streams for those services that don't support natively 192 * 193 * @param string $sourcePath 194 * @param string $destination path 195 * @param array $options 196 * @return void 197 */ 198 public function moveItem($sourcePath, $destinationPath, $options = array()) 199 { 200 try { 201 $fullSourcePath = $this->_getFullPath($sourcePath, $options); 202 $fullDestPath = $this->_getFullPath($destinationPath, $options); 203 return $this->_s3->moveObject( 204 $fullSourcePath, 205 $fullDestPath, 206 empty($options[self::METADATA]) ? null : $options[self::METADATA] 207 ); 208 } catch (Zend_Service_Amazon_S3_Exception $e) { 209 throw new Zend_Cloud_StorageService_Exception('Error on move: '.$e->getMessage(), $e->getCode(), $e); 210 } 211 } 212 213 /** 214 * Rename an item in the storage service to a given name. 215 * 216 * 217 * @param string $path 218 * @param string $name 219 * @param array $options 220 * @return void 221 */ 222 public function renameItem($path, $name, $options = null) 223 { 224 require_once 'Zend/Cloud/OperationNotAvailableException.php'; 225 throw new Zend_Cloud_OperationNotAvailableException('Rename not implemented'); 226 } 227 228 /** 229 * List items in the given directory in the storage service 230 * 231 * The $path must be a directory 232 * 233 * 234 * @param string $path Must be a directory 235 * @param array $options 236 * @return array A list of item names 237 */ 238 public function listItems($path, $options = null) 239 { 240 try { 241 // TODO Support 'prefix' parameter for Zend_Service_Amazon_S3::getObjectsByBucket() 242 return $this->_s3->getObjectsByBucket($this->_defaultBucketName); 243 } catch (Zend_Service_Amazon_S3_Exception $e) { 244 throw new Zend_Cloud_StorageService_Exception('Error on list: '.$e->getMessage(), $e->getCode(), $e); 245 } 246 } 247 248 /** 249 * Get a key/value array of metadata for the given path. 250 * 251 * @param string $path 252 * @param array $options 253 * @return array 254 */ 255 public function fetchMetadata($path, $options = array()) 256 { 257 try { 258 return $this->_s3->getInfo($this->_getFullPath($path, $options)); 259 } catch (Zend_Service_Amazon_S3_Exception $e) { 260 throw new Zend_Cloud_StorageService_Exception('Error on fetch: '.$e->getMessage(), $e->getCode(), $e); 261 } 262 } 263 264 /** 265 * Store a key/value array of metadata at the given path. 266 * WARNING: This operation overwrites any metadata that is located at 267 * $destinationPath. 268 * 269 * @param string $destinationPath 270 * @param array $options 271 * @return void 272 */ 273 public function storeMetadata($destinationPath, $metadata, $options = array()) 274 { 275 require_once 'Zend/Cloud/OperationNotAvailableException.php'; 276 throw new Zend_Cloud_OperationNotAvailableException('Storing separate metadata is not supported, use storeItem() with \'metadata\' option key'); 277 } 278 279 /** 280 * Delete a key/value array of metadata at the given path. 281 * 282 * @param string $path 283 * @param array $options 284 * @return void 285 */ 286 public function deleteMetadata($path) 287 { 288 require_once 'Zend/Cloud/OperationNotAvailableException.php'; 289 throw new Zend_Cloud_OperationNotAvailableException('Deleting metadata not supported'); 290 } 291 292 /** 293 * Get full path, including bucket, for an object 294 * 295 * @param string $path 296 * @param array $options 297 * @return void 298 */ 299 protected function _getFullPath($path, $options) 300 { 301 if (isset($options[self::BUCKET_NAME])) { 302 $bucket = $options[self::BUCKET_NAME]; 303 } else if (isset($this->_defaultBucketName)) { 304 $bucket = $this->_defaultBucketName; 305 } else { 306 require_once 'Zend/Cloud/StorageService/Exception.php'; 307 throw new Zend_Cloud_StorageService_Exception('Bucket name must be specified for S3 adapter.'); 308 } 309 310 if (isset($options[self::BUCKET_AS_DOMAIN])) { 311 // TODO: support bucket domain names 312 require_once 'Zend/Cloud/StorageService/Exception.php'; 313 throw new Zend_Cloud_StorageService_Exception('The S3 adapter does not currently support buckets in domain names.'); 314 } 315 316 return trim($bucket) . '/' . trim($path); 317 } 318 319 /** 320 * Get the concrete client. 321 * @return Zend_Service_Amazon_S3 322 */ 323 public function getClient() 324 { 325 return $this->_s3; 326 } 327}