Completed
Push — master ( ea324c...2e8bb7 )
by Andrey
01:33
created

CommonUploadController   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 269
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 13

Importance

Changes 0
Metric Value
wmc 23
lcom 2
cbo 13
dl 0
loc 269
c 0
b 0
f 0
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
getUploadComponent() 0 1 ?
A init() 0 4 1
A behaviors() 0 28 1
A afterAction() 0 5 1
A verbs() 0 7 1
A setUploadModel() 0 4 1
A getUploadModel() 0 4 1
A actionSend() 0 12 2
A actionUpdate() 0 22 3
A actionDelete() 0 19 3
A actionSave() 0 28 5
A serializeData() 0 4 1
A getUploadResponse() 0 13 1
A setMediafileModel() 0 8 2
1
<?php
2
3
namespace Itstructure\MFUploader\controllers\upload;
4
5
use Yii;
6
use yii\filters\{AccessControl, ContentNegotiator, VerbFilter};
7
use yii\base\{InvalidConfigException, UnknownMethodException, InvalidArgumentException};
8
use yii\web\{Controller, Request, Response, UploadedFile, BadRequestHttpException, NotFoundHttpException, ForbiddenHttpException};
9
use Aws\Exception\AwsException;
10
use Aws\S3\Exception\S3Exception;
11
use Itstructure\MFUploader\Module;
12
use Itstructure\MFUploader\assets\UploadmanagerAsset;
13
use Itstructure\MFUploader\models\Mediafile;
14
use Itstructure\MFUploader\traits\{ResponseTrait, MediaFilesTrait};
15
use Itstructure\MFUploader\interfaces\{UploadComponentInterface, UploadModelInterface};
16
17
/**
18
 * Class CommonUploadController
19
 * Common upload controller class to upload files.
20
 *
21
 * @property UploadComponentInterface $uploadComponent
22
 * @property UploadModelInterface $uploadModel
23
 * @property Module $module
24
 *
25
 * @package Itstructure\MFUploader\controllers\upload
26
 *
27
 * @author Andrey Girnik <[email protected]>
28
 */
