Completed
Push — master ( 7f45a1...6afdf1 )
by Andrey
01:18
created

CommonAdminController::actionCreate()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 32
rs 8.7857
c 0
b 0
f 0
cc 6
nc 3
nop 0
1
<?php
2
3
namespace Itstructure\AdminModule\controllers;
4
5
use Yii;
6
use yii\db\BaseActiveRecord;
7
use yii\helpers\ArrayHelper;
8
use yii\base\{UnknownMethodException, InvalidConfigException};
9
use yii\web\{IdentityInterface, ConflictHttpException, BadRequestHttpException, NotFoundHttpException};
10
use Itstructure\AdminModule\interfaces\{ModelInterface, ValidateComponentInterface};
11
12
/**
13
 * Class BaseController
14
 * Base controller class for the `admin` module.
15
 *
16
 * @property bool $viewCreated Watch or not created record.
17
 * @property array $additionFields Addition fields for the view template.
18
 * @property array $additionAttributes Addition attributes with values for the model.
19
 * @property bool $isMultilanguage Installing the multilingual mode.
20
 * @property bool $setEditingScenarios If it is true, scenarios 'create' and 'update' will be set automatically for app model extending from ActiveRecord.
21
 * @property ModelInterface $model Model object record.
22
 * @property BaseActiveRecord $searchModel Search new model object.
23
 * @property ValidateComponentInterface $validateComponent Validate component.
24
 *
25
 * @package Itstructure\AdminModule\controllers
26
 *
27
 * @author Andrey Girnik <[email protected]>
28
 */
