Passed
Push — master ( 6399b1...1fe07e )
by Andrey
02:40
created

BaseController::actionCreate()   A

Complexity

Conditions 6
Paths 3

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 17
c 1
b 0
f 0
nc 3
nop 0
dl 0
loc 29
rs 9.0777
1
<?php
2
3
namespace Itstructure\RbacModule\controllers;
4
5
use Yii;
6
use yii\helpers\ArrayHelper;
7
use yii\filters\{VerbFilter, AccessControl};
8
use yii\base\{Model, UnknownMethodException};
9
use yii\web\{BadRequestHttpException, ConflictHttpException, NotFoundHttpException, Controller};
10
use Itstructure\RbacModule\Module;
11
use Itstructure\RbacModule\interfaces\{ModelInterface, ValidateComponentInterface, RbacIdentityInterface};
12
13
/**
14
 * Class BaseController
15
 * Base controller class for the `Rbac` module.
16
 *
17
 * @property Module $module
18
 * @property bool $viewCreated
19
 * @property array $additionFields
20
 * @property array $additionAttributes
21
 * @property string $urlPrefix Url prefix for redirect and view links.
22
 * @property string $urlPrefixNeighbor Url prefix for redirect and view links of neighbor entity.
23
 * @property ModelInterface $model
24
 * @property Model $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
     *
59
     * @var string
60
     */
61
    protected $urlPrefix = '';
62
63
    /**
64
     * Url prefix for redirect and view links of neighbor entity.
65
     *
66
     * @var string
67
     */
68
    protected $urlPrefixNeighbor = '';
69
70
    /**
71
     * Model object record.
72
     *
73
     * @var ModelInterface
74
     */
75
    private $model;
76
77
    /**
78
     * Search new model object.
79
     *
80
     * @var Model
81
     */
82
    private $searchModel;
83
84
    /**
85
     * Multilanguage component.
86
     *
87
     * @var ValidateComponentInterface
88
     */
89
    private $validateComponent;
90
91
    /**
92
     * Returns the name of the base model.
93
     *
94
     * @return string
95
     */
96
    abstract protected function getModelName(): string;
97
98
    /**
99
     * Returns the name of the model to search it.
100
     *
101
     * @return string
102
     */
103
    abstract protected function getSearchModelName(): string;
104
105
    /**
106
     * @inheritdoc
107
     */
108
    public function behaviors()
109
    {
110
        return [
111
            'access' => [
112
                'class' => AccessControl::class,
113
                'rules' => [
114
                    [
115
                        'allow' => true,
116
                        'roles' => $this->module->accessRoles,
117
                    ],
118
                ],
119
            ],
120
            'verbs' => [
121
                'class' => VerbFilter::class,
122
                'actions' => [
123
                    'delete' => [
124
                        'POST',
125
                    ],
126
                ],
127
            ],
128
        ];
129
    }
130
131
    /**
132
     * Initializer.
133
     */
134
    public function init()
135
    {
136
        parent::init();
137
138
        $this->view->params['user'] = Yii::$app->user->identity;
139
    }
140
141
    /**
142
     * @param \yii\base\Action $action
143
     *
144
     * @return bool
145
     */
146
    public function beforeAction($action)
147
    {
148
        $this->view->params['urlPrefix']         = $this->urlPrefix;
149
        $this->view->params['urlPrefixNeighbor'] = $this->urlPrefixNeighbor;
150
151
        return parent::beforeAction($action);
152
    }
153
154
    /**
155
     * Give ability of configure view to the module class.
156
     *
157
     * @return \yii\base\View|\yii\web\View
158
     */
159
    public function getView()
160
    {
161
        if (method_exists($this->module, 'getView')) {
162
            return $this->module->getView();
163
        }
164
165
        return parent::getView();
166
    }
167
168
    /**
169
     * Set model.
170
     *
171
     * @param $model ModelInterface
172
     */
173
    public function setModel(ModelInterface $model): void
