Issues (46)

src/controllers/upload/CommonUploadController.php (3 issues)

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};
0 ignored issues
show
The type yii\base\InvalidArgumentException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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;
0 ignored issues
show
The trait Itstructure\MFUploader\traits\ResponseTrait requires the property $response which is not provided by Itstructure\MFUploader\c...\CommonUploadController.
Loading history...
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
        parent::init();
56
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function behaviors()
62
    {
63
        return [
64
            'access' => [
65
                'class' => AccessControl::class,
66
                'rules' => [
67
                    [
68
                        'allow' => true,
69
                        'roles' => $this->module->accessRoles,
70
                    ],
71
                ],
72
                'denyCallback' => function () {
73
                    \Yii::$app->response->format = Response::FORMAT_JSON;
74
                    throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
75
                }
76
            ],
77
            'contentNegotiator' => [
78
                'class' => ContentNegotiator::class,
79
                'formats' => [
80
                    'application/json' => Response::FORMAT_JSON,
81
                ],
82
            ],
83
            'verbFilter' => [
84
                'class' => VerbFilter::class,
85
                'actions' => $this->verbs(),
86
            ],
87
        ];
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function afterAction($action, $result)
94
    {
95
        $result = parent::afterAction($action, $result);
96
        return $this->serializeData($result);
97
    }
98
99
    /**
100
     * @return array
101
     */
102
    public function verbs()
103
    {
104
        return [
105
            'save' => ['POST'],
106
            'delete' => ['POST'],
107
        ];
108
    }
109
110
    /**
111
     * Set upload model.
112
     *
113
     * @param UploadModelInterface $model
114
     *
115
     * @return void
116
     */
117
    public function setUploadModel(UploadModelInterface $model): void
118
    {
119
        $this->uploadModel = $model;
120
    }
121
122
    /**
123
     * Returns upload model.
124
     *
125
     * @return UploadModelInterface
126
     */
127
    public function getUploadModel(): UploadModelInterface
128
    {
129
        return $this->uploadModel;
130
    }
131
132
    /**
133
     * Send new file to upload it.
134
     *
135
     * @throws BadRequestHttpException
136
     *
137
     * @return array
138
     */
139
    public function actionSend()
140
    {
141
        try {
142
            $this->uploadModel = $this->getUploadComponent()->setModelForSave($this->setMediafileModel());
143
144
            return $this->actionSave(Yii::$app->request);
145
146
        } catch (InvalidConfigException|UnknownMethodException|NotFoundHttpException|InvalidArgumentException|
147
            AwsException|S3Exception|\Exception $e) {
148
            throw new BadRequestHttpException($e->getMessage(), $e->getCode());
149
        }
150
    }
151
152
    /**
153
     * Update existing file.
154
     *
155
     * @throws BadRequestHttpException
156
     *
157
     * @return array
158
     */
159
    public function actionUpdate()
160
    {
161
        try {
162
            $request = Yii::$app->request;
163
164
            if (empty($request->post('id'))) {
165
                return $this->getFailResponse(Module::t('actions', 'Error to save file.'), [
166
                    'errors' => Module::t('actions', 'Parameter id must be sent.')
167
                ]);
168
            }
169
170
            $this->uploadModel = $this->getUploadComponent()->setModelForSave(
171
                $this->setMediafileModel($request->post('id'))
0 ignored issues
show
It seems like $request->post('id') can also be of type array; however, parameter $id of Itstructure\MFUploader\c...er::setMediafileModel() does only seem to accept integer|null, 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

171
                $this->setMediafileModel(/** @scrutinizer ignore-type */ $request->post('id'))
Loading history...
172
            );
173
174
            return $this->actionSave($request);
175
176
        } catch (InvalidConfigException|UnknownMethodException|NotFoundHttpException|InvalidArgumentException|
177
            AwsException|S3Exception|\Exception $e) {
178
            throw new BadRequestHttpException($e->getMessage(), $e->getCode());
179
        }
180
    }
181
182
    /**
183
     * Delete the media model entry with files.
184
     *
185
     * @throws BadRequestHttpException
186
     *
187
     * @return array
188
     */
189
    public function actionDelete()
190
    {
191
        try {
192
            $deleted = $this->deleteMediafileEntry(Yii::$app->request->post('id'), $this->module);
193
194
            if (false === $deleted) {
195
                return $this->getFailResponse(
196
                    Module::t('actions', 'Error to delete file.')
197
                );
198
            }
199
200
            return $this->getSuccessResponse(
201
                Module::t('actions', 'Deleted {0} files.', [$deleted])
202
            );
203
204
        } catch (InvalidConfigException|\Exception $e) {
205
            throw new BadRequestHttpException($e->getMessage(), $e->getCode());
206
        }
207
    }
208
209
    /**
210
     * Provides upload or update file.
211
     *
212
     * @throws InvalidConfigException
213
     * @throws BadRequestHttpException
214
     *
215
     * @param $request
216
     *
217
     * @return array
218
     */
219
    private function actionSave($request)
220
    {
221
        if (!($request instanceof Request)) {
222
            throw new InvalidArgumentException('Param $request must be instanceof yii\web\Request.');
223
        }
224
225
        if (null === $this->uploadModel) {
226
            throw new InvalidConfigException('Upload model is not defined.');
227
        }
228
229
        $this->uploadModel->setAttributes($request->post(), false);
230
        $this->uploadModel->setFile(UploadedFile::getInstanceByName($this->module->fileAttributeName));
231
232
        if (!$this->uploadModel->save()) {
233
            return $this->getFailResponse(Module::t('actions', 'Error to save file.'), [
234
                'errors' => $this->uploadModel->getErrors()
235
            ]);
236
        }
237
238
        if ($this->uploadModel->getMediafileModel()->isImage()) {
239
            $this->uploadModel->createThumbs();
240
        }
241
242
        $response = [];
243
        $response['files'][] = $this->getUploadResponse();
244
245
        return $this->getSuccessResponse(Module::t('actions', 'File saved.'), $response);
246
    }
247
248
    /**
249
     * Serializes the specified data.
250
     * The default implementation will create a serializer based on the configuration given by [[serializer]].
251
     * It then uses the serializer to serialize the given data.
252
     *
253
     * @param mixed $data the data to be serialized
254
     *
255
     * @return mixed the serialized data.
256
     */
257
    private function serializeData($data)
258
    {
259
        return Yii::createObject($this->serializer)->serialize($data);
260
    }
261
262
    /**
263
     * Response with uploaded file data.
264
     *
265
     * @return array
266
     */
267
    private function getUploadResponse(): array
268
    {
269
        $mediafileModel = $this->uploadModel->getMediafileModel();
270
271
        return [
272
            'id'            => $this->uploadModel->getId(),
273
            'url'           => $mediafileModel->getViewUrl(),
274
            'thumbnailUrl'  => $mediafileModel->getDefaultThumbUrl(UploadmanagerAsset::register($this->view)->baseUrl),
275
            'name'          => $mediafileModel->filename,
276
            'type'          => $mediafileModel->type,
277
            'size'          => $mediafileModel->size,
278
        ];
279
    }
280
281
    /**
282
     * Returns an intermediate model for working with the main.
283
     *
284
     * @param int|null $id
285
     *
286
     * @throws UnknownMethodException
287
     * @throws NotFoundHttpException
288
     *
289
     * @return Mediafile
290
     */
291
    private function setMediafileModel(int $id = null): Mediafile
292
    {
293
        if (null === $id) {
294
            return new Mediafile();
295
        } else {
296
            return $this->findMediafileModel($id);
297
        }
298
    }
299
}
300