29
abstract class CommonUploadController extends Controller
30
{
31
    use ResponseTrait, MediaFilesTrait;
32
33
    /**
34
     * @var string|array the configuration for creating the serializer that formats the response data.
35
     */
36
    public $serializer = 'yii\rest\Serializer';
37
38
    /**
39
     * @var UploadModelInterface
40
     */
41
    private $uploadModel;
42
43
    /**
44
     * @return UploadComponentInterface
45
     */
46
    abstract protected function getUploadComponent(): UploadComponentInterface;
47
48
    /**
49
     * Initialize.
50
     */
51
    public function init()
52
    {
53
        $this->enableCsrfValidation = $this->module->enableCsrfValidation;
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59
    public function behaviors()
60
    {
61
        return [
62
            'access' => [
63
                'class' => AccessControl::class,
64
                'rules' => [
65
                    [
66
                        'allow' => true,
67
                        'roles' => $this->module->accessRoles,
68
                    ],
69
                ],
70
                'denyCallback' => function () {
71
                    \Yii::$app->response->format = Response::FORMAT_JSON;
72
                    throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
73
                }
74
            ],
75
            'contentNegotiator' => [
76
                'class' => ContentNegotiator::class,
77
                'formats' => [
78
                    'application/json' => Response::FORMAT_JSON,
79
                ],
80
            ],
81
            'verbFilter' => [
82
                'class' => VerbFilter::class,
83
                'actions' => $this->verbs(),
84
            ],
85
        ];
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    public function afterAction($action, $result)
92
    {
93
        $result = parent::afterAction($action, $result);
94
        return $this->serializeData($result);
95
    }
96
97
    /**
98
     * @return array
99
     */
100
    public function verbs()
101
    {
102
        return [
103
            'save' => ['POST'],
104
            'delete' => ['POST'],
105
        ];
106
    }
107
108
    /**
109
     * Set upload model.
110
     *
111
     * @param UploadModelInterface $model
112
     *
113
     * @return void
114
     */
115
    public function setUploadModel(UploadModelInterface $model): void
116
    {
117
        $this->uploadModel = $model;
0 ignored issues
show
Documentation Bug introduced by
It seems like $model of type object<Itstructure\MFUpl...s\UploadModelInterface> is incompatible with the declared type object<UploadModelInterface> of property $uploadModel.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
118
    }
119
120
    /**
121
     * Returns upload model.
122
     *
123
     * @return UploadModelInterface
124
     */
125
    public function getUploadModel(): UploadModelInterface
126
    {
127
        return $this->uploadModel;
128
    }
129
130
    /**
131
     * Send new file to upload it.
132
     *
133
     * @throws BadRequestHttpException
134
     *
135
     * @return array
136
     */
137
    public function actionSend()
138
    {
139
        try {
140
            $this->uploadModel = $this->getUploadComponent()->setModelForSave($this->setMediafileModel());
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getUploadComponen...s->setMediafileModel()) of type object<Itstructure\MFUpl...s\UploadModelInterface> is incompatible with the declared type object<UploadModelInterface> of property $uploadModel.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
141
142
            return $this->actionSave(Yii::$app->request);
143
144
        } catch (InvalidConfigException|UnknownMethodException|NotFoundHttpException|InvalidArgumentException|
145
            AwsException|S3Exception|\Exception $e) {
146
            throw new BadRequestHttpException($e->getMessage(), $e->getCode());
147
        }
148
    }
149
150
    /**
151
     * Update existing file.
152
     *
153
     * @throws BadRequestHttpException
154
     *
155
     * @return array
156
     */
157
    public function actionUpdate()
158
    {
159
        try {
160
            $request = Yii::$app->request;
161
162
            if (empty($request->post('id'))) {
163
                return $this->getFailResponse(Module::t('actions', 'Error to save file.'), [
164
                    'errors' => Module::t('actions', 'Parameter id must be sent.')
165
                ]);
166
            }
167
168
            $this->uploadModel = $this->getUploadComponent()->setModelForSave(
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getUploadComponen...($request->post('id'))) of type object<Itstructure\MFUpl...s\UploadModelInterface> is incompatible with the declared type object<UploadModelInterface> of property $uploadModel.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
169
                $this->setMediafileModel($request->post('id'))
170
            );
171
172
            return $this->actionSave($request);
173
174
        } catch (InvalidConfigException|UnknownMethodException|NotFoundHttpException|InvalidArgumentException|
175
            AwsException|S3Exception|\Exception $e) {
176
            throw new BadRequestHttpException($e->getMessage(), $e->getCode());
177
        }
178
    }
179
180
    /**
181
     * Delete the media model entry with files.
182
     *
183
     * @throws BadRequestHttpException
184
     *
185
     * @return array
186
     */
187
    public function actionDelete()
188
    {
189
        try {
190
            $deleted = $this->deleteMediafileEntry(Yii::$app->request->post('id'), $this->module);
191
192
            if (false === $deleted) {
193
                return $this->getFailResponse(
194
                    Module::t('actions', 'Error to delete file.')
195
                );
196
            }
197
198
            return $this->getSuccessResponse(
199
                Module::t('actions', 'Deleted {0} files.', [$deleted])
200
            );
201
202
        } catch (InvalidConfigException|\Exception $e) {
203
            throw new BadRequestHttpException($e->getMessage(), $e->getCode());
204
        }
205
    }
206
207
    /**
208
     * Provides upload or update file.
209
     *
210
     * @throws InvalidConfigException
211
     * @throws BadRequestHttpException
212
     *
213
     * @param $request
214
     *
215
     * @return array
216
     */
217
    private function actionSave($request)
218
    {
219
        if (!($request instanceof Request)) {
220
            throw new InvalidArgumentException('Param $request must be instanceof yii\web\Request.');
221
        }
222
223
        if (null === $this->uploadModel) {
224
            throw new InvalidConfigException('Upload model is not defined.');
225
        }
226
227
        $this->uploadModel->setAttributes($request->post(), false);
228
        $this->uploadModel->setFile(UploadedFile::getInstanceByName($this->module->fileAttributeName));
229
230
        if (!$this->uploadModel->save()) {
231
            return $this->getFailResponse(Module::t('actions', 'Error to save file.'), [
232
                'errors' => $this->uploadModel->getErrors()
233
            ]);
234
        }
235
236
        if ($this->uploadModel->getMediafileModel()->isImage()) {
237
            $this->uploadModel->createThumbs();
238
        }
239
240
        $response = [];
241
        $response['files'][] = $this->getUploadResponse();
242
243
        return $this->getSuccessResponse(Module::t('actions', 'File saved.'), $response);
244
    }
245
246
    /**
247
     * Serializes the specified data.
248
     * The default implementation will create a serializer based on the configuration given by [[serializer]].
249
     * It then uses the serializer to serialize the given data.
250
     *
251
     * @param mixed $data the data to be serialized
252
     *
253
     * @return mixed the serialized data.
254
     */
255
    private function serializeData($data)
256
    {
257
        return Yii::createObject($this->serializer)->serialize($data);
258
    }
259
260
    /**
261
     * Response with uploaded file data.
262
     *
263
     * @return array
264
     */
265
    private function getUploadResponse(): array
266
    {
267
        $mediafileModel = $this->uploadModel->getMediafileModel();
268
269
        return [
270
            'id'            => $this->uploadModel->getId(),
271
            'url'           => $mediafileModel->getViewUrl(),
272
            'thumbnailUrl'  => $mediafileModel->getDefaultThumbUrl(UploadmanagerAsset::register($this->view)->baseUrl),
0 ignored issues
show
Compatibility introduced by
$this->view of type object<yii\base\View> is not a sub-type of object<yii\web\View>. It seems like you assume a child class of the class yii\base\View to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
273
            'name'          => $mediafileModel->filename,
274
            'type'          => $mediafileModel->type,
275
            'size'          => $mediafileModel->size,
276
        ];
277
    }
278
279
    /**
280
     * Returns an intermediate model for working with the main.
281
     *
282
     * @param int|null $id
283
     *
284
     * @throws UnknownMethodException
285
     * @throws NotFoundHttpException
286
     *
287
     * @return Mediafile
288
     */
289
    private function setMediafileModel(int $id = null): Mediafile
290
    {
291
        if (null === $id) {
292
            return new Mediafile();
293
        } else {
294
            return $this->findMediafileModel($id);
295
        }
296
    }
297
}
298