Issues (46)

src/models/Mediafile.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace Itstructure\MFUploader\models;
4
5
use yii\helpers\ArrayHelper;
6
use yii\base\InvalidConfigException;
7
use Itstructure\MFUploader\Module;
8
use Itstructure\MFUploader\helpers\Html;
9
use Itstructure\MFUploader\interfaces\UploadModelInterface;
10
11
/**
12
 * This is the model class for table "mediafiles".
13
 *
14
 * @property int $id
15
 * @property string $filename
16
 * @property string $type
17
 * @property string $url
18
 * @property string $alt
19
 * @property int $size
20
 * @property string $title
21
 * @property string $description
22
 * @property string $thumbs
23
 * @property string $storage
24
 * @property int $created_at
25
 * @property int $updated_at
26
 * @property Module $_module
27
 *
28
 * @package Itstructure\MFUploader\models
29
 *
30
 * @author Andrey Girnik <[email protected]>
31
 */
32
class Mediafile extends ActiveRecord
33
{
34
    /**
35
     * @var Module
36
     */
37
    private $_module;
38
39
    /**
40
     * {@inheritdoc}
41
     */
42
    public static function tableName()
43
    {
44
        return 'mediafiles';
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50
    public function rules()
51
    {
52
        return [
53
            [
54
                [
55
                    'filename',
56
                    'type',
57
                    'url',
58
                    'size',
59
                    'storage',
60
                ],
61
                'required',
62
            ],
63
            [
64
                [
65
                    'url',
66
                    'description',
67
                    'thumbs',
68
                ],
69
                'string',
70
            ],
71
            [
72
                [
73
                    'storage',
74
                ],
75
                'string',
76
                'max' => 12,
77
            ],
78
            [
79
                [
80
                    'type',
81
                ],
82
                'string',
83
                'max' => 64,
84
            ],
85
            [
86
                [
87
                    'filename',
88
                    'alt',
89
                    'title',
90
                ],
91
                'string',
92
                'max' => 128,
93
            ],
94
            [
95
                [
96
                    'size',
97
                ],
98
                'integer',
99
            ],
100
            [
101
                [
102
                    'created_at',
103
                    'updated_at',
104
                ],
105
                'safe',
106
            ],
107
        ];
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113
    public function attributeLabels()
114
    {
115
        return [
116
            'id' => 'ID',
117
            'filename' => 'Filename',
118
            'type' => 'Type',
119
            'url' => 'Url',
120
            'alt' => 'Alt',
121
            'size' => 'Size',
122
            'title' => 'Title',
123
            'description' => 'Description',
124
            'thumbs' => 'Thumbs',
125
            'storage' => 'Storage',
126
            'created_at' => 'Created At',
127
            'updated_at' => 'Updated At',
128
        ];
129
    }
130
131
    /**
132
     * @return Module
133
     */
134
    public function getModule(): Module
135
    {
136
137
        if ($this->_module === null) {
138
            $this->_module = \Yii::$app->getModule(Module::MODULE_NAME);
139
140
            if (empty($this->_module)) {
141
                $this->_module = Module::getInstance();
0 ignored issues
show
The method getInstance() does not exist on Itstructure\MFUploader\Module. ( Ignorable by Annotation )

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

141
                /** @scrutinizer ignore-call */ 
142
                $this->_module = Module::getInstance();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
142
            }
143
        }
144
145
        return $this->_module;
146
    }
147
148
    /**
149
     * Find model by url.
150
     *
151
     * @param string $url
152
     *
153
     * @return mixed
154
     */
155
    public static function findByUrl(string $url)
156
    {
157
        return self::findOne(['url' => $url]);
158
    }
159
160
    /**
161
     * Search models by file types.
162
     *
163
     * @param array $types
164
     *
165
     * @return array
166
     */
167
    public static function findByTypes(array $types): array
168
    {
169
        return self::find()->filterWhere(['in', 'type', $types])->all();
170
    }
171
172
    /**
173
     * Add owner to mediafiles table.
174
     *
175
     * @param int    $ownerId
176
     * @param string $owner
177
     * @param string $ownerAttribute
178
     *
179
     * @return bool
180
     */
181
    public function addOwner(int $ownerId, string $owner, string $ownerAttribute): bool
182
    {
183
        return OwnerMediafile::addOwner($this->id, $ownerId, $owner, $ownerAttribute);
184
    }
185
186
    /**
187
     * @return \yii\db\ActiveQuery
188
     */
189
    public function getOwners()
190
    {
191
        return $this->hasMany(OwnerMediafile::class, ['mediafileId' => 'id']);
192
    }
193
194
    /**
195
     * Get preview html.
196
     *
197
     * @param string $baseUrl Url to asset files which is formed on the BaseAsset.
198
     * @param string $location Where is this function calling:
199
     *      existing - if view template renders files, which are exist;
200
     *      fileinfo - for "fileinfo/index" view template of "filemanager";
201
     *      fileitem - for "_fileItem" view template of "filemanager".
202
     * You can set new location attributes by custom in Module "previewOptions"
203
     * before using in this getPreview() function inside the view template.
204
     * It is necessary to set location attributes for certain types of mediafiles.
205
     * See how it's done in "preview-options" config file as an example.
206
     * @param array $options Options for the next tags, which must be the keys of the options array:
207
     *      1. Main tag:
208
     *      mainTag - main preview html tag. Can contain different html tag options.
209
     *                And also can contain "alias" from the number of module constant aliases:
210
     *                default, original, small, medium, large.
211
     *      2. Addition tags:
212
     *      leftTag - tag that is located to the left of the "mainTag";
213
     *      rightTag - tag that is located to the right of the "mainTag";
214
     *      externalTag - tag in which the mainTag with leftTag and rightTag are embedded.
215
     * Importantly! Addition tag keys must contain the next attributes:
216
     * name - the name of addition tag.
217
     * options - html options of addition tag.
218
     * By default, the mainTag is already in the "preview-options" configuration file.
219
     * You can insert configurations values of addition tags through the third parameter of this function.
220
     *
221
     * @return string
222
     */
223
    public function getPreview(string $baseUrl = '', string $location = null, array $options = []): string
224
    {
225
        $module = $this->getModule();
226
227
        if ($this->isImage()) {
228
            $options = $this->getOptions($options, $location, $module, UploadModelInterface::FILE_TYPE_IMAGE);
229
            $preview = $this->getImagePreview(isset($options['mainTag']) ? $options['mainTag'] : []);
230
231
        } elseif ($this->isAudio()) {
232
            $options = $this->getOptions($options, $location, $module, UploadModelInterface::FILE_TYPE_AUDIO);
233
            $preview = $this->getAudioPreview(isset($options['mainTag']) ? $options['mainTag'] : []);
234
235
        } elseif ($this->isVideo()) {
236
            $options = $this->getOptions($options, $location, $module, UploadModelInterface::FILE_TYPE_VIDEO);
237
            $preview = $this->getVideoPreview(isset($options['mainTag']) ? $options['mainTag'] : []);
238
239
        } elseif ($this->isApp()) {
240
            $options = $this->getOptions($options, $location, $module, UploadModelInterface::FILE_TYPE_APP);
241
            $preview = $this->getAppPreview($baseUrl, isset($options['mainTag']) ? $options['mainTag'] : []);
242
243
        } elseif ($this->isText()) {
244
            $options = $this->getOptions($options, $location, $module, UploadModelInterface::FILE_TYPE_TEXT);
245
            $preview = $this->getTextPreview($baseUrl, isset($options['mainTag']) ? $options['mainTag'] : []);
246
247
        } else {
248
            $options = $this->getOptions($options, $location, $module, UploadModelInterface::FILE_TYPE_OTHER);
249
            $preview = $this->getOtherPreview($baseUrl, isset($options['mainTag']) ? $options['mainTag'] : []);
250
        }
251
252
        if (isset($options['leftTag']) && is_array($options['leftTag'])) {
253
            $preview = $this->compactPreviewAdditionTags($preview, 'leftTag', $options['leftTag']);
254
        }
255
256
        if (isset($options['rightTag']) && is_array($options['rightTag'])) {
257
            $preview = $this->compactPreviewAdditionTags($preview, 'rightTag', $options['rightTag']);
258
        }
259
260
        if (isset($options['externalTag']) && is_array($options['externalTag'])) {
261
            $preview = $this->compactPreviewAdditionTags($preview, 'externalTag', $options['externalTag']);
262
        }
263
264
        return $preview;
265
    }
266
267
    /**
268
     * Get image preview.
269
     *
270
     * @param array $mainTagOptions
271
     *
272
     * @return string
273
     */
274
    public function getImagePreview(array $mainTagOptions): string
275
    {
276
        if (!isset($mainTagOptions['alt'])) {
277
            $mainTagOptions['alt'] = $this->alt;
278
        }
279
280
        if (isset($mainTagOptions['alias']) && is_string($mainTagOptions['alias'])) {
281
            return Html::img($this->getThumbUrl($mainTagOptions['alias']), $mainTagOptions);
282
        }
283
284
        return Html::img($this->getThumbUrl(Module::THUMB_ALIAS_DEFAULT), $mainTagOptions);
285
    }
286
287
    /**
288
     * Get audio preview.
289
     *
290
     * @param array $mainTagOptions
291
     *
292
     * @return string
293
     */
294
    public function getAudioPreview(array $mainTagOptions): string
295
    {
296
        return Html::audio($this->getViewUrl(), ArrayHelper::merge([
297
                'source' => [
298
                    'type' => $this->type
299
                ]
300
            ], $mainTagOptions)
301
        );
302
    }
303
304
    /**
305
     * Get video preview.
306
     *
307
     * @param array $mainTagOptions
308
     *
309
     * @return string
310
     */
311
    public function getVideoPreview(array $mainTagOptions): string
312
    {
313
        return Html::video($this->getViewUrl(), ArrayHelper::merge([
314
                'source' => [
315
                    'type' => $this->type
316
                ]
317
            ], $mainTagOptions)
318
        );
319
    }
320
321
    /**
322
     * Get application preview.
323
     *
324
     * @param string $baseUrl
325
     * @param array $mainTagOptions
326
     *
327
     * @return string
328
     */
329
    public function getAppPreview(string $baseUrl = '', array $mainTagOptions): string
330
    {
331
        return Html::img($this->getAppPreviewUrl($baseUrl), $mainTagOptions);
332
    }
333
334
    /**
335
     * Get text preview.
336
     *
337
     * @param string $baseUrl
338
     * @param array $mainTagOptions
339
     *
340
     * @return string
341
     */
342
    public function getTextPreview(string $baseUrl = '', array $mainTagOptions): string
343
    {
344
        return Html::img($this->getTextPreviewUrl($baseUrl), $mainTagOptions);
345
    }
346
347
    /**
348
     * Get other preview.
349
     *
350
     * @param string $baseUrl
351
     * @param array $mainTagOptions
352
     *
353
     * @return string
354
     */
355
    public function getOtherPreview(string $baseUrl = '', array $mainTagOptions): string
356
    {
357
        return Html::img($this->getOtherPreviewUrl($baseUrl), $mainTagOptions);
358
    }
359
360
    /**
361
     * Get application preview url.
362
     *
363
     * @param string $baseUrl
364
     *
365
     * @return string
366
     */
367
    public function getAppPreviewUrl($baseUrl = ''): string
368
    {
369
        if (!empty($baseUrl) && is_string($baseUrl)) {
370
            $root = $baseUrl.DIRECTORY_SEPARATOR;
371
        } else {
372
            $root = DIRECTORY_SEPARATOR;
373
        }
374
        $module = $this->getModule();
375
376
        if ($this->isExcel()) {
377
            $url = $root . $module->thumbStubUrls[UploadModelInterface::FILE_TYPE_APP_EXCEL];
378
379
        } elseif ($this->isPdf()) {
380
            $url = $root . $module->thumbStubUrls[UploadModelInterface::FILE_TYPE_APP_PDF];
381
382
        } elseif ($this->isWord()) {
383
            $url = $root . $module->thumbStubUrls[UploadModelInterface::FILE_TYPE_APP_WORD];
384
385
        } else {
386
            $url = $root . $module->thumbStubUrls[UploadModelInterface::FILE_TYPE_APP];
387
        }
388
389
        return $url;
390
    }
391
392
    /**
393
     * Get text preview url.
394
     *
395
     * @param string $baseUrl
396
     *
397
     * @return string
398
     */
399
    public function getTextPreviewUrl($baseUrl = ''): string
400
    {
401
        if (!empty($baseUrl) && is_string($baseUrl)) {
402
            $root = $baseUrl.DIRECTORY_SEPARATOR;
403
        } else {
404
            $root = DIRECTORY_SEPARATOR;
405
        }
406
407
        return $root . $this->getModule()->thumbStubUrls[UploadModelInterface::FILE_TYPE_TEXT];
408
    }
409
410
    /**
411
     * Get other preview url.
412
     *
413
     * @param string $baseUrl
414
     *
415
     * @return string
416
     */
417
    public function getOtherPreviewUrl($baseUrl = ''): string
418
    {
419
        if (!empty($baseUrl) && is_string($baseUrl)) {
420
            $root = $baseUrl.DIRECTORY_SEPARATOR;
421
        } else {
422
            $root = DIRECTORY_SEPARATOR;
423
        }
424
        $module = $this->getModule();
425
426
        return $root . $module->thumbStubUrls[UploadModelInterface::FILE_TYPE_OTHER];
427
    }
428
429
    /**
430
     * Get thumbnails.
431
     *
432
     * @return array
433
     */
434
    public function getThumbs(): array
435
    {
436
        return unserialize($this->thumbs) ?: [];
437
    }
438
439
    /**
440
     * Get thumb url.
441
     *
442
     * @param string $alias
443
     *
444
     * @return string
445
     */
446
    public function getThumbUrl(string $alias): string
447
    {
448
        if ($alias === Module::THUMB_ALIAS_ORIGINAL) {
449
            return $this->getViewUrl();
450
451
        } else {
452
            $thumbs = $this->getThumbs();
453
454
            $url = !empty($thumbs[$alias]) ? $thumbs[$alias] : '';
455
        }
456
457
        if (empty($url)) {
458
            return '';
459
        }
460
461
        return $this->getViewUrl($url);
462
    }
463
464
    /**
465
     * Get thumb image.
466
     *
467
     * @param string $alias
468
     * @param array  $options
469
     *
470
     * @return string
471
     */
472
    public function getThumbImage(string $alias, array $options = []): string
473
    {
474
        $url = $this->getThumbUrl($alias);
475
476
        if (empty($url)) {
477
            return '';
478
        }
479
480
        if (empty($options['alt'])) {
481
            $options['alt'] = $this->alt;
482
        }
483
484
        return Html::img($url, $options);
485
    }
486
487
    /**
488
     * Get default thumbnail url.
489
     *
490
     * @param string $baseUrl
491
     *
492
     * @return string
493
     */
494
    public function getDefaultThumbUrl($baseUrl = ''): string
495
    {
496
        if ($this->isImage()) {
497
            return $this->getThumbUrl(Module::THUMB_ALIAS_DEFAULT);
498
499
        } elseif ($this->isApp()) {
500
            return $this->getAppPreviewUrl($baseUrl);
501
502
        } elseif ($this->isText()) {
503
            return $this->getTextPreviewUrl($baseUrl);
504
505
        } else {
506
            return $this->getOtherPreviewUrl($baseUrl);
507
        }
508
    }
509
510
    /**
511
     * @return string file size
512
     */
513
    public function getFileSize()
514
    {
515
        \Yii::$app->formatter->sizeFormatBase = 1000;
516
        return \Yii::$app->formatter->asShortSize($this->size, 0);
517
    }
518
519
    /**
520
     * Check if the file is image.
521
     *
522
     * @return bool
523
     */
524
    public function isImage(): bool
525
    {
526
        return strpos($this->type, UploadModelInterface::FILE_TYPE_IMAGE) !== false;
527
    }
528
529
    /**
530
     * Check if the file is audio.
531
     *
532
     * @return bool
533
     */
534
    public function isAudio(): bool
535
    {
536
        return strpos($this->type, UploadModelInterface::FILE_TYPE_AUDIO) !== false;
537
    }
538
539
    /**
540
     * Check if the file is video.
541
     *
542
     * @return bool
543
     */
544
    public function isVideo(): bool
545
    {
546
        return strpos($this->type, UploadModelInterface::FILE_TYPE_VIDEO) !== false;
547
    }
548
549
    /**
550
     * Check if the file is text.
551
     *
552
     * @return bool
553
     */
554
    public function isText(): bool
555
    {
556
        return strpos($this->type, UploadModelInterface::FILE_TYPE_TEXT) !== false;
557
    }
558
559
    /**
560
     * Check if the file is application.
561
     *
562
     * @return bool
563
     */
564
    public function isApp(): bool
565
    {
566
        return strpos($this->type, UploadModelInterface::FILE_TYPE_APP) !== false;
567
    }
568
569
    /**
570
     * Check if the file is excel.
571
     *
572
     * @return bool
573
     */
574
    public function isExcel(): bool
575
    {
576
        return strpos($this->type, UploadModelInterface::FILE_TYPE_APP_EXCEL) !== false;
577
    }
578
579
    /**
580
     * Check if the file is pdf.
581
     *
582
     * @return bool
583
     */
584
    public function isPdf(): bool
585
    {
586
        return strpos($this->type, UploadModelInterface::FILE_TYPE_APP_PDF) !== false;
587
    }
588
589
    /**
590
     * Check if the file is word.
591
     *
592
     * @return bool
593
     */
594
    public function isWord(): bool
595
    {
596
        return strpos($this->type, UploadModelInterface::FILE_TYPE_APP_WORD) !== false;
597
    }
598
599
    /**
600
     * @param string $url
601
     *
602
     * @return string
603
     */
604
    public function getFullPublicUrl(string $url): string
605
    {
606
        return rtrim(rtrim($this->getModule()->publicBaseUrl, '/'), '\\') . '/' . ltrim(str_replace('\\', '/', $url), '/');
607
    }
608
609
    /**
610
     * If storage is local, public base url will be linked with a url from DB.
611
     * It is useful for html templates.
612
     *
613
     * @param string|null $url
614
     *
615
     * @return string
616
     */
617
    public function getViewUrl(string $url = null): string
618
    {
619
        $url = empty($url) ? $this->url : $url;
620
621
        return $this->storage == Module::STORAGE_TYPE_LOCAL ? $this->getFullPublicUrl($url) : $url;
622
    }
623
624
    /**
625
     * Get preview option by location and file type.
626
     *
627
     * @param array $options
628
     * @param string|null $location
629
     * @param Module $module
630
     * @param string $fileType
631
     *
632
     * @return array
633
     */
634
    private function getOptions(
635
        array $options,
636
        string $location = null,
637
        Module $module,
638
        string $fileType) {
639
640
        return null === $location ?
641
            $options : ArrayHelper::merge($module->getPreviewOptions($fileType, $location, $this), $options);
642
    }
643
644
    /**
645
     * Compact addition tag with the main preview.
646
     *
647
     * @param string $preview
648
     * @param string $additionTagType
649
     * @param array $additionTagConfig
650
     *
651
     * @throws InvalidConfigException
652
     *
653
     * @return string
654
     */
655
    private function compactPreviewAdditionTags(
656
        string $preview,
657
        string $additionTagType,
658
        array $additionTagConfig
659
    ): string {
660
661
        if (!isset($additionTagConfig['name']) || !is_string($additionTagConfig['name'])) {
662
            throw new InvalidConfigException('Bad name configuration for addition tag: '.$additionTagType);
663
        }
664
665
        if (!isset($additionTagConfig['options']) || !is_array($additionTagConfig['options'])) {
666
            throw new InvalidConfigException('Bad options configuration for addition tag: '.$additionTagType);
667
        }
668
669
        switch ($additionTagType) {
670
            case 'leftTag':
671
                $content = isset($additionTagConfig['content']) ? $additionTagConfig['content'] : '';
672
                $preview = Html::tag($additionTagConfig['name'], $content, $additionTagConfig['options']) . $preview;
673
                break;
674
675
            case 'rightTag':
676
                $content = isset($additionTagConfig['content']) ? $additionTagConfig['content'] : '';
677
                $preview = $preview . Html::tag($additionTagConfig['name'], $content, $additionTagConfig['options']);
678
                break;
679
680
            case 'externalTag':
681
                $preview = Html::tag($additionTagConfig['name'], $preview, $additionTagConfig['options']);
682
                break;
683
684
            default:
685
                throw new InvalidConfigException('Unknown type of addition tag');
686
        }
687
688
        return $preview;
689
    }
690
}
691