174
    {
175
        $this->model = $model;
176
    }
177
178
    /**
179
     * Set search model.
180
     *
181
     * @param $model Model
182
     */
183
    public function setSearchModel(Model $model): void
184
    {
185
        $this->searchModel = $model;
186
    }
187
188
    /**
189
     * Set validate component for main model.
190
     *
191
     * @param $component ValidateComponentInterface
192
     */
193
    public function setValidateComponent(ValidateComponentInterface $component): void
194
    {
195
        $this->validateComponent = $component;
196
    }
197
198
    /**
199
     * Returns model.
200
     *
201
     * @return ModelInterface
202
     */
203
    public function getModel(): ModelInterface
204
    {
205
        return $this->model;
206
    }
207
208
    /**
209
     * Returns search model.
210
     *
211
     * @return Model
212
     */
213
    public function getSearchModel(): Model
214
    {
215
        return $this->searchModel;
216
    }
217
218
    /**
219
     * Get validate component for main model.
220
     *
221
     * @return ValidateComponentInterface
222
     */
223
    public function getValidateComponent(): ValidateComponentInterface
224
    {
225
        return $this->validateComponent;
226
    }
227
228
    /**
229
     * List of records.
230
     *
231
     * @return string
232
     */
233
    public function actionIndex()
234
    {
235
        $this->setSearchModel(
236
            $this->getNewSearchModel()
237
        );
238
239
        return $this->render('index',
240
            ArrayHelper::merge(
241
                [
242
                    'searchModel' => $this->searchModel,
243
                    'dataProvider' => $this->searchModel->search(Yii::$app->request->queryParams),
244
                ],
245
                $this->getAdditionFields()
246
            )
247
        );
248
    }
249
250
    /**
251
     * Displays one model entry.
252
     *
253
     * @param int|string $id
254
     *
255
     * @return mixed
256
     */
257
    public function actionView($id)
258
    {
259
        return $this->render('view',
260
            ArrayHelper::merge(
261
                [
262
                    'model' => $this->findModel($id),
263
                ],
264
                $this->getAdditionFields()
265
            )
266
        );
267
    }
268
269
    /**
270
     * Creates a new model record.
271
     * If the result of creation is successful, there will be a redirect to the 'view' or 'index' page.
272
     *
273
     * @return string|\yii\web\Response
274
     */
275
    public function actionCreate()
276
    {
277
        $this->setModelByConditions();
278
279
        if (Yii::$app->request->isPost &&
280
            $this->model->load(Yii::$app->request->post()) &&
281
            $this->setAdditionAttributes() &&
282
            $this->model->save()) {
283
284
            if ($this->viewCreated) {
285
                $redirectParams = [
286
                    $this->urlPrefix.'view',
287
                    'id' => $this->model->getId(),
288
                ];
289
            } else {
290
                $redirectParams = [
291
                    $this->urlPrefix.'index',
292
                ];
293
            }
294
295
            return $this->redirect($redirectParams);
296
        }
297
298
        return $this->render('create',
299
            ArrayHelper::merge(
300
                [
301
                    'model' => $this->model,
302
                ],
303
                $this->getAdditionFields()
304
            )
305
        );
306
    }
307
308
    /**
309
     * Updates the current model entry.
310
     * If the result of creation is successful, there will be a redirect to the 'view' or 'index' page.
311
     *
312
     * @param int|string $id
313
     *
314
     * @return string|\yii\web\Response
315
     */
316
    public function actionUpdate($id)
317
    {
318
        $this->setModelByConditions($id);
319
320
        if (Yii::$app->request->isPost &&
321
            $this->model->load(Yii::$app->request->post()) &&
322
            $this->setAdditionAttributes() &&
323
            $this->model->save()) {
324
325
            return $this->redirect([
326
                $this->urlPrefix.'view',
327
                'id' => $this->model->getId(),
328
            ]);
329
        }
330
331
        return $this->render('update',
332
            ArrayHelper::merge(
333
                [
334
                    'model' => $this->model,
335
                ],
336
                $this->getAdditionFields()
337
            )
338
        );
339
    }
