Transition   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 175
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 74
dl 0
loc 175
ccs 51
cts 51
cp 1
rs 10
c 0
b 0
f 0
wmc 11

8 Methods

Rating   Name   Duplication   Size   Complexity  
A attributeTypecast() 0 5 1
A userCan() 0 20 4
A tableName() 0 3 1
A rules() 0 63 1
A getSourceStage() 0 3 1
A attributeLabels() 0 7 1
A getPermissions() 0 9 1
A getTargetStage() 0 3 1
1
<?php
2
3
namespace roaresearch\yii2\workflow\models;
4
5
use Yii;
6
use yii\db\ActiveQuery;
7
8
/**
9
 * Model class for table `{{%workflow_transition}}`
10
 *
11
 * @property integer $source_stage_id
12
 * @property integer $target_stage_id
13
 * @property string $name
14
 *
15
 * @property Stage $sourceStage
16
 * @property Stage $targetStage
17
 * @property TransitionPermission[] $permissions
18
 */
19
class Transition extends \roaresearch\yii2\rmdb\models\Entity
20
{
21
    public const SCENARIO_UPDATE = 'update';
22
    public const SCENARIO_CREATE = 'create';
23
24
    /**
25
     * @var string full class name of the model to be used for the relations
26
     * `getSourceStage()` and `getTargetStage()`.
27
     */
28
    protected $stageClass = Stage::class;
29
30
    /**
31
     * @var string full class name of the model to be used for the relation
32
     * `getPermissions()`.
33
     */
34
    protected $permissionClass = TransitionPermission::class;
35
36
    /**
37
     * @inheritdoc
38
     */
39 17
    public static function tableName()
40
    {
41 17
        return '{{%workflow_transition}}';
42
    }
43
44
    /**
45
     * @inheritdoc
46
     */
47 13
    protected function attributeTypecast(): ?array
48
    {
49 13
        return parent::attributeTypecast() + [
50 13
            'source_stage_id' => 'integer',
51
            'target_stage_id' => 'integer',
52
        ];
53
    }
54
55
    /**
56
     * @inheritdoc
57
     */
58 2
    public function rules()
59
    {
60
        return [
61
            [
62 2
                ['!source_stage_id', '!target_stage_id'],
63 2
                'safe',
64 2
                'on' => [self::SCENARIO_UPDATE],
65
            ],
66
            [['name'], 'string', 'min' => 6],
67
            [['source_stage_id', 'target_stage_id', 'name'], 'required'],
68
            [
69
                ['source_stage_id', 'target_stage_id'],
70 2
                'integer',
71 2
                'on' => [self::SCENARIO_CREATE],
72
            ],
73
            [
74
                ['source_stage_id'],
75 2
                'exist',
76
                'targetClass' => Stage::class,
77
                'targetAttribute' => ['source_stage_id' => 'id'],
78
                'skipOnError' => true,
79 2
                'on' => [self::SCENARIO_CREATE],
80
            ],
81
            [
82
                ['target_stage_id'],
83 2
                'exist',
84
                'targetClass' => Stage::class,
85
                'targetAttribute' => ['target_stage_id' => 'id'],
86
                'skipOnError' => true,
87 2
                'on' => [self::SCENARIO_CREATE],
88
            ],
89
            [
90
                ['target_stage_id'],
91 2
                'exist',
92
                'targetAttribute' => [
93
                    'target_stage_id' => 'id',
94
                ],
95
                'targetClass' => Stage::class,
96
                'skipOnError' => true,
97 2
                'when' => function () {
98 1
                    return !$this->hasErrors('source_stage_id');
99 2
                },
100 2
                'filter' => function ($query) {
101 1
                    $query->innerJoinWith(['siblings'])->andWhere([
102 1
                        'siblings.id' => $this->source_stage_id
103
                    ]);
104 2
                },
105 2
                'on' => [self::SCENARIO_CREATE],
106 2
                'message' => 'The stages are not associated to the same workflow.',
107
            ],
108
109
            [
110
                ['target_stage_id'],
111 2
                'unique',
112
                'targetAttribute' => ['source_stage_id', 'target_stage_id'],
113 2
                'on' => [self::SCENARIO_CREATE],
114 2
                'message' => 'Target already in use for the source stage.'
115
            ],
116
            [
117
                ['name'],
118
                'unique',
119
                'targetAttribute' => ['source_stage_id', 'name'],
120
                'message' => 'Name already used for the source stage.'
121
            ],
122
        ];
123
    }
124
125
    /**
126
     * Whether the user can execute the transition.
127
     *
128
     * @param int $userId
129
     * @param Process $process
130
     * @return bool
131
     */
132 3
    public function userCan(?int $userId, Process $process): bool
133
    {
134 3
        if (!$this->getPermissions()->exists()) {
135 1
            return true;
136
        }
137
138 2
        $authManager = Yii::$app->authManager;
139
140 2
        foreach ($this->permissions as $permission) {
141
            if (
142 2
                !$authManager->checkAccess($userId, $permission->permission, [
143 2
                    'transition' => $this,
144 2
                    'process' => $process,
145
                ])
146
            ) {
147 2
                return false;
148
            }
149
        }
150
151 2
        return true;
152
    }
153
154
    /**
155
     * @inheritdoc
156
     */
157 3
    public function attributeLabels()
158
    {
159 3
        return array_merge([
160 3
            'source_stage_id' => 'Source Stage ID',
161
            'target_stage_id' => 'Target Stage ID',
162
            'name' => 'Transition Name',
163 3
        ], parent::attributeLabels());
164
    }
165
166
    /**
167
     * @return ActiveQuery
168
     */
169 10
    public function getSourceStage(): ActiveQuery
170
    {
171 10
        return $this->hasOne($this->stageClass, ['id' => 'source_stage_id']);
172
    }
173
174
    /**
175
     * @return ActiveQuery
176
     */
177 6
    public function getTargetStage(): ActiveQuery
178
    {
179 6
        return $this->hasOne($this->stageClass, ['id' => 'target_stage_id']);
180
    }
181
182
    /**
183
     * @return ActiveQuery
184
     */
185 4
    public function getPermissions(): ActiveQuery
186
    {
187 4
        return $this->hasMany(
188 4
            $this->permissionClass,
189
            [
190 4
                'source_stage_id' => 'source_stage_id',
191
                'target_stage_id' => 'target_stage_id',
192
            ]
193 4
        )->inverseOf('transition');
194
    }
195
}
196