Completed
Push — master ( b77654...b3682d )
by Andrey
01:32
created

BaseController::getAdditionFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Itstructure\UsersModule\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\{IdentityInterface, ConflictHttpException, BadRequestHttpException, NotFoundHttpException, Controller};
11
use Itstructure\UsersModule\Module;
12
use Itstructure\UsersModule\interfaces\{ModelInterface, ValidateComponentInterface};
13
14
/**
15
 * Class BaseController
16
 * Base controller class for the `users` module.
17
 *
18
 * @property Module $module
19
 * @property bool $viewCreated
20
 * @property array $additionFields
21
 * @property array $additionAttributes
22
 * @property ModelInterface $model
23
 * @property ActiveRecordInterface $searchModel
24
 * @property ValidateComponentInterface $validateComponent
25
 *
26
 * @package Itstructure\UsersModule\controllers
27
 */
28
abstract class BaseController extends Controller
29
{
30
    /**
31
     * Watch or not created record.
32
     *
33
     * @var bool
34
     */
35
    protected $viewCreated = false;
36
37
    /**
38
     * Addition fields for the template.
39
     *
40
     * @var array
41
     */
42
    protected $additionFields = [];
43
44
    /**
45
     * Addition attributes with values for the model.
46
     * [
47
     *    'key1' => 'value1',
48
     *    'key2' => 'value2',
49
     * ]
50
     *
51
     * @var array
52
     */
53
    protected $additionAttributes = [];
54
55
    /**
56
     * Model object record.
57
     *
58
     * @var ModelInterface
59
     */
60
    private $model;
61
62
    /**
63
     * Search new model object.
64
     *
65
     * @var ActiveRecordInterface
66
     */
67
    private $searchModel;
68
69
    /**
70
     * Validate component.
71
     *
72
     * @var ValidateComponentInterface
73
     */
74
    private $validateComponent = null;
75
76
    /**
77
     * Returns the name of the base model.
78
     *
79
     * @return string
80
     */
81
    abstract protected function getModelName():string;
82
83
    /**
84
     * Returns the name of the model to search it.
85
     *
86
     * @return string
87
     */
88
    abstract protected function getSearchModelName():string;
89
90
    /**
91
     * @inheritdoc
92
     */
93
    public function behaviors()
94
    {
95
        return [
96
            'access' => [
97
                'class' => AccessControl::class,
98
                'rules' => [
99
                    [
100
                        'allow' => true,
101
                        'roles' => $this->module->accessRoles,
102
                    ],
103
                ],
104
            ],
105
            'verbs' => [
106
                'class' => VerbFilter::class,
107
                'actions' => [
108
                    'delete' => [
109
                        'POST',
110
                    ],
111
                ],
112
            ],
113
        ];
114
    }
115
116
    /**
117
     * Initializer.
118
     */
119
    public function init()
120
    {
121
        $this->view->params['user'] = Yii::$app->user->identity;
122
    }
123
124
    /**
125
     * Give ability of configure view to the module class.
126
     *
127
     * @return \yii\base\View|\yii\web\View
128
     */
129
    public function getView()
130
    {
131
        if (method_exists($this->module, 'getView')) {
132
            return $this->module->getView();
133
        }
134
135
        return parent::getView();
136
    }
137
138
    /**
139
     * Set model.
140
     *
141
     * @param $model ModelInterface
142
     */
143
    public function setModel(ModelInterface $model): void
144
    {
145
        $this->model = $model;
0 ignored issues
show
Documentation Bug introduced by
It seems like $model of type object<Itstructure\Users...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...
146
    }
147
148
    /**
149
     * Set search model.
150
     *
151
     * @param $model ActiveRecordInterface
152
     */
153
    public function setSearchModel(ActiveRecordInterface $model): void
154
    {
155
        $this->searchModel = $model;
156
    }
157
158
    /**
159
     * Set validate component for main model.
160
     *
161
     * @param $component ValidateComponentInterface
162
     */
163
    public function setValidateComponent(ValidateComponentInterface $component): void
164
    {
165
        $this->validateComponent = $component;
0 ignored issues
show
Documentation Bug introduced by
It seems like $component of type object<Itstructure\Users...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...
166
    }
167
168
    /**
169
     * Returns model.
170
     *
171
     * @return ModelInterface
172
     */
173
    public function getModel(): ModelInterface
174
    {
175
        return $this->model;
176
    }
177
178
    /**
179
     * Returns search model.
180
     *
181
     * @return ActiveRecordInterface
182
     */
183
    public function getSearchModel(): ActiveRecordInterface
184
    {
185
        return $this->searchModel;
186
    }
187
188
    /**
189
     * Get validate component for main model.
190
     *
191
     * @return ValidateComponentInterface
192
     */
193
    public function getValidateComponent(): ValidateComponentInterface
194
    {
195
        return $this->validateComponent;
196
    }
197
198
    /**
199
     * List of records.
200
     *
201
     * @return string
202
     */
203
    public function actionIndex()
204
    {
205
        $this->setSearchModel(
206
            $this->getNewSearchModel()
207
        );
208
209
        return $this->render('index',
210
            ArrayHelper::merge(
211
                [
212
                    'searchModel' => $this->searchModel,
213
                    '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...
214
                ],
215
                $this->getAdditionFields()
216
            )
217
        );
218
    }
219
220
    /**
221
     * Displays one model entry.
222
     *
223
     * @param int|string $id
224
     *
225
     * @return mixed
226
     */
227
    public function actionView($id)
228
    {
229
        return $this->render('view',
230
            ArrayHelper::merge(
231
                [
232
                    'model' => $this->findModel($id),
233
                ],
234
                $this->getAdditionFields()
235
            )
236
        );
237
    }
238
239
    /**
240
     * Creates a new model record.
241
     * If the result of creation is successful, there will be a redirect to the 'view' or 'index' page.
242
     *
243
     * @return string|\yii\web\Response
244
     */
245
    public function actionCreate()
246
    {
247
        $this->setModelByConditions();
248
249
        if (Yii::$app->request->isPost &&
250
            $this->model->load(Yii::$app->request->post()) &&
251
            $this->setAdditionAttributes() &&
252
            $this->model->save()) {
253
254
            if ($this->viewCreated) {
255
                $redirectParams = [
256
                    'view',
257
                    'id' => $this->model->getId(),
258
                ];
259
            } else {
260
                $redirectParams = [
261
                    'index',
262
                ];
263
            }
264
265
            return $this->redirect($redirectParams);
266
        }
267
268
        return $this->render('create',
269
            ArrayHelper::merge(
270
                [
271
                    'model' => $this->model,
272
                ],
273
                $this->getAdditionFields()
274
            )
275
        );
276
    }
277
278
    /**
279
     * Updates the current model entry.
280
     * If the result of creation is successful, there will be a redirect to the 'view' or 'index' page.
281
     *
282
     * @param int|string $id
283
     *
284
     * @return string|\yii\web\Response
285
     */
286
    public function actionUpdate($id)
287
    {
288
        $this->setModelByConditions($id);
289
290
        if (Yii::$app->request->isPost &&
291
            $this->model->load(Yii::$app->request->post()) &&
292
            $this->setAdditionAttributes() &&
293
            $this->model->save()) {
294
295
            return $this->redirect([
296
                'view',
297
                'id' => $this->model->getId(),
298
            ]);
299
        }
300
301
        return $this->render('update',
302
            ArrayHelper::merge(
303
                [
304
                    'model' => $this->model,
305
                ],
306
                $this->getAdditionFields()
307
            )
308
        );
309
    }
310
311
    /**
312
     * Deletes the current model entry.
313
     * If the result of the deletion is successful, there will be a redirect to the 'index' page.
314
     *
315
     * @param int|string $id
316
     *
317
     * @return \yii\web\Response
318
     *
319
     * @throws ConflictHttpException
320
     */
321
    public function actionDelete($id)
322
    {
323
        $model = $this->findModel($id);
324
325
        if ($model instanceof IdentityInterface && $id == Yii::$app->user->identity->getId()) {
326
            throw new ConflictHttpException('You can not delete yourself.');
327
        };
328
329
        $model->delete();
330
331
        return $this->redirect(['index']);
332
    }
333
334
    /**
335
     * Set addition attributes for model.
336
     *
337
     * @return bool
338
     */
339
    protected function setAdditionAttributes(): bool
340
    {
341
        $this->model->setAttributes($this->additionAttributes, false);
342
343
        return true;
344
    }
345
346
    /**
347
     * Get addition fields for the view template.
348
     * @return array
349
     */
350
    protected function getAdditionFields(): array
351
    {
352
        return $this->additionFields;
353
    }
354
355
    /**
356
     * Returns new object of main model.
357
     *
358
     * @return mixed
359
     */
360
    protected function getNewModel()
361
    {
362
        $modelName = $this->getModelName();
363
        return new $modelName;
364
    }
365
366
    /**
367
     * Returns new object of search main model.
368
     *
369
     * @return mixed
370
     */
371
    protected function getNewSearchModel()
372
    {
373
        $searchModelName = $this->getSearchModelName();
374
        return new $searchModelName;
375
    }
376
377
    /**
378
     * Find model record.
379
     * If the model is not found, a 404 HTTP exception will be displayed.
380
     *
381
     * @param int|string $key
382
     *
383
     *
384
     * @throws BadRequestHttpException
385
     * @throws UnknownMethodException
386
     * @throws NotFoundHttpException
387
     *
388
     * @return mixed
389
     */
390
    private function findModel($key)
391
    {
392
        if (null === $key){
393
            throw new BadRequestHttpException('Key parameter is not defined in findModel method.');
394
        }
395
396
        $modelObject = $this->getNewModel();
397
398 View Code Duplication
        if (!method_exists($modelObject, 'findOne')){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
399
            $class = (new\ReflectionClass($modelObject));
400
            throw new UnknownMethodException('Method findOne does not exists in ' . $class->getNamespaceName() . '\\' . $class->getShortName().' class.');
401
        }
402
403
        $result = call_user_func([
404
            $modelObject,
405
            'findOne',
406
        ], $key);
407
408
        if ($result !== null) {
409
            return $result;
410
        }
411
412
        throw new NotFoundHttpException('The requested page does not exist.');
413
    }
414
415
    /**
416
     * Returns an intermediate model for working with the main.
417
     *
418
     * @param int|string|null $key
419
     *
420
     * @return void
421
     */
422
    private function setModelByConditions($key = null): void
423
    {
424
        $model = null === $key ? $this->getNewModel() : $this->findModel($key);
425
426
        if (null === $this->validateComponent){
427
            $this->setModel($model);
428
        } else {
429
            $this->setModel(
430
                $this->validateComponent->setModel($model)
431
            );
432
        }
433
    }
434
}