FileCreateFromInstance::execute()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 2
Metric Value
eloc 10
c 3
b 0
f 2
dl 0
loc 17
rs 9.9332
cc 4
nc 6
nop 0
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: floor12
5
 * Date: 01.01.2018
6
 * Time: 12:56
7
 */
8
9
namespace floor12\files\logic;
10
11
use floor12\files\components\SimpleImage;
12
use floor12\files\models\File;
13
use floor12\files\models\FileType;
14
use Yii;
15
use yii\base\ErrorException;
16
use yii\web\BadRequestHttpException;
17
use yii\web\IdentityInterface;
18
use yii\web\UploadedFile;
19
20
/**
21
 * Class FileCreateFromInstance
22
 * @package floor12\files\logic
23
 */
24
class FileCreateFromInstance
25
{
26
    private $_model;
27
    private $_owner;
28
    private $_attribute;
29
    private $_instance;
30
    private $_fullPath;
31
    private $_onlyUploaded;
32
33
    public function __construct(UploadedFile $file, array $data, IdentityInterface $identity = null, $onlyUploaded = true)
34
    {
35
36
        $this->_onlyUploaded = $onlyUploaded;
37
38
        if (!isset($data['attribute']) || !$data['attribute'] || !isset($data['modelClass']) || !$data['modelClass'])
39
            throw new BadRequestHttpException("Attribute or class name not set.");
40
41
        // Загружаем полученные данные
42
        $this->_instance = $file;
43
        $this->_attribute = $data['attribute'];
44
45
        if (!file_exists($this->_instance->tempName))
46
            throw new ErrorException("Tmp file not found on disk.");
47
48
        // Инициализируем класс владельца файла для валидаций и ставим сценарий
49
        $this->_owner = new $data['modelClass'];
50
51
        if (isset($data['scenario']))
52
            $this->_owner->setScenario($data['scenario']);
53
54
55
        if (isset($this->_owner->behaviors['files']->attributes[$this->_attribute]['validator'])) {
56
            foreach ($this->_owner->behaviors['files']->attributes[$this->_attribute]['validator'] as $validator) {
57
                if ($validator->maxFiles && (int)$data['count'] > $validator->maxFiles) {
58
                    throw new BadRequestHttpException('The maximum number of files has been exceeded: ' . $validator->maxFiles);
59
                }
60
61
                if (!$validator->validate($this->_instance, $error))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $error seems to be never defined.
Loading history...
62
                    throw new BadRequestHttpException($error);
63
            }
64
65
        }
66
67
        // Создаем модель нового файла и заполняем первоначальными данными
68
        $this->_model = new File();
69
        $this->_model->created = time();
70
        $this->_model->field = $this->_attribute;
71
        $this->_model->class = $data['modelClass'];
72
73
        $this->_model->filename = new PathGenerator(Yii::$app->getModule('files')->storageFullPath) . '.' . $this->_instance->extension;
74
        $this->_model->title = $this->_instance->name;
75
        $this->_model->content_type = \yii\helpers\FileHelper::getMimeType($this->_instance->tempName);
76
        $this->_model->size = $this->_instance->size;
77
        $this->_model->type = $this->detectType();
0 ignored issues
show
Documentation Bug introduced by
The property $type was declared of type integer, but $this->detectType() is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
78
        if ($identity)
79
            $this->_model->user_id = $identity->getId();
0 ignored issues
show
Documentation Bug introduced by
It seems like $identity->getId() can also be of type string. However, the property $user_id is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
80
        if ($this->_model->type == FileType::VIDEO)
81
            $this->_model->video_status = 0;
82
83
        //Генерируем полный новый адрес сохранения файла
84
        $this->_fullPath = Yii::$app->getModule('files')->storageFullPath . DIRECTORY_SEPARATOR . $this->_model->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

84
        $this->_fullPath = /** @scrutinizer ignore-type */ Yii::$app->getModule('files')->storageFullPath . DIRECTORY_SEPARATOR . $this->_model->filename;
Loading history...
85
    }
86
87
    /**
88
     * @return string
89
     */
90
    public function detectType()
91
    {
92
        $contentTypeArray = explode('/', $this->_model->content_type);
93
        if ($contentTypeArray[0] == 'image')
94
            return FileType::IMAGE;
95
        if ($contentTypeArray[0] == 'video')
96
            return FileType::VIDEO;
97
        return FileType::FILE;
98
    }
99
100
    /**
101
     * @return File
102
     */
103
104
    public function execute()
105
    {
106
        $path = Yii::$app->getModule('files')->storageFullPath . $this->_model->filename;
0 ignored issues
show
Unused Code introduced by
The assignment to $path is dead and can be removed.
Loading history...
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

106
        $path = /** @scrutinizer ignore-type */ Yii::$app->getModule('files')->storageFullPath . $this->_model->filename;
Loading history...
107
108
        if ($this->_model->save()) {
109
            if (!$this->_onlyUploaded)
110
                copy($this->_instance->tempName, $this->_fullPath);
111
            else
112
                $this->_instance->saveAs($this->_fullPath, false);
113
        }
114
115
        if ($this->_model->type == FileType::IMAGE) {
116
            $this->rotateAfterUpload();
117
            $this->resizeAfterUpload();
118
        }
119
120
        return $this->_model;
121
    }
122
123
124
    protected function rotateAfterUpload()
125
    {
126
        $exif = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $exif is dead and can be removed.
Loading history...
127
        @$exif = exif_read_data($this->_fullPath);
128
        if (isset($exif['Orientation'])) {
129
            $ort = $exif['Orientation'];
130
            $rotatingImage = new SimpleImage();
131
            $rotatingImage->load($this->_fullPath);
132
            switch ($ort) {
133
                case 3: // 180 rotate left
134
                    $rotatingImage->rotateDegrees(180);
135
                    $rotatingImage->save($this->_fullPath);
136
                    break;
137
                case 6: // 90 rotate right
138
                    $rotatingImage->rotateDegrees(270);
139
                    $rotatingImage->save($this->_fullPath);
140
                    break;
141
                case 8:    // 90 rotate left
142
                    $rotatingImage->rotateDegrees(90);
143
                    $rotatingImage->save($this->_fullPath);
144
            }
145
146
        }
147
    }
148
149
    protected function resizeAfterUpload()
150
    {
151
        $maxWidth = $this->_owner->behaviors['files']->attributes[$this->_attribute]['maxWidth'] ?? 0;
152
        $maxHeight = $this->_owner->behaviors['files']->attributes[$this->_attribute]['maxHeight'] ?? 0;
153
154
        if ($maxWidth && $maxHeight) {
155
            $resizer = new FileResize($this->_model, $maxWidth, $maxHeight);
156
            $resizer->execute();
157
        }
158
159
    }
160
}
161