Completed
Push — master ( c403d6...02c7e7 )
by Igor
06:15
created

UploadAction::upload()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 28
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 5.0164

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 28
ccs 21
cts 23
cp 0.913
rs 8.439
cc 5
eloc 19
nc 9
nop 1
crap 5.0164
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\actions;
10
11
use Yii;
12
use yii\base\Action;
13
use yii\base\DynamicModel;
14
use yii\base\InvalidParamException;
15
use yii\web\UploadedFile;
16
use yii\helpers\ArrayHelper;
17
18
class UploadAction extends Action
19
{
20
    /**
21
     * @var string $modelClass Class name of the model
22
     */
23
    public $modelClass;
24
    /**
25
     * @var string $modelObject Model
26
     */
27
    public $modelObject;
28
    /**
29
     * @var string $attribute Attribute name of the model
30
     */
31
    public $attribute;
32
    /**
33
     * @var string $inputName The name of the file input field
34
     */
35
    public $inputName;
36
    /**
37
     * @var string $resultFieldId The name of the field that contains the id of the file in the response
38
     */
39
    public $resultFieldId = 'id';
40
    /**
41
     * @var string $resultFieldPath The name of the field that contains the path of the file in the response
42
     */
43
    public $resultFieldPath = 'path';
44
    /**
45
     * @var bool $saveAfterUpload Save after upload
46
     */
47
    public $saveAfterUpload = false;
48
    /**
49
     * @var ActiveRecord $model
50
     */
51
    private $model;
52
53 28
    public function init()
54
    {
55 28
        if ($this->modelClass === null && $this->modelObject === null) {
56 1
            throw new InvalidParamException(
57 1
                get_class($this) . '::$modelClass or ' .get_class($this) . '::$modelObject must be set'
58 1
            );
59
        }
60
61 27
        $this->model = $this->modelClass ? new $this->modelClass : $this->modelObject;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->modelClass ? new ...() : $this->modelObject can also be of type string. However, the property $model is declared as type object<rkit\filemanager\actions\ActiveRecord>. 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...
62 27
    }
63
64 27
    public function run()
65
    {
66 27
        $file = UploadedFile::getInstanceByName($this->inputName);
67
68 27
        if (!$file) {
69 1
            return $this->response(
70 1
                ['error' => Yii::t('filemanager-yii2', 'An error occured, try again later…')]
71 1
            );
72
        }
73
74 26
        $rules = $this->model->fileRules($this->attribute, true);
75 26
        $type = $this->model->fileOption($this->attribute, 'type', 'image');
76
77 26
        $model = new DynamicModel(compact('file'));
78
79 26
        $maxFiles = ArrayHelper::getValue($rules, 'maxFiles');
80 26
        if ($maxFiles !== null && $maxFiles > 1) {
81 3
            $model->file = [$model->file];
82 3
        }
83
84 26
        $model->addRule('file', $type, $rules)->validate();
85 26
        if ($model->hasErrors()) {
86 1
            return $this->response(['error' => $model->getFirstError('file')]);
87
        }
88
89 25
        if (is_array($model->file)) {
90 3
            $model->file = $model->file[0];
91 3
        }
92
93 25
        return $this->upload($model->file);
94
    }
95
96
    /**
97
     * Upload
98
     *
99
     * @param UploadedFile $file
100
     * @return string JSON
101
     * @SuppressWarnings(PHPMD.ElseExpression)
102
     */
103 25
    private function upload($file)
104
    {
105 25
        $file = $this->model->createFile($this->attribute, $file->tempName, $file->name);
106 25
        if ($file) {
107 25
            if ($this->saveAfterUpload) {
108
                $this->model->save(false);
109
            }
110 25
            $presetAfterUpload = $this->model->filePresetAfterUpload($this->attribute);
111 25
            if (count($presetAfterUpload)) {
112 25
                $this->applyPreset($presetAfterUpload, $file);
113 25
            }
114 25
            $template = $this->model->fileOption($this->attribute, 'template');
115 25
            if ($template) {
116 1
                return $this->response(
117 1
                    $this->controller->renderFile(Yii::getAlias($template), [
0 ignored issues
show
Bug introduced by
It seems like \Yii::getAlias($template) targeting yii\BaseYii::getAlias() can also be of type boolean; however, yii\base\Controller::renderFile() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
118 1
                        'file' => $file,
119 1
                        'model' => $this->model,
120 1
                        'attribute' => $this->attribute
121 1
                    ])
122 1
                );
123
            }
124 24
            return $this->response([
125 24
                $this->resultFieldId => $file->getPrimaryKey(),
126 24
                $this->resultFieldPath => $this->model->fileUrl($this->attribute, $file),
127 24
            ]);
128
        }
129
        return $this->response(['error' => Yii::t('filemanager-yii2', 'Error saving file')]); // @codeCoverageIgnore
130
    }
131
132
    /**
133
     * Apply preset for file
134
     *
135
     * @param array $presetAfterUpload
136
     * @param ActiveRecord $file The file model
137
     * @return void
138
     */
139 25
    private function applyPreset($presetAfterUpload, $file)
140
    {
141 25
        foreach ($presetAfterUpload as $preset) {
142 25
            $this->model->thumbUrl($this->attribute, $preset, $file);
143 25
        }
144 25
    }
145
146
    /**
147
     * JSON Response
148
     *
149
     * @param mixed $data
150
     * @return string JSON Only for yii\web\Application, for console app returns `mixed`
151
     */
152 27
    private function response($data)
153
    {
154
        // @codeCoverageIgnoreStart
155
        if (!Yii::$app instanceof \yii\console\Application) {
156
            \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
157
        }
158
        // @codeCoverageIgnoreEnd
159 27
        return $data;
160
    }
161
}
162