Completed
Push — master ( 0fb455...ba0b4e )
by Hilmi Erdem
03:52 queued 02:19
created

DatabaseAccessTokenRepository::find()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 2
crap 1
1
<?php
2
3
namespace Erdemkeren\TemporaryAccess;
4
5
use stdClass;
6
use Carbon\Carbon;
7
use Illuminate\Database\ConnectionInterface;
8
use Erdemkeren\TemporaryAccess\Contracts\AccessTokenRepositoryInterface;
9
10
final class DatabaseAccessTokenRepository implements AccessTokenRepositoryInterface
11
{
12
    /**
13
     * The connection.
14
     *
15
     * @var ConnectionInterface
16
     */
17
    private $connection;
18
19
    /**
20
     * The temporary access token table.
21
     *
22
     * @var string
23
     */
24
    private $table;
25
26
    /**
27
     * The number of seconds a token should last.
28
     *
29
     * @var int
30
     */
31
    private $expires;
32
33
    /**
34
     * DatabaseAccessTokenRepository constructor.
35
     *
36
     * @param ConnectionInterface $connection The database connection interface.
37
     * @param string              $table      The name of the database table.
38
     * @param int                 $expires    The default expire time in minutes.
39
     */
40 11
    public function __construct(ConnectionInterface $connection, $table, $expires)
41
    {
42 11
        $this->table = $table;
43 11
        $this->expires = $expires;
44 11
        $this->connection = $connection;
45 11
    }
46
47
    /**
48
     * Retrieve an access token from the storage.
49
     *
50
     * @param  int    $authenticatableId The unique identifier of the authenticatable who has the access.
51
     * @param  string $token             The encrypted token of the authenticatable.
52
     *
53
     * @return stdClass|array|bool
54
     */
55 2
    public function retrieve($authenticatableId, $token)
56
    {
57 2
        $token = $this->find($authenticatableId, $token)->first();
58
59 2
        return $this->filterExpiredAccessToken($token);
0 ignored issues
show
Bug introduced by
It seems like $token defined by $this->find($authenticatableId, $token)->first() on line 57 can also be of type object; however, Erdemkeren\TemporaryAcce...terExpiredAccessToken() does only seem to accept object<stdClass>|array|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
60
    }
61
62
    /**
63
     * Retrieve the first valid resource by the given attributes.
64
     *
65
     * @param  array $queryParams The key - value pairs to match.
66
     * @param  array $attributes  The attributes to be returned from the storage.
67
     *
68
     * @return stdClass|array|null
69
     */
70 3
    public function retrieveByAttributes(array $queryParams, array $attributes = ['*'])
71
    {
72 3
        $query = $this->getTable();
73
74 3
        foreach ($queryParams as $column => $value) {
75 3
            $query = $query->where($column, $value);
76 3
        }
77
78 3
        $token = $query->first($attributes);
79
80 3
        return $this->filterExpiredAccessToken($token);
0 ignored issues
show
Bug introduced by
It seems like $token defined by $query->first($attributes) on line 78 can also be of type object; however, Erdemkeren\TemporaryAcce...terExpiredAccessToken() does only seem to accept object<stdClass>|array|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
81
    }
82
83
    /**
84
     * Store a new access token in the storage.
85
     *
86
     * @param  int         $authenticatableId The unique identifier of the authenticatable who has the access.
87
     * @param  string      $token             The encrypted token of the authenticatable.
88
     * @param  string|null $expiresAt         The expiration date of the access token.
89
     *
90
     * @return array
91
     */
92 2
    public function store($authenticatableId, $token, $expiresAt = null)
93
    {
94 2
        $payload = $this->getAccessTokenPayload($authenticatableId, $token, $expiresAt);
95
96 2
        $id = $this->getTable()->insertGetId($payload);
97 2
        $payload['id'] = $id;
98
99 2
        return $payload;
100
    }
101
102
    /**
103
     * Update the expire date of the given access token in the storage.
104
     *
105
     * @param  int    $authenticatableId The unique identifier of the authenticatable.
106
     * @param  string $token             The encrypted token to be updated.
107
     * @param  string $expiresAt         The new expiration date of the access token.
108
     *
109
     * @return bool
110
     */
111 1
    public function update($authenticatableId, $token, $expiresAt)
112
    {
113 1
        return (bool) $this->find($authenticatableId, $token)->update([
114 1
            'expires_at' => (string) $expiresAt,
115 1
        ]);
116
    }
117
118
    /**
119
     * Delete a resource from the storage.
120
     *
121
     * @param  string $token The encrypted token of the authenticatable.
122
     *
123
     * @return int
124
     */
125 1
    public function delete($token)
126
    {
127 1
        return $this->getTable()->where('token', $token)->delete();
128
    }
129
130
    /**
131
     * Delete expired access tokens from the storage.
132
     *
133
     * @return void
134
     */
135 1
    public function deleteExpired()
136
    {
137 1
        $this->getTable()->where('expires_at', '<=', (string) $this->getNow())->delete();
138 1
    }
139
140
    /**
141
     * Get a new find query.
142
     *
143
     * @param  int    $authenticatableId
144
     * @param  string $token
145
     *
146
     * @return \Illuminate\Database\Query\Builder
147
     */
148 3
    private function find($authenticatableId, $token)
149
    {
150 3
        return $this->getTable()->where('authenticatable_id', $authenticatableId)->where('token', $token);
151
    }
152
153
    /**
154
     * Get an access token payload.
155
     *
156
     * @param  int         $authenticatableId
157
     * @param  string      $token
158
     * @param  string|null $expiresAt
159
     *
160
     * @return array
161
     */
162 2
    private function getAccessTokenPayload($authenticatableId, $token, $expiresAt)
163
    {
164 2
        $expiresAt = $expiresAt ? $expiresAt : $this->makeExpiresAt();
165
166
        $payload = [
167 2
            'authenticatable_id' => $authenticatableId,
168 2
            'token'              => $token,
169 2
            'created_at'         => (string) $this->getNow(),
170 2
            'expires_at'         => (string) $expiresAt,
171 2
        ];
172
173 2
        return $payload;
174
    }
175
176
    /**
177
     * Filter the given database response and only return if it is not expired.
178
     *
179
     * @param stdClass|array|null $accessToken
180
     *
181
     * @return stdClass|array|null
182
     */
183 5
    private function filterExpiredAccessToken($accessToken)
184
    {
185 5
        if ($accessToken && ! $this->accessTokenExpired((object) $accessToken)) {
186 2
            return $accessToken;
187
        }
188 3
    }
189
190
    /**
191
     * Determine if the token has expired.
192
     *
193
     * @param  stdClass $accessToken
194
     *
195
     * @return bool
196
     */
197 4
    private function accessTokenExpired(stdClass $accessToken)
198
    {
199 4
        $expiresAt = $accessToken->expires_at ? new Carbon($accessToken->expires_at) : $this->makeExpiresAt();
200
201 4
        return $this->getNow()->gte($expiresAt);
202
    }
203
204
    /**
205
     * Make the expires at property from configuration.
206
     *
207
     * @return Carbon
208
     */
209 1
    private function makeExpiresAt()
210
    {
211 1
        return $this->getFuture($this->expires);
212
    }
213
214
    /**
215
     * Get the current time.
216
     *
217
     * @return Carbon
218
     */
219 7
    private function getNow()
220
    {
221 7
        return Carbon::now();
222
    }
223
224
    /**
225
     * Get the time after given minutes.
226
     *
227
     * @param  int $minutesLater
228
     *
229
     * @return Carbon
230
     */
231 1
    private function getFuture($minutesLater)
232
    {
233 1
        return $this->getNow()->addMinutes($minutesLater);
234
    }
235
236
    /**
237
     * Begin a new database query against the table.
238
     *
239
     * @return \Illuminate\Database\Query\Builder
240
     */
241 10
    private function getTable()
242
    {
243 10
        return $this->getConnection()->table($this->table);
244
    }
245
246
    /**
247
     * Get the database connection instance.
248
     *
249
     * @return ConnectionInterface
250
     */
251 10
    private function getConnection()
252
    {
253 10
        return $this->connection;
254
    }
255
}
256