├── .gitignore ├── FilemanagerAsset.php ├── FilemanagerEditorAsset.php ├── Module.php ├── README.md ├── assets ├── css │ └── filemanager.css └── js │ ├── filemanager.js │ └── yii2-filemanager.plugin.js ├── components ├── Filemanager.php ├── FilemanagerHelper.php ├── GridBox.php └── S3.php ├── composer.json ├── controllers ├── FilesController.php └── FoldersController.php ├── messages ├── config.php ├── de │ └── filemanager.php ├── en │ └── filemanager.php └── es │ └── filemanager.php ├── migrations └── m150721_075656_filemanager_init.php ├── models ├── Files.php ├── FilesRelationship.php ├── FilesSearch.php ├── FilesTag.php └── Folders.php ├── views ├── files │ ├── _file-input.php │ ├── _grid-view.php │ ├── _list-view.php │ ├── _search.php │ ├── index.php │ ├── update.php │ └── upload.php └── folders │ ├── _form.php │ ├── create.php │ ├── index.php │ ├── update.php │ └── view.php └── widgets ├── FileBrowse.php ├── FileBrowseEditor.php └── Gallery.php /.gitignore: -------------------------------------------------------------------------------- 1 | ### IDE 2 | 3 | # JetBrains / PhpStorm project files 4 | *.iml 5 | .idea 6 | .idea_modules 7 | 8 | # Crashlytics plugin (for Android Studio and IntelliJ) 9 | com_crashlytics_export_strings.xml 10 | crashlytics.properties 11 | crashlytics-build.properties 12 | 13 | # Netbeans project files 14 | nbproject 15 | 16 | # Eclipse files 17 | .buildpath 18 | .project 19 | .settings 20 | 21 | #Sublime Text 22 | .phpintel 23 | 24 | ### OPERATING SYSTEM 25 | 26 | # windows thumbnail cache 27 | Thumbs.db 28 | 29 | # Mac DS_Store Files 30 | .DS_Store 31 | 32 | ### COMPOSER AND OTHER TOOLS 33 | 34 | # composer vendor dir 35 | /vendor 36 | 37 | # composer itself is not needed 38 | composer.phar 39 | 40 | # phpunit and its config itself is not needed 41 | phpunit.phar 42 | /phpunit.xml 43 | -------------------------------------------------------------------------------- /FilemanagerAsset.php: -------------------------------------------------------------------------------- 1 | true 30 | // ]; 31 | } 32 | -------------------------------------------------------------------------------- /FilemanagerEditorAsset.php: -------------------------------------------------------------------------------- 1 | true 25 | // ]; 26 | } 27 | -------------------------------------------------------------------------------- /Module.php: -------------------------------------------------------------------------------- 1 | [ 21 | * 'host' => '', 22 | * 'key' => '', 23 | * 'secret' => '', 24 | * 'bucket' => '', 25 | * 'cdnDomain' => '', 26 | * 'prefixPath' => '', 27 | * 'cacheTime' => '', // if empty, by default is 2592000 (30 days) 28 | * ] 29 | * ]; 30 | */ 31 | public $storage = ['local']; 32 | public $cache = 'cache'; 33 | 34 | /** 35 | * @var array 36 | * Configure to use own models function 37 | */ 38 | public $models = [ 39 | 'files' => 'dpodium\filemanager\models\Files', 40 | 'filesSearch' => 'dpodium\filemanager\models\FilesSearch', 41 | 'filesRelationship' => 'dpodium\filemanager\models\FilesRelationship', 42 | 'filesTag' => 'dpodium\filemanager\models\FilesTag', 43 | 'folders' => 'dpodium\filemanager\models\Folders', 44 | ]; 45 | public $acceptedFilesType = [ 46 | 'image/jpeg', 47 | 'image/png', 48 | 'image/gif', 49 | 'application/pdf' 50 | ]; 51 | public $maxFileSize = 8; // MB 52 | public $thumbnailSize = [120, 120]; // width, height 53 | /** 54 | * This configuration will be used in 'filemanager/files/upload' 55 | * To support dynamic multiple upload 56 | * Default multiple upload is true, max file to upload is 10 57 | * @var type 58 | */ 59 | public $filesUpload = [ 60 | 'multiple' => true, 61 | 'maxFileCount' => 10 62 | ]; 63 | 64 | public function init() { 65 | if (empty($this->thumbnailSize)) { 66 | throw new \yii\base\InvalidConfigException("thumbnailSize cannot be empty."); 67 | } else if (!isset($this->thumbnailSize[0]) || !isset($this->thumbnailSize[1]) || empty($this->thumbnailSize[0]) || empty($this->thumbnailSize[1])) { 68 | throw new \yii\base\InvalidConfigException("Invalid thumbnailSize value."); 69 | } 70 | Yii::$app->i18n->translations['filemanager*'] = [ 71 | 'class' => 'yii\i18n\PhpMessageSource', 72 | 'basePath' => "@dpodium/filemanager/messages" 73 | ]; 74 | parent::init(); 75 | } 76 | 77 | public function getMimeType() { 78 | $extensions = $result = []; 79 | foreach ($this->acceptedFilesType as $mimeType) { 80 | $extensions[] = BaseFileHelper::getExtensionsByMimeType($mimeType); 81 | } 82 | 83 | foreach ($extensions as $ext) { 84 | $result = \yii\helpers\ArrayHelper::merge($result, $ext); 85 | } 86 | 87 | return $result; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | File Manager for Yii2 2 | ===================== 3 | 4 | Installation 5 | ------------ 6 | 7 | ### Install With Composer 8 | 9 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/). 10 | 11 | Either run 12 | 13 | ``` 14 | php composer.phar require dpodium/yii2-filemanager "dev-master" 15 | ``` 16 | 17 | or add 18 | 19 | ``` 20 | "dpodium/yii2-filemanager": "dev-master" 21 | ``` 22 | 23 | to the require section of your `composer.json` file. 24 | 25 | Execute migration here: 26 | ``` 27 | yii migrate --migrationPath=@dpodium/filemanager/migrations 28 | yii migrate/down --migrationPath=@dpodium/filemanager/migrations 29 | ``` 30 | 31 | Usage 32 | ----- 33 | 34 | Once the extension is installed, simply modify your application configuration as follows: 35 | 36 | Upload file in local: 37 | 38 | ```php 39 | return [ 40 | 'modules' => [ 41 | 'gridview' => [ 42 | 'class' => '\kartik\grid\Module' 43 | ], 44 | 'filemanager' => [ 45 | 'class' => 'dpodium\filemanager\Module', 46 | 'storage' => ['local'], 47 | // This configuration will be used in 'filemanager/files/upload' 48 | // To support dynamic multiple upload 49 | // Default multiple upload is true, max file to upload is 10 50 | // If multiple set to true and maxFileCount is not set, unlimited multiple upload 51 | 'filesUpload' => [ 52 | 'multiple' => true, 53 | 'maxFileCount' => 30 54 | ], 55 | // in mime type format 56 | 'acceptedFilesType' => [ 57 | 'image/jpeg', 58 | 'image/png', 59 | 'image/gif', 60 | ], 61 | // MB 62 | 'maxFileSize' => 8, 63 | // [width, height], suggested thumbnail size is 120X120 64 | 'thumbnailSize' => [120,120] 65 | ] 66 | ] 67 | ]; 68 | ``` 69 | 70 | Upload file to AWS S3: 71 | 72 | ```php 73 | return [ 74 | 'modules' => [ 75 | 'gridview' => [ 76 | 'class' => '\kartik\grid\Module' 77 | ], 78 | 'filemanager' => [ // do not change module to other name 79 | 'class' => 'dpodium\filemanager\Module', 80 | // This configuration will be used in 'filemanager/files/upload' 81 | // To support dynamic multiple upload 82 | // Default multiple upload is true, max file to upload is 10 83 | // If multiple set to true and maxFileCount is not set, unlimited multiple upload 84 | 'filesUpload' => [ 85 | 'multiple' => true, 86 | 'maxFileCount' => 30 87 | ], 88 | 'storage' => [ 89 | 's3' => [ 90 | 'key' => 'your aws s3 key', 91 | 'secret' => 'your aws s3 secret', 92 | 'bucket' => '', 93 | 'region' => '', 94 | 'proxy' => '192.168.16.1:10', 95 | 'cdnDomain' => '', 96 | 'prefixPath' => '', 97 | 'cacheTime' => '', // if empty, by default is 2592000 (30 days) 98 | ] 99 | ], 100 | // in mime type format 101 | 'acceptedFilesType' => [ 102 | 'image/jpeg', 103 | 'image/png', 104 | 'image/gif', 105 | ], 106 | // MB 107 | 'maxFileSize' => 8, 108 | // [width, height], suggested thumbnail size is 120X120 109 | 'thumbnailSize' => [120,120] 110 | ] 111 | ] 112 | ]; 113 | ``` 114 | 115 | You can then access File Manager through the following URL: 116 | 117 | ``` 118 | http://localhost/path/to/index.php?r=filemanager/folders 119 | http://localhost/path/to/index.php?r=filemanager/files 120 | ``` 121 | 122 | In order to use File Manager Browse feature: 123 | 124 | ```php 125 | use yii\helpers\Html; 126 | use yii\widgets\ActiveForm; 127 | use dpodium\filemanager\widgets\FileBrowse; 128 | 129 | // This is just an example to upload a banner 130 | $form = ActiveForm::begin(); 131 | echo $form->field($model, 'banner_name'); 132 | echo $form->field($model, 'banner_description'); 133 | 134 | // if you would like to store file_identifier in your table 135 | echo $form->field($model, 'file_identifier')->widget(FileBrowse::className(), [ 136 | 'multiple' => false, // allow multiple upload 137 | 'folderId' => 1 // set a folder to be uploaded to. 138 | ]); 139 | 140 | echo Html::submitButton('Submit', ['class' => 'btn btn-primary']); 141 | ActiveForm::end(); 142 | 143 | // !important: modal must be rendered after form 144 | echo FileBrowse::renderModal(); 145 | ``` 146 | 147 | In order to use File Manager TinyMCE integration: 148 | 149 | - install `2amigos/yii2-tinymce-widget` via composer 150 | 151 | ```php 152 | use yii\helpers\Html; 153 | use yii\widgets\ActiveForm; 154 | use dpodium\filemanager\widgets\FileBrowseEditor; 155 | 156 | // This is just an example to edit one field 157 | $form = ActiveForm::begin(); 158 | 159 | echo $form->field($model, 'editor')->widget(TinyMce::class, [ 160 | 'clientOptions' => [ 161 | // add yii2-filemanager to plugin config 162 | 'plugins' => [ 163 | "... yii2-filemanager ..." 164 | ], 165 | // optional add yii2-filemanager to toolbar 166 | 'toolbar' => "... yii2-filemanager ...", 167 | ] 168 | ]); 169 | 170 | echo Html::submitButton('Submit', ['class' => 'btn btn-primary']); 171 | ActiveForm::end(); 172 | 173 | // !important: modal must be rendered after form 174 | echo FileBrowseEditor::widget([ 175 | 'multiple' => false, // allow multiple upload 176 | 'folderId' => 1, // set a folder to be uploaded to. 177 | ]); 178 | 179 | 180 | ``` -------------------------------------------------------------------------------- /assets/css/filemanager.css: -------------------------------------------------------------------------------- 1 | /*general css*/ 2 | .fa-icon { 3 | text-align: center; 4 | } 5 | .btn > .fa-icon { 6 | margin-right: 4px; 7 | } 8 | .page-header { 9 | margin: 0 0 12px; 10 | border-bottom: 1px dotted #e2e2e2; 11 | padding-bottom: 16px; 12 | padding-top: 7px; 13 | } 14 | .page-header h1 { 15 | padding: 0; 16 | margin: 0 8px; 17 | font-size: 24px; 18 | font-weight: lighter; 19 | color: #2679b5; 20 | } 21 | .space-10 { 22 | max-height: 1px; 23 | min-height: 1px; 24 | overflow: hidden; 25 | margin: 10px 0 9px; 26 | } 27 | .space-24 { 28 | max-height: 1px; 29 | min-height: 1px; 30 | overflow: hidden; 31 | margin: 24px 0 23px; 32 | } 33 | .fm-loading { 34 | text-align: center; 35 | font-size: 50px; 36 | color: #999; 37 | } 38 | .fm-thumb { 39 | text-align: center; 40 | vertical-align: middle; 41 | } 42 | .btn-copy { 43 | border-radius: 20px; 44 | float: right; 45 | border-color: #ccc; 46 | background-color: #fff; 47 | border-style: solid; 48 | } 49 | .btn-copy:hover, .btn-copy:active { 50 | background-color: #ccc; 51 | } 52 | /*accordion*/ 53 | .fm-accordion a.collapse-toggle { 54 | display: block; 55 | width: 100%; 56 | } 57 | .fm-accordion a.collapse-toggle:hover { 58 | text-decoration: none; 59 | } 60 | 61 | /*edit bar (after upload complete)*/ 62 | .separator-box { 63 | padding: 0; 64 | box-shadow: none; 65 | margin: 3px 0; 66 | border: 1px solid #cccccc; 67 | } 68 | .separator-box .separator-box-header { 69 | border-bottom-width: 0; 70 | border-color: #bce8f1; 71 | background-color: #d9edf7; 72 | color: #31708f; 73 | padding-left: 10px; 74 | margin-bottom: 6px; 75 | } 76 | .separator-box-title { 77 | line-height: 30px; 78 | padding: 0 0 0 6px; 79 | margin: 0; 80 | display: inline; 81 | } 82 | .separator-box-toolbar { 83 | line-height: 29px; 84 | display: inline-block; 85 | padding: 0 10px; 86 | float: right; 87 | position: relative; 88 | } 89 | .separator-box-toolbar:before { 90 | display: inline-block; 91 | content: ""; 92 | position: absolute; 93 | top: 3px; 94 | bottom: 3px; 95 | left: -1px; 96 | border: 1px solid #307ecc; 97 | border-width: 0 1px 0 0; 98 | } 99 | .separator-box-header > div { 100 | vertical-align: text-top; 101 | display: inline-block; 102 | } 103 | 104 | .loading-box { 105 | display: block; 106 | width: 100%; 107 | text-align: center; 108 | margin-top: 40px; 109 | } 110 | .loading-box > .loading-icon { 111 | display: inline-block; 112 | border: 12px solid #f3f3f3; /* Light grey */ 113 | border-top: 12px solid #999999; /* Blue */ 114 | border-radius: 50%; 115 | width: 64px; 116 | height: 64px; 117 | animation: spin 1s linear infinite; 118 | } 119 | @keyframes spin { 120 | 0% { transform: rotate(0deg); } 121 | 100% { transform: rotate(360deg); } 122 | } 123 | 124 | /*modal*/ 125 | .fm-modal.modal > .modal-dialog > .modal-content > .modal-body { 126 | max-height: 450px; 127 | overflow-y: auto; 128 | } 129 | .fm-modal.modal > .modal-dialog > .modal-content > .modal-body .tab-content { 130 | min-height: 300px; 131 | } 132 | 133 | /*Gallery gridview*/ 134 | div.fm-gallery { 135 | margin-left: 0; 136 | } 137 | .fm-gallery { 138 | list-style: none; 139 | } 140 | .fm-gallery .fm-section { 141 | /*display: block;*/ 142 | /*float: left;*/ 143 | } 144 | 145 | .btn.btn-browse { 146 | display: inline-block; 147 | /*position: absolute;*/ 148 | vertical-align: top; 149 | } 150 | .btn-browse.attached { 151 | display: none; 152 | } 153 | 154 | .fm-browse-selected { 155 | position: relative; 156 | height: auto; 157 | } 158 | .fm-browse-selected > input { 159 | opacity: 0; 160 | width: 0; 161 | height: 0; 162 | } 163 | .fm-browse-selected-view { 164 | display: inline-block; 165 | } 166 | 167 | .fm-section-item { 168 | /*display: inline-block;*/ 169 | float: left; 170 | position: relative; 171 | overflow: hidden; 172 | margin: 2px; 173 | border: 3px solid #fff; 174 | box-shadow: 0 0 15px #eee inset; 175 | background: #eee none repeat; 176 | } 177 | .fm-section-item.selected > img { 178 | /*border: solid 3px #1e8cbe;*/ 179 | } 180 | .fm-section-item.selected { 181 | box-sizing:border-box; 182 | -moz-box-sizing:border-box; 183 | -webkit-box-sizing:border-box; 184 | border: solid 3px #1e8cbe; 185 | } 186 | .fm-section-item .hover-wrapper:hover, 187 | .fm-browse-selected.attached:hover { 188 | cursor: pointer; 189 | } 190 | .fm-section-item label { 191 | margin: 0px; 192 | } 193 | .fm-section-item input[type=radio] { 194 | display: none; 195 | } 196 | .fm-section-item .hover-wrapper { 197 | position: absolute; 198 | top: 0; 199 | right: 0; 200 | bottom: 0; 201 | left: 0; 202 | text-align: center; 203 | color: #ffffff; 204 | background-color: rgba(0, 0, 0, 0.55); 205 | opacity: 0; 206 | } 207 | .fm-section-item .tool-box { 208 | position: absolute; 209 | top: auto; 210 | right: 0; 211 | bottom: -10px; 212 | left: 0; 213 | text-align: center; 214 | color: #ffffff; 215 | background-color: #333333; 216 | opacity: 0; 217 | width: auto; 218 | height: 28px; 219 | padding: 4px; 220 | transition: bottom 0.2s ease; 221 | } 222 | .fm-section-item .tool-box i.fa-icon { 223 | font-size: 16px; 224 | } 225 | .fm-section-item:hover .hover-wrapper { 226 | opacity: 1; 227 | transition: all 0.2s ease; 228 | } 229 | .fm-section-item:hover .tool-box { 230 | opacity: 1; 231 | bottom: 0px; 232 | } 233 | .fm-section-item .tool-box i.fa-icon:hover { 234 | cursor: pointer; 235 | color: #428bca; 236 | } 237 | 238 | #fm-modal .modal-lg { 239 | position: absolute; 240 | padding-right: 15px; 241 | width: 98%; 242 | top: 0; 243 | bottom: 0; 244 | left: 0; 245 | right: 0; 246 | } 247 | @media (min-width: 992px) { 248 | #fm-modal .modal-lg { 249 | width: 98%; 250 | padding-right: 0; 251 | } 252 | } 253 | @media (min-width: 768px) { 254 | #fm-modal .modal-lg { 255 | padding-right: 0; 256 | } 257 | } -------------------------------------------------------------------------------- /assets/js/filemanager.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ajaxSuccess(function (event, xhr, settings) { 2 | // To-do-list: add checking only for filemanager ajax upload success 3 | if (xhr.responseJSON != undefined) { 4 | if (xhr.responseJSON.type != undefined) { 5 | if (xhr.responseJSON.type == 1) { 6 | jQuery('.edit-uploaded-container').append(xhr.responseJSON.html); 7 | } else if (xhr.responseJSON.type == 2) { 8 | var uploadTabId = jQuery('#fm-upload-tab').attr('href'); 9 | var libraryTabId = jQuery('#fm-library-tab').attr('href'); 10 | jQuery(uploadTabId).html(''); 11 | jQuery(libraryTabId).html(''); 12 | jQuery('#fm-library-tab').click(); 13 | } 14 | } 15 | } 16 | }); 17 | 18 | jQuery(document).on('click', '.btn-copy', function (e) { 19 | e.preventDefault(); 20 | var textSelector = document.querySelector('.copy-object-url'); 21 | var range = document.createRange(); 22 | range.selectNode(textSelector); 23 | window.getSelection().removeAllRanges(); 24 | window.getSelection().addRange(range); 25 | 26 | try { 27 | // Now that we've selected the anchor text, execute the copy command 28 | var successful = document.execCommand('copy'); 29 | var msg = successful ? 'successfully' : 'unsuccessfully'; 30 | alert('Object Url was copy to clipboard ' + msg); 31 | } catch (err) { 32 | alert('Oops, unable to copy!'); 33 | } 34 | 35 | // Remove the selections - NOTE: Should use 36 | // removeRange(range) when it is supported 37 | window.getSelection().removeAllRanges(); 38 | }); 39 | 40 | var $browse, $gallery; 41 | 42 | jQuery(document).on('submit', '#fm-modal form#fm-search-form', function (e) { 43 | e.preventDefault(); 44 | var postData = '?' + jQuery(this).serialize(); 45 | var tabId = jQuery('#fm-modal #fm-library-tab').attr('href'); 46 | jQuery(tabId).html(''); 47 | $browse.renderTabContent('#fm-library-tab', postData, 1); 48 | return false; 49 | }); 50 | 51 | var gridBox = function () { 52 | "use strict"; 53 | (function (jQuery) { 54 | jQuery(document).on('change', '.tool-box input[name=fm-gallery-group]:radio', function () { 55 | var selectedItem; 56 | 57 | jQuery(this).prop('checked', true); 58 | jQuery('div.selected').removeClass('selected'); 59 | selectedItem = jQuery(this).closest('.fm-section-item'); 60 | selectedItem.addClass('selected'); 61 | 62 | if ($gallery.viewFrom === 'modal') { 63 | $gallery.renderFileInfo(jQuery(this).data('url')); 64 | } else { 65 | window.location = jQuery(this).data('url'); 66 | } 67 | }); 68 | 69 | jQuery(document).on('click', '.tool-box .fm-remove', function () { 70 | var $browse_selected = jQuery(this).closest('.fm-browse-selected'); 71 | var inputId = $browse_selected.find(".fm-btn-browse").attr('for'); 72 | $browse_selected.removeClass('attached'); 73 | $browse_selected.find('.fm-browse-selected-view').html(''); 74 | $browse_selected.find('#' + inputId).val(''); 75 | $browse_selected.find('#' + inputId).blur(); 76 | }); 77 | 78 | jQuery(document).on('click', '.fm-section-item', function (e) { 79 | var target = jQuery(e.target); 80 | if (target.hasClass('fm-use')) { 81 | $browse.useFile(target); 82 | } else if (target.hasClass('hover-wrapper')) { 83 | var useTool = target.next().children('.fm-use'); 84 | $browse.useFile(useTool); 85 | } 86 | }); 87 | 88 | jQuery(document).on('click', '.tool-box .fm-delete', function () { 89 | if (confirmDelete) { 90 | var libraryTabId = jQuery('#fm-library-tab').attr('href'); 91 | jQuery(libraryTabId).html('
'); 92 | $browse.deleteFile(jQuery(this)); 93 | } 94 | }); 95 | })(window.jQuery); 96 | }; 97 | 98 | (function ($) { 99 | "use strict"; 100 | 101 | var FilemanagerBrowse, FilemanagerGallery, FilemanagerModal; 102 | var FilemanagerModal = $('#fm-modal'); 103 | 104 | var FilemanagerBrowse = function (element, options) { 105 | var self = this; 106 | self.element = $(element); 107 | self.multiple = options.multiple; 108 | self.maxFileCount = options.maxFileCount; 109 | self.folderId = options.folderId; 110 | self.tinymce = options.tinymce; 111 | 112 | self.element.find(".fm-btn-browse").on('click', function (e) { 113 | e.preventDefault(); 114 | self.renderTabContent('#fm-library-tab'); 115 | $browse = self; 116 | }); 117 | 118 | FilemanagerModal.find("#fm-library-tab").on('click', function (e) { 119 | e.preventDefault(); 120 | self.renderTabContent('#fm-library-tab'); 121 | }); 122 | 123 | FilemanagerModal.find("#fm-upload-tab").on('click', function (e) { 124 | e.preventDefault(); 125 | self.renderTabContent('#fm-upload-tab'); 126 | }); 127 | }; 128 | 129 | FilemanagerBrowse.prototype = { 130 | constructor: FilemanagerBrowse, 131 | renderTabContent: function (tabId, postData, modal) { 132 | if (postData == undefined) { 133 | postData = ''; 134 | } 135 | 136 | var $selectedTab = FilemanagerModal.find(tabId); 137 | var ajaxUrl = ''; 138 | 139 | if (modal){ 140 | ajaxUrl = $selectedTab.data('url'); 141 | if(ajaxUrl.indexOf('?') >= 0){ 142 | ajaxUrl = ajaxUrl.substring(0, ajaxUrl.indexOf('?')); 143 | } 144 | } else { 145 | ajaxUrl = $selectedTab.data('url'); 146 | } 147 | $selectedTab.tab('show'); 148 | 149 | if (tabId === '#fm-upload-tab') { 150 | postData = { 151 | multiple: this.multiple, 152 | maxFileCount: this.maxFileCount, 153 | folderId: this.folderId 154 | }; 155 | } else { 156 | ajaxUrl += postData; 157 | } 158 | 159 | if (jQuery($selectedTab.attr('href')).html() == '') { 160 | var loading_icon = '
'; 161 | jQuery($selectedTab.attr('href')).html(loading_icon); 162 | setTimeout(function () { 163 | jQuery.ajax({ 164 | url: ajaxUrl, 165 | type: 'POST', 166 | dataType: 'html', 167 | data: postData, 168 | success: function (html) { 169 | jQuery($selectedTab.attr('href')).html(html); 170 | } 171 | }); 172 | }, 800); 173 | } 174 | }, 175 | useFile: function ($this) { 176 | var tinymceEditor = this.tinymce; 177 | jQuery.ajax({ 178 | url: $this.data('url'), 179 | type: 'POST', 180 | data: { 181 | id: $this.data('id') 182 | }, 183 | dataType: 'json', 184 | success: function (data) { 185 | if(tinymceEditor !== undefined) { 186 | var link = ''+data.caption+'' 187 | tinymceEditor.execCommand('mceInsertContent', false, link); 188 | } else { 189 | jQuery('input[name^="Filemanager"]').each(function () { 190 | var index = jQuery(this).prop('name').match(/\[(.*?)\]/)[1]; 191 | jQuery(this).val(data[index]); 192 | }); 193 | 194 | var inputId = $browse.element.find(".fm-btn-browse").attr('for'); 195 | $browse.element.addClass('attached'); 196 | $browse.element.find('.fm-browse-selected-view').html(data.selectedFile); 197 | $browse.element.find('#' + inputId).val(data['file_identifier']); 198 | $browse.element.find('#' + inputId).blur(); 199 | } 200 | } 201 | }); 202 | FilemanagerModal.modal('hide'); 203 | }, 204 | deleteFile: function ($this) { 205 | jQuery.ajax({ 206 | url: $this.data('url'), 207 | type: 'POST', 208 | dataType: 'json', 209 | success: function (data) { 210 | var libraryTabId = jQuery('#fm-library-tab').attr('href'); 211 | jQuery(libraryTabId).html(''); 212 | $browse.renderTabContent('#fm-library-tab'); 213 | } 214 | }); 215 | } 216 | }; 217 | 218 | $.fn.filemanagerBrowse = function (option) { 219 | var args = Array.apply(null, arguments); 220 | args.shift(); 221 | return this.each(function () { 222 | var $this = $(this), data = $this.data('filemanagerBrowse'), options = typeof option === 'object' && option; 223 | 224 | if (!data) { 225 | $this.data('filemanagerBrowse', (data = new FilemanagerBrowse(this, $.extend({}, $.fn.filemanagerBrowse.defaults, options, $(this).data())))); 226 | } 227 | 228 | if (typeof option === 'string') { 229 | data[option].apply(data, args); 230 | } 231 | }); 232 | }; 233 | $.fn.filemanagerBrowse.defaults = {}; 234 | $.fn.filemanagerBrowse.Constructor = FilemanagerBrowse; 235 | 236 | var FilemanagerGallery = function (gallery, options) { 237 | var self = $gallery = this; 238 | 239 | self.$fileInfo = FilemanagerModal.find('.fm-file-info'); 240 | self.$btnUse = $(gallery).find('.tool-box .fm-use'); 241 | self.$btnView = $(gallery).find('input[name=fm-gallery-group]:radio'); 242 | self.viewFrom = options.viewFrom; 243 | 244 | var renderAjax = true, scrollAtBottom = false; 245 | $(window).scroll(function () { 246 | var wintop = $(window).scrollTop(), docheight = $(document).height(), winheight = $(window).height(); 247 | var scrolltrigger = 0.95; 248 | var ajaxUrl = $('.fm-section #fm-next-page a').attr('href'); 249 | 250 | if ((wintop / (docheight - winheight)) > scrolltrigger && ajaxUrl != undefined) { 251 | scrollAtBottom = true; 252 | } else { 253 | return false; 254 | } 255 | 256 | if (renderAjax === true && scrollAtBottom === true) { 257 | renderAjax = false; 258 | scrollAtBottom = false; 259 | jQuery('.fm-gallery-loading').removeClass('hide'); 260 | jQuery.ajax({ 261 | url: ajaxUrl, 262 | type: 'POST', 263 | dataType: 'html', 264 | complete: function () { 265 | renderAjax = true; 266 | jQuery('.fm-gallery-loading').addClass('hide'); 267 | }, 268 | success: function (html) { 269 | $('.fm-gallery .fm-section:last #fm-next-page').remove(); 270 | $('.fm-gallery').append(html); 271 | } 272 | }); 273 | } 274 | }); 275 | }; 276 | 277 | FilemanagerGallery.prototype = { 278 | constructor: FilemanagerGallery, 279 | renderFileInfo: function (url) { 280 | var fileInfo = this.$fileInfo; 281 | fileInfo.html(''); 282 | jQuery('.fm-file-info-loading .fm-loading').removeClass('hide'); 283 | jQuery.ajax({ 284 | url: url, 285 | type: 'POST', 286 | data: { 287 | uploadType: this.viewFrom 288 | }, 289 | complete: function () { 290 | jQuery('.fm-file-info-loading .fm-loading').addClass('hide'); 291 | }, 292 | dataType: 'html', 293 | success: function (html) { 294 | fileInfo.html(html); 295 | } 296 | }); 297 | } 298 | }; 299 | 300 | $.fn.filemanagerGallery = function (option) { 301 | var args = Array.apply(null, arguments); 302 | args.shift(); 303 | return this.each(function () { 304 | var $this = $(this), data = $this.data('filemanagerGallery'), options = typeof option === 'object' && option; 305 | 306 | if (!data) { 307 | $this.data('filemanagerGallery', (data = new FilemanagerGallery(this, $.extend({}, $.fn.filemanagerGallery.defaults, options, $(this).data())))); 308 | } 309 | 310 | if (typeof option === 'string') { 311 | data[option].apply(data, args); 312 | } 313 | }); 314 | }; 315 | $.fn.filemanagerGallery.defaults = {}; 316 | $.fn.filemanagerGallery.Constructor = FilemanagerGallery; 317 | 318 | })(window.jQuery); -------------------------------------------------------------------------------- /assets/js/yii2-filemanager.plugin.js: -------------------------------------------------------------------------------- 1 | tinymce.PluginManager.add('yii2-filemanager', function(editor, url) { 2 | editor.on('init', function (e) { 3 | var m = $('#fm-modal'); 4 | $(this.editorContainer).filemanagerBrowse({"multiple":m.data('multiple'),"maxFileCount":m.data('maxfilecount'),"folderId":m.data('folderid'), "tinymce": editor}); 5 | }); 6 | 7 | // Add a button that opens a window 8 | editor.addButton('yii2-filemanager', { 9 | text: false, 10 | tooltip: 'Insert document', 11 | icon: 'newdocument', 12 | classes: 'fm-btn-browse', 13 | onclick: function(e) { 14 | var fileBrowse = $(editor.editorContainer).data('filemanagerBrowse'); 15 | e.preventDefault(); 16 | fileBrowse.renderTabContent('#fm-library-tab'); 17 | $('#fm-modal').modal({ 18 | show: 'false' 19 | }); 20 | $browse = fileBrowse; 21 | } 22 | }); 23 | 24 | // Adds a menu item to the tools menu 25 | editor.addMenuItem('yii2-filemanager', { 26 | icon: 'newdocument', 27 | text: 'Document', 28 | context: 'insert', 29 | classes: 'fm-btn-browse', 30 | prependToContext: true, 31 | onclick: function(e) { 32 | var fileBrowse = $(editor.editorContainer).data('filemanagerBrowse'); 33 | e.preventDefault(); 34 | fileBrowse.renderTabContent('#fm-library-tab'); 35 | $('#fm-modal').modal({ 36 | show: 'false' 37 | }); 38 | $browse = fileBrowse; 39 | } 40 | }); 41 | 42 | return { 43 | getMetadata: function () { 44 | return { 45 | name: "File Manager for Yii2 - TinyMCE Integration", 46 | url: "https://github.com/dpodium/yii2-filemanager" 47 | }; 48 | } 49 | }; 50 | }); 51 | -------------------------------------------------------------------------------- /components/Filemanager.php: -------------------------------------------------------------------------------- 1 | 'separator-box-title']); 19 | $content_2 = Html::tag('div', Html::a(Yii::t('filemanager', 'Edit'), ['/filemanager/files/update', 'id' => $fileId], ['target' => '_blank']), ['class' => 'separator-box-toolbar']); 20 | $content_3 = Html::tag('div', $file . $content_1 . $content_2, ['class' => 'separator-box-header']); 21 | $html = Html::tag('div', $content_3, ['class' => 'separator-box']); 22 | 23 | return $html; 24 | } 25 | 26 | public static function getThumbnail($fileType, $src, $height = '', $width = '') { 27 | $thumbnailSize = \Yii::$app->getModule('filemanager')->thumbnailSize; 28 | 29 | if ($fileType == 'image') { 30 | return Html::img($src, ['class' => 'img-responsive']); 31 | } 32 | 33 | $availableThumbnail = ['archive', 'audio', 'code', 'excel', 'movie', 'pdf', 'powerpoint', 'text', 'video', 'word', 'zip']; 34 | $type = explode('/', $fileType); 35 | $faClass = 'fa-file-o'; 36 | $fontSize = !empty($height) ? $height : "{$thumbnailSize[1]}px"; 37 | 38 | if (in_array($type[0], $availableThumbnail)) { 39 | $faClass = "fa-file-{$type[0]}-o"; 40 | } else if (in_array($type[1], $availableThumbnail)) { 41 | $faClass = "fa-file-{$type[1]}-o"; 42 | } 43 | 44 | return Html::tag('div', Html::tag('i', '', ['class' => "fa {$faClass}", 'style' => "font-size: $fontSize"]), ['class' => 'fm-thumb', 'style' => "height: $height; width: $width"]); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /components/FilemanagerHelper.php: -------------------------------------------------------------------------------- 1 | getModule('filemanager'); 25 | $cacheKey = 'files' . '/' . $key . '/' . $value; 26 | 27 | if (isset($module->cache)) { 28 | if (is_string($module->cache) && strpos($module->cache, '\\') === false) { 29 | $cache = \Yii::$app->get($module->cache, false); 30 | } else { 31 | $cache = Yii::createObject($module->cache); 32 | } 33 | 34 | if ($file = $cache->get($cacheKey)) { 35 | return $file; 36 | } 37 | } 38 | 39 | $model = new $module->models['files']; 40 | $fileObject = $model->find()->where([$key => $value])->one(); 41 | 42 | $file = null; 43 | if ($fileObject) { 44 | foreach ($fileObject as $attribute => $value) { 45 | $file['info'][$attribute] = $value; 46 | } 47 | 48 | $domain = $fileObject->object_url; 49 | $file['backend_img_src'] = $domain . $fileObject->src_file_name . '?' . $fileObject->updated_at; 50 | $file['backend_img_thumb_src'] = $domain . $fileObject->thumbnail_name . '?' . $fileObject->updated_at; 51 | 52 | if (isset($module->storage['s3']['cdnDomain']) && !empty($module->storage['s3']['cdnDomain'])) { 53 | $domain = $module->storage['s3']['cdnDomain'] . "/{$fileObject->url}/"; 54 | } 55 | $src = $file['img_src'] = $domain . $fileObject->src_file_name . '?' . $fileObject->updated_at; 56 | $file['img_thumb_src'] = $domain . $fileObject->thumbnail_name . '?' . $fileObject->updated_at; 57 | if ($thumbnail && !is_null($fileObject->dimension)) { 58 | $src = $domain . $fileObject->thumbnail_name; 59 | } 60 | 61 | if (!is_null($fileObject->dimension)) { 62 | $file['img'] = Html::img($src); 63 | } 64 | 65 | if ($tag && isset($fileObject->filesRelationships)) { 66 | foreach ($fileObject->filesRelationships as $relationship) { 67 | if (isset($relationship->tag)) { 68 | $file['tag'][$relationship->tag->tag_id] = $relationship->tag->value; 69 | } 70 | } 71 | } 72 | } 73 | 74 | if ($file !== null && isset($cache)) { 75 | $cache->set($cacheKey, $file, 86400, new \yii\caching\TagDependency([ 76 | 'tags' => self::CACHE_TAG 77 | ])); 78 | } 79 | 80 | return $file; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /components/GridBox.php: -------------------------------------------------------------------------------- 1 | 'i', 34 | * 'options' => [ 35 | * 'class' => 'fa-icon fa fa-link fm-use', 36 | * 'data-url' => \yii\helpers\Url::to(['/filemanager/files/use']), 37 | * 'data-id' => $model->file_id, 38 | * 'title' => \Yii::t('filemanager', 'Use'), 39 | * ] 40 | * ], 41 | * [ 42 | * 'tagType' => 'label', 43 | * 'content' => $input . $view 44 | * ], 45 | * [ 46 | * 'tagType' => 'i', 47 | * 'options' => [ 48 | * 'class' => 'fa-icon fa fa-times fm-remove', 49 | * 'title' => \Yii::t('filemanager', 'Remove') 50 | * ] 51 | * ], 52 | * ]; 53 | */ 54 | public $toolArray; 55 | public $thumbnailSize = [120, 120]; 56 | 57 | public function init() { 58 | parent::init(); 59 | 60 | if (isset($this->owner->containerOptions)) { 61 | $id = $this->owner->containerOptions['id']; 62 | } else if (isset($this->owner->options)) { 63 | $id = $this->owner->options['id']; 64 | } 65 | 66 | if (isset($id)) { 67 | $view = $this->owner->getView(); 68 | $view->registerJs("gridBox();"); 69 | } 70 | } 71 | 72 | public function renderGridBox() { 73 | $fileThumb = Filemanager::getThumbnail($this->fileType, $this->src, "{$this->thumbnailSize[0]}px", "{$this->thumbnailSize[1]}px"); 74 | $toolbox = $this->renderToolbox(); 75 | $hoverWrapper = Html::tag('div', '', ['class' => 'hover-wrapper']); 76 | $width = $this->thumbnailSize[0] + 10 + 6; 77 | $height = $this->thumbnailSize[1] + 10 + 6; 78 | 79 | return Html::tag('div', $fileThumb . $hoverWrapper . $toolbox, ['class' => 'fm-section-item', 'style' => "padding: 5px; width: {$width}px; height: {$height}px;"]); 80 | } 81 | 82 | protected function renderToolbox() { 83 | $tools = ''; 84 | foreach ($this->toolArray as $tool) { 85 | $options = isset($tool['options']) ? $tool['options'] : []; 86 | $content = isset($tool['content']) ? $tool['content'] : ''; 87 | $tools .= Html::tag($tool['tagType'], $content, $options) . ' '; 88 | } 89 | 90 | return Html::tag('div', $tools, ['class' => 'tool-box hidden-xs']); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /components/S3.php: -------------------------------------------------------------------------------- 1 | getModule('filemanager'); 18 | 19 | $this->key = isset($module->storage['s3']['key']) ? $module->storage['s3']['key'] : ''; 20 | $this->secret = isset($module->storage['s3']['secret']) ? $module->storage['s3']['secret'] : ''; 21 | $this->bucket = isset($module->storage['s3']['bucket']) ? $module->storage['s3']['bucket'] : ''; 22 | 23 | if ($this->key == '') { 24 | throw new InvalidConfigException('Key cannot be empty!'); 25 | } 26 | if ($this->secret == '') { 27 | throw new InvalidConfigException('Secret cannot be empty!'); 28 | } 29 | if ($this->bucket == '') { 30 | throw new InvalidConfigException('Bucket cannot be empty!'); 31 | } 32 | 33 | $param = [ 34 | 'version' => 'latest', 35 | 'credentials' => [ 36 | 'key' => $this->key, 37 | 'secret' => $this->secret 38 | ] 39 | ]; 40 | 41 | if (isset($module->storage['s3']['version'])) { 42 | $param['version'] = $module->storage['s3']['version']; 43 | } 44 | 45 | if (isset($module->storage['s3']['region'])) { 46 | $param['region'] = $module->storage['s3']['region']; 47 | } 48 | 49 | if (isset($module->storage['s3']['proxy'])) { 50 | $param['http']['proxy'] = $module->storage['s3']['proxy']; 51 | } 52 | 53 | $this->s3 = new S3Client($param); 54 | } 55 | 56 | public function upload($file, $fileName, $path) { 57 | $result['status'] = false; 58 | 59 | try { 60 | $cacheTime = empty(\Yii::$app->getModule('filemanager')->storage['s3']['cacheTime']) ? '2592000' : \Yii::$app->getModule('filemanager')->storage['s3']['cacheTime']; 61 | $uploadResult = $this->s3->putObject([ 62 | 'Bucket' => $this->bucket, 63 | 'Key' => $path . '/' . $fileName, 64 | 'SourceFile' => $file->tempName, 65 | 'ContentType' => $file->type, 66 | 'ACL' => 'public-read', 67 | 'CacheControl' => 'max-age=' . $cacheTime, 68 | ]); 69 | 70 | $result['status'] = true; 71 | $result['objectUrl'] = $uploadResult['ObjectURL']; 72 | $result['uploadResult'] = $uploadResult; 73 | } catch (S3Exception $e) { 74 | echo $e . "\nThere was an error uploading the file.\n"; 75 | } 76 | 77 | return $result; 78 | } 79 | 80 | public function uploadThumbnail($file, $fileName, $path, $fileType) { 81 | $result['status'] = false; 82 | 83 | try { 84 | $cacheTime = empty(\Yii::$app->getModule('filemanager')->storage['s3']['cacheTime']) ? '2592000' : \Yii::$app->getModule('filemanager')->storage['s3']['cacheTime']; 85 | $uploadResult = $this->s3->putObject([ 86 | 'Body' => $file, 87 | 'Bucket' => $this->bucket, 88 | 'Key' => $path . '/' . $fileName, 89 | 'ContentType' => $fileType, 90 | 'ACL' => 'public-read', 91 | 'CacheControl' => 'max-age=' . $cacheTime 92 | ]); 93 | 94 | $result['status'] = true; 95 | $result['objectUrl'] = $uploadResult['ObjectURL']; 96 | $result['uploadResult'] = $uploadResult; 97 | } catch (S3Exception $e) { 98 | echo $e . "\nThere was an error uploading the file.\n"; 99 | } 100 | 101 | return $result; 102 | } 103 | 104 | public function delete($files) { 105 | $result['status'] = false; 106 | $objects = []; 107 | 108 | foreach ($files as $fileKey) { 109 | $objects[] = $fileKey; 110 | } 111 | try { 112 | $deleteResult = $this->s3->deleteObjects([ 113 | 'Bucket' => $this->bucket, 114 | 'Delete' => ['Objects' => $objects], 115 | ]); 116 | $result['status'] = true; 117 | $result['data'] = $deleteResult; 118 | } catch (S3Exception $e) { 119 | echo $e . "\nThere was an error uploading the file.\n"; 120 | } 121 | 122 | return $result; 123 | } 124 | 125 | public function listObject() { 126 | $result = []; 127 | $iterator = $this->s3->getIterator('ListObjects', array( 128 | 'Bucket' => $this->bucket 129 | )); 130 | 131 | foreach ($iterator as $object) { 132 | $result[] = $object['Key']; 133 | } 134 | 135 | return $result; 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dpodium/yii2-filemanager", 3 | "type": "yii2-extension", 4 | "description": "A file manager for Yii2. Allow user to manage files from any location as well as browsing files within the application.", 5 | "keywords": ["yii2", "file", "manager", "filemanager", "browse", "widget"], 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "June See", 10 | "email": "june.see@dpodium.com", 11 | "homepage": "http://www.dpodium.com" 12 | } 13 | ], 14 | "minimum-stability": "stable", 15 | "support": { 16 | "source": "https://github.com/dpodium/yii2-filemanager", 17 | "issues": "https://github.com/dpodium/yii2-filemanager/issues" 18 | }, 19 | "require": { 20 | "php": ">=5.4.0", 21 | "yiisoft/yii2": "2.0.*", 22 | "yiisoft/yii2-imagine": "*", 23 | "aws/aws-sdk-php": "3.*", 24 | "kartik-v/yii2-widgets": "*", 25 | "kartik-v/yii2-widget-activeform": "*", 26 | "kartik-v/yii2-widget-fileinput": "*", 27 | "kartik-v/yii2-editable": "*", 28 | "kartik-v/yii2-grid": "dev-master", 29 | "rmrevin/yii2-fontawesome": "~2.17" 30 | }, 31 | "autoload": { 32 | "psr-4": { 33 | "dpodium\\filemanager\\": "" 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /controllers/FilesController.php: -------------------------------------------------------------------------------- 1 | [ 32 | 'class' => VerbFilter::className(), 33 | 'actions' => [ 34 | 'delete' => ['post'], 35 | ], 36 | ], 37 | ]; 38 | } 39 | 40 | /** 41 | * Lists all Files models. 42 | * @return mixed 43 | */ 44 | public function actionIndex($view = 'list') { 45 | if (!in_array($view, ['list', 'grid'])) { 46 | throw new \Exception('Invalid view.'); 47 | } 48 | 49 | FilemanagerAsset::register($this->view); 50 | $searchModel = new $this->module->models['filesSearch']; 51 | $dataProvider = $searchModel->search(Yii::$app->request->queryParams); 52 | 53 | // lazy loading 54 | if ($view == 'grid' && \Yii::$app->request->isAjax) { 55 | \Yii::$app->response->data = Gallery::widget([ 56 | 'dataProvider' => $dataProvider, 57 | 'viewFrom' => 'full-page' 58 | ]); 59 | \Yii::$app->end(); 60 | } 61 | 62 | $folders = $this->module->models['folders']; 63 | $folderArray = ArrayHelper::merge(['' => Yii::t('filemanager', 'All')], ArrayHelper::map($folders::find()->all(), 'folder_id', 'category')); 64 | return $this->render('index', [ 65 | 'model' => $searchModel, 66 | 'dataProvider' => $dataProvider, 67 | 'folderArray' => $folderArray, 68 | 'uploadType' => Filemanager::TYPE_FULL_PAGE, 69 | 'view' => $view, 70 | 'viewFrom' => 'full-page' 71 | ]); 72 | } 73 | 74 | /** 75 | * Updates an existing Files model. 76 | * If update is successful, the browser will be redirected to the 'view' page. 77 | * @param integer $id 78 | * @return mixed 79 | */ 80 | public function actionUpdate($id, $view = 'list') { 81 | if (!in_array($view, ['list', 'grid'])) { 82 | throw new \Exception('Invalid view.'); 83 | } 84 | 85 | FilemanagerAsset::register($this->view); 86 | $model = $this->findModel($id); 87 | $filesRelationship = $this->module->models['filesRelationship']; 88 | $tagArray = $filesRelationship::getTagIdArray($id); 89 | $model->tags = ArrayHelper::getColumn($tagArray, 'id'); 90 | $editableTagsLabel = ArrayHelper::getColumn($tagArray, 'value'); 91 | $filesTag = $this->module->models['filesTag']; 92 | $tags = ArrayHelper::map($filesTag::find()->asArray()->all(), 'tag_id', 'value'); 93 | 94 | if (Yii::$app->request->post('hasEditable')) { 95 | $post = []; 96 | $post['Files'] = Yii::$app->request->post('Files'); 97 | 98 | if ($model->load($post)) { 99 | foreach ($post['Files'] as $attribute => $value) { 100 | if ($attribute === 'tags') { 101 | $tagModel = new $this->module->models['filesTag']; 102 | $tagRelationshipModel = new $this->module->models['filesRelationship']; 103 | $saveTags = $tagModel->saveTag($model->tags); 104 | if (isset($saveTags['error'])) { 105 | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 106 | \Yii::$app->response->data = ['output' => '', 'message' => $saveTags['error']]; 107 | return; 108 | } 109 | $tagRelationshipModel->saveRelationship($model->file_id, $saveTags); 110 | $editableTagsLabel = ArrayHelper::getColumn($filesRelationship::getTagIdArray($id), 'value'); 111 | $result = ['output' => implode(', ', $editableTagsLabel), 'message' => '']; 112 | } else { 113 | $model->$attribute = \yii\helpers\Html::encode($model->$attribute); 114 | if ($model->update(true, [$attribute]) !== false) { 115 | $model->touch('updated_at'); 116 | $result = ['output' => $model->$attribute, 'message' => '']; 117 | } else { 118 | $result = ['output' => $model->$attribute, 'message' => $model->errors[$attribute]]; 119 | } 120 | } 121 | } 122 | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 123 | \Yii::$app->response->data = $result; 124 | } 125 | return; 126 | } 127 | 128 | if (Yii::$app->request->post('uploadType')) { 129 | \Yii::$app->response->data = $this->renderAjax('update', [ 130 | 'model' => $model, 131 | 'tags' => $tags, 132 | 'editableTagsLabel' => $editableTagsLabel, 133 | 'uploadType' => 'modal', 134 | 'view' => $view 135 | ]); 136 | return; 137 | } else { 138 | return $this->render('update', [ 139 | 'model' => $model, 140 | 'tags' => $tags, 141 | 'editableTagsLabel' => $editableTagsLabel, 142 | 'uploadType' => 'full-page', 143 | 'view' => $view 144 | ]); 145 | } 146 | } 147 | 148 | /** 149 | * Deletes an existing Files model. 150 | * If deletion is successful, the browser will be redirected to the 'index' page. 151 | * @param integer $id 152 | * @return mixed 153 | */ 154 | public function actionDelete($id) { 155 | $model = $this->findModel($id); 156 | 157 | if (isset($this->module->storage['s3'])) { 158 | $files = [ 159 | ['Key' => $model->url . '/' . $model->src_file_name], 160 | ['Key' => $model->url . '/' . $model->thumbnail_name], 161 | ]; 162 | 163 | $s3 = new S3(); 164 | $s3->delete($files); 165 | } else { 166 | $file = Yii::getAlias($model->storage_id) . $model->object_url . $model->src_file_name; 167 | $thumb = Yii::getAlias($model->storage_id) . $model->object_url . $model->thumbnail_name; 168 | 169 | if (file_exists($file)) { 170 | unlink($file); 171 | } 172 | 173 | if (file_exists($thumb)) { 174 | unlink($thumb); 175 | } 176 | } 177 | 178 | $model->delete(); 179 | 180 | if (Yii::$app->request->isAjax) { 181 | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 182 | \Yii::$app->response->data = ['status' => true]; 183 | \Yii::$app->end(); 184 | } 185 | return $this->redirect(['index']); 186 | } 187 | 188 | public function actionUpload() { 189 | FilemanagerAsset::register($this->view); 190 | 191 | $model = new $this->module->models['files']; 192 | $model->scenario = 'upload'; 193 | $folders = $this->module->models['folders']; 194 | $folderArray = ArrayHelper::map($folders::find()->all(), 'folder_id', 'category'); 195 | 196 | if (Yii::$app->request->isAjax) { 197 | if (!in_array(Yii::$app->request->post('uploadType'), [Filemanager::TYPE_FULL_PAGE, Filemanager::TYPE_MODAL])) { 198 | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 199 | \Yii::$app->response->data = ['error' => Yii::t('filemanager', 'Invalid value: {variable}', ['variable' => 'uploadType'])]; 200 | \Yii::$app->end(); 201 | } 202 | 203 | Yii::$app->response->getHeaders()->set('Vary', 'Accept'); 204 | 205 | $file = UploadedFile::getInstances($model, 'upload_file'); 206 | if (!$file) { 207 | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 208 | \Yii::$app->response->data = ['error' => Yii::t('filemanager', 'File not found.')]; 209 | \Yii::$app->end(); 210 | } 211 | 212 | if($file[0]->getHasError()) { 213 | switch($file[0]->error) { 214 | case UPLOAD_ERR_INI_SIZE: 215 | case UPLOAD_ERR_FORM_SIZE: 216 | $error = ['error' => Yii::t('filemanager', 'File too large.')]; 217 | break; 218 | case UPLOAD_ERR_PARTIAL: 219 | case UPLOAD_ERR_NO_FILE: 220 | case UPLOAD_ERR_NO_TMP_DIR: 221 | case UPLOAD_ERR_CANT_WRITE: 222 | case UPLOAD_ERR_EXTENSION: 223 | default: 224 | $error = ['error' => Yii::t('filemanager', 'Upload fail due to some reasons.')]; 225 | break; 226 | } 227 | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 228 | \Yii::$app->response->data = $error; 229 | \Yii::$app->end(); 230 | } 231 | 232 | $model->folder_id = Yii::$app->request->post('uploadTo'); 233 | $folder = $folders::find()->select(['path', 'storage'])->where('folder_id=:folder_id', [':folder_id' => $model->folder_id])->one(); 234 | 235 | if (!$folder) { 236 | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 237 | \Yii::$app->response->data = ['error' => Yii::t('filemanager', 'Invalid folder location.')]; 238 | \Yii::$app->end(); 239 | } 240 | 241 | $model->upload_file = $file[0]; 242 | $extension = '.' . $file[0]->getExtension(); 243 | $file[0]->name = substr($file[0]->name, 0, (strlen($file[0]->name) - strlen($extension))); 244 | 245 | if (preg_match('/^[-0-9\p{L}\p{Nd}\p{M}]+$/u', $file[0]->name) === 0) { 246 | $file[0]->name = preg_replace('~[\p{P}\p{S}]~u', '-', $file[0]->name); 247 | $file[0]->name = preg_replace('/[-]+/', '-', $file[0]->name); 248 | } 249 | $file[0]->name = $file[0]->name . $extension; 250 | 251 | $model->filename = $file[0]->name; 252 | list($width, $height) = getimagesize($file[0]->tempName); 253 | $model->dimension = ($width && $height) ? $width . 'X' . $height : null; 254 | // Too large size will cause memory exhausted issue when create thumbnail 255 | if (!is_null($model->dimension)) { 256 | if (($width > 2272 || $height > 1704)) { 257 | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 258 | \Yii::$app->response->data = ['error' => Yii::t('filemanager', 'File dimension at most 2272 X 1704.')]; 259 | \Yii::$app->end(); 260 | } 261 | } 262 | $model->mime_type = $file[0]->type; 263 | $prefixPath = !empty(\Yii::$app->getModule('filemanager')->storage['s3']['prefixPath']) ? \Yii::$app->getModule('filemanager')->storage['s3']['prefixPath'] . '/' : ''; 264 | $model->url = $prefixPath . $folder->path; 265 | //$extension = '.' . $file[0]->getExtension(); 266 | 267 | $uploadResult = ['status' => true, 'error_msg' => '']; 268 | $transaction = \Yii::$app->db->beginTransaction(); 269 | if (isset($this->module->storage['s3'])) { 270 | $model->object_url = '/'; 271 | $model->host = isset($this->module->storage['s3']['host']) ? $this->module->storage['s3']['host'] : null; 272 | $model->storage_id = $this->module->storage['s3']['bucket']; 273 | $this->saveModel($model, $extension, $folder->storage); 274 | $uploadResult = $this->uploadToS3($model, $file[0], $extension); 275 | } else { 276 | $model->object_url = '/' . $folder->path . '/'; 277 | $model->storage_id = $this->module->directory; 278 | $this->saveModel($model, $extension, $folder->storage); 279 | $uploadResult = $this->uploadToLocal($model, $file[0], $extension); 280 | } 281 | 282 | if (!$uploadResult['status']) { 283 | $transaction->rollBack(); 284 | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 285 | \Yii::$app->response->data = ['error' => $uploadResult['error_msg']]; 286 | \Yii::$app->end(); 287 | } 288 | $transaction->commit(); 289 | // if upload type = 1, render edit bar below file input container 290 | // if upload type = 2, switch active tab to Library for user to select file 291 | Yii::$app->response->format = Response::FORMAT_JSON; 292 | if (Yii::$app->request->post('uploadType') == Filemanager::TYPE_FULL_PAGE) { 293 | $fileType = $model->mime_type; 294 | if ($model->dimension) { 295 | $fileType = 'image'; 296 | } 297 | $html = Filemanager::renderEditUploadedBar($model->file_id, $model->object_url, $model->src_file_name, $fileType); 298 | return ['status' => 1, 'message' => 'Upload Success', 'type' => Yii::$app->request->post('uploadType'), 'html' => $html]; 299 | } else { 300 | return ['status' => 1, 'message' => 'Upload Success', 'type' => Yii::$app->request->post('uploadType')]; 301 | } 302 | } 303 | 304 | $multiple = false; 305 | $maxFileCount = 0; 306 | if ($this->module->filesUpload['multiple'] != false) { 307 | $multiple = true; 308 | $maxFileCount = isset($this->module->filesUpload['maxFileCount']) ? $this->module->filesUpload['maxFileCount'] : 0; 309 | } 310 | 311 | return $this->render('upload', [ 312 | 'model' => $model, 313 | 'folderArray' => $folderArray, 314 | 'multiple' => $multiple, 315 | 'maxFileCount' => $maxFileCount 316 | ]); 317 | } 318 | 319 | public function actionUploadTab($ajaxRequest = true) { 320 | $model = new $this->module->models['files']; 321 | $model->scenario = 'upload'; 322 | $folderArray = []; 323 | 324 | $multiple = strtolower(Yii::$app->request->post('multiple')) === 'true' ? true : false; 325 | $maxFileCount = $multiple ? Yii::$app->request->post('maxFileCount') : 1; 326 | $folders = $this->module->models['folders']; 327 | $folderId = Yii::$app->request->post('folderId'); 328 | 329 | if (!$folders::find()->where('folder_id=:folder_id', [':folder_id' => $folderId])->exists()) { 330 | $folderArray = ArrayHelper::map($folders::find()->all(), 'folder_id', 'category'); 331 | } else { 332 | $model->folder_id = $folderId; 333 | } 334 | 335 | $uploadView = $this->renderAjax('_file-input', [ 336 | 'model' => $model, 337 | 'folderArray' => $folderArray, 338 | 'uploadType' => Filemanager::TYPE_MODAL, 339 | 'multiple' => $multiple, 340 | 'maxFileCount' => $maxFileCount 341 | ]); 342 | 343 | if ($ajaxRequest === true) { 344 | \Yii::$app->response->data = $uploadView; 345 | \Yii::$app->end(); 346 | } 347 | 348 | return $uploadView; 349 | } 350 | 351 | public function actionLibraryTab() { 352 | $searchModel = new $this->module->models['filesSearch']; 353 | $dataProvider = $searchModel->search(Yii::$app->request->queryParams); 354 | 355 | if (Yii::$app->request->getQueryParam('page')) { 356 | \Yii::$app->response->data = Gallery::widget([ 357 | 'dataProvider' => $dataProvider, 358 | 'viewFrom' => 'modal' 359 | ]); 360 | \Yii::$app->end(); 361 | } 362 | 363 | \Yii::$app->response->data = $this->renderAjax('_grid-view', [ 364 | 'model' => $searchModel, 365 | 'dataProvider' => $dataProvider, 366 | 'uploadType' => Filemanager::TYPE_MODAL, 367 | 'viewFrom' => 'modal' 368 | ]); 369 | \Yii::$app->end(); 370 | } 371 | 372 | public function actionUse() { 373 | $fileId = Yii::$app->request->post('id'); 374 | $model = $this->findModel($fileId); 375 | $fileType = $model->mime_type; 376 | if ($model->dimension) { 377 | $src = $model->object_url . $model->thumbnail_name . '?' . $model->updated_at; 378 | $fileType = 'image'; 379 | } else { 380 | $src = $model->object_url . $model->src_file_name . '?' . $model->updated_at; 381 | } 382 | 383 | $toolArray = [ 384 | ['tagType' => 'i', 'options' => ['class' => 'fa-icon fa fa-times fm-remove', 'title' => \Yii::t('filemanager', 'Remove')]] 385 | ]; 386 | $gridBox = new \dpodium\filemanager\components\GridBox([ 387 | 'src' => $src, 388 | 'fileType' => $fileType, 389 | 'toolArray' => $toolArray, 390 | 'thumbnailSize' => $this->module->thumbnailSize 391 | ]); 392 | $selectedFileView = $gridBox->renderGridBox(); 393 | 394 | Yii::$app->response->format = Response::FORMAT_JSON; 395 | return ArrayHelper::merge($model->attributes, ['selectedFile' => $selectedFileView]); 396 | } 397 | 398 | /** 399 | * Finds the Files model based on its primary key value. 400 | * If the model is not found, a 404 HTTP exception will be thrown. 401 | * @param integer $id 402 | * @return Files the loaded model 403 | * @throws NotFoundHttpException if the model cannot be found 404 | */ 405 | protected function findModel($id) { 406 | $filesModel = $this->module->models['files']; 407 | if (($model = $filesModel::findOne($id)) !== null) { 408 | return $model; 409 | } else { 410 | throw new NotFoundHttpException('The requested page does not exist.'); 411 | } 412 | } 413 | 414 | protected function saveModel(&$model, $extension, $folderStorage) { 415 | $model->filename = str_replace($extension, '', $model->filename); 416 | 417 | if ($model->validate()) { 418 | $model->scenario = 'afterValidate'; 419 | $model->caption = str_replace(" ", "_", $model->filename); 420 | $model->caption = str_replace(["\"", "'"], "", $model->filename); 421 | $model->alt_text = $model->caption; 422 | $model->src_file_name = $model->caption . $extension; 423 | $model->thumbnail_name = $model->src_file_name; 424 | $model->file_identifier = md5($folderStorage . '/' . $model->url . '/' . $model->src_file_name); 425 | 426 | if ($model->save()) { 427 | return true; 428 | } 429 | } 430 | 431 | $errors = []; 432 | foreach ($model->errors as $err) { 433 | $errors[] = $model->src_file_name . ': ' . $err[0]; 434 | } 435 | 436 | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 437 | \Yii::$app->response->data = ['error' => implode('
', $errors)]; 438 | \Yii::$app->end(); 439 | } 440 | 441 | protected function uploadToLocal($model, $file, $extension) { 442 | if (!file_exists(Yii::getAlias($model->storage_id) . '/' . $model->url)) { 443 | // File mode : 0755, Ref: http://php.net/manual/en/function.chmod.php 444 | mkdir(Yii::getAlias($model->storage_id) . '/' . $model->url, 0755, true); 445 | } 446 | 447 | if (!$file->saveAs(Yii::getAlias($model->storage_id) . '/' . $model->url . '/' . $model->src_file_name)) { 448 | return [ 449 | 'status' => false, 450 | 'error_msg' => Yii::t('filemanager', 'Upload fail due to some reasons.') 451 | ]; 452 | } 453 | $uploadThumbResult = ['status' => true, 'error_msg' => '']; 454 | if ($model->dimension) { 455 | $thumbnailSize = $this->module->thumbnailSize; 456 | $model->thumbnail_name = 'thumb_' . str_replace($extension, '', $model->src_file_name) . '_' . $thumbnailSize[0] . 'X' . $thumbnailSize[1] . $extension; 457 | $uploadThumbResult = $this->createThumbnail($model, Yii::getAlias($model->storage_id) . '/' . $model->url . '/' . $model->src_file_name); 458 | $model->update(false, ['dimension', 'thumbnail_name']); 459 | } 460 | 461 | return $uploadThumbResult; 462 | } 463 | 464 | protected function uploadToS3($model, $file, $extension) { 465 | $s3 = new S3(); 466 | $result = $s3->upload($file, $model->src_file_name, $model->url); 467 | 468 | if (!$result['status']) { 469 | return [ 470 | 'status' => false, 471 | 'error_msg' => Yii::t('filemanager', 'Upload fail due to some reasons.') 472 | ]; 473 | } 474 | 475 | //Remove filename name from object URL 476 | $model->object_url = substr($result['objectUrl'], 0, strrpos($result['objectUrl'], '/')); 477 | $model->object_url = $model->object_url . '/'; 478 | //End 479 | //$model->object_url = str_replace($model->src_file_name, '', $result['objectUrl']); 480 | $uploadThumbResult = ['status' => true, 'error_msg' => '']; 481 | if ($model->dimension) { 482 | $thumbnailSize = $this->module->thumbnailSize; 483 | $model->thumbnail_name = 'thumb_' . str_replace($extension, '', $model->src_file_name) . '_' . $thumbnailSize[0] . 'X' . $thumbnailSize[1] . $extension; 484 | $uploadThumbResult = $this->createThumbnail($model, $file->tempName); 485 | } 486 | $model->update(false, ['object_url', 'dimension', 'thumbnail_name']); 487 | 488 | return $uploadThumbResult; 489 | } 490 | 491 | protected function createThumbnail($model, $file) { 492 | $thumbnailSize = $this->module->thumbnailSize; 493 | $thumbnailFile = Image::thumbnail($file, $thumbnailSize[0], $thumbnailSize[1]); 494 | 495 | if (isset($this->module->storage['s3'])) { 496 | $s3 = new S3(); 497 | $result = $s3->uploadThumbnail($thumbnailFile, $model->thumbnail_name, $model->url, $model->mime_type); 498 | if (!$result['status']) { 499 | return [ 500 | 'status' => false, 501 | 'error_msg' => Yii::t('filemanager', 'Fail to create thumbnail.') 502 | ]; 503 | } 504 | } else { 505 | if (!file_exists(Yii::getAlias($model->storage_id) . '/' . $model->url)) { 506 | mkdir(Yii::getAlias($model->storage_id) . '/' . $model->url, 0755, true); 507 | } 508 | $result = $thumbnailFile->save(Yii::getAlias($model->storage_id) . '/' . $model->url . '/' . $model->thumbnail_name); 509 | if (!$result) { 510 | return [ 511 | 'status' => false, 512 | 'error_msg' => Yii::t('filemanager', 'Fail to create thumbnail.') 513 | ]; 514 | } 515 | } 516 | 517 | return ['status' => true, 'error_msg' => '']; 518 | } 519 | 520 | } 521 | -------------------------------------------------------------------------------- /controllers/FoldersController.php: -------------------------------------------------------------------------------- 1 | [ 20 | 'class' => VerbFilter::className(), 21 | 'actions' => [ 22 | 'delete' => ['post'], 23 | ], 24 | ], 25 | ]; 26 | } 27 | 28 | /** 29 | * Lists all Folders models. 30 | * @return mixed 31 | */ 32 | public function actionIndex() { 33 | FilemanagerAsset::register($this->view); 34 | $model = new $this->module->models['folders']; 35 | $dataProvider = new ActiveDataProvider([ 36 | 'query' => $model->find(), 37 | ]); 38 | 39 | return $this->render('index', [ 40 | 'dataProvider' => $dataProvider, 41 | 'model' => $model 42 | ]); 43 | } 44 | 45 | /** 46 | * Displays a single Folders model. 47 | * @param integer $id 48 | * @return mixed 49 | */ 50 | public function actionView($id) { 51 | FilemanagerAsset::register($this->view); 52 | return $this->render('view', [ 53 | 'model' => $this->findModel($id), 54 | ]); 55 | } 56 | 57 | /** 58 | * Creates a new Folders model. 59 | * If creation is successful, the browser will be redirected to the 'view' page. 60 | * @return mixed 61 | */ 62 | public function actionCreate() { 63 | FilemanagerAsset::register($this->view); 64 | $model = new $this->module->models['folders']; 65 | 66 | if ($model->load(Yii::$app->request->post())) { 67 | $model->storage = isset($this->module->storage['s3']) ? 'S3' : 'local'; 68 | $model->path = trim($model->path, '/'); 69 | 70 | if ($model->save()) { 71 | Yii::$app->session->setFlash('success', 'Folder successfully created.'); 72 | return $this->redirect(['view', 'id' => $model->folder_id]); 73 | } 74 | } 75 | 76 | return $this->render('create', [ 77 | 'model' => $model, 78 | ]); 79 | } 80 | 81 | /** 82 | * Updates an existing Folders model. 83 | * If update is successful, the browser will be redirected to the 'view' page. 84 | * @param integer $id 85 | * @return mixed 86 | */ 87 | public function actionUpdate($id) { 88 | FilemanagerAsset::register($this->view); 89 | $model = $this->findModel($id); 90 | 91 | if ($model->load(Yii::$app->request->post())) { 92 | $model->path = trim($model->path, '/'); 93 | 94 | if ($model->save()) { 95 | Yii::$app->session->setFlash('success', 'Folder successfully updated.'); 96 | return $this->redirect(['view', 'id' => $model->folder_id]); 97 | } 98 | } 99 | 100 | return $this->render('update', [ 101 | 'model' => $model, 102 | ]); 103 | } 104 | 105 | /** 106 | * Deletes an existing Folders model. 107 | * If deletion is successful, the browser will be redirected to the 'index' page. 108 | * @param integer $id 109 | * @return mixed 110 | */ 111 | public function actionDelete($id) { 112 | $this->findModel($id)->delete(); 113 | 114 | return $this->redirect(['index']); 115 | } 116 | 117 | /** 118 | * Finds the Folders model based on its primary key value. 119 | * If the model is not found, a 404 HTTP exception will be thrown. 120 | * @param integer $id 121 | * @return Folders the loaded model 122 | * @throws NotFoundHttpException if the model cannot be found 123 | */ 124 | protected function findModel($id) { 125 | $folders = $this->module->models['folders']; 126 | 127 | if (($model = $folders::findOne($id)) !== null) { 128 | return $model; 129 | } else { 130 | throw new NotFoundHttpException('The requested page does not exist.'); 131 | } 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /messages/config.php: -------------------------------------------------------------------------------- 1 | __DIR__ . DIRECTORY_SEPARATOR . '..', 9 | // string, required, root directory containing message translations. 10 | 'messagePath' => __DIR__, 11 | // array, required, list of language codes that the extracted messages 12 | // should be translated to. For example, ['zh-CN', 'de']. 13 | 'languages' => ['en', 'es', 'de'], 14 | // string, the name of the function for translating messages. 15 | // Defaults to 'Yii::t'. This is used as a mark to find the messages to be 16 | // translated. You may use a string for single function name or an array for 17 | // multiple function names. 18 | 'translator' => 'Yii::t', 19 | // boolean, whether to sort messages by keys when merging new messages 20 | // with the existing ones. Defaults to false, which means the new (untranslated) 21 | // messages will be separated from the old (translated) ones. 22 | 'sort' => false, 23 | // boolean, whether the message file should be overwritten with the merged messages 24 | 'overwrite' => true, 25 | // boolean, whether to remove messages that no longer appear in the source code. 26 | // Defaults to false, which means each of these messages will be enclosed with a pair of '' marks. 27 | 'removeUnused' => true, 28 | // array, list of patterns that specify which files/directories should NOT be processed. 29 | // If empty or not set, all files/directories will be processed. 30 | // A path matches a pattern if it contains the pattern string at its end. For example, 31 | // '/a/b' will match all files and directories ending with '/a/b'; 32 | // the '*.svn' will match all files and directories whose name ends with '.svn'. 33 | // and the '.svn' will match all files and directories named exactly '.svn'. 34 | // Note, the '/' characters in a pattern matches both '/' and '\'. 35 | // See helpers/FileHelper::findFiles() description for more details on pattern matching rules. 36 | 'only' => ['*.php'], 37 | // array, list of patterns that specify which files (not directories) should be processed. 38 | // If empty or not set, all files will be processed. 39 | // Please refer to "except" for details about the patterns. 40 | // If a file/directory matches both a pattern in "only" and "except", it will NOT be processed. 41 | 'except' => [ 42 | '.svn', 43 | '.git', 44 | '.gitignore', 45 | '.gitkeep', 46 | '.hgignore', 47 | '.hgkeep', 48 | '/messages', 49 | ], 50 | // Generated file format. Can be either "php", "po" or "db". 51 | 'format' => 'php', 52 | // When format is "db", you may specify the following two options 53 | //'db' => 'db', 54 | //'sourceMessageTable' => '{{%source_message}}', 55 | ]; -------------------------------------------------------------------------------- /messages/de/filemanager.php: -------------------------------------------------------------------------------- 1 | 'Erweiterte Suche', 21 | 'All' => 'Alle', 22 | 'Alternative Text' => 'alternativer Text', 23 | 'Browse' => 'Durchsuchen', 24 | 'Cancel' => 'Abbrechen', 25 | 'Category' => 'Kategorie', 26 | 'Click a file to view info.' => 'Klicken Sie auf eine Datei, um Informationen anzuzeigen.', 27 | 'Click {link} to create a folder to upload media' => 'Klicken Sie auf {link}, um einen Ordner zum Hochladen von Medien zu erstellen.', 28 | 'Confirm delete {src_file_name} ?' => 'Wollen Sie {src_file_name} wirklich löschen?', 29 | 'Copy' => 'Kopieren', 30 | 'Create Folder' => 'Ordner anlegen', 31 | 'Created At' => 'Erstellt am', 32 | 'Delete' => 'Löschen', 33 | 'Delete Permanently' => 'Dauerhaft löschen', 34 | 'Description' => 'Beschreibung', 35 | 'Dimension' => 'Abmessungen', 36 | 'Edit' => 'Bearbeiten', 37 | 'Enter or select tags...' => 'Geben Sie Tags ein oder wählen Sie sie aus', 38 | 'Fail to create thumbnail.' => 'Fehler beim Erstellen des Thumbnails', 39 | 'File ID' => 'Datei ID', 40 | 'File Identifier' => 'Datei Identifikator', 41 | 'File Name' => 'Datei Name', 42 | 'File dimension at most 2272 X 1704.' => 'Bildgröße höchstens 2272 X 1704.', 43 | 'File not found.' => 'Datei nicht gefunden.', 44 | 'File too large.' => 'Datei zu groß.', 45 | 'Filename can only contain alphanumeric characters, underscores and dashes.' => 'Der Dateiname darf nur alphanumerische Zeichen und Bindestriche enthalten.', 46 | 'Folder ID' => 'Ordner ID', 47 | 'Invalid file extension. Available file extension are {ext}' => 'Ungültige Dateiendung. Verfügbare Dateierweiterung sind {ext}', 48 | 'Invalid file type. Available file types are {types}' => 'Ungültiger Dateityp. Verfügbare Dateitypen sind {types}', 49 | 'Invalid folder location.' => 'Ungültiger Ordner Pfad', 50 | 'Invalid value: {variable}' => 'Ungültiger Wert: {variable}', 51 | 'Library' => 'Bibliothek', 52 | 'Limit is {limit}MB' => 'Limit ist {Limit} MB', 53 | 'Media Folder' => 'Medienordner', 54 | 'Media Gallery' => 'Medien Gallerie', 55 | 'Media Property' => 'Medieneigenschaft', 56 | 'Mime Type' => 'Mime Typ', 57 | 'Object Url' => 'Objekt URL', 58 | 'Path' => 'Pfad', 59 | 'Remove' => 'Löschen', 60 | 'Search' => 'Suche', 61 | 'Search by File Name, Title, Alternative Text or Description...' => 'Suche nach Dateiname, Titel, Alternativem Text oder Beschreibung...', 62 | 'Search by tag...' => 'Suche nach Tag', 63 | 'Storage' => 'Speicher', 64 | 'Storage ID' => 'Speicher ID', 65 | 'Tag ID' => 'Tag ID', 66 | 'Tags' => 'Tags', 67 | 'This {attribute} already been taken.' => 'Das Attribut {Attribut} wurde bereits vergeben.', 68 | 'Thumbnail File Name' => 'Dateiname des Thumbnails', 69 | 'Title' => 'Titel', 70 | 'Update' => 'Aktualisieren', 71 | 'Update Folder' => 'Ordner aktualisieren', 72 | 'Updated At' => 'Aktualisiert am', 73 | 'Upload New' => 'Hochladen', 74 | 'Upload New Media' => 'Laden Sie neue Medien hoch', 75 | 'Upload To' => 'Etwas hochladen auf', 76 | 'Upload fail due to some reasons.' => 'Der Upload ist aus bestimmten Gründen fehlgeschlagen.', 77 | 'Url' => 'URL', 78 | 'Use' => 'Benutzen', 79 | 'Value' => 'Wert', 80 | 'View' => 'Anschauen', 81 | 'here' => 'Hier', 82 | 'host' => 'Host', 83 | ]; 84 | -------------------------------------------------------------------------------- /messages/en/filemanager.php: -------------------------------------------------------------------------------- 1 | '', 21 | 'All' => '', 22 | 'Alternative Text' => '', 23 | 'Browse' => '', 24 | 'Cancel' => '', 25 | 'Category' => '', 26 | 'Click a file to view info.' => '', 27 | 'Click {link} to create a folder to upload media' => '', 28 | 'Confirm delete {src_file_name} ?' => '', 29 | 'Copy' => '', 30 | 'Create Folder' => '', 31 | 'Created At' => '', 32 | 'Delete' => '', 33 | 'Delete Permanently' => '', 34 | 'Description' => '', 35 | 'Dimension' => '', 36 | 'Edit' => '', 37 | 'Enter or select tags...' => '', 38 | 'Fail to create thumbnail.' => '', 39 | 'File ID' => '', 40 | 'File Identifier' => '', 41 | 'File Name' => '', 42 | 'File dimension at most 2272 X 1704.' => '', 43 | 'File not found.' => '', 44 | 'File too large.' => '', 45 | 'Filename can only contain alphanumeric characters, underscores and dashes.' => '', 46 | 'Folder ID' => '', 47 | 'Invalid file extension. Available file extension are {ext}' => '', 48 | 'Invalid file type. Available file types are {types}' => '', 49 | 'Invalid folder location.' => '', 50 | 'Invalid value: {variable}' => '', 51 | 'Library' => '', 52 | 'Limit is {limit}MB' => '', 53 | 'Media Folder' => '', 54 | 'Media Gallery' => '', 55 | 'Media Property' => '', 56 | 'Mime Type' => '', 57 | 'Object Url' => '', 58 | 'Path' => '', 59 | 'Remove' => '', 60 | 'Search' => '', 61 | 'Search by File Name, Title, Alternative Text or Description...' => '', 62 | 'Search by tag...' => '', 63 | 'Storage' => '', 64 | 'Storage ID' => '', 65 | 'Tag ID' => '', 66 | 'Tags' => '', 67 | 'This {attribute} already been taken.' => '', 68 | 'Thumbnail File Name' => '', 69 | 'Title' => '', 70 | 'Update' => '', 71 | 'Update Folder' => '', 72 | 'Updated At' => '', 73 | 'Upload New' => '', 74 | 'Upload New Media' => '', 75 | 'Upload To' => '', 76 | 'Upload fail due to some reasons.' => '', 77 | 'Url' => '', 78 | 'Use' => '', 79 | 'Value' => '', 80 | 'View' => '', 81 | 'here' => '', 82 | 'host' => '', 83 | ]; 84 | -------------------------------------------------------------------------------- /messages/es/filemanager.php: -------------------------------------------------------------------------------- 1 | '', 21 | 'Filename can only contain alphanumeric characters, underscores and dashes.' => '', 22 | 'Url' => '', 23 | 'host' => '', 24 | 'Advanced Search' => 'Búsqueda avanzada', 25 | 'All' => 'Todos', 26 | 'Alternative Text' => 'Texto alternativo', 27 | 'Browse' => 'Explorar', 28 | 'Cancel' => 'Cancelar', 29 | 'Category' => 'Categoría', 30 | 'Click a file to view info.' => 'Haga click en un archivo para ver más información.', 31 | 'Click {link} to create a folder to upload media' => 'Haga click acá: {link}, para crear un directorio y subir archivos', 32 | 'Confirm delete {src_file_name} ?' => '¿Deseas borrar {src_file_name}?', 33 | 'Copy' => 'Copiar', 34 | 'Create Folder' => 'Crear directorio', 35 | 'Created At' => 'Fecha de creación', 36 | 'Delete' => 'Borrar', 37 | 'Delete Permanently' => 'Borrar permanentemente', 38 | 'Description' => 'Descripción', 39 | 'Dimension' => 'Dimensión', 40 | 'Edit' => 'Editar', 41 | 'Enter or select tags...' => 'Ingrese o seleccione tags...', 42 | 'Fail to create thumbnail.' => 'La creación de la thumbnail ha fallado', 43 | 'File ID' => 'ID del archivo', 44 | 'File Identifier' => 'Identificador del archivo', 45 | 'File Name' => 'Nombre del archivo', 46 | 'File dimension at most 2272 X 1704.' => 'Las dimensiones máximas del archivo son 2272 X 1704', 47 | 'File not found.' => 'Archivo no encontrado', 48 | 'Folder ID' => 'ID del directorio', 49 | 'Invalid file extension. Available file extension are {ext}' => 'La extensión del archivo es inválida. Las extensiones permitidas son {ext}', 50 | 'Invalid file type. Available file types are {types}' => 'EL tipo de archivo es inválido. Los tipos permitidos son {types}', 51 | 'Invalid folder location.' => 'Ubicación del directorio inválida', 52 | 'Invalid value: {variable}' => 'Valor inválido: {variable}', 53 | 'Library' => 'Librería', 54 | 'Limit is {limit}MB' => 'El límite es {limit}MB', 55 | 'Media Folder' => 'Directorio de archivos multimedia', 56 | 'Media Gallery' => 'Galería multimedia', 57 | 'Media Property' => 'Propiedades de archivo', 58 | 'Mime Type' => 'Tipos de archivos', 59 | 'Object Url' => 'Url del objeto', 60 | 'Path' => 'Ruta', 61 | 'Remove' => 'Remover', 62 | 'Search' => 'Buscar', 63 | 'Search by File Name, Title, Alternative Text or Description...' => 'Buscar por el Nombre del archivo, Titulo, Texto alternativo o Descripción', 64 | 'Search by tag...' => 'Buscar por Tag', 65 | 'Storage' => 'Almacenamiento', 66 | 'Storage ID' => 'ID del almacenamiento', 67 | 'Tag ID' => 'ID del Tag', 68 | 'Tags' => 'Tags', 69 | 'This {attribute} already been taken.' => 'Este {attribute} ya ha sido tomado', 70 | 'Thumbnail File Name' => 'Nombre de la miniatura', 71 | 'Title' => 'Título', 72 | 'Update' => 'Actualizar', 73 | 'Update Folder' => 'Actualizar directorio', 74 | 'Updated At' => 'Última actualización', 75 | 'Upload New' => 'Subir nuevo', 76 | 'Upload New Media' => 'Subir nuevo archivo multimedia', 77 | 'Upload To' => 'Subir a', 78 | 'Upload fail due to some reasons.' => 'Por alguna razón la subida a fallado', 79 | 'Use' => 'Usar', 80 | 'Value' => 'Valor', 81 | 'View' => 'Vista', 82 | 'here' => 'aquí', 83 | ]; 84 | -------------------------------------------------------------------------------- /migrations/m150721_075656_filemanager_init.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; 12 | } 13 | 14 | $this->createTable('{{%folders}}', [ 15 | 'folder_id' => Schema::TYPE_BIGPK, 16 | 'category' => Schema::TYPE_STRING . '(64) NOT NULL', 17 | 'path' => Schema::TYPE_STRING . '(255) UNIQUE NOT NULL', 18 | 'storage' => Schema::TYPE_STRING . '(32) NOT NULL', 19 | ], $tableOptions); 20 | 21 | $this->createTable('{{%files}}', [ 22 | 'file_id' => Schema::TYPE_BIGPK, 23 | 'file_identifier' => Schema::TYPE_STRING . '(32) NOT NULL', 24 | 'host' => Schema::TYPE_STRING . '(64) NULL', 25 | 'url' => Schema::TYPE_STRING . '(255) NOT NULL', // folder path 26 | 'storage_id' => Schema::TYPE_STRING . '(64) NOT NULL', // S3 bucket ID or module directory(@webroot) 27 | 'object_url' => Schema::TYPE_STRING . '(255) NOT NULL', // S3 ObjectUrl 28 | 'thumbnail_name' => Schema::TYPE_STRING . '(100) NULL', // thumb_`src_file_name`_`dimension` 29 | 'src_file_name' => Schema::TYPE_STRING . '(64) NOT NULL', // use to search by filename 30 | 'mime_type' => Schema::TYPE_STRING . '(100) NOT NULL', // eg. image/png 31 | 'caption' => Schema::TYPE_STRING . '(64) NULL', 32 | 'alt_text' => Schema::TYPE_STRING . '(64) NULL', 33 | 'description' => Schema::TYPE_STRING . '(255) NULL', 34 | 'dimension' => Schema::TYPE_STRING . '(12) NULL', // width and height 35 | 'folder_id' => Schema::TYPE_BIGINT . ' NOT NULL', 36 | 'created_at' => Schema::TYPE_INTEGER . ' NOT NULL', 37 | 'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL', 38 | ], $tableOptions); 39 | 40 | $this->addCommentOnColumn('{{%files}}', 'dimension', 'w X h'); 41 | $this->createIndex('idx__file_identifier', '{{%files}}', 'file_identifier'); 42 | $this->addForeignKey('fk__files__folders', '{{%files}}', 'folder_id', '{{%folders}}', 'folder_id', 'RESTRICT'); 43 | 44 | $this->createTable('{{%files_tag}}', [ 45 | 'tag_id' => Schema::TYPE_BIGPK, 46 | 'value' => Schema::TYPE_STRING . '(32) NOT NULL', 47 | 'created_at' => Schema::TYPE_INTEGER . ' NOT NULL', 48 | ], $tableOptions); 49 | 50 | $this->createTable('{{%files_relationship}}', [ 51 | 'file_id' => Schema::TYPE_BIGINT, 52 | 'tag_id' => Schema::TYPE_BIGINT, 53 | ], $tableOptions); 54 | $this->createIndex('idx__file_id__tag_id', '{{%files_relationship}}', ['file_id', 'tag_id']); 55 | $this->addForeignKey('fk__files_relationship__files', '{{%files_relationship}}', 'file_id', '{{%files}}', 'file_id', 'CASCADE'); 56 | $this->addForeignKey('fk__files_relationship__files_tag', '{{%files_relationship}}', 'tag_id', '{{%files_tag}}', 'tag_id', 'CASCADE'); 57 | 58 | echo "m150721_075656_filemanager_init successfully applied.\n"; 59 | } 60 | 61 | public function down() { 62 | $this->dropTable('{{%files_relationship}}'); 63 | $this->dropTable('{{%files_tag}}'); 64 | $this->dropTable('{{%files}}'); 65 | $this->dropTable('{{%folders}}'); 66 | 67 | echo "m150721_075656_filemanager_init successfully reverted.\n"; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /models/Files.php: -------------------------------------------------------------------------------- 1 | TimestampBehavior::className(), 42 | 'attributes' => [ 43 | ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], 44 | ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], 45 | ] 46 | ] 47 | ]; 48 | } 49 | 50 | /** 51 | * @inheritdoc 52 | */ 53 | public static function tableName() { 54 | return 'files'; 55 | } 56 | 57 | /** 58 | * @inheritdoc 59 | */ 60 | public function rules() { 61 | // convert MB to byte 62 | $maxSize = (int) \Yii::$app->controller->module->maxFileSize * 1000 * 1024; 63 | $extensions = \Yii::$app->controller->module->getMimeType(); 64 | return [ 65 | [['object_url', 'url', 'mime_type', 'folder_id', 'storage_id', 'filename'], 'required'], 66 | [['src_file_name', 'file_identifier'], 'required', 'on' => 'afterValidate'], 67 | [['folder_id'], 'integer'], 68 | [['url', 'thumbnail_name', 'description'], 'string', 'max' => 255], 69 | [['src_file_name', 'caption', 'alt_text'], 'string', 'max' => 64], 70 | [['mime_type'], 'string', 'max' => 100], 71 | [['file_identifier'], 'string', 'max' => 32], 72 | [['dimension'], 'string', 'max' => 12], 73 | // unique filename 74 | ['src_file_name', 'unique', 'targetAttribute' => ['src_file_name', 'folder_id'], 'message' => Yii::t('filemanager', 'This {attribute} already been taken.')], 75 | // 76 | [['upload_file', 'tags'], 'safe'], 77 | // validate file type and size 78 | ['upload_file', 'file', 'skipOnEmpty' => false, 'on' => 'upload', 79 | 'mimeTypes' => \Yii::$app->controller->module->acceptedFilesType, 80 | 'wrongMimeType' => Yii::t('filemanager', 'Invalid file type. Available file types are {types}', ['types' => implode(',', \Yii::$app->controller->module->acceptedFilesType)]), 81 | 'extensions' => $extensions, 82 | 'wrongExtension' => Yii::t('filemanager', 'Invalid file extension. Available file extension are {ext}', ['ext' => implode(',', $extensions)]), 83 | 'maxSize' => $maxSize, 84 | 'tooBig' => Yii::t('filemanager', 'Limit is {limit}MB', ['limit' => \Yii::$app->controller->module->maxFileSize]) 85 | ], 86 | // validate src_file_name 87 | // /^[a-zA-Z0-9_-]+$/ 88 | ['filename', 'match', 'pattern' => '/^[-0-9\p{L}\p{Nd}\p{M}]+$/u', 'message' => Yii::t('filemanager', 'Filename can only contain alphanumeric characters and dashes.')] 89 | ]; 90 | } 91 | 92 | /** 93 | * @inheritdoc 94 | */ 95 | public function attributeLabels() { 96 | return [ 97 | 'file_id' => Yii::t('filemanager', 'File ID'), 98 | 'file_identifier' => Yii::t('filemanager', 'File Identifier'), 99 | 'host' => Yii::t('filemanager', 'host'), 100 | 'object_url' => Yii::t('filemanager', 'Object Url'), 101 | 'url' => Yii::t('filemanager', 'Url'), 102 | 'thumbnail_name' => Yii::t('filemanager', 'Thumbnail File Name'), 103 | 'src_file_name' => Yii::t('filemanager', 'File Name'), 104 | 'mime_type' => Yii::t('filemanager', 'Mime Type'), 105 | 'caption' => Yii::t('filemanager', 'Title'), 106 | 'alt_text' => Yii::t('filemanager', 'Alternative Text'), 107 | 'description' => Yii::t('filemanager', 'Description'), 108 | 'dimension' => Yii::t('filemanager', 'Dimension'), 109 | 'storage_id' => Yii::t('filemanager', 'Storage ID'), 110 | 'folder_id' => Yii::t('filemanager', 'Folder ID'), 111 | 'created_at' => Yii::t('filemanager', 'Created At'), 112 | 'updated_at' => Yii::t('filemanager', 'Updated At'), 113 | // 114 | 'upload_to' => Yii::t('filemanager', 'Upload To'), 115 | 'upload_file' => '', 116 | 'tags' => Yii::t('filemanager', 'Tags'), 117 | ]; 118 | } 119 | 120 | /** 121 | * @return \yii\db\ActiveQuery 122 | */ 123 | public function getFolder() { 124 | return $this->hasOne(Folders::className(), ['folder_id' => 'folder_id']); 125 | } 126 | 127 | /** 128 | * @return \yii\db\ActiveQuery 129 | */ 130 | public function getFilesRelationships() { 131 | return $this->hasMany(FilesRelationship::className(), ['file_id' => 'file_id']); 132 | } 133 | 134 | public function getFileUrl($thumbnail = false) { 135 | $domain = $this->object_url; 136 | // Append timestamp to prevent getting cached image from S3 137 | if ($thumbnail) { 138 | return $domain . $this->thumbnail_name . '?' . $this->updated_at; 139 | } 140 | return $domain . $this->src_file_name . '?' . $this->updated_at; 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /models/FilesRelationship.php: -------------------------------------------------------------------------------- 1 | Yii::t('filemanager', 'File ID'), 41 | 'tag_id' => Yii::t('filemanager', 'Tag ID'), 42 | ]; 43 | } 44 | 45 | /** 46 | * @return \yii\db\ActiveQuery 47 | */ 48 | public function getTag() { 49 | return $this->hasOne(FilesTag::className(), ['tag_id' => 'tag_id']); 50 | } 51 | 52 | /** 53 | * @return \yii\db\ActiveQuery 54 | */ 55 | public function getFile() { 56 | return $this->hasOne(Files::className(), ['file_id' => 'file_id']); 57 | } 58 | 59 | public static function getTagIdArray($fileId) { 60 | $models = static::findAll(['file_id' => $fileId]); 61 | $tags = []; 62 | 63 | foreach ($models as $model) { 64 | if (isset($model->tag)) { 65 | $tags[] = [ 66 | 'id' => $model->tag->tag_id, 67 | 'value' => $model->tag->value 68 | ]; 69 | } 70 | } 71 | 72 | return $tags; 73 | } 74 | 75 | public function saveRelationship($fileId, $tagArray) { 76 | // delete all tags before save 77 | $this->deleteAll(['file_id' => $fileId]); 78 | 79 | foreach ($tagArray as $tagId) { 80 | $this->setIsNewRecord(true); 81 | $this->file_id = $fileId; 82 | $this->tag_id = $tagId; 83 | $this->save(); 84 | } 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /models/FilesSearch.php: -------------------------------------------------------------------------------- 1 | $query, 49 | 'pagination' => ['pageSize' => 25], 50 | 'sort' => [ 51 | 'defaultOrder' => [ 52 | 'updated_at' => SORT_DESC, 53 | 'file_id' => SORT_ASC 54 | ], 55 | ] 56 | ]); 57 | 58 | $this->load($params); 59 | 60 | if (!$this->validate()) { 61 | // uncomment the following line if you do not want to return any records when validation fails 62 | // $query->where('0=1'); 63 | return $dataProvider; 64 | } 65 | 66 | $filesType = \Yii::$app->controller->module->acceptedFilesType; 67 | $mime_type = isset($filesType[$this->mime_type]) ? $filesType[$this->mime_type] : $this->mime_type; 68 | 69 | $query->andFilterWhere([ 70 | 'mime_type' => $mime_type, 71 | 'folder_id' => $this->folder_id 72 | ]); 73 | 74 | if (!empty($this->tags)) { 75 | $tagKeyword = $this->tags; 76 | $this->tags = []; 77 | $query->joinWith(['filesRelationships' => function($query) use ($tagKeyword) { 78 | $query->joinWith(['tag' => function($query) use ($tagKeyword) { 79 | foreach ($tagKeyword as $tkey) { 80 | $query->orFilterWhere(['like', 'value', $tkey]); 81 | } 82 | }], true, 'INNER JOIN'); 83 | }], false, 'INNER JOIN'); 84 | foreach ($tagKeyword as $tkey) { 85 | $this->tags[$tkey] = $tkey; 86 | } 87 | } 88 | 89 | $query->andFilterWhere(['OR', 90 | ['like', 'src_file_name', $this->keywords], 91 | ['like', 'caption', $this->keywords], 92 | ['like', 'alt_text', $this->keywords], 93 | ['like', 'description', $this->keywords] 94 | ]); 95 | 96 | return $dataProvider; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /models/FilesTag.php: -------------------------------------------------------------------------------- 1 | TimestampBehavior::className(), 24 | 'attributes' => [ 25 | ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'] 26 | ] 27 | ] 28 | ]; 29 | } 30 | 31 | /** 32 | * @inheritdoc 33 | */ 34 | public static function tableName() { 35 | return 'files_tag'; 36 | } 37 | 38 | /** 39 | * @inheritdoc 40 | */ 41 | public function rules() { 42 | return [ 43 | [['value'], 'required'], 44 | [['value'], 'string', 'max' => 32] 45 | ]; 46 | } 47 | 48 | /** 49 | * @inheritdoc 50 | */ 51 | public function attributeLabels() { 52 | return [ 53 | 'tag_id' => Yii::t('filemanager', 'Tag ID'), 54 | 'value' => Yii::t('filemanager', 'Value'), 55 | 'created_at' => Yii::t('filemanager', 'Created At'), 56 | ]; 57 | } 58 | 59 | /** 60 | * @return \yii\db\ActiveQuery 61 | */ 62 | public function getFilesRelationships() { 63 | return $this->hasMany(FilesRelationship::className(), ['tag_id' => 'tag_id']); 64 | } 65 | 66 | public function saveTag($tagArray) { 67 | $saveTags = []; 68 | 69 | if (is_array($tagArray)) { 70 | foreach ($tagArray as $tag) { 71 | if ($tagObj = $this->find()->where('value=:value', [':value' => $tag])->one()) { 72 | $saveTags[] = $tagObj->tag_id; 73 | } else if (!$this->find()->where('tag_id=:tag_id', [':tag_id' => (int) $tag])->exists()) { 74 | $this->value = \yii\helpers\Html::encode($tag); 75 | if ($this->save()) { 76 | $saveTags[] = $this->tag_id; 77 | $this->setIsNewRecord(true); 78 | unset($this->tag_id); 79 | } else { 80 | return ['error' => $this->errors['value'][0]]; 81 | } 82 | } else { 83 | $saveTags[] = $tag; 84 | } 85 | } 86 | } 87 | 88 | return $saveTags; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /models/Folders.php: -------------------------------------------------------------------------------- 1 | 64], 33 | [['path'], 'string', 'max' => 255], 34 | [['storage'], 'string', 'max' => 32], 35 | [['path'], 'unique'] 36 | ]; 37 | } 38 | 39 | /** 40 | * @inheritdoc 41 | */ 42 | public function attributeLabels() { 43 | return [ 44 | 'folder_id' => Yii::t('filemanager', 'Folder ID'), 45 | 'category' => Yii::t('filemanager', 'Category'), 46 | 'path' => Yii::t('filemanager', 'Path'), 47 | 'storage' => Yii::t('filemanager', 'Storage'), 48 | ]; 49 | } 50 | 51 | /** 52 | * @return \yii\db\ActiveQuery 53 | */ 54 | public function getFiles() { 55 | return $this->hasMany(Files::className(), ['folder_id' => 'folder_id']); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /views/files/_file-input.php: -------------------------------------------------------------------------------- 1 | \Yii::$app->urlManager->createUrl(['/filemanager/files/upload']), 14 | 'id' => 'fm-upload-form', 15 | 'options' => ['enctype' => 'multipart/form-data'] // important 16 | ]); 17 | 18 | if (!empty($folderArray)) { 19 | echo $form->field($model, 'folder_id')->dropDownList($folderArray); 20 | } 21 | 22 | $script = <<< SCRIPT 23 | function (event, params) { 24 | params.form.append('uploadType', {$uploadType}); 25 | if(jQuery('select[name="Files[folder_id]"]').val() != undefined) { 26 | params.form.append('uploadTo', jQuery('select[name="Files[folder_id]"]').val()); 27 | } else { 28 | params.form.append('uploadTo', '{$model->folder_id}'); 29 | } 30 | } 31 | SCRIPT; 32 | echo $form->field($model, 'upload_file[]')->widget(FileInput::classname(), [ 33 | 'options' => [ 34 | 'multiple' => $multiple, 35 | 'accept' => implode(',', \Yii::$app->controller->module->acceptedFilesType) 36 | ], 37 | 'pluginOptions' => [ 38 | 'uploadUrl' => Url::to(['/filemanager/files/upload']), 39 | 'browseClass' => 'btn btn-sm btn-success', 40 | 'uploadClass' => 'btn btn-sm btn-info', 41 | 'removeClass' => 'btn btn-sm btn-danger', 42 | 'maxFileCount' => $maxFileCount 43 | ], 44 | 'pluginEvents' => [ 45 | 'filepreupload' => $script 46 | ] 47 | ]); 48 | 49 | ActiveForm::end(); 50 | -------------------------------------------------------------------------------- /views/files/_grid-view.php: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 |
12 | getModule('filemanager')->models['folders']; 14 | $folderArray = ArrayHelper::merge(['' => Yii::t('filemanager', 'All')], ArrayHelper::map($folders::find()->all(), 'folder_id', 'category')); 15 | echo $this->renderAjax('_search', [ 16 | 'model' => $model, 17 | 'folderArray' => $folderArray 18 | ]); 19 | ?> 20 | 21 |
22 |
23 | 26 |
27 |
28 | 39 |
40 | 41 | 46 | 51 | 52 |
53 | registerJs($script); 88 | } 89 | -------------------------------------------------------------------------------- /views/files/_list-view.php: -------------------------------------------------------------------------------- 1 | 6 |
7 |
8 | controller->module->thumbnailSize; 10 | $gridWidth = $thumbnailSize[0] + 40; 11 | echo GridView::widget([ 12 | 'dataProvider' => $dataProvider, 13 | 'filterModel' => false, 14 | 'export' => false, 15 | 'pjax' => true, 16 | 'columns' => [ 17 | [ 18 | 'class' => 'yii\grid\DataColumn', 19 | 'format' => 'html', 20 | 'contentOptions' => ['style' => "width: {$gridWidth}px; text-align: center;"], 21 | 'value' => function ($model) { 22 | $fileType = $model->mime_type; 23 | if ($model->dimension) { 24 | $fileType = 'image'; 25 | } 26 | return dpodium\filemanager\components\Filemanager::getThumbnail($fileType, $model->getFileUrl(true)); 27 | } 28 | ], 29 | 'caption', 30 | 'alt_text', 31 | 'description', 32 | [ 33 | 'class' => 'yii\grid\DataColumn', 34 | 'attribute' => 'mime_type', 35 | 'filter' => false 36 | ], 37 | [ 38 | 'class' => 'yii\grid\ActionColumn', 39 | 'template' => '{update} {delete}', 40 | 'buttons' => [ 41 | 'update' => function ($url, $model) use ($view) { 42 | $url = \Yii::$app->urlManager->createUrl(['/filemanager/files/update', 'id' => $model['file_id'], 'view' => $view]); 43 | return Html::a('', $url, ['title' => Yii::t('filemanager', 'Edit')]); 44 | }, 45 | 'delete' => function ($url, $model) { 46 | $url = \Yii::$app->urlManager->createUrl(['/filemanager/files/delete', 'id' => $model['file_id']]); 47 | return Html::a('', $url, [ 48 | 'title' => Yii::t('filemanager', 'Delete'), 49 | 'data-method' => 'post', 50 | 'data-confirm' => Yii::t('filemanager', 'Confirm delete {src_file_name} ?', ['src_file_name' => $model['src_file_name']]) 51 | ]); 52 | }, 53 | ], 54 | ], 55 | ], 56 | ]); 57 | ?> 58 |
59 |
-------------------------------------------------------------------------------- /views/files/_search.php: -------------------------------------------------------------------------------- 1 | 8 |
9 |
10 |
11 |

