From 2966b3490399776a42f877fbdd0be6148944c835 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Mon, 5 Nov 2018 00:17:29 +0200 Subject: [PATCH 01/26] Use database for upload session instead of Yii::$app->session --- guide/README.md | 7 +++++ src/FileManager.php | 5 ---- src/behaviors/FileBehavior.php | 36 ++++++++++++++++-------- src/models/FileUploadSession.php | 48 ++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 src/models/FileUploadSession.php diff --git a/guide/README.md b/guide/README.md index a12f1d3..410b45a 100644 --- a/guide/README.md +++ b/guide/README.md @@ -39,6 +39,13 @@ Let's do it. ``` > You can add any extra fields, such as `type` to divide files by type or `position` to set sort order + Migration for upload session + + ```php + php yii migrate/create create_file_upload_session_table --fields="file_id:integer:notNull:defaultValue(0),created_user_id:integer:notNull:defaultValue(0),target_model_id:integer:notNull:defaultValue(0),target_model_class:string:notNull:defaultValue(''),target_model_attribute:string:notNull:defaultValue(''),created_on:datetime" + ``` + > You can add any extra fields, such as `type` to divide files by type or `position` to set sort order + 3. **Applying Migrations** ```php diff --git a/src/FileManager.php b/src/FileManager.php index ac7acc2..d0dbfa6 100644 --- a/src/FileManager.php +++ b/src/FileManager.php @@ -18,11 +18,6 @@ */ class FileManager extends Component { - /** - * @var string Session variable name - */ - public $sessionName = 'filemanager.uploads'; - /** * @internal */ diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index 4dd21a9..8c496a2 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -8,6 +8,7 @@ namespace rkit\filemanager\behaviors; +use rkit\filemanager\models\FileUploadSession; use Yii; use yii\base\Behavior; use yii\db\ActiveRecord; @@ -125,19 +126,23 @@ public function beforeDelete() private function clearState($attribute) { - $state = Yii::$app->session->get(Yii::$app->fileManager->sessionName); - unset($state[$attribute]); - Yii::$app->session->set(Yii::$app->fileManager->sessionName, $state); + FileUploadSession::deleteAll([ + 'created_user_id' => Yii::$app->user->id, + 'target_model_class' => get_class($this->owner), + 'target_model_id' => $this->owner->getPrimaryKey(), + 'target_model_attribute' => $attribute, + ]); } private function setState($attribute, $file) { - $state = Yii::$app->session->get(Yii::$app->fileManager->sessionName); - if (!is_array($state)) { - $state = []; - } - $state[$attribute][] = $file->getPrimaryKey(); - Yii::$app->session->set(Yii::$app->fileManager->sessionName, $state); + $rec = new FileUploadSession(); + $rec->created_user_id = Yii::$app->user->id; + $rec->file_id = $file->getPrimaryKey(); + $rec->target_model_attribute = $attribute; // TODO: write model/object id? + $rec->target_model_id = (!$this->owner->isNewRecord ? $this->owner->getPrimaryKey() : null); + $rec->target_model_class = get_class($this->owner); + $rec->save(false); } private function setValue($attribute, $file, $defaultValue) @@ -335,8 +340,17 @@ public function fileRules($attribute, $onlyCoreValidators = false) */ public function fileState($attribute) { - $state = Yii::$app->session->get(Yii::$app->fileManager->sessionName); - return ArrayHelper::getValue($state === null ? [] : $state, $attribute, []); + $data = FileUploadSession::find()->where([ + 'created_user_id' => Yii::$app->user->id, + 'target_model_class' => get_class($this->owner), + 'target_model_id' => $this->owner->getPrimaryKey(), + 'target_model_attribute' => $attribute, + ])->all(); + if ($data) { + return ArrayHelper::getColumn($data, ['file_id']); + } else { + return []; + } } /** diff --git a/src/models/FileUploadSession.php b/src/models/FileUploadSession.php new file mode 100644 index 0000000..0f9df8d --- /dev/null +++ b/src/models/FileUploadSession.php @@ -0,0 +1,48 @@ + + * + * Copyright (C) 2018-present Sergii Webkadabra + */ + +namespace rkit\filemanager\models; + +/** + * Class FileUploadSession + * @package rkit\filemanager\models + * + * @property int $id + * @property int $file_id + * @property int $created_user_id + * @property string $created_on + * @property string $target_model_class + * @property string $target_model_id + * @property string $target_model_attribute + */ +class FileUploadSession extends \yii\db\ActiveRecord +{ + + /** + * @inheritdoc + */ + public static function tableName() + { + return '{{%file_upload_session}}'; + } + + public function behaviors() + { + return [ + [ + 'class' => BlameableBehavior::class, + 'createdByAttribute' => 'created_user_id', + 'updatedByAttribute' => false, + ], + [ + 'class' => TimestampBehavior::class, + 'createdAtAttribute' => 'created_on', + 'value' => new Expression('NOW()'), + ], + ]; + } +} \ No newline at end of file From 288113b560ac15ae4fed039964a3e97b2cec03d2 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Mon, 5 Nov 2018 00:45:18 +0200 Subject: [PATCH 02/26] Bump version --- guide/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/README.md b/guide/README.md index 410b45a..591dea4 100644 --- a/guide/README.md +++ b/guide/README.md @@ -39,7 +39,7 @@ Let's do it. ``` > You can add any extra fields, such as `type` to divide files by type or `position` to set sort order - Migration for upload session + Migration for upload session (since 5.0) ```php php yii migrate/create create_file_upload_session_table --fields="file_id:integer:notNull:defaultValue(0),created_user_id:integer:notNull:defaultValue(0),target_model_id:integer:notNull:defaultValue(0),target_model_class:string:notNull:defaultValue(''),target_model_attribute:string:notNull:defaultValue(''),created_on:datetime" From e87ff052e129a94c3d76ce682f058a3bf2e8b2c7 Mon Sep 17 00:00:00 2001 From: WEBKADABRA Date: Mon, 19 Nov 2018 20:23:00 +0200 Subject: [PATCH 03/26] Fix Error with message "Class rkit\filemanager\models\Expression not found" --- src/models/FileUploadSession.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/models/FileUploadSession.php b/src/models/FileUploadSession.php index 0f9df8d..5742a58 100644 --- a/src/models/FileUploadSession.php +++ b/src/models/FileUploadSession.php @@ -6,6 +6,8 @@ */ namespace rkit\filemanager\models; +use yii\behaviors\BlameableBehavior; +use yii\db\Expression; /** * Class FileUploadSession @@ -45,4 +47,4 @@ public function behaviors() ], ]; } -} \ No newline at end of file +} From 122d1cb674520e9ace324365526120bf9592e595 Mon Sep 17 00:00:00 2001 From: WEBKADABRA Date: Mon, 19 Nov 2018 20:28:44 +0200 Subject: [PATCH 04/26] Fix error Class rkit\filemanager\models\TimestampBehavior does not exist --- src/models/FileUploadSession.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/models/FileUploadSession.php b/src/models/FileUploadSession.php index 5742a58..29badf4 100644 --- a/src/models/FileUploadSession.php +++ b/src/models/FileUploadSession.php @@ -7,6 +7,7 @@ namespace rkit\filemanager\models; use yii\behaviors\BlameableBehavior; +use yii\behaviors\TimestampBehavior; use yii\db\Expression; /** From 4b59efded52cda6afeddcc6e78780b9ecc75d496 Mon Sep 17 00:00:00 2001 From: WEBKADABRA Date: Mon, 19 Nov 2018 20:35:04 +0200 Subject: [PATCH 05/26] Fix error: 'Setting unknown property: rkit\filemanager\models\FileUploadSession::updated_at' --- src/models/FileUploadSession.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/models/FileUploadSession.php b/src/models/FileUploadSession.php index 29badf4..112275b 100644 --- a/src/models/FileUploadSession.php +++ b/src/models/FileUploadSession.php @@ -44,6 +44,7 @@ public function behaviors() [ 'class' => TimestampBehavior::class, 'createdAtAttribute' => 'created_on', + 'updatedAtAttribute' => false, 'value' => new Expression('NOW()'), ], ]; From ce9833daff0996bb65141187cf0b21373c92ff0a Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Sat, 5 Jan 2019 21:50:12 +0200 Subject: [PATCH 06/26] Update documentation --- guide/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/README.md b/guide/README.md index 591dea4..d50324a 100644 --- a/guide/README.md +++ b/guide/README.md @@ -42,7 +42,7 @@ Let's do it. Migration for upload session (since 5.0) ```php - php yii migrate/create create_file_upload_session_table --fields="file_id:integer:notNull:defaultValue(0),created_user_id:integer:notNull:defaultValue(0),target_model_id:integer:notNull:defaultValue(0),target_model_class:string:notNull:defaultValue(''),target_model_attribute:string:notNull:defaultValue(''),created_on:datetime" + php yii migrate/create create_file_upload_session_table --fields="file_id:integer:notNull:defaultValue(0),created_user_id:integer:notNull:defaultValue(0),target_model_id:integer:defaultValue(0),target_model_class:string:notNull:defaultValue(''),target_model_attribute:string:notNull:defaultValue(''),created_on:datetime" ``` > You can add any extra fields, such as `type` to divide files by type or `position` to set sort order From 07415ab54f9d70b293c9359236d95d8159e27c90 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Sun, 6 Jan 2019 13:32:16 +0200 Subject: [PATCH 07/26] Improve support for cases of uploads when original model was a new record at the moment of upload --- src/behaviors/FileBehavior.php | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index 8c496a2..df15f83 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -108,7 +108,7 @@ public function afterSave() $files = array_shift($files); } - $this->clearState($attribute); + $this->clearState($attribute, $files); $this->setValue($attribute, $files, $options['oldValue']); } } @@ -124,14 +124,25 @@ public function beforeDelete() } } - private function clearState($attribute) + public function clearState($attribute, $files) { - FileUploadSession::deleteAll([ + if (!is_array($files)) { + $files = [$files]; + } + $query = [ 'created_user_id' => Yii::$app->user->id, 'target_model_class' => get_class($this->owner), 'target_model_id' => $this->owner->getPrimaryKey(), 'target_model_attribute' => $attribute, - ]); + ]; + if ($files) { + $fileIDs = ArrayHelper::getColumn($files, 'id'); + $query['file_id'] = $fileIDs; + } + FileUploadSession::deleteAll($query); + $query['target_model_id'] = null; + FileUploadSession::deleteAll($query); // for cases of uploads when original model was a new record at the moment of uploads + return; } private function setState($attribute, $file) @@ -340,12 +351,17 @@ public function fileRules($attribute, $onlyCoreValidators = false) */ public function fileState($attribute) { - $data = FileUploadSession::find()->where([ + $query = FileUploadSession::find()->where([ 'created_user_id' => Yii::$app->user->id, 'target_model_class' => get_class($this->owner), - 'target_model_id' => $this->owner->getPrimaryKey(), 'target_model_attribute' => $attribute, - ])->all(); + ]); + $query->andWhere(['or', + ['target_model_id' => $this->owner->getPrimaryKey()], + ['target_model_id' => null] // for cases of uploads when original model was a new record at the moment of uploads + ]); + + $data = $query->all(); if ($data) { return ArrayHelper::getColumn($data, ['file_id']); } else { From 109d765e63e05035c33a53042b15071b1c08b3aa Mon Sep 17 00:00:00 2001 From: WEBKADABRA Date: Tue, 8 Jan 2019 01:20:17 +0200 Subject: [PATCH 08/26] Fix use of `clearState` --- src/behaviors/FileBehavior.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index df15f83..065d754 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -104,12 +104,13 @@ public function afterSave() } $files = $this->fileBind->bind($this->owner, $attribute, $files); + + $this->clearState($attribute, $files); + if (is_array($files)) { $files = array_shift($files); + $this->setValue($attribute, $files, $options['oldValue']); } - - $this->clearState($attribute, $files); - $this->setValue($attribute, $files, $options['oldValue']); } } @@ -156,6 +157,12 @@ private function setState($attribute, $file) $rec->save(false); } + /** + * for models with single upload only + * @param $attribute + * @param $file + * @param $defaultValue + */ private function setValue($attribute, $file, $defaultValue) { $saveFilePath = $this->fileOption($attribute, 'saveFilePathInAttribute'); @@ -360,7 +367,6 @@ public function fileState($attribute) ['target_model_id' => $this->owner->getPrimaryKey()], ['target_model_id' => null] // for cases of uploads when original model was a new record at the moment of uploads ]); - $data = $query->all(); if ($data) { return ArrayHelper::getColumn($data, ['file_id']); From df9c6726b47264b75d8c4f614a0216d82e6c6902 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Mon, 8 Apr 2019 18:04:15 +0300 Subject: [PATCH 09/26] Add remote upload support Example: ``` $file = UploadFromUrl::getInstance($model,'logo_url'); // `logo_url` must be a full URL to a remote image $model->createRemoteFile('logo', $file, '/uploads/logo.jpg'); ``` --- composer.json | 3 ++- guide/README.md | 11 +++++++++++ src/behaviors/FileBehavior.php | 31 +++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7b449ba..bec9a83 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "source": "https://github.com/rkit/filemanager-yii2" }, "require": { - "yiisoft/yii2": "^2.0" + "yiisoft/yii2": "^2.0", + "igogo5yo/yii2-upload-from-url": "^1.4" }, "scripts": { "phpdoc": "phpdoc", diff --git a/guide/README.md b/guide/README.md index d50324a..e0efa75 100644 --- a/guide/README.md +++ b/guide/README.md @@ -126,6 +126,17 @@ Let's do it. $file->save(); return $file; }, + // a callback for creating `File` model for remote uploads + 'createRemoteFile' => function ($info, $name) { + $file = new File(); + $file->title = $name; + $file->created_on = new yii\db\Expression('NOW()'); + $file->created_user_id = Yii::$app->user->id; + $file->size_bytes = $info->size; + $file->generateName($info->url, $name, $this); + $file->save(); + return $file; + }, // core validators 'rules' => [ 'imageSize' => ['minWidth' => 300, 'minHeight' => 300], diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index 065d754..3693258 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -446,4 +446,35 @@ public function createFile($attribute, $path, $name) } // @codeCoverageIgnore return false; // @codeCoverageIgnore } + + /** + * Create a file from remote URL + * + * @author Sergii Gamaiunov + * + * @param string $attribute The attribute name + * @param \igogo5yo\uploadfromurl\UploadFromUrl $remoteFile + * @param string $name The file name + * @return \ActiveRecord The file model + */ + public function createRemoteFile($attribute, $remoteFile, $name) + { + $url = $remoteFile->url; + $handlerCreateFile = $this->fileOption($attribute, 'createRemoteFile'); + $file = $handlerCreateFile($remoteFile, $name); + if ($file) { + $storage = $this->fileStorage($attribute); + $stream = fopen($url, 'r'); + $handlerTemplatePath = $this->fileOption($attribute, 'templatePath'); + if ($storage->putStream($handlerTemplatePath($file), $stream)) { + if (is_resource($stream)) { // some adapters close resources on their own + fclose($stream); + } + $this->setState($attribute, $file); + $this->owner->{$attribute} = $file->id; + return $file; + } + } // @codeCoverageIgnore + return false; // @codeCoverageIgnore + } } From 1b997a5e3cdd148c5549de83114ebc9a52f57ab7 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Sun, 21 Apr 2019 00:33:48 +0300 Subject: [PATCH 10/26] Add compatibility with console contorllers --- src/behaviors/FileBehavior.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index 3693258..85611fd 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -127,6 +127,9 @@ public function beforeDelete() public function clearState($attribute, $files) { + if (!isset(Yii::$app->user)) { + return []; + } if (!is_array($files)) { $files = [$files]; } @@ -358,6 +361,9 @@ public function fileRules($attribute, $onlyCoreValidators = false) */ public function fileState($attribute) { + if (!isset(Yii::$app->user)) { + return []; + } $query = FileUploadSession::find()->where([ 'created_user_id' => Yii::$app->user->id, 'target_model_class' => get_class($this->owner), @@ -470,7 +476,9 @@ public function createRemoteFile($attribute, $remoteFile, $name) if (is_resource($stream)) { // some adapters close resources on their own fclose($stream); } - $this->setState($attribute, $file); + if (isset(Yii::$app->user)) { + $this->setState($attribute, $file); + } $this->owner->{$attribute} = $file->id; return $file; } From 0cea45b21132b330baa156c85a47d172aac899a6 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Tue, 7 May 2019 21:33:48 +0300 Subject: [PATCH 11/26] Add `onSuccess` option Add `onSuccess` option - a callable function to be returned after successful upload instead of responce. Function signature is ```function (File $file, ActiveRecord $model){}```, where `File` is the model that's configured in `createFile` option of model's file behavior configuration --- src/actions/UploadAction.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/actions/UploadAction.php b/src/actions/UploadAction.php index c342197..ae8ebb0 100644 --- a/src/actions/UploadAction.php +++ b/src/actions/UploadAction.php @@ -45,6 +45,13 @@ class UploadAction extends Action * @var bool $saveAfterUpload Save after upload */ public $saveAfterUpload = false; + /** + * @var callable $onSuccess Function to be returned after successful upload instead of responce. Function signature + * is ```function (File $file, ActiveRecord $model){}```, where `File` is the model that's configured in `createFile` + * option of model's file behavior configuration + * @since 5.3.0 + */ + public $onSuccess; /** * @var ActiveRecord $model */ @@ -111,6 +118,14 @@ private function upload($file) if (count($presetAfterUpload)) { $this->applyPreset($presetAfterUpload, $file); } + if ($this->onSuccess) { + $responce = call_user_func($this->onSuccess, $file, $this->model); + if (is_array($responce)) { + return $this->controller->asJson($responce); + } else { + return $responce; + } + } $template = $this->model->fileOption($this->attribute, 'template'); if ($template) { return $this->response( From 1cc5419f64d512317e55cea08a0ab2fceb6d8198 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Tue, 7 May 2019 21:37:21 +0300 Subject: [PATCH 12/26] Bump version --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index bec9a83..7299d1d 100644 --- a/composer.json +++ b/composer.json @@ -4,6 +4,7 @@ "keywords": ["yii2", "extension", "file manager", "manager", "upload", "resize", "files"], "homepage": "https://github.com/rkit/filemanager-yii2", "type": "yii2-extension", + "version": "5.3.1", "license": "MIT", "authors": [ { From 86fe36b46b6e993105a4908989adc1348242c593 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Wed, 8 May 2019 01:39:53 +0300 Subject: [PATCH 13/26] Add `userComponent` property --- src/behaviors/FileBehavior.php | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index 85611fd..41c69af 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -28,6 +28,10 @@ class FileBehavior extends Behavior * @var FileBind */ private $fileBind; + /** + * @var string name of application component that represents `user` + */ + public $userComponent = 'user'; /** * @internal @@ -125,16 +129,24 @@ public function beforeDelete() } } + protected function getUser() + { + if (!$this->userComponent || !isset(Yii::$app->{$this->userComponent})) { + return false; + } + return Yii::$app->{$this->userComponent}; + } + public function clearState($attribute, $files) { - if (!isset(Yii::$app->user)) { + if (!$this->getUser()) { return []; } if (!is_array($files)) { $files = [$files]; } $query = [ - 'created_user_id' => Yii::$app->user->id, + 'created_user_id' => $this->getUser()->id, 'target_model_class' => get_class($this->owner), 'target_model_id' => $this->owner->getPrimaryKey(), 'target_model_attribute' => $attribute, @@ -152,7 +164,7 @@ public function clearState($attribute, $files) private function setState($attribute, $file) { $rec = new FileUploadSession(); - $rec->created_user_id = Yii::$app->user->id; + $rec->created_user_id = $this->getUser()->id; $rec->file_id = $file->getPrimaryKey(); $rec->target_model_attribute = $attribute; // TODO: write model/object id? $rec->target_model_id = (!$this->owner->isNewRecord ? $this->owner->getPrimaryKey() : null); @@ -361,11 +373,11 @@ public function fileRules($attribute, $onlyCoreValidators = false) */ public function fileState($attribute) { - if (!isset(Yii::$app->user)) { + if (!$this->getUser()) { return []; } $query = FileUploadSession::find()->where([ - 'created_user_id' => Yii::$app->user->id, + 'created_user_id' => $this->getUser()->id, 'target_model_class' => get_class($this->owner), 'target_model_attribute' => $attribute, ]); @@ -476,7 +488,7 @@ public function createRemoteFile($attribute, $remoteFile, $name) if (is_resource($stream)) { // some adapters close resources on their own fclose($stream); } - if (isset(Yii::$app->user)) { + if ($this->getUser()) { $this->setState($attribute, $file); } $this->owner->{$attribute} = $file->id; From ffb596517ea1727fb523c95927b724e4247bc96d Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Wed, 8 May 2019 02:39:20 +0300 Subject: [PATCH 14/26] Bump version --- composer.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7299d1d..a2ec5a3 100644 --- a/composer.json +++ b/composer.json @@ -4,12 +4,16 @@ "keywords": ["yii2", "extension", "file manager", "manager", "upload", "resize", "files"], "homepage": "https://github.com/rkit/filemanager-yii2", "type": "yii2-extension", - "version": "5.3.1", + "version": "5.4.1", "license": "MIT", "authors": [ { "name": "Igor Romanov", "email": "rkit.ru@gmail.com" + }, + { + "name": "Sergii Gamaiunov", + "email": "devkadabra@gmail.com" } ], "support": { From 67d9855df43589b1a2481929707b0b47017806f2 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Tue, 18 Jun 2019 02:37:31 +0300 Subject: [PATCH 15/26] Add `FileBehavior::addClassAlias` to be able to upload files for different versions of a model to a single API endpoint ``` class OldCar extends Car { public function init() { parent::init(); $this->car_type = 'old; FileBehavior::addClassAlias(get_class($this), Car::className()); } public function formName() { return 'Car'; } } ``` --- src/behaviors/FileBehavior.php | 46 +++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index 41c69af..e441012 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -20,14 +20,22 @@ class FileBehavior extends Behavior * @var array */ public $attributes = []; + /** * @var ActiveQuery */ private $relation; + /** * @var FileBind */ private $fileBind; + + /** + * @var array + */ + protected static $classPathMap = []; + /** * @var string name of application component that represents `user` */ @@ -147,7 +155,7 @@ public function clearState($attribute, $files) } $query = [ 'created_user_id' => $this->getUser()->id, - 'target_model_class' => get_class($this->owner), + 'target_model_class' => static::getClass(get_class($this->owner)), 'target_model_id' => $this->owner->getPrimaryKey(), 'target_model_attribute' => $attribute, ]; @@ -168,7 +176,7 @@ private function setState($attribute, $file) $rec->file_id = $file->getPrimaryKey(); $rec->target_model_attribute = $attribute; // TODO: write model/object id? $rec->target_model_id = (!$this->owner->isNewRecord ? $this->owner->getPrimaryKey() : null); - $rec->target_model_class = get_class($this->owner); + $rec->target_model_class = static::getClass(get_class($this->owner)); $rec->save(false); } @@ -378,7 +386,7 @@ public function fileState($attribute) } $query = FileUploadSession::find()->where([ 'created_user_id' => $this->getUser()->id, - 'target_model_class' => get_class($this->owner), + 'target_model_class' => static::getClass(get_class($this->owner)), 'target_model_attribute' => $attribute, ]); $query->andWhere(['or', @@ -497,4 +505,36 @@ public function createRemoteFile($attribute, $remoteFile, $name) } // @codeCoverageIgnore return false; // @codeCoverageIgnore } + + /** + * Add class alias to be able to upload files for different versions of a model to a single API endpoint + * + * Example: + * ``` + * class OldCar extends Car + * { + * public function init() + * { + * parent::init(); + * $this->car_type = 'old; + * FileBehavior::addClassAlias(get_class($this), Car::className()); + * } + * + * public function formName() { + * return 'Car'; + * } + * } + * ``` + * @param $source + * @param $mapTo + */ + public static function addClassAlias($source, $mapTo) { + static::$classPathMap[$source] = $mapTo; + } + + protected static function getClass($source) { + return isset(static::$classPathMap[$source]) + ? static::$classPathMap[$source] + : $source; + } } From be261ec05ed354d1d7639d8e71f4f0790a0b37e4 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Tue, 18 Jun 2019 02:39:47 +0300 Subject: [PATCH 16/26] Bump version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a2ec5a3..212ebd1 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "keywords": ["yii2", "extension", "file manager", "manager", "upload", "resize", "files"], "homepage": "https://github.com/rkit/filemanager-yii2", "type": "yii2-extension", - "version": "5.4.1", + "version": "5.6.0", "license": "MIT", "authors": [ { From 162f4911452a314d4d83092513cbbad81f00a008 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Tue, 18 Jun 2019 02:41:48 +0300 Subject: [PATCH 17/26] Revert "Bump version" This reverts commit be261ec05ed354d1d7639d8e71f4f0790a0b37e4. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 212ebd1..a2ec5a3 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "keywords": ["yii2", "extension", "file manager", "manager", "upload", "resize", "files"], "homepage": "https://github.com/rkit/filemanager-yii2", "type": "yii2-extension", - "version": "5.6.0", + "version": "5.4.1", "license": "MIT", "authors": [ { From 7fdf79325c37945029043e9660b638e5e6c6997a Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Fri, 2 Aug 2019 03:01:37 +0300 Subject: [PATCH 18/26] Ability to mark current upload session as already linked (e.g. file is linked during `createFile`) to avoid duplicate links --- composer.json | 2 +- src/behaviors/FileBehavior.php | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index a2ec5a3..212ebd1 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "keywords": ["yii2", "extension", "file manager", "manager", "upload", "resize", "files"], "homepage": "https://github.com/rkit/filemanager-yii2", "type": "yii2-extension", - "version": "5.4.1", + "version": "5.6.0", "license": "MIT", "authors": [ { diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index e441012..78539bc 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -41,6 +41,12 @@ class FileBehavior extends Behavior */ public $userComponent = 'user'; + /** + * @since 5.6.0 + * @var bool + */ + protected $markedLinked = false; + /** * @internal */ @@ -465,7 +471,9 @@ public function createFile($attribute, $path, $name) $contents = file_get_contents($path); $handlerTemplatePath = $this->fileOption($attribute, 'templatePath'); if ($storage->write($handlerTemplatePath($file), $contents)) { - $this->setState($attribute, $file); + if (!$this->markedLinked) { + $this->setState($attribute, $file); + } $this->owner->{$attribute} = $file->id; return $file; } @@ -497,7 +505,9 @@ public function createRemoteFile($attribute, $remoteFile, $name) fclose($stream); } if ($this->getUser()) { - $this->setState($attribute, $file); + if (!$this->markedLinked) { + $this->setState($attribute, $file); + } } $this->owner->{$attribute} = $file->id; return $file; @@ -537,4 +547,14 @@ protected static function getClass($source) { ? static::$classPathMap[$source] : $source; } + + /** + * Mark current upload session as already linked (e.g. file is linked during `createFile`) to avoid duplicate links + * @return $this + * @since 5.6.0 + */ + public function markLinked() { + $this->markedLinked = true; + return $this; + } } From d8019d923d86d606d2b727e5c4cd4e2ea1123831 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Fri, 20 Sep 2019 01:56:12 +0300 Subject: [PATCH 19/26] Bump version --- composer.json | 2 +- src/behaviors/FileBehavior.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 212ebd1..6e027c3 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "keywords": ["yii2", "extension", "file manager", "manager", "upload", "resize", "files"], "homepage": "https://github.com/rkit/filemanager-yii2", "type": "yii2-extension", - "version": "5.6.0", + "version": "5.7.0", "license": "MIT", "authors": [ { diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index 78539bc..d14329d 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -551,7 +551,7 @@ protected static function getClass($source) { /** * Mark current upload session as already linked (e.g. file is linked during `createFile`) to avoid duplicate links * @return $this - * @since 5.6.0 + * @since 5.7.0 */ public function markLinked() { $this->markedLinked = true; From 8dacc69c334917a78f466e5f167cd8eb2e3b2870 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Fri, 20 Sep 2019 01:58:00 +0300 Subject: [PATCH 20/26] Add file option `disableAutobind` --- src/behaviors/FileBehavior.php | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index d14329d..3867b15 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -11,6 +11,7 @@ use rkit\filemanager\models\FileUploadSession; use Yii; use yii\base\Behavior; +use yii\base\Exception; use yii\db\ActiveRecord; use yii\helpers\ArrayHelper; @@ -95,7 +96,13 @@ public function beforeSave($insert) */ public function afterSave() { - foreach ($this->attributes as $attribute => $options) { + foreach ($this->attributes as $attribute => $options) + { + $disableAutobind = $this->fileOption($attribute, 'disableAutobind'); + if ($disableAutobind) { + continue; + } + $files = $this->owner->{$attribute}; $isAttributeNotChanged = $options['isAttributeChanged'] === false || $files === null; @@ -139,7 +146,10 @@ public function afterSave() public function beforeDelete() { foreach ($this->attributes as $attribute => $options) { - $this->fileBind->delete($this->owner, $attribute, $this->files($attribute)); + $disableAutobind = $this->fileOption($attribute, 'disableAutobind'); + if (!$disableAutobind) { + $this->fileBind->delete($this->owner, $attribute, $this->files($attribute)); + } } } @@ -333,6 +343,9 @@ public function fileUrl($attribute, $file = null) */ public function fileExtraFields($attribute) { + if ($this->fileOption($attribute, 'disableAutobind')) { + return []; + } $fields = $this->fileBind->relations($this->owner, $attribute); if (!$this->fileOption($attribute, 'multiple')) { return array_shift($fields); @@ -348,6 +361,9 @@ public function fileExtraFields($attribute) */ public function files($attribute) { + if ($this->fileOption($attribute, 'disableAutobind')) { + throw new Exception('Accessing `files()` is not allowed when auto-bind is disabled, see `FileBehavior::$disableAutobind`'); + } return $this->fileBind->files($this->owner, $attribute); } @@ -359,6 +375,9 @@ public function files($attribute) */ public function file($attribute) { + if ($this->fileOption($attribute, 'disableAutobind')) { + throw new Exception('Accessing `file()` is not allowed when auto-bind is disabled, see `FileBehavior::$disableAutobind`'); + } return $this->fileBind->file($this->owner, $attribute); } @@ -471,7 +490,8 @@ public function createFile($attribute, $path, $name) $contents = file_get_contents($path); $handlerTemplatePath = $this->fileOption($attribute, 'templatePath'); if ($storage->write($handlerTemplatePath($file), $contents)) { - if (!$this->markedLinked) { + $disableAutobind = $this->fileOption($attribute, 'disableAutobind'); + if (!$this->markedLinked && !$disableAutobind) { $this->setState($attribute, $file); } $this->owner->{$attribute} = $file->id; @@ -551,7 +571,7 @@ protected static function getClass($source) { /** * Mark current upload session as already linked (e.g. file is linked during `createFile`) to avoid duplicate links * @return $this - * @since 5.7.0 + * @since 5.6.0 */ public function markLinked() { $this->markedLinked = true; From 3bee64ec8b99e968212fc2c5f5632e12a1fa6e7f Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Fri, 20 Sep 2019 02:54:03 +0300 Subject: [PATCH 21/26] Set correct mime type when uploading --- src/behaviors/FileBehavior.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index 3867b15..b6f705a 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -489,7 +489,10 @@ public function createFile($attribute, $path, $name) $storage = $this->fileStorage($attribute); $contents = file_get_contents($path); $handlerTemplatePath = $this->fileOption($attribute, 'templatePath'); - if ($storage->write($handlerTemplatePath($file), $contents)) { + if ($storage->write($handlerTemplatePath($file), $contents, [ + // set correct mime type: + 'mimetype' => yii\helpers\FileHelper::getMimeTypeByExtension($name), + ])) { $disableAutobind = $this->fileOption($attribute, 'disableAutobind'); if (!$this->markedLinked && !$disableAutobind) { $this->setState($attribute, $file); From 28eec209cd1f5dfaece6e8687223242587eedf40 Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Fri, 4 Oct 2019 04:04:20 +0300 Subject: [PATCH 22/26] Fix error: `path` is not available in every adapter --- src/behaviors/FileBehavior.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index b6f705a..b1d0022 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -319,7 +319,9 @@ public function fileStorage($attribute) public function filePath($attribute, $file = null) { $path = $this->templatePath($attribute, $file); - return $this->fileStorage($attribute)->path . $path; + /** @var Filesystem $fs */ + $fs = $this->fileStorage($attribute); + return $fs->getAdapter()->getPathPrefix() . $path; } /** From c2dfbdf30dae71d2665a647ed1bee8899c30bfcd Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Sun, 6 Sep 2020 02:01:44 +0300 Subject: [PATCH 23/26] Update FileBehavior.php --- src/behaviors/FileBehavior.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/behaviors/FileBehavior.php b/src/behaviors/FileBehavior.php index b1d0022..5fe7b9b 100644 --- a/src/behaviors/FileBehavior.php +++ b/src/behaviors/FileBehavior.php @@ -260,13 +260,14 @@ private function templatePath($attribute, $file = null) $saveFileId = $this->fileOption($attribute, 'saveFileIdInAttribute'); $isFilledId = $saveFileId && is_numeric($value) && $value; - if (($isFilledPath || $isFilledId) && $file === null) { - $file = $this->file($attribute); - } - - if ($file !== null) { - $handlerTemplatePath = $this->fileOption($attribute, 'templatePath'); - return $handlerTemplatePath($file); + if ($this->fileOption($attribute, 'disableAutobind')) { + if (($isFilledPath || $isFilledId) && $file === null) { + $file = $this->file($attribute); + } + if ($file !== null) { + $handlerTemplatePath = $this->fileOption($attribute, 'templatePath'); + return $handlerTemplatePath($file); + } } return $value; } From cb778df3cc5af1fd4ce6ddfc150877557e56527f Mon Sep 17 00:00:00 2001 From: Sergii Gama Date: Sun, 6 Sep 2020 02:04:26 +0300 Subject: [PATCH 24/26] Update composer.json --- composer.json | 102 +++++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/composer.json b/composer.json index 6e027c3..5c411e5 100644 --- a/composer.json +++ b/composer.json @@ -1,51 +1,51 @@ -{ - "name": "rkit/filemanager-yii2", - "description": "FileManager for Yii2", - "keywords": ["yii2", "extension", "file manager", "manager", "upload", "resize", "files"], - "homepage": "https://github.com/rkit/filemanager-yii2", - "type": "yii2-extension", - "version": "5.7.0", - "license": "MIT", - "authors": [ - { - "name": "Igor Romanov", - "email": "rkit.ru@gmail.com" - }, - { - "name": "Sergii Gamaiunov", - "email": "devkadabra@gmail.com" - } - ], - "support": { - "issues": "https://github.com/rkit/filemanager-yii2/issues?state=open", - "source": "https://github.com/rkit/filemanager-yii2" - }, - "require": { - "yiisoft/yii2": "^2.0", - "igogo5yo/yii2-upload-from-url": "^1.4" - }, - "scripts": { - "phpdoc": "phpdoc", - "test-prepare": [ - "php tests/yii migrate --migrationPath=@tests/migrations/ --interactive=0" - ], - "test": "phpunit --colors=always", - "test-coverage": "phpunit --coverage-html=tests/tmp/coverage.html --colors=always", - "test-coverage-open": "open tests/tmp/coverage.html/index.html" - }, - "autoload": { - "psr-4": { - "rkit\\filemanager\\": "src" - } - }, - "require-dev": { - "intervention/image": "^2.3.2", - "phpunit/phpunit": "^4.8", - "phpunit/dbunit": "^1.4", - "phpdocumentor/phpdocumentor": "^2.8.0", - "cvuorinen/phpdoc-markdown-public": "^0.1.2", - "league/flysystem": "^1.0", - "creocoder/yii2-flysystem": "^0.8.1", - "squizlabs/php_codesniffer": "3.0.0RC1" - } -} +{ + "name": "rkit/filemanager-yii2", + "description": "FileManager for Yii2", + "keywords": ["yii2", "extension", "file manager", "manager", "upload", "resize", "files"], + "homepage": "https://github.com/rkit/filemanager-yii2", + "type": "yii2-extension", + "version": "5.8.1", + "license": "MIT", + "authors": [ + { + "name": "Igor Romanov", + "email": "rkit.ru@gmail.com" + }, + { + "name": "Sergii Gamaiunov", + "email": "devkadabra@gmail.com" + } + ], + "support": { + "issues": "https://github.com/rkit/filemanager-yii2/issues?state=open", + "source": "https://github.com/rkit/filemanager-yii2" + }, + "require": { + "yiisoft/yii2": "^2.0", + "igogo5yo/yii2-upload-from-url": "^1.4" + }, + "scripts": { + "phpdoc": "phpdoc", + "test-prepare": [ + "php tests/yii migrate --migrationPath=@tests/migrations/ --interactive=0" + ], + "test": "phpunit --colors=always", + "test-coverage": "phpunit --coverage-html=tests/tmp/coverage.html --colors=always", + "test-coverage-open": "open tests/tmp/coverage.html/index.html" + }, + "autoload": { + "psr-4": { + "rkit\\filemanager\\": "src" + } + }, + "require-dev": { + "intervention/image": "^2.3.2", + "phpunit/phpunit": "^4.8", + "phpunit/dbunit": "^1.4", + "phpdocumentor/phpdocumentor": "^2.8.0", + "cvuorinen/phpdoc-markdown-public": "^0.1.2", + "league/flysystem": "^1.0", + "creocoder/yii2-flysystem": "^0.8.1", + "squizlabs/php_codesniffer": "3.0.0RC1" + } +} From 02f33d90efdefe05f62c8cb00e2b36529263e6da Mon Sep 17 00:00:00 2001 From: WEBKADABRA Date: Tue, 16 Mar 2021 00:55:07 +0200 Subject: [PATCH 25/26] Update composer.json --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 5c411e5..1cb9bff 100644 --- a/composer.json +++ b/composer.json @@ -44,8 +44,8 @@ "phpunit/dbunit": "^1.4", "phpdocumentor/phpdocumentor": "^2.8.0", "cvuorinen/phpdoc-markdown-public": "^0.1.2", - "league/flysystem": "^1.0", - "creocoder/yii2-flysystem": "^0.8.1", + "league/flysystem": "*", + "creocoder/yii2-flysystem": "*", "squizlabs/php_codesniffer": "3.0.0RC1" } } From 91f83e57396dc037a3382c20ac7993e6bbe0a53c Mon Sep 17 00:00:00 2001 From: WEBKADABRA Date: Fri, 19 Mar 2021 08:56:49 +0200 Subject: [PATCH 26/26] Update FileBind.php --- src/behaviors/FileBind.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/behaviors/FileBind.php b/src/behaviors/FileBind.php index 0062042..09e77c6 100644 --- a/src/behaviors/FileBind.php +++ b/src/behaviors/FileBind.php @@ -175,7 +175,7 @@ public function delete($model, $attribute, $files) foreach ($presets as $preset) { $thumbPath = $model->thumbPath($attribute, $preset, $file); $filePath = str_replace($storage->path, '', $thumbPath); - if ($storage->has($filePath)) { + if ($storage->fileExists($filePath)) { $storage->delete($filePath); } } @@ -185,7 +185,7 @@ public function delete($model, $attribute, $files) current($relation->link) => $file->getPrimaryKey() ])->execute(); $filePath = $handlerTemplatePath($file); - if ($storage->has($filePath)) { + if ($storage->fileExists($filePath)) { $storage->delete($filePath); } }