Completed
Push — master ( 5b873e...d824de )
by Alexey
02:27
created

m170615_234118_create_rbac_table::safeUp()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 85
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 85
c 0
b 0
f 0
rs 8.6875
cc 3
eloc 51
nc 4
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace modules\rbac\migrations;
4
5
use Yii;
6
use yii\base\InvalidConfigException;
7
use yii\db\Migration;
8
use yii\rbac\DbManager;
9
10
/**
11
 * Class m170615_234118_create_rbac_table
12
 * @package modules\rbac\migrations
13
 */
14
class m170615_234118_create_rbac_table extends Migration
15
{
16
    /**
17
     * @throws \yii\base\InvalidConfigException
18
     * @return DbManager
19
     */
20
    protected function getAuthManager()
21
    {
22
        $authManager = Yii::$app->getAuthManager();
23
        if (!$authManager instanceof DbManager) {
24
            throw new InvalidConfigException('You should configure "authManager" component to use database before executing this migration.');
25
        }
26
        return $authManager;
27
    }
28
29
    /**
30
     * @return bool
31
     */
32
    protected function isMSSQL()
33
    {
34
        return $this->db->driverName === 'mssql' || $this->db->driverName === 'sqlsrv' || $this->db->driverName === 'dblib';
35
    }
36
37
    protected function isOracle()
38
    {
39
        return $this->db->driverName === 'oci';
40
    }
41
42
    /**
43
     * @inheritdoc
44
     */
45
    public function safeUp()
46
    {
47
        $authManager = $this->getAuthManager();
48
        $this->db = $authManager->db;
49
50
        $tableOptions = null;
51
        if ($this->db->driverName === 'mysql') {
52
            // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
53
            $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
54
        }
55
56
        $this->createTable($authManager->ruleTable, [
57
            'name' => $this->string(64)->notNull(),
58
            'data' => $this->binary(),
59
            'created_at' => $this->integer(),
60
            'updated_at' => $this->integer(),
61
            'PRIMARY KEY ([[name]])',
62
        ], $tableOptions);
63
64
        $this->createTable($authManager->itemTable, [
65
            'name' => $this->string(64)->notNull(),
66
            'type' => $this->smallInteger()->notNull(),
67
            'description' => $this->text(),
68
            'rule_name' => $this->string(64),
69
            'data' => $this->binary(),
70
            'created_at' => $this->integer(),
71
            'updated_at' => $this->integer(),
72
            'PRIMARY KEY ([[name]])',
73
            'FOREIGN KEY ([[rule_name]]) REFERENCES ' . $authManager->ruleTable . ' ([[name]])'.
74
            $this->buildFkClause('ON DELETE SET NULL', 'ON UPDATE CASCADE')
75
        ], $tableOptions);
76
        $this->createIndex('idx-auth_item-type', $authManager->itemTable, 'type');
77
78
        $this->createTable($authManager->itemChildTable, [
79
            'parent' => $this->string(64)->notNull(),
80
            'child' => $this->string(64)->notNull(),
81
            'PRIMARY KEY ([[parent]], [[child]])',
82
            'FOREIGN KEY ([[parent]]) REFERENCES ' . $authManager->itemTable . ' ([[name]])'.
83
            $this->buildFkClause('ON DELETE CASCADE', 'ON UPDATE CASCADE'),
84
            'FOREIGN KEY ([[child]]) REFERENCES ' . $authManager->itemTable . ' ([[name]])'.
85
            $this->buildFkClause('ON DELETE CASCADE', 'ON UPDATE CASCADE'),
86
        ], $tableOptions);
87
88
        $this->createTable($authManager->assignmentTable, [
89
            'item_name' => $this->string(64)->notNull(),
90
            'user_id' => $this->string(64)->notNull(),
91
            'created_at' => $this->integer(),
92
            'PRIMARY KEY ([[item_name]], [[user_id]])',
93
            'FOREIGN KEY ([[item_name]]) REFERENCES ' . $authManager->itemTable . ' ([[name]])' .
94
            $this->buildFkClause('ON DELETE CASCADE', 'ON UPDATE CASCADE'),
95
        ], $tableOptions);
96
97
        if ($this->isMSSQL()) {
98
            $this->execute("CREATE TRIGGER dbo.trigger_auth_item_child
99
            ON dbo.{$authManager->itemTable}
100
            INSTEAD OF DELETE, UPDATE
101
            AS
102
            DECLARE @old_name VARCHAR (64) = (SELECT name FROM deleted)
103
            DECLARE @new_name VARCHAR (64) = (SELECT name FROM inserted)
104
            BEGIN
105
            IF COLUMNS_UPDATED() > 0
106
                BEGIN
107
                    IF @old_name <> @new_name
108
                    BEGIN
109
                        ALTER TABLE {$authManager->itemChildTable} NOCHECK CONSTRAINT FK__auth_item__child;
110
                        UPDATE {$authManager->itemChildTable} SET child = @new_name WHERE child = @old_name;
111
                    END
112
                UPDATE {$authManager->itemTable}
113
                SET name = (SELECT name FROM inserted),
114
                type = (SELECT type FROM inserted),
115
                description = (SELECT description FROM inserted),
116
                rule_name = (SELECT rule_name FROM inserted),
117
                data = (SELECT data FROM inserted),
118
                created_at = (SELECT created_at FROM inserted),
119
                updated_at = (SELECT updated_at FROM inserted)
120
                WHERE name IN (SELECT name FROM deleted)
121
                IF @old_name <> @new_name
122
                    BEGIN
123
                        ALTER TABLE {$authManager->itemChildTable} CHECK CONSTRAINT FK__auth_item__child;
124
                    END
125
                END
126
                ELSE
127
                    BEGIN
128
                        DELETE FROM dbo.{$authManager->itemChildTable} WHERE parent IN (SELECT name FROM deleted) OR child IN (SELECT name FROM deleted);
129
                        DELETE FROM dbo.{$authManager->itemTable} WHERE name IN (SELECT name FROM deleted);
130
                    END
131
            END;");
132
        }
133
    }
134
135
    /**
136
     * @inheritdoc
137
     */
138
    public function safeDown()
139
    {
140
        $authManager = $this->getAuthManager();
141
        $this->db = $authManager->db;
142
143
        if ($this->isMSSQL()) {
144
            $this->execute('DROP TRIGGER dbo.trigger_auth_item_child;');
145
        }
146
147
        $this->dropTable($authManager->assignmentTable);
148
        $this->dropTable($authManager->itemChildTable);
149
        $this->dropTable($authManager->itemTable);
150
        $this->dropTable($authManager->ruleTable);
151
    }
152
153
    protected function buildFkClause($delete = '', $update = '')
154
    {
155
        if ($this->isMSSQL()) {
156
            return '';
157
        }
158
159
        if ($this->isOracle()) {
160
            return ' ' . $delete;
161
        }
162
163
        return implode(' ', ['', $delete, $update]);
164
    }
165
}
166