340
341
    /**
342
     * Deletes the current model entry.
343
     * If the result of the deletion is successful, there will be a redirect to the 'index' page.
344
     *
345
     * @param int|string $id
346
     *
347
     * @throws ConflictHttpException
348
     *
349
     * @return \yii\web\Response
350
     */
351
    public function actionDelete($id)
352
    {
353
        $model = $this->findModel($id);
354
355
        if (($model instanceof RbacIdentityInterface) && $id == Yii::$app->user->identity->getId()) {
0 ignored issues
show
Bug introduced by
The method getId() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

355
        if (($model instanceof RbacIdentityInterface) && $id == Yii::$app->user->identity->/** @scrutinizer ignore-call */ getId()) {

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...
356
            throw new ConflictHttpException('You can not delete yourself.');
357
        };
358
359
        $model->delete();
360
361
        return $this->redirect(['index']);
362
    }
363
364
    /**
365
     * Set addition attributes for model.
366
     *
367
     * @return bool
368
     */
369
    protected function setAdditionAttributes(): bool
370
    {
371
        $this->model->setAttributes($this->additionAttributes, false);
372
373
        return true;
374
    }
375
376
    /**
377
     * Get addition fields for the view template.
378
     *
379
     * @return array
380
     */
381
    protected function getAdditionFields(): array
382
    {
383
        return $this->additionFields;
384
    }
385
386
    /**
387
     * Returns new object of main model.
388
     *
389
     * @return mixed
390
     */
391
    protected function getNewModel()
392
    {
393
        $modelName = $this->getModelName();
394
        return new $modelName;
395
    }
396
397
    /**
398
     * Returns new object of search main model.
399
     *
400
     * @return RbacIdentityInterface|ModelInterface
401
     */
402
    protected function getNewSearchModel()
403
    {
404
        $searchModelName = $this->getSearchModelName();
405
        return new $searchModelName;
406
    }
407
408
    /**
409
     * Find model record.
410
     * If the model is not found, a 404 HTTP exception will be displayed.
411
     *
412
     * @param int|string $key
413
     *
414
     *
415
     * @throws BadRequestHttpException
416
     * @throws UnknownMethodException
417
     * @throws NotFoundHttpException
418
     *
419
     * @return mixed
420
     */
421
    private function findModel($key)
422
    {
423
        if (null === $key) {
0 ignored issues
show
introduced by
The condition null === $key is always false.
Loading history...
424
            throw new BadRequestHttpException('Key parameter is not defined in findModel method.');
425
        }
426
427
        $modelObject = $this->getNewModel();
428
429
        if (!method_exists($modelObject, 'findOne')) {
430
            $class = (new\ReflectionClass($modelObject));
0 ignored issues
show
Bug introduced by
The function ReflectionClass was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

430
            $class = (/** @scrutinizer ignore-call */ new\ReflectionClass($modelObject));
Loading history...
431
            throw new UnknownMethodException('Method findOne does not exists in ' . $class->getNamespaceName() . '\\' .
432
                $class->getShortName().' class.');
433
        }
434
435
        $result = call_user_func([
436
            $modelObject,
437
            'findOne',
438
        ], $key);
439
440
        if ($result !== null) {
441
            return $result;
442
        }
443
444
        throw new NotFoundHttpException('The requested page does not exist.');
445
    }
446
447
    /**
448
     * Returns an intermediate model for working with the main.
449
     *
450
     * @param int|string|null $key
451
     *
452
     * @return void
453
     */
454
    private function setModelByConditions($key = null): void
455
    {
456
        $model = null === $key ? $this->getNewModel() : $this->findModel($key);
457
458
        if (null === $this->validateComponent) {
459
            $this->setModel($model);
460
        } else {
461
            $this->setModel(
462
                $this->validateComponent->setModel($model)
463
            );
464
        }
465
    }
466
}
467