Completed
Push — master ( 0929bc...18a624 )
by Igor
01:49
created

FileBehavior::binding()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 18
ccs 14
cts 14
cp 1
rs 8.2222
cc 7
eloc 11
nc 7
nop 6
crap 7
1
<?php
2
3
/**
4
 * @link https://github.com/rkit/filemanager-yii2
5
 * @copyright Copyright (c) 2015 Igor Romanov
6
 * @license [MIT](http://opensource.org/licenses/MIT)
7
 */
8
9
namespace rkit\filemanager\behaviors;
10
11
use Yii;
12
use yii\base\Behavior;
13
use yii\db\ActiveRecord;
14
use yii\helpers\ArrayHelper;
15
use yii\base\InvalidParamException;
16
use rkit\filemanager\models\File;
17
use rkit\filemanager\helpers\FileRules;
18
use rkit\filemanager\behaviors\FileBind;
19
20
class FileBehavior extends Behavior
21
{
22
    /**
23
     * @var array
24
     */
25
    public $attributes = [];
26
    /**
27
     * @var rkit\filemanager\behaviors\FileBind
28
     */
29
    private static $bind;
30
31 42
    public function init()
32
    {
33 42
        parent::init();
34
35 42
        $this->setBind();
36 42
        Yii::$app->fileManager->registerTranslations();
37 42
    }
38
39
    /**
40
     * Set Decoder
41
     *
42
     * @return void
43
     */
44 42
    public function setBind()
45
    {
46 42
        $this->bind = new FileBind();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \rkit\filemanager\behaviors\FileBind() of type object<rkit\filemanager\behaviors\FileBind> is incompatible with the declared type object<rkit\filemanager\...ger\behaviors\FileBind> of property $bind.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
47 42
    }
48
49
    /**
50
     * @inheritdoc
51
     */
52 42
    public function events()
53
    {
54
        return [
55 42
            ActiveRecord::EVENT_AFTER_INSERT  => 'afterSave',
56 42
            ActiveRecord::EVENT_AFTER_UPDATE  => 'afterSave',
57 42
            ActiveRecord::EVENT_BEFORE_INSERT => 'beforeSave',
58 42
            ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeSave',
59 42
            ActiveRecord::EVENT_BEFORE_DELETE => 'beforeDelete',
60 42
        ];
61
    }
62
63 27
    public function beforeSave($insert)
64
    {
65 27
        foreach ($this->attributes as $attribute => $data) {
66 27
            $oldValue = $this->owner->isNewRecord ? null : $this->owner->getOldAttribute($attribute);
67 27
            $isAttributeChanged = $oldValue === null ? true : $this->owner->isAttributeChanged($attribute);
68
69 27
            $this->attributes[$attribute]['isAttributeChanged'] = $isAttributeChanged;
70 27
            $this->attributes[$attribute]['oldValue'] = $oldValue;
71 27
        }
72 27
    }
73
74 42
    public function afterSave()
75
    {
76 27
        foreach ($this->attributes as $attribute => $data) {
77 27
            $fileId = $this->owner->{$attribute};
78
79 27
            if ($data['isAttributeChanged'] === false || $fileId === null) {
80 27
                continue;
81
            }
82
83 27
            $storage = $this->getFileStorage($attribute);
84 27
            $ownerId = $this->owner->primaryKey;
85 27
            $ownerType = $this->getFileOwnerType($attribute);
86
87 27
            if ($fileId === [] || $fileId === '') {
88 3
                (new File())->deleteByOwner($storage, $ownerId, $ownerType);
89 3
                continue;
90
            }
91
92 27
            $this->binding($data, $attribute, $storage, $ownerId, $ownerType, $fileId);
93 27
        }
94 42
    }
95
96 1
    public function beforeDelete()
97
    {
98 1
        foreach ($this->attributes as $attribute => $data) {
99 1
            $ownerType = $this->getFileOwnerType($attribute);
100 1
            $storage = $this->getFileStorage($attribute);
101 1
            (new File())->deleteByOwner($storage, $this->owner->primaryKey, $ownerType);
102 1
        }
103 1
    }
104
105 27
    private function binding($data, $attribute, $storage, $ownerId, $ownerType, $fileId)
106
    {
107 27
        if ($this->isMultiple($attribute)) {
108 9
            $this->bind->bindMultiple($storage, $ownerId, $ownerType, $fileId);
109 9
        } else {
110 18
            $file = $this->bind->bindSingle($storage, $ownerId, $ownerType, $fileId);
111
112 18
            if (isset($data['saveFilePath']) && $data['saveFilePath'] === true) {
113 13
                $value = $this->prepareFilePath($file, $data['oldValue']);
114 18
            } elseif (isset($data['saveFileId']) && $data['saveFileId'] === true) {
115 5
                $value = $this->prepareFileId($file, $data['oldValue']);
116 5
            }
117
118 18
            if (isset($value)) {
119 18
                $this->owner->updateAttributes([$attribute => $value]);
120 18
            }
121
        }
122 27
    }
123
124
    /**
125
     * Prepare the path of the file
126
     *
127
     * @param mixed $file
128
     * @param mixed $oldValue
129
     * @return string
130
     */
131 13
    private function prepareFilePath($file, $oldValue)
132
    {
133 13
        if (is_object($file)) {
134 12
            return $file->getStorage()->path();
135 3
        } elseif ($file === false && $oldValue !== null) {
136 2
            return $oldValue;
137
        }
138
139 1
        return '';
140
    }
141
142
    /**
143
     * Prepare the id of the file
144
     *
145
     * @param mixed $file
146
     * @param mixed $oldValue
147
     * @return int
148
     */
149 5
    private function prepareFileId($file, $oldValue)
150
    {
151 5
        if (is_object($file)) {
152 5
            return $file->id;
153 1
        } elseif ($file === false && $oldValue !== null) {
154 1
            return $oldValue;
155
        }
156
157 1
        return 0;
158
    }
159
160
    /**
161
     * Get the path to the upload directory
162
     *
163
     * @param string $attribute
164
     * @return string
165
     */
166 31
    public function uploadDir($attribute)
167
    {
168 31
        if ($this->isFileProtected($attribute)) {
169 5
            return Yii::getAlias(Yii::$app->fileManager->uploadDirProtected);
170
        } else {
171 26
            return Yii::getAlias(Yii::$app->fileManager->uploadDirUnprotected);
172
        }
173
    }
174
175
    /**
176
     * Get the type of the owner in as string
177
     *
178
     * @param string $attribute
179
     * @return string
180
     */
181 31
    private function getStringOwnerType($attribute)
182
    {
183 31
        return $this->owner->tableName() . '.' . $attribute;
184
    }
185
186
    /**
187
     * Get the type of the owner
188
     *
189
     * @param string $attribute
190
     * @return int
191
     */
192 31
    public function getFileOwnerType($attribute)
193
    {
194 31
        return Yii::$app->fileManager->getOwnerType($this->getStringOwnerType($attribute));
195
    }
196
197
    /**
198
     * Get files
199
     *
200
     * @param string $attribute
201
     * @return array
202
     */
203 9
    public function getFiles($attribute)
204
    {
205 9
        $files = File::findAllByOwner($this->owner->primaryKey, $this->getFileOwnerType($attribute));
206 9
        foreach ($files as $file) {
207 9
            $file->setStorage($this->getFileStorage($attribute));
208 9
        }
209
210 9
        return $files;
211
    }
212
213
    /**
214
     * Get the file
215
     *
216
     * @param string $attribute
217
     * @return File|null
218
     */
219 1
    public function getFile($attribute)
220
    {
221 1
        $file = File::findOneByOwner($this->owner->primaryKey, $this->getFileOwnerType($attribute));
222 1
        $file->setStorage($this->getFileStorage($attribute));
223 1
        return $file;
224
    }
225
226
    /**
227
     * Multiple files
228
     *
229
     * @param string $attribute
230
     * @return bool
231
     */
232 27
    public function isMultiple($attribute)
233
    {
234 27
        return ArrayHelper::getValue($this->attributes[$attribute], 'multiple', false);
235
    }
236
237
    /**
238
     * The file is protected
239
     *
240
     * @param string $attribute
241
     * @return bool
242
     */
243 31
    public function isFileProtected($attribute)
244
    {
245 31
        return ArrayHelper::getValue($this->attributes[$attribute], 'protected', false);
246
    }
247
248
    /**
249
     * Get rules
250
     *
251
     * @param string $attribute
252
     * @return array
253
     */
254 33
    public function getFileRules($attribute)
255
    {
256 33
        return ArrayHelper::getValue($this->attributes[$attribute], 'rules', []);
257
    }
258
259
    /**
260
     * Get the presets of the file
261
     *
262
     * @param string $attribute
263
     * @return array
264
     */
265 5
    public function getFilePreset($attribute)
266
    {
267 5
        return array_keys(ArrayHelper::getValue($this->attributes[$attribute], 'preset', []));
268
    }
269
270
    /**
271
     * Get the presets of the file for apply after upload
272
     *
273
     * @param string $attribute
274
     * @return array
275
     */
276 31
    public function getFilePresetAfterUpload($attribute)
277
    {
278 31
        $preset = ArrayHelper::getValue($this->attributes[$attribute], 'applyPresetAfterUpload', false);
279 31
        if (is_string($preset) && $preset === '*') {
280 5
            return $this->getFilePreset($attribute);
281 26
        } elseif (is_array($preset)) {
282 17
            return $preset;
283
        }
284
285 9
        return [];
286
    }
287
288
    /**
289
     * Get the storage of the file
290
     *
291
     * @param string $attribute
292
     * @return Storage
293
     */
294 31
    public function getFileStorage($attribute)
295
    {
296 31
        $storage = ArrayHelper::getValue($this->attributes[$attribute], 'storage', null);
297 31
        if ($storage) {
298 31
            return new $storage();
299
        }
300
301
        throw new InvalidParamException('The storage is not defined'); // @codeCoverageIgnore
302
    }
303
304
    /**
305
     * Generate a thumb name
306
     *
307
     * @param string $path
308
     * @param string $prefix
309
     * @return string
310
     */
311 31
    public function generateThumbName($path, $prefix)
312
    {
313 31
        $fileName = pathinfo($path, PATHINFO_FILENAME);
314 31
        return str_replace($fileName, $prefix . '_' . $fileName, $path);
315
    }
316
317
    /**
318
     * Resize image
319
     *
320
     * @param string $attribute
321
     * @param string $preset
322
     * @param string $pathToFile Use this path to the file
323
     * @param bool $returnRealPath Return the real path to the file
324
     * @return string
325
     */
326 31
    public function thumb($attribute, $preset, $pathToFile = null, $returnRealPath = false)
327
    {
328 31
        $realPath = $this->uploadDir($attribute);
329 31
        $publicPath = $pathToFile ? $pathToFile : $this->owner->$attribute;
330 31
        $thumbPath = $this->generateThumbName($publicPath, $preset);
331
332 31
        if (!file_exists($realPath . $thumbPath)) {
333 31
            if (file_exists($realPath . $publicPath)) {
334 30
                $thumbInit = ArrayHelper::getValue($this->attributes[$attribute]['preset'], $preset);
335 30
                if ($thumbInit) {
336 30
                    $thumbInit($realPath, $publicPath, $thumbPath);
337 30
                }
338 30
            }
339 31
        }
340
341 31
        return $returnRealPath ? $realPath . $thumbPath : $thumbPath;
342
    }
343
344
    /**
345
     * Get description the rules of the file in as text
346
     *
347
     * @param string $attribute
348
     * @return string
349
     */
350 9
    public function getFileRulesDescription($attribute)
351
    {
352 9
        return FileRules::getDescription($this->attributes[$attribute]['rules']);
353
    }
354
}
355