Completed
Push — master ( c5eccd...ec8b64 )
by Evgenii
04:45
created

File::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
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 floor12\files\assets\IconHelper;
13
use Yii;
14
use yii\db\ActiveRecord;
15
use yii\helpers\Url;
16
17
18
/**
19
 * @property integer $id
20
 * @property string $class
21
 * @property string $field
22
 * @property integer $object_id
23
 * @property string $title
24
 * @property string $filename
25
 * @property string $content_type
26
 * @property integer $type
27
 * @property integer $video_status
28
 * @property integer $ordering
29
 * @property integer $created
30
 * @property integer $user_id
31
 * @property integer $size
32
 * @property string $hash
33
 * @property string $href
34
 * @property string $icon
35
 * @property string $rootPath
36
 * @property string|null $watermark
37
 */
38
class File extends ActiveRecord
39
{
40
    const DIRECTORY_SEPARATOR = "/";
41
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public static function getDb()
47
    {
48
        return Yii::$app->getModule('files')->db;
49
    }
50
51
    /**
52
     * @inheritdoc
53
     */
54
55
    public static function tableName()
56
    {
57
        return '{{%file}}';
58
    }
59
60
    /**
61
     * Create hash if its empty
62
     * @param bool $insert
63
     * @return bool
64
     */
65
    public function beforeSave($insert)
66
    {
67
        if (!$this->hash) {
68
            $this->changeHash();
69
        }
70
        return parent::beforeSave($insert);
71
    }
72
73
    /**
74
     * Change object hash
75
     */
76
    public function changeHash()
77
    {
78
        $this->hash = md5(time() . rand(99999, 99999999));
79
80
    }
81
82
    /**
83
     * @return string
84
     */
85
    public function getIcon()
86
    {
87
        $icon = IconHelper::FILE;
88
89
        if ($this->content_type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document')
90
            $icon = IconHelper::FILE_WORD;
91
92
        if ($this->content_type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
93
            $icon = IconHelper::FILE_EXCEL;
94
95
        if ($this->content_type == 'application/vnd.openxmlformats-officedocument.presentationml.presentation')
96
            $icon = IconHelper::FILE_POWERPOINT;
97
98
        if ($this->content_type == 'application/x-zip-compressed')
99
            $icon = IconHelper::FILE_ARCHIVE;
100
101
        if ($this->content_type == 'application/octet-stream')
102
            $icon = IconHelper::FILE_ARCHIVE;
103
104
        if (preg_match('/audio/', $this->content_type))
105
            $icon = IconHelper::FILE_AUDIO;
106
107
        if (preg_match('/pdf/', $this->content_type))
108
            $icon = IconHelper::FILE_PDF;
109
110
        if ($this->type == FileType::VIDEO)
111
            $icon = IconHelper::FILE_VIDEO;
112
113
        return $icon;
114
    }
115
116
    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...
117
    {
118
        $idx = explode('.', $filename);
119
        $count_explode = count($idx);
120
        $idx = strtolower($idx[$count_explode - 1]);
121
122
        $mimet = array(
123
            'txt' => 'text/plain',
124
            'htm' => 'text/html',
125
            'html' => 'text/html',
126
            'php' => 'text/html',
127
            'css' => 'text/css',
128
            'js' => 'application/javascript',
129
            'json' => 'application/json',
130
            'xml' => 'application/xml',
131
            'swf' => 'application/x-shockwave-flash',
132
            'flv' => 'video/x-flv',
133
134
            // images
135
            'png' => 'image/png',
136
            'jpe' => 'image/jpeg',
137
            'jpeg' => 'image/jpeg',
138
            'jpg' => 'image/jpeg',
139
            'gif' => 'image/gif',
140
            'bmp' => 'image/bmp',
141
            'ico' => 'image/vnd.microsoft.icon',
142
            'tiff' => 'image/tiff',
143
            'tif' => 'image/tiff',
144
            'svg' => 'image/svg+xml',
145
            'svgz' => 'image/svg+xml',
146
147
            // archives
148
            'zip' => 'application/zip',
149
            'rar' => 'application/x-rar-compressed',
150
            'exe' => 'application/x-msdownload',
151
            'msi' => 'application/x-msdownload',
152
            'cab' => 'application/vnd.ms-cab-compressed',
153
154
            // audio/video
155
            'mp3' => 'audio/mpeg',
156
            'qt' => 'video/quicktime',
157
            'mov' => 'video/quicktime',
158
159
            // adobe
160
            'pdf' => 'application/pdf',
161
            'psd' => 'image/vnd.adobe.photoshop',
162
            'ai' => 'application/postscript',
163
            'eps' => 'application/postscript',
164
            'ps' => 'application/postscript',
165
166
            // ms office
167
            'doc' => 'application/msword',
168
            'rtf' => 'application/rtf',
169
            'xls' => 'application/vnd.ms-excel',
170
            'ppt' => 'application/vnd.ms-powerpoint',
171
            'docx' => 'application/msword',
172
            'xlsx' => 'application/vnd.ms-excel',
173
            'pptx' => 'application/vnd.ms-powerpoint',
174
175
176
            // open office
177
            'odt' => 'application/vnd.oasis.opendocument.text',
178
            'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
179
        );
180
181
        if (isset($mimet[$idx])) {
182
            return $mimet[$idx];
183
        } else {
184
            return 'application/octet-stream';
185
        }
186
    }
187
188
    /**
189
     * @inheritdoc
190
     */
191
192
    public function rules()
193
    {
194
        return [
195
            [['class', 'field', 'filename', 'content_type', 'type'], 'required'],
196
            [['object_id', 'type', 'video_status', 'ordering'], 'integer'],
197
            [['class', 'field', 'title', 'filename', 'content_type'], 'string', 'max' => 255],
198
        ];
199
    }
200
201
    /**
202
     * @inheritdoc
203
     */
204
205
    public function attributeLabels()
206
    {
207
        return [
208
            'id' => Yii::t('app', 'ID'),
209
            'class' => Yii::t('app', 'Class'),
210
            'field' => Yii::t('app', 'Field'),
211
            'object_id' => Yii::t('app', 'Object ID'),
212
            'title' => Yii::t('app', 'Title'),
213
            'filename' => Yii::t('app', 'Filename'),
214
            'content_type' => Yii::t('app', 'Con tent Type'),
215
            'type' => Yii::t('app', 'Type'),
216
            'video_status' => Yii::t('app', 'Video Status'),
217
        ];
218
    }
219
220
    /**
221
     * Return root path of preview
222
     * @return string
223
     */
224
225
    public function getRootPreviewPath()
226
    {
227
        if ($this->isSvg())
228
            return $this->getRootPath();
229
230
        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

230
        return /** @scrutinizer ignore-type */ Yii::$app->getModule('files')->storageFullPath . DIRECTORY_SEPARATOR . $this->filename . '.jpg';
Loading history...
231
    }
232
233
    /**
234
     * @return bool
235
     */
236
    public function isSvg()
237
    {
238
        return $this->content_type == 'image/svg+xml';
239
    }
240
241
    /**
242
     * Return root path of image
243
     * @return string
244
     */
245
246
    public function getRootPath()
247
    {
248
        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

248
        return /** @scrutinizer ignore-type */ Yii::$app->getModule('files')->storageFullPath . DIRECTORY_SEPARATOR . $this->filename;
Loading history...
249
    }
250
251
252
    /**
253
     * Return web path
254
     * @return string
255
     */
256
257
    public function getHref()
258
    {
259
        if (Yii::$app->getModule('files')->hostStatic)
260
            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

260
            return /** @scrutinizer ignore-type */ Yii::$app->getModule('files')->hostStatic . $this->filename;
Loading history...
261
        return Url::to(['/files/default/get', 'hash' => $this->hash]);
262
    }
263
264
    /**
265
     * Delete files from disk
266
     */
267
268
    public function afterDelete()
269
    {
270
        $this->deleteFiles();
271
        parent::afterDelete();
272
    }
273
274
    /**
275
     * Delete all files
276
     */
277
    public function deleteFiles()
278
    {
279
        $extension = pathinfo($this->rootPath, PATHINFO_EXTENSION);
280
        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

280
        array_map('unlink', /** @scrutinizer ignore-type */ glob(str_replace(".{$extension}", '*', $this->rootPath)));
Loading history...
281
    }
282
283
    /**
284
     * Method to read files from any mime types
285
     * @return bool
286
     */
287
288
    public function imageCreateFromAny()
289
    {
290
        $type = exif_imagetype($this->rootPath);
291
        $allowedTypes = array(
292
            1, // [] gif
293
            2, // [] jpg
294
            3, // [] png
295
            6   // [] bmp
296
        );
297
        if (!in_array($type, $allowedTypes)) {
298
            return false;
299
        }
300
        switch ($type) {
301
            case 1 :
302
                $im = imageCreateFromGif($this->rootPath);
303
                break;
304
            case 2 :
305
                $im = imageCreateFromJpeg($this->rootPath);
306
                break;
307
            case 3 :
308
                $im = imageCreateFromPng($this->rootPath);
309
                break;
310
            case 6 :
311
                $im = imageCreateFromBmp($this->rootPath);
312
                break;
313
        }
314
        return $im;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $im does not seem to be defined for all execution paths leading up to this point.
Loading history...
315
    }
316
317
    /**
318
     * Set object_id to 0 to break link with object
319
     * @return void
320
     */
321
    public function setZeroObject()
322
    {
323
        $this->object_id = 0;
324
        $this->save(false);
325
    }
326
327
    /**
328
     * @return mixed|null
329
     */
330
    public function getWatermark()
331
    {
332
        if (
333
            isset($this->behaviors['files']) &&
334
            isset($this->behaviors['files']->attributes[$this->field]) &&
335
            isset($this->behaviors['files']->attributes[$this->field]['watermark'])
336
        )
337
            $this->behaviors['files']->attributes[$this->field]['watermark'];
338
    }
339
340
    /**
341
     * @return string
342
     */
343
    public function __toString()
344
    {
345
        return $this->href;
346
    }
347
348
    /**
349
     * Return webp path to preview
350
     * @param int $width
351
     * @param int $height
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, $height, $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, $height, $webp = false);
Loading history...
Comprehensibility Best Practice introduced by
The variable $height seems to be never defined.
Loading history...
Unused Code introduced by
The call to floor12\files\models\File::makeNameWithSize() has too many arguments starting with $webp = false. ( Ignorable by Annotation )

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

365
            return Yii::$app->getModule('files')->hostStatic . $this->/** @scrutinizer ignore-call */ makeNameWithSize($this->filename, $width, $height, $webp = false);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
366
367
        return Url::toRoute(['/files/default/image', 'hash' => $this->hash, 'width' => $width, 'height' => $height, '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