Completed
Push — master ( 4b9759...190a84 )
by Neomerx
11:49
created

DatabaseSchemaMigrationTrait::createClientsView()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 20
cts 20
cp 1
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 22
nc 1
nop 2
crap 1
1
<?php namespace Limoncello\Passport\Adaptors\MySql;
2
3
/**
4
 * Copyright 2015-2017 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use Doctrine\DBAL\Connection;
20
use Doctrine\DBAL\DBALException;
21
use Limoncello\Passport\Contracts\Entities\DatabaseSchemaInterface;
22
use Limoncello\Passport\Traits\DatabaseSchemaMigrationTrait as BaseDatabaseSchemaMigrationTrait;
23
24
/**
25
 * @package Limoncello\Passport
26
 */
27
trait DatabaseSchemaMigrationTrait
28
{
29
    use BaseDatabaseSchemaMigrationTrait {
30
        BaseDatabaseSchemaMigrationTrait::createDatabaseSchema as createDatabaseTables;
31
        BaseDatabaseSchemaMigrationTrait::removeDatabaseSchema as removeDatabaseTables;
32
    }
33
34
    /**
35
     * @param Connection              $connection
36
     * @param DatabaseSchemaInterface $schema
37
     *
38
     * @throws DBALException
39
     *
40
     * @return void
41
     */
42 2
    protected function createDatabaseSchema(Connection $connection, DatabaseSchemaInterface $schema): void
43
    {
44
        try {
45 2
            $this->createDatabaseTables($connection, $schema);
0 ignored issues
show
Bug introduced by
It seems like createDatabaseTables() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
46 2
            $this->createDatabaseViews($connection, $schema);
47 2
        } catch (DBALException $exception) {
48 2
            if ($connection->isConnected() === true) {
49 2
                $this->removeDatabaseSchema($connection, $schema);
50
            }
51
52 2
            throw $exception;
53
        }
54
    }
55
56
    /**
57
     * @param Connection              $connection
58
     * @param DatabaseSchemaInterface $schema
59
     *
60
     * @return void
61
     */
62 2
    protected function removeDatabaseSchema(Connection $connection, DatabaseSchemaInterface $schema): void
63
    {
64 2
        $this->removeDatabaseTables($connection, $schema);
0 ignored issues
show
Bug introduced by
It seems like removeDatabaseTables() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
65 2
        $this->removeDatabaseViews($connection, $schema);
66
    }
67
68
    /**
69
     * @param Connection              $connection
70
     * @param DatabaseSchemaInterface $schema
71
     *
72
     * @return void
73
     */
74 2
    protected function createDatabaseViews(Connection $connection, DatabaseSchemaInterface $schema): void
75
    {
76 2
        $this->createClientsView($connection, $schema);
77 1
        $this->createTokensView($connection, $schema);
78 1
        $this->createUsersView($connection, $schema);
79 1
        $this->createPassportView($connection, $schema);
80
    }
81
82
    /**
83
     * @param Connection              $connection
84
     * @param DatabaseSchemaInterface $schema
85
     *
86
     * @return void
87
     */
88 2
    protected function removeDatabaseViews(Connection $connection, DatabaseSchemaInterface $schema): void
89
    {
90 2
        $this->removePassportView($connection, $schema);
91 2
        $this->removeClientsView($connection, $schema);
92 2
        $this->removeTokensView($connection, $schema);
93 2
        $this->removeUsersView($connection, $schema);
94
    }
95
96
    /**
97
     * @param Connection              $connection
98
     * @param DatabaseSchemaInterface $schema
99
     *
100
     * @throws DBALException
101
     *
102
     * @return void
103
     */
104 1
    protected function createTokensView(Connection $connection, DatabaseSchemaInterface $schema): void
105
    {
106 1
        $view                = $schema->getTokensView();
107 1
        $tokens              = $schema->getTokensTable();
108 1
        $intermediate        = $schema->getTokensScopesTable();
109 1
        $tokensTokenId       = $schema->getTokensIdentityColumn();
110 1
        $intermediateTokenId = $schema->getTokensScopesTokenIdentityColumn();
111 1
        $intermediateScopeId = $schema->getTokensScopesScopeIdentityColumn();
112 1
        $scopes              = $schema->getTokensViewScopesColumn();
113
114
        $sql = <<< EOT
115 1
CREATE OR REPLACE VIEW {$view} AS
116
    SELECT
117
      t.*,
118 1
      GROUP_CONCAT(DISTINCT s.{$intermediateScopeId} ORDER BY s.{$intermediateScopeId} ASC SEPARATOR ' ') AS {$scopes}
119 1
    FROM {$tokens} AS t
120 1
      LEFT JOIN {$intermediate} AS s ON t.{$tokensTokenId} = s.{$intermediateTokenId}
121 1
    GROUP BY t.{$tokensTokenId};
122
EOT;
123 1
        $connection->exec($sql);
124
    }
125
126
    /**
127
     * @param Connection              $connection
128
     * @param DatabaseSchemaInterface $schema
129
     *
130
     * @throws DBALException
131
     *
132
     * @return void
133
     */
134 2
    protected function removeTokensView(Connection $connection, DatabaseSchemaInterface $schema)
135
    {
136 2
        $view = $schema->getTokensView();
137 2
        $sql  = "DROP VIEW IF EXISTS {$view}";
138 2
        $connection->exec($sql);
139
    }
140
141
    /**
142
     * @param Connection              $connection
143
     * @param DatabaseSchemaInterface $schema
144
     *
145
     * @throws DBALException
146
     *
147
     * @return void
148
     */
149 1
    protected function createPassportView(Connection $connection, DatabaseSchemaInterface $schema): void
150
    {
151 1
        $tokensView   = $schema->getTokensView();
152 1
        $view         = $schema->getPassportView();
153 1
        $users        = $schema->getUsersTable();
154 1
        $tokensUserFk = $schema->getTokensUserIdentityColumn();
155
156
        $sql = <<< EOT
157 1
CREATE OR REPLACE VIEW {$view} AS
158
    SELECT *
159 1
    FROM $tokensView
160 1
      LEFT JOIN $users USING ($tokensUserFk);
161
EOT;
162 1
        $connection->exec($sql);
163
    }
164
165
    /**
166
     * @param Connection              $connection
167
     * @param DatabaseSchemaInterface $schema
168
     *
169
     * @throws DBALException
170
     *
171
     * @return void
172
     */
173 2
    protected function removePassportView(Connection $connection, DatabaseSchemaInterface $schema): void
174
    {
175 2
        $view = $schema->getPassportView();
176 2
        $sql  = "DROP VIEW IF EXISTS {$view}";
177 2
        $connection->exec($sql);
178
    }
179
180
    /**
181
     * @param Connection              $connection
182
     * @param DatabaseSchemaInterface $schema
183
     *
184
     * @throws DBALException
185
     *
186
     * @return void
187
     */
188 2
    protected function createClientsView(Connection $connection, DatabaseSchemaInterface $schema)
189
    {
190 2
        $view             = $schema->getClientsView();
191 2
        $scopes           = $schema->getClientsViewScopesColumn();
192 2
        $redirectUris     = $schema->getClientsViewRedirectUrisColumn();
193 2
        $clientsScopes    = $schema->getClientsScopesTable();
194 2
        $clientsUris      = $schema->getRedirectUrisTable();
195 2
        $clients          = $schema->getClientsTable();
196 2
        $clientsClientId  = $schema->getClientsIdentityColumn();
197 2
        $clScopesClientId = $schema->getClientsScopesClientIdentityColumn();
198 2
        $clUrisClientId   = $schema->getRedirectUrisClientIdentityColumn();
199 2
        $urisValue        = $schema->getRedirectUrisValueColumn();
200 2
        $scopesScopeId    = $schema->getScopesIdentityColumn();
201
        $sql              = <<< EOT
202 2
CREATE VIEW {$view} AS
203
    SELECT
204
      c.*,
205 2
      GROUP_CONCAT(DISTINCT s.{$scopesScopeId} ORDER BY s.{$scopesScopeId} ASC SEPARATOR ' ') AS {$scopes},
206 2
      GROUP_CONCAT(DISTINCT u.{$urisValue}     ORDER BY u.{$urisValue} ASC SEPARATOR ' ')     AS {$redirectUris}
207 2
    FROM {$clients} AS c
208 2
      LEFT JOIN {$clientsScopes} AS s ON c.{$clientsClientId} = s.{$clScopesClientId}
209 2
      LEFT JOIN {$clientsUris}   AS u ON c.{$clientsClientId} = u.{$clUrisClientId}
210 2
    GROUP BY c.{$clientsClientId};
211
EOT;
212 2
        $connection->exec($sql);
213
    }
214
215
    /**
216
     * @param Connection              $connection
217
     * @param DatabaseSchemaInterface $schema
218
     *
219
     * @throws DBALException
220
     *
221
     * @return void
222
     */
223 2
    protected function removeClientsView(Connection $connection, DatabaseSchemaInterface $schema)
224
    {
225 2
        $view = $schema->getClientsView();
226 2
        $sql  = "DROP VIEW IF EXISTS {$view}";
227 2
        $connection->exec($sql);
228
    }
229
230
    /**
231
     * @param Connection              $connection
232
     * @param DatabaseSchemaInterface $schema
233
     *
234
     * @throws DBALException
235
     *
236
     * @return void
237
     */
238 1
    protected function createUsersView(Connection $connection, DatabaseSchemaInterface $schema)
239
    {
240 1
        $users = $schema->getUsersTable();
241 1
        if ($users !== null) {
242 1
            $view            = $schema->getUsersView();
243 1
            $tokensValue     = $schema->getTokensValueColumn();
244 1
            $tokensValueAt   = $schema->getTokensValueCreatedAtColumn();
245 1
            $tokensScopes    = $schema->getTokensViewScopesColumn();
246 1
            $tokensView      = $schema->getTokensView();
247 1
            $tokensUserId    = $schema->getTokensUserIdentityColumn();
248 1
            $usersUserId     = $schema->getUsersIdentityColumn();
249 1
            $tokensIsEnabled = $schema->getTokensIsEnabledColumn();
250
251
            $sql = <<< EOT
252 1
CREATE OR REPLACE VIEW {$view} AS
253
    SELECT
254 1
        t.$tokensValue, t.$tokensValueAt, t.$tokensScopes, u.*
255 1
    FROM {$tokensView} AS t
256 1
      LEFT JOIN {$users} AS u ON t.{$tokensUserId} = u.{$usersUserId}
257 1
    WHERE $tokensIsEnabled IS TRUE;
258
EOT;
259 1
            $connection->exec($sql);
260
        }
261
    }
262
263
    /**
264
     * @param Connection              $connection
265
     * @param DatabaseSchemaInterface $schema
266
     *
267
     * @throws DBALException
268
     *
269
     * @return void
270
     */
271 2
    protected function removeUsersView(Connection $connection, DatabaseSchemaInterface $schema)
272
    {
273 2
        $view = $schema->getUsersView();
274 2
        $sql  = "DROP VIEW IF EXISTS {$view}";
275 2
        $connection->exec($sql);
276
    }
277
}
278