29
abstract class CommonAdminController extends AdminController
30
{
31
    /**
32
     * Watch or not created record.
33
     *
34
     * @var bool
35
     */
36
    protected $viewCreated = false;
37
38
    /**
39
     * Addition fields for the view template.
40
     *
41
     * @var array
42
     */
43
    protected $additionFields = [];
44
45
    /**
46
     * Addition attributes with values for the model.
47
     * [
48
     *    'key1' => 'value1',
49
     *    'key2' => 'value2',
50
     * ]
51
     * @var array
52
     */
53
    protected $additionAttributes = [];
54
55
    /**
56
     * Installing the multilingual mode.
57
     *
58
     * @var bool
59
     */
60
    protected $isMultilanguage = false;
61
62
    /**
63
     * If it is true, scenarios 'create' and 'update' will be set automatically for app model extending from ActiveRecord.
64
     *
65
     * @var bool
66
     */
67
    protected $setEditingScenarios = false;
68
69
    /**
70
     * Model object record.
71
     *
72
     * @var ModelInterface
73
     */
74
    private $model;
75
76
    /**
77
     * Search new model object.
78
     *
79
     * @var BaseActiveRecord
80
     */
81
    private $searchModel;
82
83
    /**
84
     * Validate component.
85
     *
86
     * @var ValidateComponentInterface
87
     */
88
    private $validateComponent;
89
90
    /**
91
     * Returns the name of the base model.
92
     *
93
     * @return string
94
     */
95
    abstract protected function getModelName():string;
96
97
    /**
98
     * Returns the name of the model to search it.
99
     *
100
     * @return string
101
     */
102
    abstract protected function getSearchModelName():string;
103
104
    /**
105
     * Initialize.
106
     *
107
     * @throws InvalidConfigException
108
     *
109
     * @return void
110
     */
111
    public function init()
112
    {
113
        if ($this->isMultilanguage) {
114
            $validateComponent = $this->module->get('multilanguage-validate-component');
115
116
            if (null === $validateComponent) {
117
                throw new InvalidConfigException('Multilanguage validate component is not defined.');
118
            }
119
            /** @var ValidateComponentInterface $validateComponent */
120
            $this->setValidateComponent($validateComponent);
121
        }
122
123
        parent::init();
124
    }
125
126
    /**
127
     * Set model.
128
     *
129
     * @param $model ModelInterface
130
     */
131
    public function setModel(ModelInterface $model): void
132
    {
133
        $this->model = $model;
0 ignored issues
show
Documentation Bug introduced by
It seems like $model of type object<Itstructure\Admin...erfaces\ModelInterface> is incompatible with the declared type object<ModelInterface> of property $model.

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...
134
    }
135
136
    /**
137
     * Set search model.
138
     *
139
     * @param $model BaseActiveRecord
140
     */
141
    public function setSearchModel(BaseActiveRecord $model): void
142
    {
143
        $this->searchModel = $model;
144
    }
145
146
    /**
147
     * Set validate component for main model.
148
     *
149
     * @param $component ValidateComponentInterface
150
     */
151
    public function setValidateComponent(ValidateComponentInterface $component): void
152
    {
153
        $this->validateComponent = $component;
0 ignored issues
show
Documentation Bug introduced by
It seems like $component of type object<Itstructure\Admin...dateComponentInterface> is incompatible with the declared type object<ValidateComponentInterface> of property $validateComponent.

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...
154
    }
155
156
    /**
157
     * Returns model.
158
     *
159
     * @return ModelInterface
160
     */
161
    public function getModel(): ModelInterface
162
    {
163
        return $this->model;
164
    }
165
166
    /**
167
     * Returns search model.
168
     *
169
     * @return BaseActiveRecord
170
     */
171
    public function getSearchModel(): BaseActiveRecord
172
    {
173
        return $this->searchModel;
174
    }
175
176
    /**
177
     * Get validate component for main model.
178
     *
179
     * @return ValidateComponentInterface
180
     */
181
    public function getValidateComponent(): ValidateComponentInterface
182
    {
183
        return $this->validateComponent;
184
    }
185
186
    /**
187
     * List of records.
188
     *
189
     * @return string
190
     */
191
    public function actionIndex()
192
    {
193
        $this->setSearchModel(
194
            $this->getNewSearchModel()
195
        );
196
197
        return $this->render('index',
198
            ArrayHelper::merge(
199
                [
200
                    'searchModel' => $this->searchModel,
201
                    'dataProvider' => $this->searchModel->search(Yii::$app->request->queryParams)
202
                ],
203
                $this->getAdditionFields()
204
            )
205
        );
206
    }
207
208
    /**
209
     * Displays one model entry.
210
     *
211
     * @param int|string $id
212
     *
213
     * @return mixed
214
     */
215
    public function actionView($id)
216
    {
217
        return $this->render('view',
218
            ArrayHelper::merge(
219
                [
220
                    'model' => $this->findModel($id)
221
                ],
222
                $this->getAdditionFields()
223
            )
224
        );
225
    }
226
227
    /**
228
     * Creates a new model record.
229
     * If the result of creation is successful, there will be a redirect to the 'view' or 'index' page.
230
     *
231
     * @return string|\yii\web\Response
232
     */
233
    public function actionCreate()
234
    {
235
        $this->setModelByConditions();
236
237
        if (Yii::$app->request->isPost &&
238
            $this->model->load(Yii::$app->request->post()) &&
239
            $this->setAdditionAttributes() &&
240
            $this->model->save()) {
241
242
            if ($this->viewCreated) {
243
                $redirectParams = [
244
                    $this->urlPrefix.'view',
245
                    'id' => $this->model->getId(),
246
                ];
247
            } else {
248
                $redirectParams = [
249
                    $this->urlPrefix.'index',
250
                ];
251
            }
252
253
            return $this->redirect($redirectParams);
254
        }
255
256
        return $this->render('create',
257
            ArrayHelper::merge(
258
                [
259
                    'model' => $this->model
260
                ],
261
                $this->getAdditionFields()
262
            )
263
        );
264
    }
265
266
    /**
267
     * Updates the current model entry.
268
     * If the result of creation is successful, there will be a redirect to the 'view' or 'index' page.
269
     *
270
     * @param int|string $id
271
     *
272
     * @return string|\yii\web\Response
273
     */
274
    public function actionUpdate($id)
275
    {
276
        $this->setModelByConditions($id);
277
278
        if (Yii::$app->request->isPost &&
279
            $this->model->load(Yii::$app->request->post()) &&
280
            $this->setAdditionAttributes() &&
281
            $this->model->save()) {
282
283
            return $this->redirect([
284
                $this->urlPrefix.'view',
285
                'id' => $this->model->getId(),
286
            ]);
287
        }
288
289
        return $this->render('update',
290
            ArrayHelper::merge(
291
                [
292
                    'model' => $this->model
293
                ],
294
                $this->getAdditionFields()
295
            )
296
        );
297
    }
298
299
    /**
300
     * Deletes the current model entry.
301
     * If the result of the deletion is successful, there will be a redirect to the 'index' page.
302
     *
303
     * @param int|string $id
304
     *
305
     * @return \yii\web\Response
306
     *
307
     * @throws ConflictHttpException
308
     */
309
    public function actionDelete($id)
310
    {
311
        $model = $this->findModel($id);
312
313
        if (($model instanceof IdentityInterface) && $id == Yii::$app->user->identity->getId()) {
314
            throw new ConflictHttpException('You can not delete yourself.');
315
        };
316
317
        $model->delete();
318
319
        return $this->redirect([$this->urlPrefix.'index']);
320
    }
321
322
    /**
323
     * Set addition attributes for model.
324
     *
325
     * @return bool
326
     */
327
    protected function setAdditionAttributes(): bool
328
    {
329
        $this->model->setAttributes($this->additionAttributes, false);
330
331
        return true;
332
    }
333
334
    /**
335
     * Get addition fields for the view template.
336
     *
337
     * @return array
338
     */
339
    protected function getAdditionFields(): array
340
    {
341
        return $this->additionFields;
342
    }
343
344
    /**
345
     * Returns new object of main model.
346
     *
347
     * @return mixed
348
     */
349
    protected function getNewModel()
350
    {
351
        $modelName = $this->getModelName();
352
        return new $modelName;
353
    }
354
355
    /**
356
     * Returns new object of search main model.
357
     *
358
     * @return mixed
359
     */
360
    protected function getNewSearchModel()
361
    {
362
        $searchModelName = $this->getSearchModelName();
363
        return new $searchModelName;
364
    }
365
366
    /**
367
     * Find model record.
368
     * If the model is not found, a 404 HTTP exception will be displayed.
369
     *
370
     * @param int|string $key
371
     *
372
     * @throws BadRequestHttpException
373
     * @throws UnknownMethodException
374
     * @throws NotFoundHttpException
375
     *
376
     * @return mixed
377
     */
378
    protected function findModel($key)
379
    {
380
        if (null === $key) {
381
            throw new BadRequestHttpException('Key parameter is not defined in findModel method.');
382
        }
383
384
        $modelObject = $this->getNewModel();
385
386
        if (!method_exists($modelObject, 'findOne')) {
387
            $class = (new\ReflectionClass($modelObject));
388
            throw new UnknownMethodException('Method findOne does not exists in ' . $class->getNamespaceName() . '\\' .
389
                $class->getShortName().' class.');
390
        }
391
392
        $result = call_user_func([
393
            $modelObject,
394
            'findOne',
395
        ], $key);
396
397
        if ($result !== null) {
398
            return $result;
399
        }
400
401
        throw new NotFoundHttpException('The requested page does not exist.');
402
    }
403
404
    /**
405
     * Returns an intermediate model for working with the main.
406
     *
407
     * @param int|string|null $key
408
     *
409
     * @return void
410
     */
411
    private function setModelByConditions($key = null): void
412
    {
413
        $model = null === $key ? $this->getNewModel() : $this->findModel($key);
414
415
        if ($this->setEditingScenarios && $model instanceof BaseActiveRecord) {
416
            $scenario = $model->getIsNewRecord() ? ModelInterface::SCENARIO_CREATE : ModelInterface::SCENARIO_UPDATE;
417
            $model->setScenario($scenario);
418
        }
419
420
        if (null === $this->validateComponent) {
421
            $this->setModel($model);
422
        } else {
423
            $this->setModel(
424
                $this->validateComponent->setModel($model)
425
            );
426
        }
427
    }
428
}