├── .gitignore ├── AmazonS3ResourceManager.php ├── FileSystemResourceManager.php ├── LICENSE ├── README.md ├── ResourceManagerInterface.php └── composer.json /.gitignore: -------------------------------------------------------------------------------- 1 | # phpstorm project files 2 | .idea 3 | 4 | # netbeans project files 5 | nbproject 6 | 7 | # zend studio for eclipse project files 8 | .buildpath 9 | .project 10 | .settings 11 | 12 | # windows thumbnail cache 13 | Thumbs.db 14 | 15 | # composer vendor dir 16 | /vendor 17 | 18 | # composer itself is not needed 19 | composer.phar 20 | # composer.lock should not be committed as we always want the latest versions 21 | /composer.lock 22 | 23 | # Mac DS_Store Files 24 | .DS_Store 25 | 26 | # phpunit itself is not needed 27 | phpunit.phar 28 | # local phpunit config 29 | /phpunit.xml -------------------------------------------------------------------------------- /AmazonS3ResourceManager.php: -------------------------------------------------------------------------------- 1 | 23 | * @link http://www.ramirezcobos.com/ 24 | * @link http://www.2amigos.us/ 25 | */ 26 | class AmazonS3ResourceManager extends Component implements ResourceManagerInterface 27 | { 28 | 29 | /** 30 | * @var string Amazon access key 31 | */ 32 | public $key; 33 | /** 34 | * @var string Amazon secret access key 35 | */ 36 | public $secret; 37 | /** 38 | * @var string Amazon Bucket 39 | */ 40 | public $bucket; 41 | /** 42 | * @var \Aws\S3\S3Client 43 | */ 44 | private $_client; 45 | 46 | /** 47 | * @var boolean V4 signature 48 | */ 49 | public $enableV4=false; 50 | 51 | /** 52 | * @inheritdoc 53 | */ 54 | public function init() 55 | { 56 | foreach (['key', 'secret', 'bucket'] as $attribute) { 57 | if ($this->$attribute === null) { 58 | throw new InvalidConfigException(strtr('"{class}::{attribute}" cannot be empty.', [ 59 | '{class}' => static::className(), 60 | '{attribute}' => '$' . $attribute 61 | ])); 62 | } 63 | } 64 | parent::init(); 65 | } 66 | 67 | /** 68 | * Saves a file 69 | * @param \yii\web\UploadedFile $file the file uploaded. The [[UploadedFile::$tempName]] will be used as the source 70 | * file. 71 | * @param string $name the name of the file 72 | * @param array $options extra options for the object to save on the bucket. For more information, please visit 73 | * [[http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.S3.S3Client.html#_putObject]] 74 | * @return \Guzzle\Service\Resource\Model 75 | */ 76 | public function save($file, $name, $options = []) 77 | { 78 | $options = ArrayHelper::merge([ 79 | 'Bucket' => $this->bucket, 80 | 'Key' => $name, 81 | 'SourceFile' => $file->tempName, 82 | 'ACL' => CannedAcl::PUBLIC_READ // default to ACL public read 83 | ], $options); 84 | 85 | return $this->getClient()->putObject($options); 86 | } 87 | 88 | /** 89 | * Removes a file 90 | * @param string $name the name of the file to remove 91 | * @return boolean 92 | */ 93 | public function delete($name) 94 | { 95 | $result = $this->getClient()->deleteObject([ 96 | 'Bucket' => $this->bucket, 97 | 'Key' => $name 98 | ]); 99 | 100 | return $result['DeleteMarker']; 101 | } 102 | 103 | /** 104 | * Checks whether a file exists or not. This method only works for public resources, private resources will throw 105 | * a 403 error exception. 106 | * @param string $name the name of the file 107 | * @return boolean 108 | */ 109 | public function fileExists($name) 110 | { 111 | $http = new \Guzzle\Http\Client(); 112 | try { 113 | $response = $http->get($this->getUrl($name))->send(); 114 | } catch(ClientErrorResponseException $e) { 115 | return false; 116 | } 117 | return $response->isSuccessful(); 118 | } 119 | 120 | /** 121 | * Returns the url of the file or empty string if the file does not exists. 122 | * @param string $name the key name of the file to access 123 | * @param mixed $expires The time at which the URL should expire 124 | * @return string 125 | */ 126 | public function getUrl($name, $expires = NULL) 127 | { 128 | return $this->getClient()->getObjectUrl($this->bucket, $name, $expires); 129 | } 130 | 131 | /** 132 | * Delete all objects that match a specific key prefix. 133 | * @param string $prefix delete only objects under this key prefix 134 | * @return type 135 | */ 136 | public function deleteMatchingObjects($prefix) { 137 | return $this->getClient()->deleteMatchingObjects($this->bucket, $prefix); 138 | } 139 | 140 | /** 141 | * Return the full path a file names only (no directories) within s3 virtual "directory" by treating s3 keys as path names. 142 | * @param string $directory the prefix of keys to find 143 | * @return array of ['path' => string, 'name' => string, 'type' => string, 'size' => int] 144 | */ 145 | public function listFiles($directory) { 146 | $files = []; 147 | 148 | $iterator = $this->getClient()->getIterator('ListObjects', [ 149 | 'Bucket' => $this->bucket, 150 | 'Prefix' => $directory, 151 | ]); 152 | 153 | foreach ($iterator as $object) { 154 | // don't return directories 155 | if(substr($object['Key'], -1) != '/') { 156 | $file = [ 157 | 'path' => $object['Key'], 158 | 'name' => substr($object['Key'], strrpos($object['Key'], '/' ) + 1), 159 | 'type' => $object['StorageClass'], 160 | 'size' => (int)$object['Size'], 161 | ]; 162 | $files[] = $file; 163 | } 164 | } 165 | 166 | return $files; 167 | } 168 | 169 | /** 170 | * Returns a S3Client instance 171 | * @return \Aws\S3\S3Client 172 | */ 173 | public function getClient() 174 | { 175 | if ($this->_client === null) { 176 | $settings=[ 177 | 'key' => $this->key, 178 | 'secret' => $this->secret 179 | ]; 180 | if($this->enableV4) 181 | $settings['signature']='v4'; 182 | 183 | $this->_client = S3Client::factory($settings); 184 | } 185 | return $this->_client; 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /FileSystemResourceManager.php: -------------------------------------------------------------------------------- 1 | 18 | * @link http://www.ramirezcobos.com/ 19 | * @link http://www.2amigos.us/ 20 | */ 21 | class FileSystemResourceManager extends Component implements ResourceManagerInterface 22 | { 23 | private $_basePath = '@webroot/uploads'; 24 | private $_baseUrl = '@web/uploads'; 25 | 26 | /** 27 | * Saves a file 28 | * @param \yii\web\UploadedFile $file the file uploaded 29 | * @param string $name the name of the file. If empty, it will be set to the name of the uploaded file 30 | * @param array $options to save the file. The options can be any of the following: 31 | * - `folder` : whether we should create a subfolder where to save the file 32 | * - `override` : whether we allow rewriting a existing file 33 | * @return boolean 34 | */ 35 | public function save($file, $name, $options = []) 36 | { 37 | $name = ltrim($name, DIRECTORY_SEPARATOR); 38 | 39 | if ($folder = trim(ArrayHelper::getValue($options, 'folder'), DIRECTORY_SEPARATOR)) { 40 | $name = $folder . DIRECTORY_SEPARATOR . $name; 41 | } 42 | 43 | if (!ArrayHelper::getValue($options, 'override', true) && $this->fileExists($name)) { 44 | return false; 45 | } 46 | 47 | $path = $this->getBasePath() . DIRECTORY_SEPARATOR . $name; 48 | @mkdir(dirname($path), 0777, true); 49 | 50 | return $file->saveAs($path); 51 | } 52 | 53 | /** 54 | * Removes a file 55 | * @param string $name the name of the file to remove 56 | * @return boolean 57 | */ 58 | public function delete($name) 59 | { 60 | return $this->fileExists($name) ? @unlink($this->getBasePath() . DIRECTORY_SEPARATOR . $name) : false; 61 | } 62 | 63 | /** 64 | * Checks whether a file exists or not 65 | * @param string $name the name of the file 66 | * @return boolean 67 | */ 68 | public function fileExists($name) 69 | { 70 | return file_exists($this->getBasePath() . DIRECTORY_SEPARATOR . $name); 71 | } 72 | 73 | /** 74 | * Returns the url of the file or empty string if the file doesn't exist. 75 | * @param string $name the name of the file 76 | * @return string 77 | */ 78 | public function getUrl($name) 79 | { 80 | return $this->getBaseUrl() . '/' . $name; 81 | } 82 | 83 | /** 84 | * Returns the upload directory path 85 | * @return string 86 | */ 87 | public function getBasePath() 88 | { 89 | return Yii::getAlias($this->_basePath); 90 | } 91 | 92 | /** 93 | * Sets the upload directory path 94 | * @param $value 95 | */ 96 | public function setBasePath($value) 97 | { 98 | $this->_basePath = rtrim($value, DIRECTORY_SEPARATOR); 99 | } 100 | 101 | /** 102 | * Returns the base url 103 | * @return string the url pointing to the directory where we saved the files 104 | */ 105 | public function getBaseUrl() 106 | { 107 | return Yii::getAlias($this->_baseUrl); 108 | } 109 | 110 | /** 111 | * Sets the base url 112 | * @param string $value the url pointing to the directory where to get the files 113 | */ 114 | public function setBaseUrl($value) 115 | { 116 | $this->_baseUrl = rtrim($value, '/'); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, 2amigOS! Consulting Group 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Resource Manager component for Yii 2 2 | ==================================== 3 | 4 | [![Latest Stable Version](https://poser.pugx.org/2amigos/yii2-resource-manager-component/v/stable.svg)](https://packagist.org/packages/2amigos/yii2-ckeditor-widget) [![Total Downloads](https://poser.pugx.org/2amigos/yii2-resource-manager-component/downloads.svg)](https://packagist.org/packages/2amigos/yii2-resource-manager-component) [![Latest Unstable Version](https://poser.pugx.org/2amigos/yii2-resource-manager-component/v/unstable.svg)](https://packagist.org/packages/2amigos/yii2-resource-manager-component) [![License](https://poser.pugx.org/2amigos/yii2-resource-manager-component/license.svg)](https://packagist.org/packages/2amigos/yii2-resource-manager-component) 5 | 6 | This extension allows you to manage resources. Currently supports two possible scenarios: 7 | 8 | - Resources to save/or saved on a server's folder 9 | - Resources to save/or saved on an Amazon S3 bucket 10 | 11 | 12 | 13 | Installation 14 | ------------ 15 | 16 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/). 17 | 18 | Either run 19 | 20 | ```sh 21 | php composer.phar require 2amigos/yii2-resource-manager-component "*" 22 | ``` 23 | 24 | or add 25 | 26 | ```json 27 | "2amigos/yii2-resource-manager-component": "*" 28 | ``` 29 | 30 | to the require section of your `composer.json` file. 31 | 32 | Configuring 33 | -------------------------- 34 | 35 | Configure the selected component on your configuration file as follows: 36 | 37 | ``` 38 | // For this example we using AmazonS3ResourceManager component 39 | // ... 40 | 'components' => [ 41 | // ... 42 | 'resourceManager' => [ 43 | 'class' => 'dosamigos\resourcemanager\AmazonS3ResourceManager', 44 | 'key' => 'YOUR-AWS-KEY-HERE', 45 | 'secret' => 'YOUR-AWS-SECRET-HERE', 46 | 'bucket' => 'YOUR-AWS-BUCKET-NAME-HERE' 47 | ] 48 | // ... 49 | ] 50 | // ... 51 | ``` 52 | 53 | Done... Now, to save a resource to AWS S3 server, we just need to do the following: 54 | 55 | ``` 56 | // Defensive code checks not written for the example 57 | $resource = yii\web\UploadedFile::getInstanceByName('instance-name'); 58 | $name = md5($resource->name) . '.' . $resource->getExtension(); 59 | if(\Yii::$app->resourceManager->save($resource, $name)) { 60 | echo 'Done...'; 61 | } 62 | 63 | ``` 64 | 65 | Notes 66 | ----- 67 | 68 | Looking for a version for the Yii 1.1? There is dedicated repository for it: 69 | [2amigos/resource-manager](https://github.com/2amigos/resource-manager). 70 | 71 | > [![2amigOS!](http://www.gravatar.com/avatar/55363394d72945ff7ed312556ec041e0.png)](http://www.2amigos.us)
72 | Web development has never been so fun!
73 | [www.2amigos.us](http://www.2amigos.us) 74 | -------------------------------------------------------------------------------- /ResourceManagerInterface.php: -------------------------------------------------------------------------------- 1 | 13 | * @link http://www.ramirezcobos.com/ 14 | * @link http://www.2amigos.us/ 15 | */ 16 | interface ResourceManagerInterface 17 | { 18 | /** 19 | * Saves a file 20 | * @param \yii\web\UploadedFile $file the file uploaded 21 | * @param string $name the name of the file 22 | * @param array $options 23 | * @return boolean 24 | */ 25 | public function save($file, $name, $options = []); 26 | 27 | /** 28 | * Removes a file 29 | * @param string $name the name of the file to remove 30 | * @return boolean 31 | */ 32 | public function delete($name); 33 | 34 | /** 35 | * Checks whether a file exists or not 36 | * @param string $name the name of the file 37 | * @return boolean 38 | */ 39 | public function fileExists($name); 40 | 41 | /** 42 | * Returns the url of the file or empty string if the file doesn't exist. 43 | * @param string $name the name of the file 44 | * @return string 45 | */ 46 | public function getUrl($name); 47 | 48 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2amigos/yii2-resource-manager-component", 3 | "description": "Resource manager eases your project resources management.", 4 | "keywords": ["yii", "extension", "component", "resource"], 5 | "homepage": "https://github.com/2amigos/yii2-resource-manager-component", 6 | "type": "yii2-extension", 7 | "license": "BSD-3-Clause", 8 | "authors": [ 9 | { 10 | "name": "Antonio Ramirez", 11 | "email": "amigo.cobos@gmail.com", 12 | "homepage" : "http://2amigos.us" 13 | } 14 | ], 15 | "minimum-stability": "dev", 16 | "require": { 17 | "yiisoft/yii2": "*", 18 | "aws/aws-sdk-php": "2.5.2" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "dosamigos\\resourcemanager\\": "" 23 | } 24 | } 25 | } --------------------------------------------------------------------------------