UserSqlDataMapperTest::testUpdateWithRelated()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 59
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 47
dl 0
loc 59
rs 9.1563
c 0
b 0
f 0
cc 1
nc 1
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
declare(strict_types=1);
4
5
namespace AbterPhp\Admin\Orm\DataMappers;
6
7
use AbterPhp\Admin\Domain\Entities\User;
8
use AbterPhp\Admin\Domain\Entities\UserGroup;
9
use AbterPhp\Admin\Domain\Entities\UserLanguage;
10
use AbterPhp\Admin\TestCase\Orm\DataMapperTestCase;
11
use AbterPhp\Admin\TestDouble\Orm\MockIdGeneratorFactory;
12
use AbterPhp\Framework\Domain\Entities\IStringerEntity;
13
use AbterPhp\Framework\TestDouble\Database\MockStatementFactory;
14
use PHPUnit\Framework\MockObject\MockObject;
15
16
class UserSqlDataMapperTest extends DataMapperTestCase
17
{
18
    /** @var UserSqlDataMapper */
19
    protected $sut;
20
21
    public function setUp(): void
22
    {
23
        parent::setUp();
24
25
        $this->sut = new UserSqlDataMapper($this->readConnectionMock, $this->writeConnectionMock);
26
    }
27
28
    public function testAddWithoutRelated()
29
    {
30
        $nextId            = '041532f6-d84c-4827-9404-b426609b99b1';
31
        $username          = 'foo';
32
        $email             = '[email protected]';
33
        $password          = '';
34
        $userLanguage      = new UserLanguage('c486784f-a067-402b-94f0-fe85c838c71c', 'baz', 'Baz');
35
        $canLogin          = true;
36
        $isGravatarAllowed = true;
37
38
        $sql0       = 'INSERT INTO users (id, username, email, password, user_language_id, can_login, is_gravatar_allowed) VALUES (?, ?, ?, ?, ?, ?, ?)'; // phpcs:ignore
39
        $values     = [
40
            [$nextId, \PDO::PARAM_STR],
41
            [$username, \PDO::PARAM_STR],
42
            [$email, \PDO::PARAM_STR],
43
            [$password, \PDO::PARAM_STR],
44
            [$userLanguage->getId(), \PDO::PARAM_STR],
45
            [$canLogin, \PDO::PARAM_INT],
46
            [$isGravatarAllowed, \PDO::PARAM_INT],
47
        ];
48
        $statement0 = MockStatementFactory::createWriteStatement($this, $values);
49
50
        $this->writeConnectionMock
51
            ->expects($this->once())
52
            ->method('prepare')
53
            ->with($sql0)
54
            ->willReturn($statement0);
55
56
        $entity = new User($nextId, $username, $email, $password, $canLogin, $isGravatarAllowed, $userLanguage);
57
        $this->sut->add($entity);
58
59
        $this->assertSame($nextId, $entity->getId());
60
    }
61
62
    public function testAddWithRelated()
63
    {
64
        $nextId            = '92c633eb-70f0-4300-930c-6a797f213014';
65
        $username          = 'foo';
66
        $email             = '[email protected]';
67
        $password          = '';
68
        $userLanguage      = new UserLanguage('5dbea768-0dc9-426e-b434-d225535d440f', 'baz', 'Baz');
69
        $canLogin          = true;
70
        $isGravatarAllowed = true;
71
        $uugId0            = '76036dfa-5978-434e-96a6-9c5d5e8831c7';
72
        $uugId1            = '81c6f4a6-583a-41ff-b5bb-9015d9f97bd3';
73
        $userGroups        = [
74
            new UserGroup('feaf4cc1-fc70-4468-b34b-738ea17ab94e', 'ug-38', 'UG 38'),
75
            new UserGroup('47123e47-067e-4542-80b7-a5aa78916a30', 'ug-51', 'UG 51'),
76
        ];
77
78
        $this->sut->setIdGenerator(MockIdGeneratorFactory::create($this, $uugId0, $uugId1));
79
80
        $sql0       = 'INSERT INTO users (id, username, email, password, user_language_id, can_login, is_gravatar_allowed) VALUES (?, ?, ?, ?, ?, ?, ?)'; // phpcs:ignore
81
        $values     = [
82
            [$nextId, \PDO::PARAM_STR],
83
            [$username, \PDO::PARAM_STR],
84
            [$email, \PDO::PARAM_STR],
85
            [$password, \PDO::PARAM_STR],
86
            [$userLanguage->getId(), \PDO::PARAM_STR],
87
            [$canLogin, \PDO::PARAM_INT],
88
            [$isGravatarAllowed, \PDO::PARAM_INT],
89
        ];
90
        $statement0 = MockStatementFactory::createWriteStatement($this, $values);
91
92
        $sql1       = 'INSERT INTO users_user_groups (id, user_id, user_group_id) VALUES (?, ?, ?)'; // phpcs:ignore
93
        $values1    = [
94
            [$uugId0, \PDO::PARAM_STR],
95
            [$nextId, \PDO::PARAM_STR],
96
            [$userGroups[0]->getId(), \PDO::PARAM_STR],
97
        ];
98
        $statement1 = MockStatementFactory::createWriteStatement($this, $values1);
99
100
        $sql2       = 'INSERT INTO users_user_groups (id, user_id, user_group_id) VALUES (?, ?, ?)'; // phpcs:ignore
101
        $values2    = [
102
            [$uugId1, \PDO::PARAM_STR],
103
            [$nextId, \PDO::PARAM_STR],
104
            [$userGroups[1]->getId(), \PDO::PARAM_STR],
105
        ];
106
        $statement2 = MockStatementFactory::createWriteStatement($this, $values2);
107
108
        $this->writeConnectionMock
109
            ->expects($this->exactly(3))
110
            ->method('prepare')
111
            ->withConsecutive([$sql0], [$sql1], [$sql2])
112
            ->willReturnOnConsecutiveCalls($statement0, $statement1, $statement2);
113
114
        $entity = new User(
115
            $nextId,
116
            $username,
117
            $email,
118
            $password,
119
            $canLogin,
120
            $isGravatarAllowed,
121
            $userLanguage,
122
            $userGroups
123
        );
124
        $this->sut->add($entity);
125
126
        $this->assertSame($nextId, $entity->getId());
127
    }
128
129
    public function testDelete()
130
    {
131
        $id                = '1c36adc9-47e7-4d64-884d-f3c0ef0c89a3';
132
        $username          = 'foo';
133
        $email             = '[email protected]';
134
        $password          = 'somePassword';
135
        $storedPassword    = '';
136
        $userLanguage      = new UserLanguage('5c66b4ac-5d92-434f-85ee-040f3d1572dc', 'baz', 'Baz');
137
        $canLogin          = true;
138
        $isGravatarAllowed = true;
139
140
        $sql0       = 'DELETE FROM users_user_groups WHERE (user_id = ?)'; // phpcs:ignore
141
        $values0    = [[$id, \PDO::PARAM_STR]];
142
        $statement0 = MockStatementFactory::createWriteStatement($this, $values0);
143
144
        $sql1       = 'UPDATE users AS users SET deleted_at = NOW(), username = LEFT(MD5(RAND()), 8), email = CONCAT(username, "@example.com"), password = ? WHERE (id = ?)'; // phpcs:ignore
145
        $values1    = [
146
            [$storedPassword, \PDO::PARAM_STR],
147
            [$id, \PDO::PARAM_STR],
148
        ];
149
        $statement1 = MockStatementFactory::createWriteStatement($this, $values1);
150
151
        $this->writeConnectionMock
152
            ->expects($this->exactly(2))
153
            ->method('prepare')
154
            ->withConsecutive([$sql0], [$sql1])
155
            ->willReturnOnConsecutiveCalls($statement0, $statement1);
156
157
        $entity = new User($id, $username, $email, $password, $canLogin, $isGravatarAllowed, $userLanguage);
158
        $this->sut->delete($entity);
159
    }
160
161
    public function testGetAll()
162
    {
163
        $id                = '85cc9880-4d86-4ffb-8289-98843c0e97eb';
164
        $username          = 'foo';
165
        $email             = '[email protected]';
166
        $password          = '';
167
        $userLanguage      = new UserLanguage('a6fe61fd-4e03-4ec2-b066-e7d26fbdade3', 'baz', 'Baz');
168
        $canLogin          = true;
169
        $isGravatarAllowed = true;
170
171
        $sql0         = 'SELECT users.id, users.username, users.email, users.password, users.user_language_id, ul.identifier AS user_language_identifier, users.can_login, users.is_gravatar_allowed, GROUP_CONCAT(ug.id) AS user_group_ids, GROUP_CONCAT(ug.identifier) AS user_group_identifiers, GROUP_CONCAT(ug.name) AS user_group_names FROM users INNER JOIN user_languages AS ul ON ul.id = users.user_language_id AND ul.deleted_at IS NULL LEFT JOIN users_user_groups AS uug ON uug.user_id = users.id AND uug.deleted_at IS NULL LEFT JOIN user_groups AS ug ON ug.id = uug.user_group_id AND ug.deleted_at IS NULL WHERE (users.deleted_at IS NULL) GROUP BY users.id'; // phpcs:ignore
172
        $values       = [];
173
        $expectedData = [
174
            [
175
                'id'                       => $id,
176
                'username'                 => $username,
177
                'email'                    => $email,
178
                'password'                 => $password,
179
                'user_language_id'         => $userLanguage->getId(),
180
                'user_language_identifier' => $userLanguage->getIdentifier(),
181
                'can_login'                => $canLogin,
182
                'is_gravatar_allowed'      => $isGravatarAllowed,
183
            ],
184
        ];
185
        $statement0   = MockStatementFactory::createReadStatement($this, $values, $expectedData);
186
187
        $this->readConnectionMock
188
            ->expects($this->once())
189
            ->method('prepare')
190
            ->with($sql0)
191
            ->willReturn($statement0);
192
193
        $actualResult = $this->sut->getAll();
194
195
        $this->assertCollection($expectedData, $actualResult);
196
    }
197
198
    public function testGetAllWithRelated()
199
    {
200
        $id                   = '85cc9880-4d86-4ffb-8289-98843c0e97eb';
201
        $username             = 'foo';
202
        $email                = '[email protected]';
203
        $password             = '';
204
        $userLanguage         = new UserLanguage('a6fe61fd-4e03-4ec2-b066-e7d26fbdade3', 'baz', 'Baz');
205
        $canLogin             = true;
206
        $isGravatarAllowed    = true;
207
        $userGroupIds         = 'd6aae5b8-b34d-409b-9085-e02947e32b8e,aaad5aa6-7044-432d-ae28-2017376a1a55';
208
        $userGroupIdentifiers = 'ug-1,ug-2';
209
        $userGroupNames       = 'UG #1,UG #2';
210
211
        $sql0         = 'SELECT users.id, users.username, users.email, users.password, users.user_language_id, ul.identifier AS user_language_identifier, users.can_login, users.is_gravatar_allowed, GROUP_CONCAT(ug.id) AS user_group_ids, GROUP_CONCAT(ug.identifier) AS user_group_identifiers, GROUP_CONCAT(ug.name) AS user_group_names FROM users INNER JOIN user_languages AS ul ON ul.id = users.user_language_id AND ul.deleted_at IS NULL LEFT JOIN users_user_groups AS uug ON uug.user_id = users.id AND uug.deleted_at IS NULL LEFT JOIN user_groups AS ug ON ug.id = uug.user_group_id AND ug.deleted_at IS NULL WHERE (users.deleted_at IS NULL) GROUP BY users.id'; // phpcs:ignore
212
        $values       = [];
213
        $expectedData = [
214
            [
215
                'id'                       => $id,
216
                'username'                 => $username,
217
                'email'                    => $email,
218
                'password'                 => $password,
219
                'user_language_id'         => $userLanguage->getId(),
220
                'user_language_identifier' => $userLanguage->getIdentifier(),
221
                'can_login'                => $canLogin,
222
                'is_gravatar_allowed'      => $isGravatarAllowed,
223
                'user_group_ids'           => $userGroupIds,
224
                'user_group_identifiers'   => $userGroupIdentifiers,
225
                'user_group_names'         => $userGroupNames,
226
            ],
227
        ];
228
        $statement0   = MockStatementFactory::createReadStatement($this, $values, $expectedData);
229
230
        $this->readConnectionMock
231
            ->expects($this->once())
232
            ->method('prepare')
233
            ->with($sql0)
234
            ->willReturn($statement0);
235
236
        $actualResult = $this->sut->getAll();
237
238
        $this->assertCollection($expectedData, $actualResult);
239
    }
240
241
    public function testGetPage()
242
    {
243
        $id                = '85cc9880-4d86-4ffb-8289-98843c0e97eb';
244
        $username          = 'foo';
245
        $email             = '[email protected]';
246
        $password          = '';
247
        $userLanguage      = new UserLanguage('a6fe61fd-4e03-4ec2-b066-e7d26fbdade3', 'baz', 'Baz');
248
        $canLogin          = true;
249
        $isGravatarAllowed = true;
250
251
        $sql0         = 'SELECT SQL_CALC_FOUND_ROWS users.id, users.username, users.email, users.password, users.user_language_id, ul.identifier AS user_language_identifier, users.can_login, users.is_gravatar_allowed, GROUP_CONCAT(ug.id) AS user_group_ids, GROUP_CONCAT(ug.identifier) AS user_group_identifiers, GROUP_CONCAT(ug.name) AS user_group_names FROM users INNER JOIN user_languages AS ul ON ul.id = users.user_language_id AND ul.deleted_at IS NULL LEFT JOIN users_user_groups AS uug ON uug.user_id = users.id AND uug.deleted_at IS NULL LEFT JOIN user_groups AS ug ON ug.id = uug.user_group_id AND ug.deleted_at IS NULL WHERE (users.deleted_at IS NULL) GROUP BY users.id ORDER BY username ASC LIMIT 10 OFFSET 0'; // phpcs:ignore
252
        $values       = [];
253
        $expectedData = [
254
            [
255
                'id'                       => $id,
256
                'username'                 => $username,
257
                'email'                    => $email,
258
                'password'                 => $password,
259
                'user_language_id'         => $userLanguage->getId(),
260
                'user_language_identifier' => $userLanguage->getIdentifier(),
261
                'can_login'                => $canLogin,
262
                'is_gravatar_allowed'      => $isGravatarAllowed,
263
            ],
264
        ];
265
        $statement0   = MockStatementFactory::createReadStatement($this, $values, $expectedData);
266
267
        $this->readConnectionMock
268
            ->expects($this->once())
269
            ->method('prepare')
270
            ->with($sql0)
271
            ->willReturn($statement0);
272
273
        $actualResult = $this->sut->getPage(0, 10, [], [], []);
274
275
        $this->assertCollection($expectedData, $actualResult);
276
    }
277
278
    public function testGetPageWithOrdersAndConditions()
279
    {
280
        $id                = '85cc9880-4d86-4ffb-8289-98843c0e97eb';
281
        $username          = 'foo';
282
        $email             = '[email protected]';
283
        $password          = '';
284
        $userLanguage      = new UserLanguage('a6fe61fd-4e03-4ec2-b066-e7d26fbdade3', 'baz', 'Baz');
285
        $canLogin          = true;
286
        $isGravatarAllowed = true;
287
288
        $orders     = ['ac.description ASC'];
289
        $conditions = ['ac.description LIKE \'abc%\'', 'abc.description LIKE \'%bca\''];
290
291
        $sql0         = 'SELECT SQL_CALC_FOUND_ROWS users.id, users.username, users.email, users.password, users.user_language_id, ul.identifier AS user_language_identifier, users.can_login, users.is_gravatar_allowed, GROUP_CONCAT(ug.id) AS user_group_ids, GROUP_CONCAT(ug.identifier) AS user_group_identifiers, GROUP_CONCAT(ug.name) AS user_group_names FROM users INNER JOIN user_languages AS ul ON ul.id = users.user_language_id AND ul.deleted_at IS NULL LEFT JOIN users_user_groups AS uug ON uug.user_id = users.id AND uug.deleted_at IS NULL LEFT JOIN user_groups AS ug ON ug.id = uug.user_group_id AND ug.deleted_at IS NULL WHERE (users.deleted_at IS NULL) AND (ac.description LIKE \'abc%\') AND (abc.description LIKE \'%bca\') GROUP BY users.id ORDER BY ac.description ASC LIMIT 10 OFFSET 0'; // phpcs:ignore
292
        $values       = [];
293
        $expectedData = [
294
            [
295
                'id'                       => $id,
296
                'username'                 => $username,
297
                'email'                    => $email,
298
                'password'                 => $password,
299
                'user_language_id'         => $userLanguage->getId(),
300
                'user_language_identifier' => $userLanguage->getIdentifier(),
301
                'can_login'                => $canLogin,
302
                'is_gravatar_allowed'      => $isGravatarAllowed,
303
            ],
304
        ];
305
        $statement0   = MockStatementFactory::createReadStatement($this, $values, $expectedData);
306
307
        $this->readConnectionMock
308
            ->expects($this->once())
309
            ->method('prepare')
310
            ->with($sql0)
311
            ->willReturn($statement0);
312
313
        $actualResult = $this->sut->getPage(0, 10, $orders, $conditions, []);
314
315
        $this->assertCollection($expectedData, $actualResult);
316
    }
317
318
    public function testGetById()
319
    {
320
        $id                = 'a83be8c1-fb9a-471f-9284-133487837c46';
321
        $username          = 'foo';
322
        $email             = '[email protected]';
323
        $password          = '';
324
        $userLanguage      = new UserLanguage('0133699c-7826-4b19-b69a-61b894b924d7', 'baz', 'Baz');
325
        $canLogin          = true;
326
        $isGravatarAllowed = true;
327
328
        $sql0         = 'SELECT users.id, users.username, users.email, users.password, users.user_language_id, ul.identifier AS user_language_identifier, users.can_login, users.is_gravatar_allowed, GROUP_CONCAT(ug.id) AS user_group_ids, GROUP_CONCAT(ug.identifier) AS user_group_identifiers, GROUP_CONCAT(ug.name) AS user_group_names FROM users INNER JOIN user_languages AS ul ON ul.id = users.user_language_id AND ul.deleted_at IS NULL LEFT JOIN users_user_groups AS uug ON uug.user_id = users.id AND uug.deleted_at IS NULL LEFT JOIN user_groups AS ug ON ug.id = uug.user_group_id AND ug.deleted_at IS NULL WHERE (users.deleted_at IS NULL) AND (users.id = :user_id) GROUP BY users.id'; // phpcs:ignore
329
        $values       = ['user_id' => [$id, \PDO::PARAM_STR]];
330
        $expectedData = [
331
            [
332
                'id'                       => $id,
333
                'username'                 => $username,
334
                'email'                    => $email,
335
                'password'                 => $password,
336
                'user_language_id'         => $userLanguage->getId(),
337
                'user_language_identifier' => $userLanguage->getIdentifier(),
338
                'can_login'                => $canLogin,
339
                'is_gravatar_allowed'      => $isGravatarAllowed,
340
            ],
341
        ];
342
        $statement0   = MockStatementFactory::createReadStatement($this, $values, $expectedData);
343
344
        $this->readConnectionMock
345
            ->expects($this->once())
346
            ->method('prepare')
347
            ->with($sql0)
348
            ->willReturn($statement0);
349
350
        $actualResult = $this->sut->getById($id);
351
352
        $this->assertEntity($expectedData[0], $actualResult);
353
    }
354
355
    public function testGetByUsername()
356
    {
357
        $id                = '792de058-0d5b-4ae3-8e80-6b4470626530';
358
        $username          = 'foo';
359
        $email             = '[email protected]';
360
        $password          = '';
361
        $userLanguage      = new UserLanguage('e3d2689c-5284-43b4-a847-b84053623b30', 'baz', 'Baz');
362
        $canLogin          = true;
363
        $isGravatarAllowed = true;
364
365
        $sql0         = 'SELECT users.id, users.username, users.email, users.password, users.user_language_id, ul.identifier AS user_language_identifier, users.can_login, users.is_gravatar_allowed, GROUP_CONCAT(ug.id) AS user_group_ids, GROUP_CONCAT(ug.identifier) AS user_group_identifiers, GROUP_CONCAT(ug.name) AS user_group_names FROM users INNER JOIN user_languages AS ul ON ul.id = users.user_language_id AND ul.deleted_at IS NULL LEFT JOIN users_user_groups AS uug ON uug.user_id = users.id AND uug.deleted_at IS NULL LEFT JOIN user_groups AS ug ON ug.id = uug.user_group_id AND ug.deleted_at IS NULL WHERE (users.deleted_at IS NULL) AND (`username` = :username) GROUP BY users.id'; // phpcs:ignore
366
        $values       = ['username' => [$username, \PDO::PARAM_STR]];
367
        $expectedData = [
368
            [
369
                'id'                       => $id,
370
                'username'                 => $username,
371
                'email'                    => $email,
372
                'password'                 => $password,
373
                'user_language_id'         => $userLanguage->getId(),
374
                'user_language_identifier' => $userLanguage->getIdentifier(),
375
                'can_login'                => $canLogin,
376
                'is_gravatar_allowed'      => $isGravatarAllowed,
377
            ],
378
        ];
379
        $statement0   = MockStatementFactory::createReadStatement($this, $values, $expectedData);
380
381
        $this->readConnectionMock
382
            ->expects($this->once())
383
            ->method('prepare')
384
            ->with($sql0)
385
            ->willReturn($statement0);
386
387
        $actualResult = $this->sut->getByUsername($username);
388
389
        $this->assertEntity($expectedData[0], $actualResult);
390
    }
391
392
    public function testGetByEmail()
393
    {
394
        $id                = 'd26ae765-e801-4444-9bed-af1b825414b3';
395
        $username          = 'foo';
396
        $email             = '[email protected]';
397
        $password          = '';
398
        $userLanguage      = new UserLanguage('8eb0a9eb-fd6e-4036-a6f6-4da7d99baa65', 'baz', 'Baz');
399
        $canLogin          = true;
400
        $isGravatarAllowed = true;
401
402
        $sql0         = 'SELECT users.id, users.username, users.email, users.password, users.user_language_id, ul.identifier AS user_language_identifier, users.can_login, users.is_gravatar_allowed, GROUP_CONCAT(ug.id) AS user_group_ids, GROUP_CONCAT(ug.identifier) AS user_group_identifiers, GROUP_CONCAT(ug.name) AS user_group_names FROM users INNER JOIN user_languages AS ul ON ul.id = users.user_language_id AND ul.deleted_at IS NULL LEFT JOIN users_user_groups AS uug ON uug.user_id = users.id AND uug.deleted_at IS NULL LEFT JOIN user_groups AS ug ON ug.id = uug.user_group_id AND ug.deleted_at IS NULL WHERE (users.deleted_at IS NULL) AND (email = :email) GROUP BY users.id'; // phpcs:ignore
403
        $values       = ['email' => [$email, \PDO::PARAM_STR]];
404
        $expectedData = [
405
            [
406
                'id'                       => $id,
407
                'username'                 => $username,
408
                'email'                    => $email,
409
                'password'                 => $password,
410
                'user_language_id'         => $userLanguage->getId(),
411
                'user_language_identifier' => $userLanguage->getIdentifier(),
412
                'can_login'                => $canLogin,
413
                'is_gravatar_allowed'      => $isGravatarAllowed,
414
            ],
415
        ];
416
        $statement0   = MockStatementFactory::createReadStatement($this, $values, $expectedData);
417
418
        $this->readConnectionMock
419
            ->expects($this->once())
420
            ->method('prepare')
421
            ->with($sql0)
422
            ->willReturn($statement0);
423
424
        $actualResult = $this->sut->getByEmail($email);
425
426
        $this->assertEntity($expectedData[0], $actualResult);
427
    }
428
429
    public function testFindByUsername()
430
    {
431
        $id                = 'd9954f10-1ee9-462e-a1e5-6065c032adaa';
432
        $username          = 'foo';
433
        $email             = '[email protected]';
434
        $password          = '';
435
        $userLanguage      = new UserLanguage('d1284a66-6fad-4e40-a7f6-4c144aa5de5e', 'baz', 'Baz');
436
        $canLogin          = true;
437
        $isGravatarAllowed = true;
438
439
        $sql0         = 'SELECT users.id, users.username, users.email, users.password, users.user_language_id, ul.identifier AS user_language_identifier, users.can_login, users.is_gravatar_allowed, GROUP_CONCAT(ug.id) AS user_group_ids, GROUP_CONCAT(ug.identifier) AS user_group_identifiers, GROUP_CONCAT(ug.name) AS user_group_names FROM users INNER JOIN user_languages AS ul ON ul.id = users.user_language_id AND ul.deleted_at IS NULL LEFT JOIN users_user_groups AS uug ON uug.user_id = users.id AND uug.deleted_at IS NULL LEFT JOIN user_groups AS ug ON ug.id = uug.user_group_id AND ug.deleted_at IS NULL WHERE (users.deleted_at IS NULL) AND ((username = :identifier OR email = :identifier)) GROUP BY users.id'; // phpcs:ignore
440
        $values       = ['identifier' => [$username, \PDO::PARAM_STR]];
441
        $expectedData = [
442
            [
443
                'id'                       => $id,
444
                'username'                 => $username,
445
                'email'                    => $email,
446
                'password'                 => $password,
447
                'user_language_id'         => $userLanguage->getId(),
448
                'user_language_identifier' => $userLanguage->getIdentifier(),
449
                'can_login'                => $canLogin,
450
                'is_gravatar_allowed'      => $isGravatarAllowed,
451
            ],
452
        ];
453
        $statement0   = MockStatementFactory::createReadStatement($this, $values, $expectedData);
454
455
        $this->readConnectionMock
456
            ->expects($this->once())
457
            ->method('prepare')
458
            ->with($sql0)
459
            ->willReturn($statement0);
460
461
        $actualResult = $this->sut->find($username);
462
463
        $this->assertEntity($expectedData[0], $actualResult);
464
    }
465
466
    public function testFindByEmail()
467
    {
468
        $id                = '0496d1d1-a750-4c91-822e-03a0fd6718b7';
469
        $username          = 'foo';
470
        $email             = '[email protected]';
471
        $password          = '';
472
        $userLanguage      = new UserLanguage('8b9543ad-17e8-4e54-af17-e8a8b271a70e', 'baz', 'Baz');
473
        $canLogin          = true;
474
        $isGravatarAllowed = true;
475
476
        $sql0         = 'SELECT users.id, users.username, users.email, users.password, users.user_language_id, ul.identifier AS user_language_identifier, users.can_login, users.is_gravatar_allowed, GROUP_CONCAT(ug.id) AS user_group_ids, GROUP_CONCAT(ug.identifier) AS user_group_identifiers, GROUP_CONCAT(ug.name) AS user_group_names FROM users INNER JOIN user_languages AS ul ON ul.id = users.user_language_id AND ul.deleted_at IS NULL LEFT JOIN users_user_groups AS uug ON uug.user_id = users.id AND uug.deleted_at IS NULL LEFT JOIN user_groups AS ug ON ug.id = uug.user_group_id AND ug.deleted_at IS NULL WHERE (users.deleted_at IS NULL) AND ((username = :identifier OR email = :identifier)) GROUP BY users.id'; // phpcs:ignore
477
        $values       = ['identifier' => [$email, \PDO::PARAM_STR]];
478
        $expectedData = [
479
            [
480
                'id'                       => $id,
481
                'username'                 => $username,
482
                'email'                    => $email,
483
                'password'                 => $password,
484
                'user_language_id'         => $userLanguage->getId(),
485
                'user_language_identifier' => $userLanguage->getIdentifier(),
486
                'can_login'                => $canLogin,
487
                'is_gravatar_allowed'      => $isGravatarAllowed,
488
            ],
489
        ];
490
        $statement0   = MockStatementFactory::createReadStatement($this, $values, $expectedData);
491
492
        $this->readConnectionMock
493
            ->expects($this->once())
494
            ->method('prepare')
495
            ->with($sql0)
496
            ->willReturn($statement0);
497
498
        $actualResult = $this->sut->find($email);
499
500
        $this->assertEntity($expectedData[0], $actualResult);
501
    }
502
503
    public function testGetByClientId()
504
    {
505
        $id                = '0496d1d1-a750-4c91-822e-03a0fd6718b7';
506
        $username          = 'foo';
507
        $email             = '[email protected]';
508
        $password          = '';
509
        $userLanguage      = new UserLanguage('8b9543ad-17e8-4e54-af17-e8a8b271a70e', 'baz', 'Baz');
510
        $canLogin          = true;
511
        $isGravatarAllowed = true;
512
        $clientId          = '063b730f-3458-49dc-b60e-8171cefacabf';
513
514
        $sql0         = 'SELECT users.id, users.username, users.email, users.password, users.user_language_id, ul.identifier AS user_language_identifier, users.can_login, users.is_gravatar_allowed, GROUP_CONCAT(ug.id) AS user_group_ids, GROUP_CONCAT(ug.identifier) AS user_group_identifiers, GROUP_CONCAT(ug.name) AS user_group_names FROM users INNER JOIN user_languages AS ul ON ul.id = users.user_language_id AND ul.deleted_at IS NULL INNER JOIN api_clients AS ac ON ac.user_id = users.id AND ac.deleted_at IS NULL LEFT JOIN users_user_groups AS uug ON uug.user_id = users.id AND uug.deleted_at IS NULL LEFT JOIN user_groups AS ug ON ug.id = uug.user_group_id AND ug.deleted_at IS NULL WHERE (users.deleted_at IS NULL) AND (ac.id = :client_id) GROUP BY users.id'; // phpcs:ignore
515
        $values       = ['client_id' => [$clientId, \PDO::PARAM_STR]];
516
        $expectedData = [
517
            [
518
                'id'                       => $id,
519
                'username'                 => $username,
520
                'email'                    => $email,
521
                'password'                 => $password,
522
                'user_language_id'         => $userLanguage->getId(),
523
                'user_language_identifier' => $userLanguage->getIdentifier(),
524
                'can_login'                => $canLogin,
525
                'is_gravatar_allowed'      => $isGravatarAllowed,
526
            ],
527
        ];
528
        $statement0   = MockStatementFactory::createReadStatement($this, $values, $expectedData);
529
530
        $this->readConnectionMock
531
            ->expects($this->once())
532
            ->method('prepare')
533
            ->with($sql0)
534
            ->willReturn($statement0);
535
536
        $actualResult = $this->sut->getByClientId($clientId);
537
538
        $this->assertEntity($expectedData[0], $actualResult);
539
    }
540
541
    public function testUpdateWithoutRelated()
542
    {
543
        $id                = '76b408bc-d061-4bc7-8e03-8892317e4c78';
544
        $username          = 'foo';
545
        $email             = '[email protected]';
546
        $password          = '';
547
        $userLanguage      = new UserLanguage('eae6da9c-16fc-4929-8bc6-1a81e2982702', 'baz', 'Baz');
548
        $canLogin          = true;
549
        $isGravatarAllowed = true;
550
551
        $sql0       = 'UPDATE users AS users SET username = ?, email = ?, password = ?, user_language_id = ?, can_login = ?, is_gravatar_allowed = ? WHERE (id = ?)'; // phpcs:ignore
552
        $values0    = [
553
            [$username, \PDO::PARAM_STR],
554
            [$email, \PDO::PARAM_STR],
555
            [$password, \PDO::PARAM_STR],
556
            [$userLanguage->getId(), \PDO::PARAM_STR],
557
            [$canLogin, \PDO::PARAM_INT],
558
            [$isGravatarAllowed, \PDO::PARAM_INT],
559
            [$id, \PDO::PARAM_STR],
560
        ];
561
        $statement0 = MockStatementFactory::createWriteStatement($this, $values0);
562
563
        $sql1       = 'DELETE FROM users_user_groups WHERE (user_id = ?)'; // phpcs:ignore
564
        $values1    = [[$id, \PDO::PARAM_STR]];
565
        $statement1 = MockStatementFactory::createWriteStatement($this, $values1);
566
567
        $this->writeConnectionMock
568
            ->expects($this->exactly(2))
569
            ->method('prepare')
570
            ->withConsecutive([$sql0], [$sql1])
571
            ->willReturnOnConsecutiveCalls($statement0, $statement1);
572
573
        $entity = new User($id, $username, $email, $password, $canLogin, $isGravatarAllowed, $userLanguage);
574
        $this->sut->update($entity);
575
    }
576
577
    public function testUpdateWithRelated()
578
    {
579
        $id                = '2410891a-5e7f-4b39-ad00-5d0379b54b25';
580
        $username          = 'foo';
581
        $email             = '[email protected]';
582
        $password          = '';
583
        $userLanguage      = new UserLanguage('aa489d5d-c3bd-4039-b431-4aaa2d33418a', 'baz', 'Baz');
584
        $canLogin          = true;
585
        $isGravatarAllowed = true;
586
        $uugId0            = '76036dfa-5978-434e-96a6-9c5d5e8831c7';
587
        $uugId1            = '81c6f4a6-583a-41ff-b5bb-9015d9f97bd3';
588
        $userGroups        = [
589
            new UserGroup('7858a040-5b45-4989-b0ea-941a668e9db8', 'ug-38', 'UG 38'),
590
            new UserGroup('e4ecde09-2b7a-4445-be68-abd5be948d28', 'ug-51', 'UG 51'),
591
        ];
592
593
        $this->sut->setIdGenerator(MockIdGeneratorFactory::create($this, $uugId0, $uugId1));
594
595
        $sql0       = 'UPDATE users AS users SET username = ?, email = ?, password = ?, user_language_id = ?, can_login = ?, is_gravatar_allowed = ? WHERE (id = ?)'; // phpcs:ignore
596
        $values0    = [
597
            [$username, \PDO::PARAM_STR],
598
            [$email, \PDO::PARAM_STR],
599
            [$password, \PDO::PARAM_STR],
600
            [$userLanguage->getId(), \PDO::PARAM_STR],
601
            [$canLogin, \PDO::PARAM_INT],
602
            [$isGravatarAllowed, \PDO::PARAM_INT],
603
            [$id, \PDO::PARAM_STR],
604
        ];
605
        $statement0 = MockStatementFactory::createWriteStatement($this, $values0);
606
607
        $sql1       = 'DELETE FROM users_user_groups WHERE (user_id = ?)'; // phpcs:ignore
608
        $values1    = [[$id, \PDO::PARAM_STR]];
609
        $statement1 = MockStatementFactory::createWriteStatement($this, $values1);
610
611
        $sql2       = 'INSERT INTO users_user_groups (id, user_id, user_group_id) VALUES (?, ?, ?)'; // phpcs:ignore
612
        $values2    = [[$uugId0, \PDO::PARAM_STR], [$id, \PDO::PARAM_STR], [$userGroups[0]->getId(), \PDO::PARAM_STR]];
613
        $statement2 = MockStatementFactory::createWriteStatement($this, $values2);
614
615
        $sql3       = 'INSERT INTO users_user_groups (id, user_id, user_group_id) VALUES (?, ?, ?)'; // phpcs:ignore
616
        $values3    = [[$uugId1, \PDO::PARAM_STR], [$id, \PDO::PARAM_STR], [$userGroups[1]->getId(), \PDO::PARAM_STR]];
617
        $statement3 = MockStatementFactory::createWriteStatement($this, $values3);
618
619
        $this->writeConnectionMock
620
            ->expects($this->exactly(4))
621
            ->method('prepare')
622
            ->withConsecutive([$sql0], [$sql1], [$sql2], [$sql3])
623
            ->willReturnOnConsecutiveCalls($statement0, $statement1, $statement2, $statement3);
624
625
        $entity = new User(
626
            $id,
627
            $username,
628
            $email,
629
            $password,
630
            $canLogin,
631
            $isGravatarAllowed,
632
            $userLanguage,
633
            $userGroups
634
        );
635
        $this->sut->update($entity);
636
    }
637
638
    public function testAddThrowsExceptionIfCalledWithInvalidEntity()
639
    {
640
        $this->expectException(\InvalidArgumentException::class);
641
642
        /** @var IStringerEntity|MockObject $entity */
643
        $entity = $this->createMock(IStringerEntity::class);
644
645
        $this->sut->add($entity);
646
    }
647
648
    public function testDeleteThrowsExceptionIfCalledWithInvalidEntity()
649
    {
650
        $this->expectException(\InvalidArgumentException::class);
651
652
        /** @var IStringerEntity|MockObject $entity */
653
        $entity = $this->createMock(IStringerEntity::class);
654
655
        $this->sut->delete($entity);
656
    }
657
658
    public function testUpdateThrowsExceptionIfCalledWithInvalidEntity()
659
    {
660
        $this->expectException(\InvalidArgumentException::class);
661
662
        /** @var IStringerEntity|MockObject $entity */
663
        $entity = $this->createMock(IStringerEntity::class);
664
665
        $this->sut->update($entity);
666
    }
667
668
    /**
669
     * @param array $expectedData
670
     * @param User  $entity
671
     */
672
    protected function assertEntity(array $expectedData, $entity)
673
    {
674
        $this->assertInstanceOf(User::class, $entity);
675
        $this->assertSame($expectedData['id'], $entity->getId());
676
        $this->assertSame($expectedData['username'], $entity->getUsername());
677
        $this->assertSame($expectedData['email'], $entity->getEmail());
678
        $this->assertSame($expectedData['password'], $entity->getPassword());
679
        $this->assertSame($expectedData['user_language_id'], $entity->getUserLanguage()->getId());
680
        $this->assertSame($expectedData['user_language_identifier'], $entity->getUserLanguage()->getIdentifier());
681
        $this->assertSame($expectedData['can_login'], $entity->canLogin());
682
        $this->assertSame($expectedData['is_gravatar_allowed'], $entity->isGravatarAllowed());
683
684
        $this->assertUserGroups($expectedData, $entity);
685
    }
686
687
    /**
688
     * @param array $expectedData
689
     * @param User  $entity
690
     */
691
    protected function assertUserGroups(array $expectedData, $entity)
692
    {
693
        if (empty($expectedData['user_group_ids'])) {
694
            return;
695
        }
696
697
        $ugIds         = explode(',', $expectedData['user_group_ids']);
698
        $ugIdentifiers = explode(',', $expectedData['user_group_identifiers']);
699
        $ugNames       = explode(',', $expectedData['user_group_names']);
700
701
        foreach ($entity->getUserGroups() as $idx => $ug) {
702
            $this->assertSame($ugIds[$idx], $ug->getId());
703
            $this->assertSame($ugIdentifiers[$idx], $ug->getIdentifier());
704
            $this->assertSame($ugNames[$idx], $ug->getName());
705
        }
706
    }
707
}
708