12 | 15 |

16 |
17 | 58 |
59 |
60 | -------------------------------------------------------------------------------- /views/files/index.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('filemanager', 'Media Gallery'); 7 | $this->params['breadcrumbs'][] = $this->title; 8 | ?> 9 | 23 | render('_search', [ 25 | 'model' => $model, 26 | 'folderArray' => $folderArray 27 | ]); 28 | ?> 29 |
30 |
31 | 39 |
40 |
41 |
42 | render("_{$view}-view", [ 44 | 'model' => $model, 45 | 'dataProvider' => $dataProvider, 46 | 'uploadType' => $uploadType, 47 | 'view' => $view, 48 | 'viewFrom' => $viewFrom 49 | ]); 50 | -------------------------------------------------------------------------------- /views/files/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('filemanager', 'Media Property'); 8 | $this->params['breadcrumbs'][] = ['label' => Yii::t('filemanager', 'Media Gallery'), 'url' => ['files/index']]; 9 | $this->params['breadcrumbs'][] = $this->title; 10 | ?> 11 | 12 | 15 | 16 |
17 |
18 | 19 |
20 | mime_type; 22 | if ($model->dimension) { 23 | $fileType = 'image'; 24 | } 25 | echo dpodium\filemanager\components\Filemanager::getThumbnail($fileType, $model->object_url . $model->src_file_name . '?'. $model->updated_at, "250px", "250px"); 26 | ?> 27 |
28 | 29 |
30 |
31 | tags); 33 | $objectUrl = $model->object_url . $model->src_file_name . '?'. $model->updated_at; 34 | $btnCopyToClipboard = Html::button('', [ 35 | 'class' => 'btn-copy btn-xs', 36 | 'title' => Yii::t('filemanager', 'Copy') 37 | ]); 38 | echo DetailView::widget([ 39 | 'model' => $model, 40 | 'attributes' => [ 41 | 'src_file_name', 42 | 'thumbnail_name', 43 | [ 44 | 'label' => $model->folder->getAttributeLabel('storage'), 45 | 'value' => $model->folder->storage, 46 | ], 47 | [ 48 | 'label' => $model->folder->getAttributeLabel('category'), 49 | 'value' => $model->folder->category, 50 | ], 51 | 'mime_type', 52 | 'dimension', 53 | [ 54 | 'label' => $model->getAttributeLabel('object_url'), 55 | 'format' => 'raw', 56 | 'value' => Html::tag('div', $objectUrl, ['class' => 'copy-object-url', 'style' => 'float: left']) . $btnCopyToClipboard, 57 | ], 58 | [ 59 | 'label' => $model->getAttributeLabel('caption'), 60 | 'format' => 'raw', 61 | 'value' => Editable::widget([ 62 | 'model' => $model, 63 | 'attribute' => 'caption', 64 | 'asPopover' => false, 65 | ]) 66 | ], 67 | [ 68 | 'label' => $model->getAttributeLabel('alt_text'), 69 | 'format' => 'raw', 70 | 'value' => Editable::widget([ 71 | 'model' => $model, 72 | 'attribute' => 'alt_text', 73 | 'asPopover' => false, 74 | ]) 75 | ], 76 | [ 77 | 'label' => $model->getAttributeLabel('description'), 78 | 'format' => 'raw', 79 | 'value' => Editable::widget([ 80 | 'model' => $model, 81 | 'attribute' => 'description', 82 | 'asPopover' => false, 83 | 'submitOnEnter' => false, 84 | 'inputType' => Editable::INPUT_TEXTAREA, 85 | ]) 86 | ], 87 | [ 88 | 'label' => $model->getAttributeLabel('tags'), 89 | 'format' => 'raw', 90 | 'value' => Editable::widget([ 91 | 'model' => $model, 92 | 'attribute' => 'tags', 93 | 'asPopover' => false, 94 | 'submitOnEnter' => false, 95 | 'inputType' => Editable::INPUT_SELECT2, 96 | 'displayValue' => implode(', ', $editableTagsLabel), 97 | 'options' => [ 98 | 'data' => $tags, 99 | 'options' => [ 100 | 'multiple' => true, 101 | 'placeholder' => Yii::t('filemanager', 'Enter or select tags...'), 102 | ], 103 | 'pluginOptions' => [ 104 | 'tags' => true, 105 | 'maximumInputLength' => 32 106 | ], 107 | ], 108 | 'pluginEvents' => [ 109 | 'editableReset' => "function(event) { 110 | jQuery('#' + event.currentTarget.id + ' .kv-editable-parent .input-group select').select2('val', {$tagDisplayValue}); 111 | }" 112 | ] 113 | ]) 114 | ], 115 | 'created_at:dateTime', 116 | 'updated_at:dateTime', 117 | ] 118 | ]); 119 | ?> 120 |
121 |
122 | 123 |
124 |
125 | urlManager->createUrl(['/filemanager/files/index']); 127 | if (empty($view)) { 128 | $cancelUrl = \Yii::$app->urlManager->createUrl(['/filemanager/files/index', 'view' => 'grid']); 129 | } 130 | echo Html::a(Yii::t('filemanager', 'Cancel'), $cancelUrl, ['class' => 'btn btn-primary']); 131 | ?> 132 |
133 |
134 | title = Yii::t('filemanager', 'Upload New Media'); 7 | $this->params['breadcrumbs'][] = ['label' => Yii::t('filemanager', 'Media Gallery'), 'url' => ['files/index']]; 8 | $this->params['breadcrumbs'][] = $this->title; 9 | ?> 10 | 13 |
14 |
15 | 16 | 25 | render('_file-input', [ 28 | 'model' => $model, 29 | 'folderArray' => $folderArray, 30 | 'uploadType' => Filemanager::TYPE_FULL_PAGE, 31 | 'multiple' => $multiple, 32 | 'maxFileCount' => $maxFileCount 33 | ]); 34 | } 35 | ?> 36 |
37 |
38 |
39 |
40 |
41 |
-------------------------------------------------------------------------------- /views/folders/_form.php: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | 13 | field($model, 'category')->textInput(['maxlength' => true]); 17 | 18 | echo $form->field($model, 'path')->textInput(['maxlength' => true]); 19 | ?> 20 |
21 | isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> 22 |
23 | 24 | 25 | 26 |
27 | -------------------------------------------------------------------------------- /views/folders/create.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('filemanager', 'Create Folder'); 7 | $this->params['breadcrumbs'][] = ['label' => Yii::t('filemanager', 'Media Folder'), 'url' => ['index']]; 8 | $this->params['breadcrumbs'][] = $this->title; 9 | ?> 10 | 13 |
14 |
15 | render('_form', [ 17 | 'model' => $model, 18 | ]); 19 | ?> 20 |
21 |
22 | -------------------------------------------------------------------------------- /views/folders/index.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('filemanager', 'Media Folder'); 10 | $this->params['breadcrumbs'][] = $this->title; 11 | ?> 12 | 20 |
21 |
22 | $dataProvider, 25 | 'filterModel' => $model, 26 | 'export' => false, 27 | 'columns' => [ 28 | ['class' => 'yii\grid\SerialColumn'], 29 | 'category', 30 | [ 31 | 'class' => 'kartik\grid\DataColumn', 32 | 'attribute' => 'path', 33 | 'value' => function ($model) { 34 | $path = $model->path; 35 | if ($model->storage == 'local') { 36 | $path = Yii::getAlias('@webroot') . '/' . $model['path']; 37 | } 38 | return $path; 39 | } 40 | ], 41 | 'storage', 42 | ['class' => 'yii\grid\ActionColumn'], 43 | ], 44 | ]); 45 | ?> 46 |
47 |
48 | -------------------------------------------------------------------------------- /views/folders/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('filemanager', 'Update Folder').': ' . ' ' . $model->category; 9 | $this->params['breadcrumbs'][] = ['label' => Yii::t('filemanager', 'Media Folder'), 'url' => ['index']]; 10 | $this->params['breadcrumbs'][] = ['label' => $model->category, 'url' => ['view', 'id' => $model->folder_id]]; 11 | $this->params['breadcrumbs'][] = Yii::t('filemanager', 'Update'); 12 | ?> 13 | 16 |
17 |
18 | render('_form', [ 20 | 'model' => $model, 21 | ]); 22 | ?> 23 |
24 |
25 | -------------------------------------------------------------------------------- /views/folders/view.php: -------------------------------------------------------------------------------- 1 | title = $model->category; 10 | $this->params['breadcrumbs'][] = ['label' => Yii::t('filemanager', 'Media Folder'), 'url' => ['index']]; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 | 16 |
17 |
18 |

