File indexing completed on 2025-01-26 05:24:52

0001 <?php
0002 /**
0003  * LICENSE
0004  *
0005  * This source file is subject to the new BSD license that is bundled
0006  * with this package in the file LICENSE.txt.
0007  * It is also available through the world-wide-web at this URL:
0008  * http://framework.zend.com/license/new-bsd
0009  * If you did not receive a copy of the license and are unable to
0010  * obtain it through the world-wide-web, please send an email
0011  * to license@zend.com so we can send you a copy immediately.
0012  *
0013  * @category   Zend
0014  * @package    Zend_Cloud
0015  * @subpackage StorageService
0016  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0017  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0018  */
0019 
0020 // require_once 'Zend/Cloud/StorageService/Adapter.php';
0021 // require_once 'Zend/Service/WindowsAzure/Storage/Blob.php';
0022 // require_once 'Zend/Cloud/StorageService/Exception.php';
0023 
0024 /**
0025  *
0026  * Windows Azure Blob Service abstraction
0027  *
0028  * @category   Zend
0029  * @package    Zend_Cloud
0030  * @subpackage StorageService
0031  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0032  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0033  */
0034 class Zend_Cloud_StorageService_Adapter_WindowsAzure
0035     implements Zend_Cloud_StorageService_Adapter
0036 {
0037     const ACCOUNT_NAME      = 'storage_accountname';
0038     const ACCOUNT_KEY       = 'storage_accountkey';
0039     const HOST              = "storage_host";
0040     const PROXY_HOST        = "storage_proxy_host";
0041     const PROXY_PORT        = "storage_proxy_port";
0042     const PROXY_CREDENTIALS = "storage_proxy_credentials";
0043     const CONTAINER         = "storage_container";
0044     const RETURN_TYPE       = 'return_type';
0045     const RETURN_PATHNAME   = 'return_path';
0046     const RETURN_OPENMODE   = 'return_openmode';
0047 
0048     /** return types  for fetch */
0049     const RETURN_PATH   = 1;   // return filename
0050     const RETURN_STRING = 2; // return data as string
0051     const RETURN_STREAM = 3; // return PHP stream
0052 
0053     /** return types  for list */
0054     const RETURN_LIST  = 1;   // return native list
0055     const RETURN_NAMES = 2;  // return only names
0056 
0057     const DEFAULT_HOST = Zend_Service_WindowsAzure_Storage::URL_CLOUD_BLOB;
0058 
0059     /**
0060      * Storage container to operate on
0061      *
0062      * @var string
0063      */
0064     protected $_container;
0065 
0066     /**
0067      * Storage client
0068      *
0069      * @var Zend_Service_WindowsAzure_Storage_Blob
0070      */
0071     protected $_storageClient = null;
0072 
0073     /**
0074      * Creates a new Zend_Cloud_Storage_WindowsAzure instance
0075      *
0076      * @param array|Zend_Config  $options   Options for the Zend_Cloud_Storage_WindowsAzure instance
0077      */
0078     public function __construct($options = array())
0079     {
0080         if ($options instanceof Zend_Config) {
0081             $options = $options->toArray();
0082         }
0083 
0084         if (!is_array($options)) {
0085             throw new Zend_Cloud_StorageService_Exception('Invalid options provided');
0086         }
0087 
0088         // Build Zend_Service_WindowsAzure_Storage_Blob instance
0089         if (!isset($options[self::HOST])) {
0090             $host = self::DEFAULT_HOST;
0091         } else {
0092             $host = $options[self::HOST];
0093         }
0094 
0095         if (!isset($options[self::ACCOUNT_NAME])) {
0096             throw new Zend_Cloud_StorageService_Exception('No Windows Azure account name provided.');
0097         }
0098         if (!isset($options[self::ACCOUNT_KEY])) {
0099             throw new Zend_Cloud_StorageService_Exception('No Windows Azure account key provided.');
0100         }
0101 
0102         $this->_storageClient = new Zend_Service_WindowsAzure_Storage_Blob($host,
0103              $options[self::ACCOUNT_NAME], $options[self::ACCOUNT_KEY]);
0104 
0105         // Parse other options
0106         if (!empty($options[self::PROXY_HOST])) {
0107             $proxyHost = $options[self::PROXY_HOST];
0108             $proxyPort = isset($options[self::PROXY_PORT]) ? $options[self::PROXY_PORT] : 8080;
0109             $proxyCredentials = isset($options[self::PROXY_CREDENTIALS]) ? $options[self::PROXY_CREDENTIALS] : '';
0110 
0111             $this->_storageClient->setProxy(true, $proxyHost, $proxyPort, $proxyCredentials);
0112         }
0113 
0114         if (isset($options[self::HTTP_ADAPTER])) {
0115             $this->_storageClient->setHttpClientChannel($options[self::HTTP_ADAPTER]);
0116         }
0117 
0118         // Set container
0119         $this->_container = $options[self::CONTAINER];
0120 
0121         // Make sure the container exists
0122         if (!$this->_storageClient->containerExists($this->_container)) {
0123             $this->_storageClient->createContainer($this->_container);
0124         }
0125     }
0126 
0127     /**
0128      * Get an item from the storage service.
0129      *
0130      * @param  string $path
0131      * @param  array $options
0132      * @return mixed
0133      */
0134     public function fetchItem($path, $options = null)
0135     {
0136         // Options
0137         $returnType = self::RETURN_STRING;
0138         $returnPath = tempnam('', 'azr');
0139         $openMode   = 'r';
0140 
0141         // Parse options
0142         if (is_array($options)) {
0143             if (isset($options[self::RETURN_TYPE])) {
0144                 $returnType = $options[self::RETURN_TYPE];
0145             }
0146 
0147             if (isset($options[self::RETURN_PATHNAME])) {
0148                 $returnPath = $options[self::RETURN_PATHNAME];
0149             }
0150 
0151             if (isset($options[self::RETURN_OPENMODE])) {
0152                 $openMode = $options[self::RETURN_OPENMODE];
0153             }
0154         }
0155 
0156         // Fetch the blob
0157         try {
0158             $this->_storageClient->getBlob(
0159                 $this->_container,
0160                 $path,
0161                 $returnPath
0162             );
0163         } catch (Zend_Service_WindowsAzure_Exception $e) {
0164             if (strpos($e->getMessage(), "does not exist") !== false) {
0165                 return false;
0166             }
0167             throw new Zend_Cloud_StorageService_Exception('Error on fetch: '.$e->getMessage(), $e->getCode(), $e);
0168         }
0169 
0170         // Return value
0171         if ($returnType == self::RETURN_PATH) {
0172             return $returnPath;
0173         }
0174         if ($returnType == self::RETURN_STRING) {
0175             return file_get_contents($returnPath);
0176         }
0177         if ($returnType == self::RETURN_STREAM) {
0178             return fopen($returnPath, $openMode);
0179         }
0180     }
0181 
0182     /**
0183      * Store an item in the storage service.
0184      * WARNING: This operation overwrites any item that is located at
0185      * $destinationPath.
0186      * @param string $destinationPath
0187      * @param mixed  $data
0188      * @param  array $options
0189      * @return boolean
0190      */
0191     public function storeItem($destinationPath, $data, $options = null)
0192     {
0193         // Create a temporary file that will be uploaded
0194         $temporaryFilePath       = '';
0195         $removeTemporaryFilePath = false;
0196 
0197         if (is_resource($data))    {
0198             $temporaryFilePath = tempnam('', 'azr');
0199             $fpDestination     = fopen($temporaryFilePath, 'w');
0200 
0201             $fpSource = $data;
0202             rewind($fpSource);
0203             while (!feof($fpSource)) {
0204                 fwrite($fpDestination, fread($fpSource, 8192));
0205             }
0206 
0207             fclose($fpDestination);
0208 
0209             $removeTemporaryFilePath = true;
0210         } elseif (file_exists($data)) {
0211             $temporaryFilePath       = $data;
0212             $removeTemporaryFilePath = false;
0213         } else {
0214             $temporaryFilePath = tempnam('', 'azr');
0215             file_put_contents($temporaryFilePath, $data);
0216             $removeTemporaryFilePath = true;
0217         }
0218 
0219         try {
0220             // Upload data
0221             $this->_storageClient->putBlob(
0222                 $this->_container,
0223                 $destinationPath,
0224                 $temporaryFilePath
0225             );
0226         } catch(Zend_Service_WindowsAzure_Exception $e) {
0227             @unlink($temporaryFilePath);
0228             throw new Zend_Cloud_StorageService_Exception('Error on store: '.$e->getMessage(), $e->getCode(), $e);
0229         }
0230         if ($removeTemporaryFilePath) {
0231             @unlink($temporaryFilePath);
0232         }
0233     }
0234 
0235     /**
0236      * Delete an item in the storage service.
0237      *
0238      * @param  string $path
0239      * @param  array  $options
0240      * @return void
0241      */
0242     public function deleteItem($path, $options = null)
0243     {
0244         try {
0245             $this->_storageClient->deleteBlob(
0246                 $this->_container,
0247                 $path
0248             );
0249         } catch (Zend_Service_WindowsAzure_Exception $e) {
0250             throw new Zend_Cloud_StorageService_Exception('Error on delete: '.$e->getMessage(), $e->getCode(), $e);
0251         }
0252     }
0253 
0254     /**
0255      * Copy an item in the storage service to a given path.
0256      *
0257      * @param  string $sourcePath
0258      * @param  string $destinationPath
0259      * @param  array  $options
0260      * @return void
0261      */
0262     public function copyItem($sourcePath, $destinationPath, $options = null)
0263     {
0264         try {
0265             $this->_storageClient->copyBlob(
0266                 $this->_container,
0267                 $sourcePath,
0268                 $this->_container,
0269                 $destinationPath
0270             );
0271         } catch (Zend_Service_WindowsAzure_Exception $e) {
0272             throw new Zend_Cloud_StorageService_Exception('Error on copy: '.$e->getMessage(), $e->getCode(), $e);
0273         }
0274     }
0275 
0276     /**
0277      * Move an item in the storage service to a given path.
0278      *
0279      * @param  string $sourcePath
0280      * @param  string $destinationPath
0281      * @param  array  $options
0282      * @return void
0283      */
0284     public function moveItem($sourcePath, $destinationPath, $options = null)
0285     {
0286         try {
0287             $this->_storageClient->copyBlob(
0288                 $this->_container,
0289                 $sourcePath,
0290                 $this->_container,
0291                 $destinationPath
0292             );
0293 
0294             $this->_storageClient->deleteBlob(
0295                 $this->_container,
0296                 $sourcePath
0297             );
0298         } catch (Zend_Service_WindowsAzure_Exception $e) {
0299             throw new Zend_Cloud_StorageService_Exception('Error on move: '.$e->getMessage(), $e->getCode(), $e);
0300         }
0301 
0302     }
0303 
0304     /**
0305      * Rename an item in the storage service to a given name.
0306      *
0307      *
0308      * @param  string $path
0309      * @param  string $name
0310      * @param  array $options
0311      * @return void
0312      */
0313     public function renameItem($path, $name, $options = null)
0314     {
0315         return $this->moveItem($path, $name, $options);
0316     }
0317 
0318     /**
0319      * List items in the given directory in the storage service
0320      *
0321      * The $path must be a directory
0322      *
0323      *
0324      * @param  string $path Must be a directory
0325      * @param  array $options
0326      * @return array A list of item names
0327      */
0328     public function listItems($path, $options = null)
0329     {
0330         // Options
0331         $returnType = self::RETURN_NAMES; // 1: return list of paths, 2: return raw output from underlying provider
0332 
0333         // Parse options
0334         if (is_array($options)&& isset($options[self::RETURN_TYPE])) {
0335                $returnType = $options[self::RETURN_TYPE];
0336         }
0337 
0338         try {
0339             // Fetch list
0340             $blobList = $this->_storageClient->listBlobs(
0341                 $this->_container,
0342                 $path
0343             );
0344         } catch (Zend_Service_WindowsAzure_Exception $e) {
0345             throw new Zend_Cloud_StorageService_Exception('Error on list: '.$e->getMessage(), $e->getCode(), $e);
0346         }
0347 
0348         // Return
0349         if ($returnType == self::RETURN_LIST) {
0350             return $blobList;
0351         }
0352 
0353         $returnValue = array();
0354         foreach ($blobList as $blob) {
0355             $returnValue[] = $blob->Name;
0356         }
0357 
0358         return $returnValue;
0359     }
0360 
0361     /**
0362      * Get a key/value array of metadata for the given path.
0363      *
0364      * @param  string $path
0365      * @param  array  $options
0366      * @return array
0367      */
0368     public function fetchMetadata($path, $options = null)
0369     {
0370         try {
0371             return $this->_storageClient->getBlobMetaData(
0372                 $this->_container,
0373                 $path
0374             );
0375         } catch (Zend_Service_WindowsAzure_Exception $e) {
0376             if (strpos($e->getMessage(), "could not be accessed") !== false) {
0377                 return false;
0378             }
0379             throw new Zend_Cloud_StorageService_Exception('Error on fetch: '.$e->getMessage(), $e->getCode(), $e);
0380         }
0381     }
0382 
0383     /**
0384      * Store a key/value array of metadata at the given path.
0385      * WARNING: This operation overwrites any metadata that is located at
0386      * $destinationPath.
0387      *
0388      * @param  string $destinationPath
0389      * @param  array $options
0390      * @return void
0391      */
0392     public function storeMetadata($destinationPath, $metadata, $options = null)
0393     {
0394         try    {
0395             $this->_storageClient->setBlobMetadata($this->_container, $destinationPath, $metadata);
0396         } catch (Zend_Service_WindowsAzure_Exception $e) {
0397             if (strpos($e->getMessage(), "could not be accessed") === false) {
0398                 throw new Zend_Cloud_StorageService_Exception('Error on store metadata: '.$e->getMessage(), $e->getCode(), $e);
0399             }
0400         }
0401     }
0402 
0403     /**
0404      * Delete a key/value array of metadata at the given path.
0405      *
0406      * @param  string $path
0407      * @param  array $options
0408      * @return void
0409      */
0410     public function deleteMetadata($path, $options = null)
0411     {
0412         try {
0413             $this->_storageClient->setBlobMetadata($this->_container, $destinationPath, array());
0414         } catch (Zend_Service_WindowsAzure_Exception $e) {
0415             if (strpos($e->getMessage(), "could not be accessed") === false) {
0416                 throw new Zend_Cloud_StorageService_Exception('Error on delete metadata: '.$e->getMessage(), $e->getCode(), $e);
0417             }
0418         }
0419     }
0420 
0421     /**
0422      * Delete container
0423      *
0424      * @return void
0425      */
0426     public function deleteContainer()
0427     {
0428         try {
0429             $this->_storageClient->deleteContainer($this->_container);
0430         } catch (Zend_Service_WindowsAzure_Exception $e) {
0431             throw new Zend_Cloud_StorageService_Exception('Error on delete: '.$e->getMessage(), $e->getCode(), $e);
0432         }
0433     }
0434 
0435     /**
0436      * Get the concrete adapter.
0437      * @return Zend_Service_Azure_Storage_Blob
0438      */
0439     public function getClient()
0440     {
0441          return $this->_storageClient;
0442     }
0443 }