ToggleAction   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 23
lcom 1
cbo 6
dl 0
loc 133
ccs 0
cts 58
cp 0
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 7 2
D run() 0 45 18
A findModel() 0 8 3
1
<?php
2
3
/*
4
 * This file is part of the 2amigos/yii2-grid-view-library project.
5
 * (c) 2amigOS! <http://2amigos.us/>
6
 * For the full copyright and license information, please view
7
 * the LICENSE file that was distributed with this source code.
8
 */
9
10
namespace dosamigos\grid\actions;
11
12
use Yii;
13
use yii\base\Action;
14
use yii\base\InvalidConfigException;
15
use yii\web\BadRequestHttpException;
16
use yii\web\NotFoundHttpException;
17
use yii\web\Response;
18
19
/**
20
 * ToggleAction works in conjunction with ToggleColumn to ease the task to update the model.
21
 */
22
class ToggleAction extends Action
23
{
24
    const TOGGLE_ANY = 'toggleany';
25
    const TOGGLE_UNIQ = 'toggleuniq';
26
    const TOGGLE_COND = 'togglecond';
27
    /**
28
     * @var string the class name of the model.
29
     */
30
    public $modelClass;
31
    /**
32
     * @var mixed the on value to set the attribute with.
33
     */
34
    public $onValue = 1;
35
    /**
36
     * @var mixed the off value to set the attribute with.
37
     */
38
    public $offValue = 0;
39
40
    /**
41
     * one of constants
42
     * ToggleAction::TOGGLE_ANY - change state of any element (by default)
43
     * ToggleAction::TOGGLE_UNIQ - only one element must be equal $onValue
44
     * ToggleAction::TOGGLE_COND - toggle one element to $onValue per condition (for example only one foto can be set as cover per album)
45
     *
46
     * @var string
47
     */
48
    public $toggleType = self::TOGGLE_ANY;
49
50
    /**
51
     * property for TOGGLE_UNIQ and TOGGLE_COND types - allow set all in offValue
52
     *
53
     * @var bool
54
     */
55
    public $allowAllOff = false;
56
57
    /**
58
     * @var mixed (array|string|callable) $condition the conditions that will be put in the WHERE part of the UPDATE SQL
59
     *            (used where $toggleType=ToggleAction::TOGGLE_COND)
60
     *            Please refer to [[Query::where()]] on how to specify this parameter.
61
     *
62
     * @example
63
     * ['another_attribute'=>20]
64
     * or
65
     * function($model){
66
     *     return ['attr'=>$model->attr];
67
     * }
68
     * where $model - is current toggled model object
69
     **/
70
    public $condition = [];
71
72
    /**
73
     * @var string scenario for this action
74
     **/
75
    public $scenario = 'default';
76
77
    /**
78
     * @inheritdoc
79
     * @throws \yii\base\InvalidConfigException
80
     */
81
    public function init()
82
    {
83
        if ($this->modelClass === null) {
84
            throw new InvalidConfigException('"modelClass" cannot be empty.');
85
        }
86
        parent::init();
87
    }
88
89
    /**
90
     * @inheritdoc
91
     * @throws \yii\web\BadRequestHttpException
92
     */
93
    public function run($id, $attribute)
94
    {
95
        if (Yii::$app->request->isAjax) {
96
            $model = $this->findModel($id);
97
            $model->setScenario($this->scenario);
98
            Yii::$app->response->format = Response::FORMAT_JSON;
99
            if ($this->toggleType == self::TOGGLE_ANY) {
100
                $model->setAttributes(
101
                    [$attribute => $model->$attribute == $this->offValue ? $this->onValue : $this->offValue]
102
                );
103
                if ($model->validate() && $model->save(false, [$attribute])) {
104
                    return ['result' => true, 'value' => ($model->$attribute == $this->onValue)];
105
                }
106
            } elseif ($this->toggleType == self::TOGGLE_UNIQ) {
107
                if ($model->$attribute == $this->offValue || $this->allowAllOff) {
108
                    $model->setAttributes(
109
                        [$attribute => $model->$attribute == $this->offValue ? $this->onValue : $this->offValue]
110
                    );
111
                    if ($model->validate()) {
112
                        /**may  be transaction?**/
113
                        $model->updateAll([$attribute => $this->offValue]);
114
                        if ($model->save(false, [$attribute])) {
115
                            return ['result' => true, 'value' => ($model->$attribute == $this->onValue)];
116
                        }
117
                    }
118
                }
119
            } else {
120
                if ($model->$attribute == $this->offValue || $this->allowAllOff) {
121
                    $cond = is_callable($this->condition) ? call_user_func($this->condition, $model) : $this->condition;
122
                    $model->setAttributes(
123
                        [$attribute => $model->$attribute == $this->offValue ? $this->onValue : $this->offValue]
124
                    );
125
                    if ($model->validate()) {
126
                        $model->updateAll([$attribute => $this->offValue], $cond);
127
                        if ($model->save(false, [$attribute])) {
128
                            return ['result' => true, 'value' => ($model->$attribute == $this->onValue)];
129
                        }
130
                    }
131
                }
132
            }
133
134
            return ['result' => false, 'errors' => $model->getErrors()];
135
        }
136
        throw new BadRequestHttpException(Yii::t('app', 'Invalid request'));
137
    }
138
139
    /**
140
     * Finds the model based on its primary key value.
141
     * If the model is not found, a 404 HTTP exception will be thrown.
142
     * @param  integer               $id
143
     * @throws NotFoundHttpException if the model cannot be found
144
     * @return \yii\db\ActiveRecord  the loaded model
145
     */
146
    protected function findModel($id)
147
    {
148
        $class = $this->modelClass;
149
        if ($id !== null && ($model = $class::findOne($id)) !== null) {
150
            return $model;
151
        }
152
        throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.'));
153
    }
154
}
155