Completed
Push — master ( ec8b64...2e7118 )
by Evgenii
03:09
created

File::beforeSave()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
dl 0
loc 6
rs 10
c 1
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: floor12
5
 * Date: 23.06.2016
6
 * Time: 11:23
7
 */
8
9
namespace floor12\files\models;
10
11
12
use ErrorException;
13
use floor12\files\assets\IconHelper;
14
use Yii;
15
use yii\db\ActiveRecord;
16
use yii\helpers\Url;
17
18
19
/**
20
 * @property integer $id
21
 * @property string $class
22
 * @property string $field
23
 * @property integer $object_id
24
 * @property string $title
25
 * @property string $filename
26
 * @property string $content_type
27
 * @property integer $type
28
 * @property integer $video_status
29
 * @property integer $ordering
30
 * @property integer $created
31
 * @property integer $user_id
32
 * @property integer $size
33
 * @property string $hash
34
 * @property string $href
35
 * @property string $icon
36
 * @property string $rootPath
37
 * @property string|null $watermark
38
 */
39
class File extends ActiveRecord
40
{
41
    const DIRECTORY_SEPARATOR = "/";
42
43
44
    /**
45
     * {@inheritdoc}
46
     */
47
    public static function getDb()
48
    {
49
        return Yii::$app->getModule('files')->db;
50
    }
51
52
    /**
53
     * @inheritdoc
54
     */
55
56
    public static function tableName()
57
    {
58
        return '{{%file}}';
59
    }
60
61
    /**
62
     * Create hash if its empty
63
     * @param bool $insert
64
     * @return bool
65
     */
66
    public function beforeSave($insert)
67
    {
68
        if (!$this->hash) {
69
            $this->changeHash();
70
        }
71
        return parent::beforeSave($insert);
72
    }
73
74
    /**
75
     * Change object hash
76
     */
77
    public function changeHash()
78
    {
79
        $this->hash = md5(time() . rand(99999, 99999999));
80
81
    }
82
83
    /**
84
     * @return string
85
     */
86
    public function getIcon()
87
    {
88
        $icon = IconHelper::FILE;
89
90
        if ($this->content_type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document')
91
            $icon = IconHelper::FILE_WORD;
92
93
        if ($this->content_type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
94
            $icon = IconHelper::FILE_EXCEL;
95
96
        if ($this->content_type == 'application/vnd.openxmlformats-officedocument.presentationml.presentation')
97
            $icon = IconHelper::FILE_POWERPOINT;
98
99
        if ($this->content_type == 'application/x-zip-compressed')
100
            $icon = IconHelper::FILE_ARCHIVE;
101
102
        if ($this->content_type == 'application/octet-stream')
103
            $icon = IconHelper::FILE_ARCHIVE;
104
105
        if (preg_match('/audio/', $this->content_type))
106
            $icon = IconHelper::FILE_AUDIO;
107
108
        if (preg_match('/pdf/', $this->content_type))
109
            $icon = IconHelper::FILE_PDF;
110
111
        if ($this->type == FileType::VIDEO)
112
            $icon = IconHelper::FILE_VIDEO;
113
114
        return $icon;
115
    }
116
117
    function mime_content_type($filename)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
118
    {
119
        $idx = explode('.', $filename);
120
        $count_explode = count($idx);
121
        $idx = strtolower($idx[$count_explode - 1]);
122
123
        $mimet = array(
124
            'txt' => 'text/plain',
125
            'htm' => 'text/html',
126
            'html' => 'text/html',
127
            'php' => 'text/html',
128
            'css' => 'text/css',
129
            'js' => 'application/javascript',
130
            'json' => 'application/json',
131
            'xml' => 'application/xml',
132
            'swf' => 'application/x-shockwave-flash',
133
            'flv' => 'video/x-flv',
134
135
            // images
136
            'png' => 'image/png',
137
            'jpe' => 'image/jpeg',
138
            'jpeg' => 'image/jpeg',
139
            'jpg' => 'image/jpeg',
140
            'gif' => 'image/gif',
141
            'bmp' => 'image/bmp',
142
            'ico' => 'image/vnd.microsoft.icon',
143
            'tiff' => 'image/tiff',
144
            'tif' => 'image/tiff',
145
            'svg' => 'image/svg+xml',
146
            'svgz' => 'image/svg+xml',
147
148
            // archives
149
            'zip' => 'application/zip',
150
            'rar' => 'application/x-rar-compressed',
151
            'exe' => 'application/x-msdownload',
152
            'msi' => 'application/x-msdownload',
153
            'cab' => 'application/vnd.ms-cab-compressed',
154
155
            // audio/video
156
            'mp3' => 'audio/mpeg',
157
            'qt' => 'video/quicktime',
158
            'mov' => 'video/quicktime',
159
160
            // adobe
161
            'pdf' => 'application/pdf',
162
            'psd' => 'image/vnd.adobe.photoshop',
163
            'ai' => 'application/postscript',
164
            'eps' => 'application/postscript',
165
            'ps' => 'application/postscript',
166
167
            // ms office
168
            'doc' => 'application/msword',
169
            'rtf' => 'application/rtf',
170
            'xls' => 'application/vnd.ms-excel',
171
            'ppt' => 'application/vnd.ms-powerpoint',
172
            'docx' => 'application/msword',
173
            'xlsx' => 'application/vnd.ms-excel',
174
            'pptx' => 'application/vnd.ms-powerpoint',
175
176
177
            // open office
178
            'odt' => 'application/vnd.oasis.opendocument.text',
179
            'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
180
        );
181
182
        if (isset($mimet[$idx])) {
183
            return $mimet[$idx];
184
        } else {
185
            return 'application/octet-stream';
186
        }
187
    }
188
189
    /**
190
     * @inheritdoc
191
     */
192
193
    public function rules()
194
    {
195
        return [
196
            [['class', 'field', 'filename', 'content_type', 'type'], 'required'],
197
            [['object_id', 'type', 'video_status', 'ordering'], 'integer'],
198
            [['class', 'field', 'title', 'filename', 'content_type'], 'string', 'max' => 255],
199
        ];
200
    }
201
202
    /**
203
     * @inheritdoc
204
     */
205
206
    public function attributeLabels()
207
    {
208
        return [
209
            'id' => Yii::t('app', 'ID'),
210
            'class' => Yii::t('app', 'Class'),
211
            'field' => Yii::t('app', 'Field'),
212
            'object_id' => Yii::t('app', 'Object ID'),
213
            'title' => Yii::t('app', 'Title'),
214
            'filename' => Yii::t('app', 'Filename'),
215
            'content_type' => Yii::t('app', 'Con tent Type'),
216
            'type' => Yii::t('app', 'Type'),
217
            'video_status' => Yii::t('app', 'Video Status'),
218
        ];
219
    }
220
221
    /**
222
     * Return root path of preview
223
     * @return string
224
     */
225
226
    public function getRootPreviewPath()
227
    {
228
        if ($this->isSvg())
229
            return $this->getRootPath();
230
231
        return Yii::$app->getModule('files')->storageFullPath . DIRECTORY_SEPARATOR . $this->filename . '.jpg';
0 ignored issues
show
Bug introduced by
Are you sure Yii::app->getModule('files')->storageFullPath of type mixed|null|object can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

231
        return /** @scrutinizer ignore-type */ Yii::$app->getModule('files')->storageFullPath . DIRECTORY_SEPARATOR . $this->filename . '.jpg';
Loading history...
232
    }
233
234
    /**
235
     * @return bool
236
     */
237
    public function isSvg()
238
    {
239
        return $this->content_type == 'image/svg+xml';
240
    }
241
242
    /**
243
     * Return root path of image
244
     * @return string
245
     */
246
247
    public function getRootPath()
248
    {
249
        return Yii::$app->getModule('files')->storageFullPath . DIRECTORY_SEPARATOR . $this->filename;
0 ignored issues
show
Bug introduced by
Are you sure Yii::app->getModule('files')->storageFullPath of type mixed|null|object can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

249
        return /** @scrutinizer ignore-type */ Yii::$app->getModule('files')->storageFullPath . DIRECTORY_SEPARATOR . $this->filename;
Loading history...
250
    }
251
252
253
    /**
254
     * Return web path
255
     * @return string
256
     */
257
258
    public function getHref()
259
    {
260
        if (Yii::$app->getModule('files')->hostStatic)
261
            return Yii::$app->getModule('files')->hostStatic . $this->filename;
0 ignored issues
show
Bug introduced by
Are you sure Yii::app->getModule('files')->hostStatic of type mixed|null|object can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

261
            return /** @scrutinizer ignore-type */ Yii::$app->getModule('files')->hostStatic . $this->filename;
Loading history...
262
        return Url::to(['/files/default/get', 'hash' => $this->hash]);
263
    }
264
265
    /**
266
     * Delete files from disk
267
     */
268
269
    public function afterDelete()
270
    {
271
        $this->deleteFiles();
272
        parent::afterDelete();
273
    }
274
275
    /**
276
     * Delete all files
277
     */
278
    public function deleteFiles()
279
    {
280
        $extension = pathinfo($this->rootPath, PATHINFO_EXTENSION);
281
        array_map('unlink', glob(str_replace(".{$extension}", '*', $this->rootPath)));
0 ignored issues
show
Bug introduced by
It seems like glob(str_replace('.'.$ex... '*', $this->rootPath)) can also be of type false; however, parameter $arr1 of array_map() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

281
        array_map('unlink', /** @scrutinizer ignore-type */ glob(str_replace(".{$extension}", '*', $this->rootPath)));
Loading history...
282
    }
283
284
    /**
285
     * Method to read files from any mime types
286
     * @return bool
287
     */
288
289
//    public function imageCreateFromAny()
290
//    {
291
//        $type = exif_imagetype($this->rootPath);
292
//        $allowedTypes = array(
293
//            1, // [] gif
294
//            2, // [] jpg
295
//            3, // [] png
296
//            6   // [] bmp
297
//        );
298
//        if (!in_array($type, $allowedTypes)) {
299
//            return false;
300
//        }
301
//        switch ($type) {
302
//            case 1 :
303
//                $im = imageCreateFromGif($this->rootPath);
304
//                break;
305
//            case 2 :
306
//                $im = imageCreateFromJpeg($this->rootPath);
307
//                break;
308
//            case 3 :
309
//                $im = imageCreateFromPng($this->rootPath);
310
//                break;
311
//            case 6 :
312
//                $im = imageCreateFromBmp($this->rootPath);
313
//                break;
314
//        }
315
//        return $im;
316
//    }
317
318
    /**
319
     * Set object_id to 0 to break link with object
320
     * @return void
321
     */
322
    public function setZeroObject()
323
    {
324
        $this->object_id = 0;
325
        $this->save(false);
326
    }
327
328
    /**
329
     * @return mixed|null
330
     */
331
    public function getWatermark()
332
    {
333
        if (
334
            isset($this->behaviors['files']) &&
335
            isset($this->behaviors['files']->attributes[$this->field]) &&
336
            isset($this->behaviors['files']->attributes[$this->field]['watermark'])
337
        )
338
            return $this->behaviors['files']->attributes[$this->field]['watermark'];
339
    }
340
341
    /**
342
     * @return string
343
     */
344
    public function __toString()
345
    {
346
        return $this->href;
347
    }
348
349
    /**
350
     * Return webp path to preview
351
     * @param int $width
352
     * @param bool $webp
353
     * @return string
354
     * @throws ErrorException
355
     */
356
    public function getPreviewWebPath(int $width = 0, bool $webp = false)
357
    {
358
        if (!file_exists($this->getRootPath()))
359
            return null;
360
361
        if (!$this->isVideo() && !$this->isImage())
362
            throw new ErrorException('Requiested file is not an image and its implsible to resize it.');
363
364
        if (Yii::$app->getModule('files')->hostStatic)
365
            return Yii::$app->getModule('files')->hostStatic . $this->makeNameWithSize($this->filename, $width, $webp = false);
0 ignored issues
show
Bug introduced by
Are you sure Yii::app->getModule('files')->hostStatic of type mixed|null|object can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

365
            return /** @scrutinizer ignore-type */ Yii::$app->getModule('files')->hostStatic . $this->makeNameWithSize($this->filename, $width, $webp = false);
Loading history...
366
367
        return Url::toRoute(['/files/default/image', 'hash' => $this->hash, 'width' => $width, 'webp' => $webp]);
368
    }
369
370
    /**
371
     * @return bool
372
     */
373
    public function isVideo(): bool
374
    {
375
        return $this->type == FileType::VIDEO;
376
    }
377
378
    /**
379
     * @return bool
380
     */
381
    public function isImage(): bool
382
    {
383
        return $this->type == FileType::IMAGE;
384
    }
385
386
    /**
387
     * Creates file paths to file versions
388
     * @param $name
389
     * @param int $width
390
     * @param bool $webp
391
     * @return string
392
     */
393
    public function makeNameWithSize($name, $width = 0, $webp = false)
394
    {
395
        $extension = pathinfo($this->rootPath, PATHINFO_EXTENSION);
396
        $rootPath = str_replace(".{$extension}", '', $name) . "_w" . $width . ".{$extension}";
397
        return str_replace($extension, $webp ? 'webp' : 'jpeg', $rootPath);
398
    }
399
400
    /**
401
     * Returns full path to custom preview version
402
     * @param int $width
403
     * @param bool $webp
404
     * @return string
405
     * @throws ErrorException
406
     */
407
    public function getPreviewRootPath($width = 0, $webp = false)
408
    {
409
        if (!$this->isVideo() && !$this->isImage())
410
            throw new ErrorException('Requiested file is not an image and its implsible to resize it.');
411
        return $this->makeNameWithSize($this->rootPath, $width, $webp);
412
    }
413
414
    /**
415
     * @return bool
416
     */
417
    public function isFile(): bool
418
    {
419
        return $this->type == FileType::FILE;
420
    }
421
422
}
423