19 | $model->folder_id], ['class' => 'btn btn-primary']); ?> 20 | $model->folder_id], [ 22 | 'class' => 'btn btn-danger', 23 | 'data' => [ 24 | 'confirm' => 'Are you sure you want to delete this item?', 25 | 'method' => 'post', 26 | ], 27 | ]); 28 | ?> 29 |

30 |
31 |
32 |
33 | $model, 36 | 'attributes' => [ 37 | 'category', 38 | 'path', 39 | 'storage', 40 | ], 41 | ]); 42 | ?> 43 |
44 |
-------------------------------------------------------------------------------- /widgets/FileBrowse.php: -------------------------------------------------------------------------------- 1 | getView(); 54 | FilemanagerAsset::register($view); 55 | 56 | if (empty($this->containerOptions['id'])) { 57 | $this->containerOptions['id'] = $this->getId(); 58 | } 59 | 60 | $fileContent = $this->renderFileContent(); 61 | $opts = \yii\helpers\Json::encode([ 62 | 'multiple' => $this->multiple, 63 | 'maxFileCount' => $this->maxFileCount, 64 | 'folderId' => $this->folderId, 65 | ]); 66 | $script .= "$('#{$this->containerOptions['id']}').filemanagerBrowse({$opts});"; 67 | $this->_browseClientFunc = 'fmBrowseInit_' . hash('crc32', $script); 68 | $view->registerJs("var {$this->_browseClientFunc}=function(){\n{$script}\n};\n{$this->_browseClientFunc}();"); 69 | 70 | echo Html::tag('div', $fileContent, ['id' => $this->containerOptions['id'], 'class' => 'fm-browse-selected']); 71 | } 72 | 73 | public function renderFileContent() { 74 | $attribute = preg_replace('/\[(.*?)\]/', '', $this->attribute); 75 | $input = $thumb = ''; 76 | $selectedFileOpt = ['class' => 'fm-browse-input']; 77 | 78 | if ($this->model->$attribute) { 79 | $filesModel = \Yii::$app->getModule('filemanager')->models['files']; 80 | $file = $filesModel::findOne(['file_identifier' => $this->model->$attribute]); 81 | } 82 | 83 | if (isset($file) && $file) { 84 | $fileType = $file->mime_type; 85 | if ($file->dimension) { 86 | $src = $file->object_url . $file->thumbnail_name . '?' . $file->updated_at; 87 | $fileType = 'image'; 88 | } else { 89 | $src = $file->object_url . $file->src_file_name . '?' . $file->updated_at; 90 | } 91 | $gridBox = new \dpodium\filemanager\components\GridBox([ 92 | 'owner' => $this, 93 | 'src' => $src, 94 | 'fileType' => $fileType, 95 | 'toolArray' => [['tagType' => 'i', 'options' => ['class' => 'fa-icon fa fa-times fm-remove', 'title' => Yii::t('filemanager', 'Remove')]]], 96 | 'thumbnailSize' => \Yii::$app->getModule('filemanager')->thumbnailSize 97 | ]); 98 | 99 | foreach ($this->fileData as $attribute) { 100 | $value = isset($file->$attribute) ? $file->$attribute : null; 101 | $input .= Html::input('input', "Filemanager[{$attribute}]", $value); 102 | } 103 | $thumb = $gridBox->renderGridBox(); 104 | } else { 105 | $selectedFileOpt['value'] = ''; 106 | } 107 | 108 | $fileView = Html::tag('div', $thumb, ['class' => 'fm-browse-selected-view']); 109 | $selectedFile = Html::activeInput('input', $this->model, $this->attribute, $selectedFileOpt); 110 | 111 | $buttonClass = empty($this->options['class']) ? 'btn btn-primary' : $this->options['class']; 112 | $browseButton = Html::label(Yii::t('filemanager', 'Browse'), Html::getInputId($this->model, $this->attribute), [ 113 | 'class' => 'fm-btn-browse btn-browse ' . $buttonClass, 114 | 'data-url' => Url::to(['/filemanager/files/browse']), 115 | 'data-backdrop' => 'static', 116 | 'data-toggle' => 'modal', 117 | 'data-target' => '#fm-modal', 118 | ]); 119 | 120 | return $fileView . $browseButton . $selectedFile . $input; 121 | } 122 | 123 | public static function renderModal() { 124 | $btnClose = Html::button(Html::tag('span', '×', ['aria-hidden' => 'true']), [ 125 | 'class' => 'close', 126 | 'data-dismiss' => 'modal', 127 | 'aria-label' => "Close" 128 | ]); 129 | $modalTitle = Html::tag('h4', Yii::t('filemanager', 'Media Gallery'), ['class' => 'modal-title', 'id' => 'fm-modal-label']); 130 | $modalHeader = Html::tag('div', $btnClose . $modalTitle, ['class' => 'modal-header']); 131 | 132 | $tab = Tabs::widget([ 133 | 'items' => [ 134 | [ 135 | 'label' => Yii::t('filemanager', 'Media Gallery'), 136 | 'linkOptions' => [ 137 | 'id' => 'fm-upload-tab', 138 | 'data-url' => \yii\helpers\Url::to(['/filemanager/files/upload-tab']) 139 | ] 140 | ], 141 | [ 142 | 'label' => Yii::t('filemanager', 'Library'), 143 | 'linkOptions' => [ 144 | 'id' => 'fm-library-tab', 145 | 'data-url' => \yii\helpers\Url::to(['/filemanager/files/library-tab']) 146 | ] 147 | ], 148 | ], 149 | ]); 150 | $modalBody = Html::tag('div', $tab, ['class' => 'modal-body', 'style' => 'min-height: 560px;']); 151 | $modalContent = Html::tag('div', $modalHeader . $modalBody, ['class' => 'modal-content']); 152 | $modalHtml = Html::tag('div', Html::tag('div', $modalContent, ['class' => 'modal-dialog modal-lg', 'role' => 'document']), [ 153 | 'class' => 'fm-modal modal fade', 154 | 'id' => "fm-modal", 155 | 'tabindex' => "-1", 156 | 'role' => "dialog", 157 | 'aria-labelledby' => "fm-modal-label" 158 | ]); 159 | 160 | return $modalHtml; 161 | } 162 | 163 | } 164 | -------------------------------------------------------------------------------- /widgets/FileBrowseEditor.php: -------------------------------------------------------------------------------- 1 | getView(); 41 | FilemanagerEditorAsset::register($view); 42 | 43 | Yii::$app->i18n->translations['filemanager*'] = [ 44 | 'class' => 'yii\i18n\PhpMessageSource', 45 | 'basePath' => "@dpodium/filemanager/messages" 46 | ]; 47 | 48 | } 49 | 50 | public function run() { 51 | $btnClose = Html::button(Html::tag('span', '×', ['aria-hidden' => 'true']), [ 52 | 'class' => 'close', 53 | 'data-dismiss' => 'modal', 54 | 'aria-label' => "Close" 55 | ]); 56 | $modalTitle = Html::tag('h4', Yii::t('filemanager', 'Media Gallery'), ['class' => 'modal-title', 'id' => 'fm-modal-label']); 57 | $modalHeader = Html::tag('div', $btnClose . $modalTitle, ['class' => 'modal-header']); 58 | 59 | $tab = Tabs::widget([ 60 | 'items' => [ 61 | [ 62 | 'label' => Yii::t('filemanager', 'Media Gallery'), 63 | 'linkOptions' => [ 64 | 'id' => 'fm-upload-tab', 65 | 'data-url' => \yii\helpers\Url::to(['/filemanager/files/upload-tab']) 66 | ] 67 | ], 68 | [ 69 | 'label' => Yii::t('filemanager', 'Library'), 70 | 'linkOptions' => [ 71 | 'id' => 'fm-library-tab', 72 | 'data-url' => \yii\helpers\Url::to(['/filemanager/files/library-tab']) 73 | ] 74 | ], 75 | ], 76 | ]); 77 | $modalBody = Html::tag('div', $tab, ['class' => 'modal-body', 'style' => 'min-height: 560px;']); 78 | $modalContent = Html::tag('div', $modalHeader . $modalBody, ['class' => 'modal-content']); 79 | $modalHtml = Html::tag('div', Html::tag('div', $modalContent, ['class' => 'modal-dialog modal-lg', 'role' => 'document']), [ 80 | 'class' => 'fm-modal modal fade', 81 | 'id' => "fm-modal", 82 | 'tabindex' => "-1", 83 | 'role' => "dialog", 84 | 'aria-labelledby' => "fm-modal-label", 85 | 'data-multiple' => $this->multiple, 86 | 'data-maxfilecount' => $this->maxFileCount, 87 | 'data-folderid' => $this->folderId, 88 | ]); 89 | 90 | return $modalHtml; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /widgets/Gallery.php: -------------------------------------------------------------------------------- 1 | 'fm-section', 'class' => 'fm-section']; 18 | public $layout = "{items}\n{pager}"; 19 | public $viewFrom = 'full-page'; 20 | public $gridBox = []; 21 | protected $_galleryClientFunc = ''; 22 | 23 | /** 24 | * Initializes the grid view. 25 | * This method will initialize required property values and instantiate [[columns]] objects. 26 | */ 27 | public function init() { 28 | parent::init(); 29 | 30 | $script = ''; 31 | $view = $this->getView(); 32 | 33 | if (empty($this->options['id'])) { 34 | $this->options['id'] = $this->getId(); 35 | } 36 | 37 | $opts = \yii\helpers\Json::encode([ 38 | 'viewFrom' => $this->viewFrom 39 | ]); 40 | $script .= "$('#{$this->options['id']}').filemanagerGallery({$opts});"; 41 | $this->_galleryClientFunc = 'fmGalleryInit_' . hash('crc32', $script); 42 | $view->registerJs("var {$this->_galleryClientFunc}=function(){\n{$script}\n};\n{$this->_galleryClientFunc}();"); 43 | } 44 | 45 | /** 46 | * Runs the widget. 47 | */ 48 | public function run() { 49 | $view = $this->getView(); 50 | FilemanagerAsset::register($view); 51 | parent::run(); 52 | } 53 | 54 | public function renderItems() { 55 | if (empty($this->dataProvider)) { 56 | return 'No images in the library.'; 57 | } 58 | 59 | $items = ''; 60 | foreach ($this->dataProvider->getModels() as $model) { 61 | $src = ''; 62 | $fileType = $model->mime_type; 63 | if ($model->dimension) { 64 | $src = $model->object_url . $model->thumbnail_name . '?' . $model->updated_at; 65 | $fileType = 'image'; 66 | } else { 67 | $src = $model->object_url . $model->src_file_name . '?' . $model->updated_at; 68 | } 69 | 70 | $toolArray = $this->_getToolArray($model->file_id); 71 | $items .= $this->renderGridBox($src, $fileType, $toolArray); 72 | } 73 | 74 | return $items; 75 | } 76 | 77 | public function renderPager() { 78 | $pagination = $this->dataProvider->getPagination(); 79 | $links = $pagination->getLinks(); 80 | 81 | if (isset($links[\yii\data\Pagination::LINK_NEXT])) { 82 | $link = Html::a('', $links[\yii\data\Pagination::LINK_NEXT]); 83 | return Html::tag('div', $link, ['id' => 'fm-next-page']); 84 | } 85 | 86 | return; 87 | } 88 | 89 | public function renderGridBox($src, $fileType, $toolArray) { 90 | $gridBox = new GridBox([ 91 | 'owner' => $this, 92 | 'src' => $src, 93 | 'fileType' => $fileType, 94 | 'toolArray' => $toolArray 95 | ]); 96 | 97 | return $gridBox->renderGridBox(); 98 | } 99 | 100 | private function _getToolArray($fileId) { 101 | $input = Html::input('radio', 'fm-gallery-group', $fileId, ['data-url' => \yii\helpers\Url::to(['/filemanager/files/update', 'id' => $fileId])]); 102 | $view = Html::tag('i', '', ['class' => 'fa-icon fa fa-eye fm-view', 'title' => \Yii::t('filemanager', 'View')]); 103 | 104 | $toolArray = [ 105 | [ 106 | 'tagType' => 'label', 107 | 'content' => $input . $view 108 | ] 109 | ]; 110 | 111 | if ($this->viewFrom == 'modal') { 112 | $toolArray[] = [ 113 | 'tagType' => 'i', 114 | 'options' => [ 115 | 'class' => 'fa-icon fa fa-link fm-use', 116 | 'title' => \Yii::t('filemanager', 'Use'), 117 | 'data-url' => \yii\helpers\Url::to(['/filemanager/files/use']), 118 | 'data-id' => $fileId 119 | ] 120 | ]; 121 | $toolArray[] = [ 122 | 'tagType' => 'i', 123 | 'options' => [ 124 | 'class' => 'fa-icon fa fa-trash fm-delete', 125 | 'title' => \Yii::t('filemanager', 'Delete Permanently'), 126 | 'data-url' => \yii\helpers\Url::to(['/filemanager/files/delete', 'id' => $fileId]), 127 | 'onclick' => 'confirmDelete = confirm("Confirm delete this file?");' 128 | ] 129 | ]; 130 | } 131 | 132 | return $toolArray; 133 | } 134 | 135 | } 136 | --------------------------------------------------------------------------------