Completed
Push — master ( a63e95...f7fb11 )
by Andrey
01:59
created

BaseController::beforeAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Itstructure\RbacModule\controllers;
4
5
use Yii;
6
use yii\db\ActiveRecordInterface;
7
use yii\helpers\ArrayHelper;
8
use yii\filters\{VerbFilter, AccessControl};
9
use yii\base\UnknownMethodException;
10
use yii\web\{BadRequestHttpException, NotFoundHttpException, Controller};
11
use Itstructure\RbacModule\Module;
12
use Itstructure\RbacModule\interfaces\{ModelInterface, ValidateComponentInterface};
13
14
/**
15
 * Class BaseController
16
 * Base controller class for the `Rbac` module.
17
 *
18
 * @property Module $module
19
 * @property bool $viewCreated
20
 * @property array $additionFields
21
 * @property array $additionAttributes
22
 * @property string $urlPrefix Url prefix for redirect and view links.
23
 * @property ModelInterface $model
24
 * @property ActiveRecordInterface $searchModel
25
 * @property ValidateComponentInterface $validateComponent
26
 *
27
 * @package Itstructure\RbacModule\controllers
28
 */
29
abstract class BaseController extends Controller
30
{
31
    /**
32
     * Watch or not created record.
33
     *
34
     * @var bool
35
     */
36
    protected $viewCreated = false;
37
38
    /**
39
     * Addition fields for the 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
     *
52
     * @var array
53
     */
54
    protected $additionAttributes = [];
55
56
    /**
57
     * Url prefix for redirect and view links.
58
     * @var string
59
     */
60
    protected $urlPrefix = '';
61
62
    /**
63
     * Model object record.
64
     *
65
     * @var ModelInterface
66
     */
67
    private $model;
68
69
    /**
70
     * Search new model object.
71
     *
72
     * @var ActiveRecordInterface
73
     */
74
    private $searchModel;
75
76
    /**
77
     * Multilanguage component.
78
     *
79
     * @var ValidateComponentInterface
80
     */
81
    private $validateComponent;
82
83
    /**
84
     * Returns the name of the base model.
85
     *
86
     * @return string
87
     */
88
    abstract protected function getModelName():string;
89
90
    /**
91
     * Returns the name of the model to search it.
92
     *
93
     * @return string
94
     */
95
    abstract protected function getSearchModelName():string;
96
97
    /**
98
     * @inheritdoc
99
     */
100
    public function behaviors()
101
    {
102
        return [
103
            'access' => [
104
                'class' => AccessControl::class,
105
                'rules' => [
106
                    [
107
                        'allow' => true,
108
                        'roles' => $this->module->accessRoles,
109
                    ],
110
                ],
111
            ],
112
            'verbs' => [
113
                'class' => VerbFilter::class,
114
                'actions' => [
115
                    'delete' => [
116
                        'POST',
117
                    ],
118
                ],
119
            ],
120
        ];
121
    }
122
123
    /**
124
     * Initializer.
125
     */
126
    public function init()
127
    {
128
        $this->view->params['user'] = Yii::$app->user->identity;
129
    }
130
131
    /**
132
     * @param \yii\base\Action $action
133
     * @return bool
134
     */
135
    public function beforeAction($action)
136
    {
137
        $this->view->params['urlPrefix'] = $this->urlPrefix;
138
139
        return parent::beforeAction($action);
140
    }
141
142
    /**
143
     * Give ability of configure view to the module class.
144
     *
145
     * @return \yii\base\View|\yii\web\View
146
     */
147
    public function getView()
148
    {
149
        if (method_exists($this->module, 'getView')) {
150
            return $this->module->getView();
151
        }
152
153
        return parent::getView();
154
    }
155
156
    /**
157
     * Set model.
158
     *
159
     * @param $model ModelInterface
160
     */
161
    public function setModel(ModelInterface $model): void
162
    {
163
        $this->model = $model;
0 ignored issues
show
Documentation Bug introduced by
It seems like $model of type object<Itstructure\RbacM...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...
164
    }
165
166
    /**
167
     * Set search model.
168
     *
169
     * @param $model ActiveRecordInterface
170
     */
171
    public function setSearchModel(ActiveRecordInterface $model): void
172
    {
173
        $this->searchModel = $model;
174
    }
175
176
    /**
177
     * Set validate component for main model.
178
     *
179
     * @param $component ValidateComponentInterface
180
     */
181
    public function setValidateComponent(ValidateComponentInterface $component): void
182
    {
183
        $this->validateComponent = $component;
0 ignored issues
show
Documentation Bug introduced by
It seems like $component of type object<Itstructure\RbacM...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...
184
    }
185
186
    /**
187
     * Returns model.
188
     *
189
     * @return ModelInterface
190
     */
191
    public function getModel(): ModelInterface
192
    {
193
        return $this->model;
194
    }
195
196
    /**
197
     * Returns search model.
198
     *
199
     * @return ActiveRecordInterface
200
     */
201
    public function getSearchModel(): ActiveRecordInterface
202
    {
203
        return $this->searchModel;
204
    }
205
206
    /**
207
     * Get validate component for main model.
208
     *
209
     * @return ValidateComponentInterface
210
     */
211
    public function getValidateComponent(): ValidateComponentInterface
212
    {
213
        return $this->validateComponent;
214
    }
215
216
    /**
217
     * List of records.
218
     *
219
     * @return string
220
     */
221
    public function actionIndex()
222
    {
223
        $this->setSearchModel(
224
            $this->getNewSearchModel()
225
        );
226
227
        return $this->render('index',
228
            ArrayHelper::merge(
229
                [
230
                    'searchModel' => $this->searchModel,
231
                    'dataProvider' => $this->searchModel->search(Yii::$app->request->queryParams),
0 ignored issues
show
Bug introduced by
The method search() does not seem to exist on object<yii\db\ActiveRecordInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
232
                ],
233
                $this->additionFields
234
            )
235
        );
236
    }
237
238
    /**
239
     * Displays one model entry.
240
     *
241
     * @param int|string $id
242
     *
243
     * @return mixed
244
     */
245
    public function actionView($id)
246
    {
247
        return $this->render('view',
248
            ArrayHelper::merge(
249
                [
250
                    'model' => $this->findModel($id),
251
                ],
252
                $this->additionFields
253
            )
254
        );
255
    }
256
257
    /**
258
     * Creates a new model record.
259
     * If the result of creation is successful, there will be a redirect to the 'view' or 'index' page.
260
     *
261
     * @return string|\yii\web\Response
262
     */
263
    public function actionCreate()
264
    {
265
        $this->setModelByConditions();
266
267
        if (Yii::$app->request->isPost &&
268
            $this->model->load(Yii::$app->request->post()) &&
269
            $this->setAdditionAttributes() &&
270
            $this->model->save()) {
271
272
            if ($this->viewCreated) {
273
                $redirectParams = [
274
                    $this->urlPrefix.'view',
275
                    'id' => $this->model->getId(),
276
                ];
277
            } else {
278
                $redirectParams = [
279
                    $this->urlPrefix.'index',
280
                ];
281
            }
282
283
            return $this->redirect($redirectParams);
284
        }
285
286
        return $this->render('create',
287
            ArrayHelper::merge(
288
                [
289
                    'model' => $this->model,
290
                ],
291
                $this->additionFields
292
            )
293
        );
294
    }
295
296
    /**
297
     * Updates the current model entry.
298
     * If the result of creation is successful, there will be a redirect to the 'view' or 'index' page.
299
     *
300
     * @param int|string $id
301
     *
302
     * @return string|\yii\web\Response
303
     */
304
    public function actionUpdate($id)
305
    {
306
        $this->setModelByConditions($id);
307
308
        if (Yii::$app->request->isPost &&
309
            $this->model->load(Yii::$app->request->post()) &&
310
            $this->setAdditionAttributes() &&
311
            $this->model->save()) {
312
313
            return $this->redirect([
314
                $this->urlPrefix.'view',
315
                'id' => $this->model->getId(),
316
            ]);
317
        }
318
319
        return $this->render('update',
320
            ArrayHelper::merge(
321
                [
322
                    'model' => $this->model,
323
                ],
324
                $this->additionFields
325
            )
326
        );
327
    }
328
329
    /**
330
     * Deletes the current model entry.
331
     * If the result of the deletion is successful, there will be a redirect to the 'index' page.
332
     *
333
     * @param int|string $id
334
     *
335
     * @return \yii\web\Response
336
     */
337
    public function actionDelete($id)
338
    {
339
        $model = $this->findModel($id);
340
341
        $model->delete();
342
343
        return $this->redirect(['index']);
344
    }
345
346
    /**
347
     * Set addition attributes for model.
348
     *
349
     * @return bool
350
     */
351
    protected function setAdditionAttributes(): bool
352
    {
353
        $this->model->setAttributes($this->additionAttributes, false);
354
355
        return true;
356
    }
357
358
    /**
359
     * Returns new object of main model.
360
     *
361
     * @return mixed
362
     */
363
    protected function getNewModel()
364
    {
365
        $modelName = $this->getModelName();
366
        return new $modelName;
367
    }
368
369
    /**
370
     * Returns new object of search main model.
371
     *
372
     * @return mixed
373
     */
374
    protected function getNewSearchModel()
375
    {
376
        $searchModelName = $this->getSearchModelName();
377
        return new $searchModelName;
378
    }
379
380
    /**
381
     * Find model record.
382
     * If the model is not found, a 404 HTTP exception will be displayed.
383
     *
384
     * @param int|string $key
385
     *
386
     *
387
     * @throws BadRequestHttpException
388
     * @throws UnknownMethodException
389
     * @throws NotFoundHttpException
390
     *
391
     * @return mixed
392
     */
393
    private function findModel($key)
394
    {
395
        if (null === $key){
396
            throw new BadRequestHttpException('Key parameter is not defined in findModel method.');
397
        }
398
399
        $modelObject = $this->getNewModel();
400
401
        if (!method_exists($modelObject, 'findOne')){
402
            $class = (new\ReflectionClass($modelObject));
403
            throw new UnknownMethodException('Method findOne does not exists in ' . $class->getNamespaceName() . '\\' . $class->getShortName().' class.');
404
        }
405
406
        $result = call_user_func([
407
            $modelObject,
408
            'findOne',
409
        ], $key);
410
411
        if ($result !== null) {
412
            return $result;
413
        }
414
415
        throw new NotFoundHttpException('The requested page does not exist.');
416
    }
417
418
    /**
419
     * Returns an intermediate model for working with the main.
420
     *
421
     * @param int|string|null $key
422
     *
423
     * @return void
424
     */
425
    private function setModelByConditions($key = null): void
426
    {
427
        $model = null === $key ? $this->getNewModel() : $this->findModel($key);
428
429
        if (null === $this->validateComponent){
430
            $this->setModel($model);
431
        } else {
432
            $this->setModel(
433
                $this->validateComponent->setModel($model)
434
            );
435
        }
436
    }
437
}
438