/ */ class P4Cms_AssetHandler_S3 implements P4Cms_AssetHandlerInterface { protected $_bucket; protected $_accessKey; protected $_secretKey; protected $_s3Service; /** * Constructor allows passing options for accessKey, secretKey * or bucket. * * @param array $options Options to use on this instance */ public function __construct(array $options = null) { foreach ($options ?: array() as $option => $value) { $method = 'set' . ucfirst($option); if (method_exists($this, $method)) { $this->$method($value); } } } /** * Used to set the bucket for storage. * * @param string|null $bucket The bucket to store assets under * @return P4Cms_AssetHandler_S3 To maintain a fluent interface */ public function setBucket($bucket) { if (!is_string($bucket) && !is_null($bucket)) { throw new InvalidArgumentException("Bucket must be a string or null"); } $this->_bucket = $bucket; return $this; } /** * Returns the bucket to store objects under. The * DEFAULT_BUCKET constant will be used if no value * has been provided. * * @return string The bucket assets will be stored in */ public function getBucket() { return $this->_bucket; } /** * Used to set the s3 access key. * * @param string|null $key The access key to use * @return P4Cms_AssetHandler_S3 To maintain a fluent interface */ public function setAccessKey($key) { if (!is_string($key) && !is_null($key)) { throw new InvalidArgumentException("Access Key must be a string or null"); } $this->_s3Service = null; $this->_accessKey = $key; return $this; } /** * Returns the s3 access key. * * @return string The access key in use */ public function getAccessKey() { return $this->_accessKey; } /** * Used to set the s3 secret key. * * @param string|null $key The secret key to use * @return P4Cms_AssetHandler_S3 To maintain a fluent interface */ public function setSecretKey($key) { if (!is_string($key) && !is_null($key)) { throw new InvalidArgumentException("Secret Key must be a string or null"); } $this->_s3Service = null; $this->_secretKey = $key; return $this; } /** * Returns the s3 access key. * * @return string The secret key in use */ public function getSecretKey() { return $this->_secretKey; } /** * Check if the given ID exists in storage. * * @param string $id The ID to test * @return bool true if exists, false otherwise */ public function exists($id) { $cacheId = 's3_asset_' . md5($id); if (P4Cms_Cache::load($cacheId)) { return true; } // if we can retreive meta-data cache result and return true $info = $this->_getS3Service()->getInfo($this->_toObjectId($id)); if ($info) { P4Cms_Cache::save(true, $cacheId); return true; } // we don't cache failures as we will, most likely, // upload a copy shortly; simply return false return false; } /** * Store the passed data using indicated ID. * Will clobber any existing entry with the same ID. * * @param string $id The ID to store under * @param string $data The data to store * @return bool True if put was successful, false otherwise */ public function put($id, $data) { return $this->_getS3Service()->putObject( $this->_toObjectId($id), $data, $this->_getHeaders($id) ); } /** * Provide a URI for the indicated asset ID. * * @param string $id The ID to get a URI for * @return string|bool The uri used for the specified asset or false */ public function uri($id) { return 'http://' . Zend_Service_Amazon_S3::S3_ENDPOINT . '/' . $this->getBucket() . '/' . $id; } /** * Used to determine if the asset handler will be storing * assets offsite or not. Assets such as CSS need to know * this so they can decide if they need to include the * site's url when referencing images. * * @return bool true if assets stored offsite, false otherwise */ public function isOffsite() { return true; } /** * Returns the s3 service instance in use. * * @return Zend_Service_Amazon_S3 the s3 service instance */ protected function _getS3Service() { if (!$this->_s3Service) { $this->_s3Service = new Zend_Service_Amazon_S3( $this->getAccessKey(), $this->getSecretKey() ); } return $this->_s3Service; } /** * Translates a Asset ID to S3 Object ID. This is a simple * task of tacking the bucket name on the front. * * @param string $id The id to translate to an object ID * @return string The object ID to use for S3 purposes */ protected function _toObjectId($id) { return $this->getBucket() . '/' . $id; } /** * This method will provide the appropriate headers for the passed id. * It ensures the asset is publicly available and properly detects the * cssgz and jsgz file extensions to set content encoding/type as needed. * * @param string $id The id to generate headers for */ protected function _getHeaders($id) { $headers = array( Zend_Service_Amazon_S3::S3_ACL_HEADER => Zend_Service_Amazon_S3::S3_ACL_PUBLIC_READ ); // the S3 class won't detect our compressed assets // correctly so we manually setup the headers here. $extension = substr(strrchr($id, '.'), 1); if ($extension == 'cssgz') { $headers['Content-Type'] = 'text/css'; $headers['Content-Encoding'] = 'gzip'; } else if ($extension == 'jsgz') { $headers['Content-Type'] = 'text/javascript'; $headers['Content-Encoding'] = 'gzip'; } return $headers; } }