Completed
Push — master ( 96a86d...9a9433 )
by Neomerx
02:30
created

TokenRepository::readByUser()   C

Complexity

Conditions 8
Paths 2

Size

Total Lines 48
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 48
rs 5.9322
c 0
b 0
f 0
cc 8
eloc 31
nc 2
nop 3
1
<?php namespace Limoncello\Passport\Adaptors\Generic;
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\Query\QueryBuilder;
21
use Limoncello\Passport\Contracts\Entities\DatabaseSchemeInterface;
22
use Limoncello\Passport\Contracts\Entities\TokenInterface;
23
use PDO;
24
25
/**
26
 * @package Limoncello\Passport
27
 */
28
class TokenRepository extends \Limoncello\Passport\Repositories\TokenRepository
29
{
30
    /**
31
     * @var string
32
     */
33
    private $modelClass;
34
35
    /**
36
     * @param Connection              $connection
37
     * @param DatabaseSchemeInterface $databaseScheme
38
     * @param string                  $modelClass
39
     */
40
    public function __construct(
41
        Connection $connection,
42
        DatabaseSchemeInterface $databaseScheme,
43
        string $modelClass = Token::class
44
    ) {
45
        $this->setConnection($connection)->setDatabaseScheme($databaseScheme);
46
        $this->modelClass = $modelClass;
47
    }
48
49
    /**
50
     * @inheritdoc
51
     */
52
    public function read(int $identifier)
53
    {
54
        $token = parent::read($identifier);
55
56
        if ($token !== null) {
57
            $this->addScope($token);
58
        }
59
60
        return $token;
61
    }
62
63
    /**
64
     * @inheritdoc
65
     */
66
    public function readByCode(string $code, int $expirationInSeconds)
67
    {
68
        $token = parent::readByCode($code, $expirationInSeconds);
69
        if ($token !== null) {
70
            $this->addScope($token);
71
        }
72
73
        return $token;
74
    }
75
76
    /**
77
     * @inheritdoc
78
     */
79
    public function readByValue(string $tokenValue, int $expirationInSeconds)
80
    {
81
        $token = parent::readByValue($tokenValue, $expirationInSeconds);
82
        if ($token !== null) {
83
            $this->addScope($token);
84
        }
85
86
        return $token;
87
    }
88
89
    /**
90
     * @inheritdoc
91
     */
92
    public function readByRefresh(string $refreshValue, int $expirationInSeconds)
93
    {
94
        $token = parent::readByRefresh($refreshValue, $expirationInSeconds);
95
        if ($token !== null) {
96
            $this->addScope($token);
97
        }
98
99
        return $token;
100
    }
101
102
    /**
103
     * @inheritdoc
104
     */
105
    public function readByUser(int $userId, int $expirationInSeconds, int $limit = null): array
106
    {
107
        /** @var TokenInterface[] $tokens */
108
        $tokens = parent::readByUser($userId, $expirationInSeconds, $limit);
109
110
        // select scope identifiers for tokens
111
        if (empty($tokens) === false) {
112
            $scheme        = $this->getDatabaseScheme();
113
            $tokenIdColumn = $scheme->getTokensScopesTokenIdentityColumn();
114
            $scopeIdColumn = $scheme->getTokensScopesScopeIdentityColumn();
115
116
            $connection = $this->getConnection();
117
            $query      = $connection->createQueryBuilder();
118
119
            $tokenIds = array_keys($tokens);
120
            $query
121
                ->select([$tokenIdColumn, $scopeIdColumn])
122
                ->from($scheme->getTokensScopesTable())
123
                ->where($query->expr()->in($tokenIdColumn, $tokenIds))
124
                ->orderBy($tokenIdColumn);
125
126
            $statement = $query->execute();
127
            $statement->setFetchMode(PDO::FETCH_ASSOC);
128
            $tokenScopePairs = $statement->fetchAll();
129
130
            $curTokenId = null;
131
            $curScopes  = null;
132
            // set selected scopes to tokens
133
            foreach ($tokenScopePairs as $pair) {
134
                $tokenId = $pair[$tokenIdColumn];
135
                $scopeId = $pair[$scopeIdColumn];
136
137
                if ($curTokenId !== $tokenId) {
138
                    $assignScopes = $curTokenId !== null && empty($curScopes) === false;
139
                    $assignScopes ? $tokens[$curTokenId]->setScopeIdentifiers($curScopes) : null;
140
                    $curTokenId = $tokenId;
141
                    $curScopes  = [$scopeId];
142
143
                    continue;
144
                }
145
146
                $curScopes[] = $scopeId;
147
            }
148
            $curTokenId === null || empty($curScopes) === true ?: $tokens[$curTokenId]->setScopeIdentifiers($curScopes);
149
        }
150
151
        return $tokens;
152
    }
153
154
    /**
155
     * @inheritdoc
156
     */
157
    public function readPassport(string $tokenValue, int $expirationInSeconds)
158
    {
159
        $statement = $this->createPassportDataQuery($tokenValue, $expirationInSeconds)->execute();
160
        $statement->setFetchMode(PDO::FETCH_ASSOC);
161
        $data = $statement->fetch();
162
        $result = null;
163
        if ($data !== false) {
164
            $scheme  = $this->getDatabaseScheme();
165
            $tokenId = $data[$scheme->getTokensIdentityColumn()];
166
            $scopes  =  $this->readScopeIdentifiers($tokenId);
167
            $data[$scheme->getTokensViewScopesColumn()] = $scopes;
168
            $result = $data;
169
        }
170
171
        return $result;
172
    }
173
174
    /**
175
     * @inheritdoc
176
     */
177
    protected function getClassName(): string
178
    {
179
        return $this->modelClass;
180
    }
181
182
    /**
183
     * @inheritdoc
184
     */
185
    protected function getTableNameForReading(): string
186
    {
187
        return $this->getTableNameForWriting();
188
    }
189
190
    /**
191
     * @param string $tokenValue
192
     * @param int    $expirationInSeconds
193
     *
194
     * @return QueryBuilder
195
     */
196
    private function createPassportDataQuery(
197
        string $tokenValue,
198
        int $expirationInSeconds
199
    ): QueryBuilder {
200
        $scheme = $this->getDatabaseScheme();
201
        $query  = $this->createEnabledTokenByColumnWithExpirationCheckQuery(
202
            $tokenValue,
203
            $scheme->getTokensValueColumn(),
204
            $expirationInSeconds,
205
            $scheme->getTokensValueCreatedAtColumn()
206
        );
207
208
        $tokensTable = $this->getTableNameForReading();
209
        $usersTable  = $aliased = $scheme->getUsersTable();
210
        $usersFk     = $scheme->getTokensUserIdentityColumn();
211
        $usersPk     = $scheme->getUsersIdentityColumn();
212
        $query->innerJoin(
213
            $tokensTable,
214
            $usersTable,
215
            $aliased,
216
            "`$tokensTable`.`$usersFk` = `$aliased`.`$usersPk`"
217
        );
218
219
        return $query;
220
    }
221
222
    /**
223
     * @param TokenInterface $token
224
     *
225
     * @return void
226
     */
227
    private function addScope(TokenInterface $token)
228
    {
229
        $token->setScopeIdentifiers($this->readScopeIdentifiers($token->getIdentifier()));
230
    }
231
}
232