UserServiceTest::testLoadSubUserGroups()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
namespace eZ\Publish\API\Repository\Tests;
8
9
use DateInterval;
10
use DateTime;
11
use DateTimeImmutable;
12
use eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException;
13
use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException;
14
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
15
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
16
use eZ\Publish\API\Repository\Values\Content\Language;
17
use eZ\Publish\API\Repository\Values\Content\VersionInfo as APIVersionInfo;
18
use eZ\Publish\API\Repository\Values\ContentType\ContentType;
19
use eZ\Publish\API\Repository\Values\User\Limitation\SubtreeLimitation;
20
use eZ\Publish\API\Repository\Values\User\PasswordInfo;
21
use eZ\Publish\API\Repository\Values\User\PasswordValidationContext;
22
use eZ\Publish\API\Repository\Values\User\UserGroupUpdateStruct;
23
use eZ\Publish\API\Repository\Values\User\UserTokenUpdateStruct;
24
use eZ\Publish\API\Repository\Values\User\UserUpdateStruct;
25
use eZ\Publish\API\Repository\Values\User\User;
26
use eZ\Publish\Core\FieldType\ValidationError;
27
use eZ\Publish\Core\Repository\Values\Content\Content;
28
use eZ\Publish\Core\Repository\Values\Content\VersionInfo;
29
use eZ\Publish\Core\Repository\Values\User\UserGroup;
30
use Exception;
31
32
/**
33
 * Test case for operations in the UserService using in memory storage.
34
 *
35
 * @see eZ\Publish\API\Repository\UserService
36
 * @group integration
37
 * @group user
38
 */
39
class UserServiceTest extends BaseTest
40
{
41
    // Example password matching default rules
42
    private const EXAMPLE_PASSWORD = 'P@ssword123!';
43
44
    private const EXAMPLE_PASSWORD_TTL = 30;
45
    private const EXAMPLE_PASSWORD_TTL_WARNING = 14;
46
47
    /**
48
     * Test for the loadUserGroup() method.
49
     *
50
     * @see \eZ\Publish\API\Repository\UserService::loadUserGroup()
51
     */
52
    public function testLoadUserGroup()
53
    {
54
        $repository = $this->getRepository();
55
56
        $mainGroupId = $this->generateId('group', 4);
57
        /* BEGIN: Use Case */
58
        // $mainGroupId is the ID of the main "Users" group
59
60
        $userService = $repository->getUserService();
61
62
        $userGroup = $userService->loadUserGroup($mainGroupId);
63
        /* END: Use Case */
64
65
        $this->assertInstanceOf(UserGroup::class, $userGroup);
66
67
        // User group happens to also be a Content; isUserGroup() should be true and isUser() should be false
68
        $this->assertTrue($userService->isUserGroup($userGroup), 'isUserGroup() => false on a user group');
69
        $this->assertFalse($userService->isUser($userGroup), 'isUser() => true on a user group');
70
        $this->assertSame(0, $userGroup->parentId, 'parentId should be equal `0` because it is top level node');
71
    }
72
73
    /**
74
     * Test for the loadUserGroup() method to ensure that DomainUserGroupObject is created properly even if a user
75
     * has no access to parent of UserGroup.
76
     *
77
     * @see \eZ\Publish\API\Repository\UserService::loadUserGroup()
78
     */
79
    public function testLoadUserGroupWithNoAccessToParent()
80
    {
81
        $repository = $this->getRepository();
82
83
        $mainGroupId = $this->generateId('group', 4);
84
        /* BEGIN: Use Case */
85
        // $mainGroupId is the ID of the main "Users" group
86
87
        $userService = $repository->getUserService();
88
89
        $user = $this->createUserWithPolicies(
90
            'user',
91
            [
92
                ['module' => 'content', 'function' => 'read'],
93
            ],
94
            new SubtreeLimitation(['limitationValues' => ['/1/5']])
95
        );
96
        $repository->getPermissionResolver()->setCurrentUserReference($user);
97
98
        $userGroup = $userService->loadUserGroup($mainGroupId);
99
        /* END: Use Case */
100
101
        $this->assertInstanceOf(UserGroup::class, $userGroup);
102
103
        // User group happens to also be a Content; isUserGroup() should be true and isUser() should be false
104
        $this->assertTrue($userService->isUserGroup($userGroup), 'isUserGroup() => false on a user group');
105
        $this->assertFalse($userService->isUser($userGroup), 'isUser() => true on a user group');
106
        $this->assertSame(0, $userGroup->parentId, 'parentId should be equal `0` because it is top level node');
107
    }
108
109
    /**
110
     * Test for the loadUserGroup() method.
111
     *
112
     * @see \eZ\Publish\API\Repository\UserService::loadUserGroup()
113
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
114
     */
115
    public function testLoadUserGroupThrowsNotFoundException()
116
    {
117
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
118
119
        $repository = $this->getRepository();
120
121
        $nonExistingGroupId = $this->generateId('group', self::DB_INT_MAX);
122
        /* BEGIN: Use Case */
123
        $userService = $repository->getUserService();
124
125
        // This call will fail with a NotFoundException
126
        $userService->loadUserGroup($nonExistingGroupId);
127
        /* END: Use Case */
128
    }
129
130
    /**
131
     * Test for the loadSubUserGroups() method.
132
     *
133
     * @see \eZ\Publish\API\Repository\UserService::loadSubUserGroups()
134
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
135
     */
136
    public function testLoadSubUserGroups()
137
    {
138
        $repository = $this->getRepository();
139
140
        $mainGroupId = $this->generateId('group', 4);
141
        /* BEGIN: Use Case */
142
        // $mainGroupId is the ID of the main "Users" group
143
144
        $userService = $repository->getUserService();
145
146
        $userGroup = $userService->loadUserGroup($mainGroupId);
147
148
        $subUserGroups = $userService->loadSubUserGroups($userGroup);
149
        foreach ($subUserGroups as $subUserGroup) {
150
            // Do something with the $subUserGroup
151
            $this->assertInstanceOf(UserGroup::class, $subUserGroup);
152
        }
153
        /* END: Use Case */
154
    }
155
156
    /**
157
     * Test loading sub groups throwing NotFoundException.
158
     *
159
     * @covers \eZ\Publish\API\Repository\UserService::loadSubUserGroups
160
     */
161
    public function testLoadSubUserGroupsThrowsNotFoundException()
162
    {
163
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
164
165
        $repository = $this->getRepository();
166
        $userService = $repository->getUserService();
167
168
        $parentGroup = new UserGroup(
169
            [
170
                'content' => new Content(
171
                    [
172
                        'versionInfo' => new VersionInfo(
173
                            [
174
                                'contentInfo' => new ContentInfo(
175
                                    ['id' => 123456]
176
                                ),
177
                            ]
178
                        ),
179
                        'internalFields' => [],
180
                    ]
181
                ),
182
            ]
183
        );
184
        $userService->loadSubUserGroups($parentGroup);
185
    }
186
187
    /**
188
     * Test for the newUserGroupCreateStruct() method.
189
     *
190
     * @return \eZ\Publish\API\Repository\Values\User\UserGroupCreateStruct
191
     *
192
     * @see \eZ\Publish\API\Repository\UserService::newUserGroupCreateStruct()
193
     * @depends eZ\Publish\API\Repository\Tests\ContentTypeServiceTest::testLoadContentTypeByIdentifier
194
     */
195
    public function testNewUserGroupCreateStruct()
196
    {
197
        $repository = $this->getRepository();
198
199
        /* BEGIN: Use Case */
200
        $userService = $repository->getUserService();
201
202
        $groupCreate = $userService->newUserGroupCreateStruct('eng-US');
203
        /* END: Use Case */
204
205
        $this->assertInstanceOf(
206
            '\\eZ\\Publish\\API\\Repository\\Values\\User\\UserGroupCreateStruct',
207
            $groupCreate
208
        );
209
210
        return $groupCreate;
211
    }
212
213
    /**
214
     * Test for the newUserGroupCreateStruct() method.
215
     *
216
     * @param \eZ\Publish\API\Repository\Values\User\UserGroupCreateStruct $groupCreate
217
     *
218
     * @see \eZ\Publish\API\Repository\UserService::newUserGroupCreateStruct()
219
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupCreateStruct
220
     */
221
    public function testNewUserGroupCreateStructSetsMainLanguageCode($groupCreate)
222
    {
223
        $this->assertEquals('eng-US', $groupCreate->mainLanguageCode);
224
    }
225
226
    /**
227
     * Test for the newUserGroupCreateStruct() method.
228
     *
229
     * @param \eZ\Publish\API\Repository\Values\User\UserGroupCreateStruct $groupCreate
230
     *
231
     * @see \eZ\Publish\API\Repository\UserService::newUserGroupCreateStruct()
232
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupCreateStruct
233
     */
234
    public function testNewUserGroupCreateStructSetsContentType($groupCreate)
235
    {
236
        $this->assertInstanceOf(
237
            '\\eZ\\Publish\\API\\Repository\\Values\\ContentType\\ContentType',
238
            $groupCreate->contentType
239
        );
240
    }
241
242
    /**
243
     * Test for the newUserGroupCreateStruct() method.
244
     *
245
     * @see \eZ\Publish\API\Repository\UserService::newUserGroupCreateStruct($mainLanguageCode, $contentType)
246
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupCreateStruct
247
     * @depends eZ\Publish\API\Repository\Tests\ContentTypeServiceTest::testLoadContentTypeByIdentifier
248
     */
249
    public function testNewUserGroupCreateStructWithSecondParameter()
250
    {
251
        $repository = $this->getRepository();
252
253
        /* BEGIN: Use Case */
254
        $contentTypeService = $repository->getContentTypeService();
255
        $userService = $repository->getUserService();
256
257
        // Load the default ContentType for user groups
258
        $groupType = $contentTypeService->loadContentTypeByIdentifier('user_group');
259
260
        // Instantiate a new group create struct
261
        $groupCreate = $userService->newUserGroupCreateStruct(
262
            'eng-US',
263
            $groupType
264
        );
265
        /* END: Use Case */
266
267
        $this->assertSame($groupType, $groupCreate->contentType);
268
    }
269
270
    /**
271
     * Test for the createUserGroup() method.
272
     *
273
     * @return \eZ\Publish\API\Repository\Values\User\UserGroup
274
     *
275
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
276
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupCreateStruct
277
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
278
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
279
     */
280
    public function testCreateUserGroup()
281
    {
282
        /* BEGIN: Use Case */
283
        $userGroup = $this->createUserGroupVersion1();
284
        /* END: Use Case */
285
286
        $this->assertInstanceOf(
287
            UserGroup::class,
288
            $userGroup
289
        );
290
291
        $versionInfo = $userGroup->getVersionInfo();
292
293
        $this->assertEquals(APIVersionInfo::STATUS_PUBLISHED, $versionInfo->status);
294
        $this->assertEquals(1, $versionInfo->versionNo);
295
296
        return $userGroup;
297
    }
298
299
    /**
300
     * Test for the createUserGroup() method.
301
     *
302
     * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup
303
     *
304
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
305
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
306
     */
307
    public function testCreateUserGroupSetsExpectedProperties($userGroup)
308
    {
309
        $this->assertEquals(
310
            [
311
                'parentId' => $this->generateId('group', 4),
312
            ],
313
            [
314
                'parentId' => $userGroup->parentId,
315
            ]
316
        );
317
    }
318
319
    /**
320
     * Test for the createUserGroup() method.
321
     *
322
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
323
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
324
     */
325
    public function testCreateUserGroupThrowsInvalidArgumentException()
326
    {
327
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
328
329
        $repository = $this->getRepository();
330
331
        $mainGroupId = $this->generateId('group', 4);
332
        /* BEGIN: Use Case */
333
        // $mainGroupId is the ID of the main "Users" group
334
335
        $userService = $repository->getUserService();
336
337
        // Load main group
338
        $parentUserGroup = $userService->loadUserGroup($mainGroupId);
339
340
        // Instantiate a new create struct
341
        $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
342
        $userGroupCreate->setField('name', 'Example Group');
343
        $userGroupCreate->remoteId = '5f7f0bdb3381d6a461d8c29ff53d908f';
344
345
        // This call will fail with an "InvalidArgumentException", because the
346
        // specified remoteId is already used for the "Members" user group.
347
        $userService->createUserGroup(
348
            $userGroupCreate,
349
            $parentUserGroup
350
        );
351
        /* END: Use Case */
352
    }
353
354
    /**
355
     * Test for the createUserGroup() method.
356
     *
357
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
358
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
359
     */
360
    public function testCreateUserGroupThrowsInvalidArgumentExceptionFieldTypeNotAccept()
361
    {
362
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
363
364
        $repository = $this->getRepository();
365
366
        $mainGroupId = $this->generateId('group', 4);
367
        /* BEGIN: Use Case */
368
        // $mainGroupId is the ID of the main "Users" group
369
370
        $userService = $repository->getUserService();
371
372
        // Load main group
373
        $parentUserGroup = $userService->loadUserGroup($mainGroupId);
374
375
        // Instantiate a new create struct
376
        $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
377
        $userGroupCreate->setField('name', new \stdClass());
378
379
        // This call will fail with an "InvalidArgumentException", because the
380
        // specified remoteId is already used for the "Members" user group.
381
        $userService->createUserGroup(
382
            $userGroupCreate,
383
            $parentUserGroup
384
        );
385
        /* END: Use Case */
386
    }
387
388
    /**
389
     * Test for the createUserGroup() method.
390
     *
391
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
392
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
393
     */
394
    public function testCreateUserGroupWhenMissingField()
395
    {
396
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException::class);
397
398
        $repository = $this->getRepository();
399
400
        $mainGroupId = $this->generateId('group', 4);
401
        /* BEGIN: Use Case */
402
        // $mainGroupId is the ID of the main "Users" group
403
404
        $userService = $repository->getUserService();
405
406
        // Load main group
407
        $parentUserGroup = $userService->loadUserGroup($mainGroupId);
408
409
        // Instantiate a new create struct
410
        $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
411
412
        // This call will fail with a "ContentFieldValidationException", because the
413
        // only mandatory field "name" is not set.
414
        $userService->createUserGroup($userGroupCreate, $parentUserGroup);
415
        /* END: Use Case */
416
    }
417
418
    /**
419
     * Test for the createUserGroup() method.
420
     *
421
     * @return \eZ\Publish\API\Repository\Values\User\UserGroup
422
     *
423
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
424
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupCreateStruct
425
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
426
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
427
     */
428
    public function testCreateUserGroupInTransactionWithRollback()
429
    {
430
        $repository = $this->getRepository();
431
432
        $mainGroupId = $this->generateId('group', 4);
433
        /* BEGIN: Use Case */
434
        // $mainGroupId is the ID of the main "Users" group
435
436
        $userService = $repository->getUserService();
437
438
        $repository->beginTransaction();
439
440
        try {
441
            // Load main group
442
            $parentUserGroup = $userService->loadUserGroup($mainGroupId);
443
444
            // Instantiate a new create struct
445
            $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
446
            $userGroupCreate->setField('name', 'Example Group');
447
448
            // Create the new user group
449
            $createdUserGroupId = $userService->createUserGroup(
450
                $userGroupCreate,
451
                $parentUserGroup
452
            )->id;
453
        } catch (Exception $e) {
454
            // Cleanup hanging transaction on error
455
            $repository->rollback();
456
            throw $e;
457
        }
458
459
        $repository->rollback();
460
461
        try {
462
            // Throws exception since creation of user group was rolled back
463
            $loadedGroup = $userService->loadUserGroup($createdUserGroupId);
0 ignored issues
show
Unused Code introduced by
$loadedGroup is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
464
        } catch (NotFoundException $e) {
465
            return;
466
        }
467
        /* END: Use Case */
468
469
        $this->fail('User group object still exists after rollback.');
470
    }
471
472
    /**
473
     * Test for the deleteUserGroup() method.
474
     *
475
     * @see \eZ\Publish\API\Repository\UserService::deleteUserGroup()
476
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
477
     */
478
    public function testDeleteUserGroup()
479
    {
480
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
481
482
        $repository = $this->getRepository();
483
        $userService = $repository->getUserService();
484
485
        /* BEGIN: Use Case */
486
        $userGroup = $this->createUserGroupVersion1();
487
488
        // Delete the currently created user group again
489
        $userService->deleteUserGroup($userGroup);
490
        /* END: Use Case */
491
492
        // We use the NotFoundException here for verification
493
        $userService->loadUserGroup($userGroup->id);
494
    }
495
496
    /**
497
     * Test deleting user group throwing NotFoundException.
498
     *
499
     * @covers \eZ\Publish\API\Repository\UserService::deleteUserGroup
500
     */
501
    public function testDeleteUserGroupThrowsNotFoundException()
502
    {
503
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
504
505
        $repository = $this->getRepository();
506
        $userService = $repository->getUserService();
507
508
        $userGroup = new UserGroup(
509
            [
510
                'content' => new Content(
511
                    [
512
                        'versionInfo' => new VersionInfo(
513
                            ['contentInfo' => new ContentInfo(['id' => 123456])]
514
                        ),
515
                        'internalFields' => [],
516
                    ]
517
                ),
518
            ]
519
        );
520
        $userService->deleteUserGroup($userGroup);
521
    }
522
523
    /**
524
     * Test for the moveUserGroup() method.
525
     *
526
     * @see \eZ\Publish\API\Repository\UserService::moveUserGroup()
527
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
528
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadSubUserGroups
529
     */
530
    public function testMoveUserGroup()
531
    {
532
        $repository = $this->getRepository();
533
        $userService = $repository->getUserService();
534
535
        $membersGroupId = $this->generateId('group', 13);
536
        /* BEGIN: Use Case */
537
        // $membersGroupId is the ID of the "Members" user group in an eZ
538
        // Publish demo installation
539
540
        $userGroup = $this->createUserGroupVersion1();
541
542
        // Load the new parent group
543
        $membersUserGroup = $userService->loadUserGroup($membersGroupId);
544
545
        // Move user group from "Users" to "Members"
546
        $userService->moveUserGroup($userGroup, $membersUserGroup);
547
548
        // Reload the user group to get an updated $parentId
549
        $userGroup = $userService->loadUserGroup($userGroup->id);
550
551
        $this->refreshSearch($repository);
552
553
        // The returned array will no contain $userGroup
554
        $subUserGroups = $userService->loadSubUserGroups(
555
            $membersUserGroup
556
        );
557
        /* END: Use Case */
558
559
        $subUserGroupIds = array_map(
560
            function ($content) {
561
                return $content->id;
562
            },
563
            $subUserGroups
564
        );
565
566
        $this->assertEquals($membersGroupId, $userGroup->parentId);
567
        $this->assertEquals([$userGroup->id], $subUserGroupIds);
568
    }
569
570
    /**
571
     * Test moving a user group below another group throws NotFoundException.
572
     *
573
     * @covers \eZ\Publish\API\Repository\UserService::moveUserGroup
574
     */
575
    public function testMoveUserGroupThrowsNotFoundException()
576
    {
577
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
578
579
        $repository = $this->getRepository();
580
        $userService = $repository->getUserService();
581
582
        $userGroupToMove = new UserGroup(
583
            [
584
                'content' => new Content(
585
                    [
586
                        'versionInfo' => new VersionInfo(
587
                            ['contentInfo' => new ContentInfo(['id' => 123456])]
588
                        ),
589
                        'internalFields' => [],
590
                    ]
591
                ),
592
            ]
593
        );
594
        $parentUserGroup = new UserGroup(
595
            [
596
                'content' => new Content(
597
                    [
598
                        'versionInfo' => new VersionInfo(
599
                            ['contentInfo' => new ContentInfo(['id' => 123455])]
600
                        ),
601
                        'internalFields' => [],
602
                    ]
603
                ),
604
            ]
605
        );
606
        $userService->moveUserGroup($userGroupToMove, $parentUserGroup);
607
    }
608
609
    /**
610
     * Test for the newUserGroupUpdateStruct() method.
611
     *
612
     * @covers \eZ\Publish\API\Repository\UserService::newUserGroupUpdateStruct
613
     */
614
    public function testNewUserGroupUpdateStruct()
615
    {
616
        $repository = $this->getRepository();
617
618
        /* BEGIN: Use Case */
619
        $userService = $repository->getUserService();
620
621
        $groupUpdate = $userService->newUserGroupUpdateStruct();
622
        /* END: Use Case */
623
624
        $this->assertInstanceOf(
625
            UserGroupUpdateStruct::class,
626
            $groupUpdate
627
        );
628
629
        $this->assertNull($groupUpdate->contentUpdateStruct);
630
        $this->assertNull($groupUpdate->contentMetadataUpdateStruct);
631
    }
632
633
    /**
634
     * Test for the updateUserGroup() method.
635
     *
636
     * @see \eZ\Publish\API\Repository\UserService::updateUserGroup()
637
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
638
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupUpdateStruct
639
     */
640
    public function testUpdateUserGroup()
641
    {
642
        $repository = $this->getRepository();
643
        $userService = $repository->getUserService();
644
645
        /* BEGIN: Use Case */
646
        $userGroup = $this->createUserGroupVersion1();
647
648
        // Create a group update struct and change nothing
649
        $groupUpdate = $userService->newUserGroupUpdateStruct();
650
651
        // This update will do nothing
652
        $userGroup = $userService->updateUserGroup(
653
            $userGroup,
654
            $groupUpdate
655
        );
656
        /* END: Use Case */
657
658
        $this->assertInstanceOf(
659
            UserGroup::class,
660
            $userGroup
661
        );
662
663
        $this->assertEquals(1, $userGroup->getVersionInfo()->versionNo);
664
    }
665
666
    /**
667
     * Test for the updateUserGroup() method.
668
     *
669
     * @see \eZ\Publish\API\Repository\UserService::updateUserGroup()
670
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUserGroup
671
     */
672
    public function testUpdateUserGroupWithSubContentUpdateStruct()
673
    {
674
        $repository = $this->getRepository();
675
        $userService = $repository->getUserService();
676
677
        /* BEGIN: Use Case */
678
        $userGroup = $this->createUserGroupVersion1();
679
680
        // Load the content service
681
        $contentService = $repository->getContentService();
682
683
        // Create a content update struct and update the group name
684
        $contentUpdate = $contentService->newContentUpdateStruct();
685
        $contentUpdate->setField('name', 'Sindelfingen', 'eng-US');
686
687
        // Create a group update struct and set content update struct
688
        $groupUpdate = $userService->newUserGroupUpdateStruct();
689
        $groupUpdate->contentUpdateStruct = $contentUpdate;
690
691
        // This will update the name and the increment the group version number
692
        $userGroup = $userService->updateUserGroup(
693
            $userGroup,
694
            $groupUpdate
695
        );
696
        /* END: Use Case */
697
698
        $this->assertEquals('Sindelfingen', $userGroup->getFieldValue('name', 'eng-US'));
699
700
        $versionInfo = $userGroup->getVersionInfo();
701
702
        $this->assertEquals(APIVersionInfo::STATUS_PUBLISHED, $versionInfo->status);
703
        $this->assertEquals(2, $versionInfo->versionNo);
704
    }
705
706
    /**
707
     * Test for the updateUserGroup() method.
708
     *
709
     * @see \eZ\Publish\API\Repository\UserService::updateUserGroup()
710
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUserGroup
711
     */
712
    public function testUpdateUserGroupWithSubContentMetadataUpdateStruct()
713
    {
714
        $repository = $this->getRepository();
715
        $userService = $repository->getUserService();
716
717
        /* BEGIN: Use Case */
718
        $userGroup = $this->createUserGroupVersion1();
719
720
        // Load the content service
721
        $contentService = $repository->getContentService();
722
723
        // Create a metadata update struct and change the remoteId
724
        $metadataUpdate = $contentService->newContentMetadataUpdateStruct();
725
        $metadataUpdate->remoteId = '3c61299780663bafa3af2101e52125da';
726
727
        // Create a group update struct and set content update struct
728
        $groupUpdate = $userService->newUserGroupUpdateStruct();
729
        $groupUpdate->contentMetadataUpdateStruct = $metadataUpdate;
730
731
        // This will update the name and the increment the group version number
732
        $userGroup = $userService->updateUserGroup(
733
            $userGroup,
734
            $groupUpdate
735
        );
736
        /* END: Use Case */
737
738
        $this->assertEquals(
739
            '3c61299780663bafa3af2101e52125da',
740
            $userGroup->contentInfo->remoteId
741
        );
742
743
        $versionInfo = $userGroup->getVersionInfo();
744
745
        $this->assertEquals(APIVersionInfo::STATUS_PUBLISHED, $versionInfo->status);
746
        $this->assertEquals(1, $versionInfo->versionNo);
747
    }
748
749
    /**
750
     * Test for the updateUserGroup() method.
751
     *
752
     * @see \eZ\Publish\API\Repository\UserService::updateUserGroup()
753
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUserGroup
754
     */
755
    public function testUpdateUserGroupThrowsInvalidArgumentExceptionOnFieldTypeNotAccept()
756
    {
757
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
758
759
        $repository = $this->getRepository();
760
        $userService = $repository->getUserService();
761
762
        /* BEGIN: Use Case */
763
        $userGroup = $this->createUserGroupVersion1();
764
765
        // Load the content service
766
        $contentService = $repository->getContentService();
767
768
        // Create a content update struct and update the group name
769
        $contentUpdate = $contentService->newContentUpdateStruct();
770
        // An object of stdClass is not accepted as a value by the field "name"
771
        $contentUpdate->setField('name', new \stdClass(), 'eng-US');
772
773
        // Create a group update struct and set content update struct
774
        $groupUpdate = $userService->newUserGroupUpdateStruct();
775
        $groupUpdate->contentUpdateStruct = $contentUpdate;
776
777
        // This call will fail with an InvalidArgumentException, because the
778
        // field "name" does not accept the given value
779
        $userService->updateUserGroup($userGroup, $groupUpdate);
780
        /* END: Use Case */
781
    }
782
783
    /**
784
     * Test for the newUserCreateStruct() method.
785
     *
786
     * @see \eZ\Publish\API\Repository\UserService::newUserCreateStruct()
787
     */
788
    public function testNewUserCreateStruct()
789
    {
790
        $repository = $this->getRepository();
791
792
        /* BEGIN: Use Case */
793
        $userService = $repository->getUserService();
794
795
        $userCreate = $userService->newUserCreateStruct(
796
            'user',
797
            '[email protected]',
798
            'secret',
799
            'eng-US'
800
        );
801
        /* END: Use Case */
802
803
        $this->assertInstanceOf(
804
            '\\eZ\\Publish\\API\\Repository\\Values\\User\\UserCreateStruct',
805
            $userCreate
806
        );
807
808
        return $userCreate;
809
    }
810
811
    /**
812
     * Test updating a user group throws ContentFieldValidationException.
813
     *
814
     * @covers \eZ\Publish\API\Repository\UserService::updateUserGroup
815
     */
816
    public function testUpdateUserGroupThrowsContentFieldValidationExceptionOnRequiredFieldEmpty()
817
    {
818
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException::class);
819
820
        $repository = $this->getRepository();
821
        $userService = $repository->getUserService();
822
        $contentService = $repository->getContentService();
823
824
        $userGroup = $userService->loadUserGroup(42);
825
        $userGroupUpdateStruct = $userService->newUserGroupUpdateStruct();
826
        $userGroupUpdateStruct->contentUpdateStruct = $contentService->newContentUpdateStruct();
827
        $userGroupUpdateStruct->contentUpdateStruct->setField('name', '', 'eng-US');
828
829
        $userService->updateUserGroup($userGroup, $userGroupUpdateStruct);
830
    }
831
832
    /**
833
     * Test for the newUserCreateStruct() method.
834
     *
835
     * @param \eZ\Publish\API\Repository\Values\User\UserCreateStruct $userCreate
836
     *
837
     * @see \eZ\Publish\API\Repository\UserService::newUserCreateStruct()
838
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserCreateStruct
839
     */
840
    public function testNewUserCreateStructSetsExpectedProperties($userCreate)
841
    {
842
        $this->assertEquals(
843
            [
844
                'login' => 'user',
845
                'email' => '[email protected]',
846
                'password' => 'secret',
847
                'mainLanguageCode' => 'eng-US',
848
            ],
849
            [
850
                'login' => $userCreate->login,
851
                'email' => $userCreate->email,
852
                'password' => $userCreate->password,
853
                'mainLanguageCode' => $userCreate->mainLanguageCode,
854
            ]
855
        );
856
    }
857
858
    /**
859
     * Test for the newUserCreateStruct() method.
860
     *
861
     * @see \eZ\Publish\API\Repository\UserService::newUserCreateStruct($login, $email, $password, $mainLanguageCode, $contentType)
862
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserCreateStruct
863
     * @depends eZ\Publish\API\Repository\Tests\ContentTypeServiceTest::testLoadContentTypeByIdentifier
864
     */
865
    public function testNewUserCreateStructWithFifthParameter()
866
    {
867
        $repository = $this->getRepository();
868
869
        /* BEGIN: Use Case */
870
        $contentTypeService = $repository->getContentTypeService();
871
        $userService = $repository->getUserService();
872
873
        $userType = $contentTypeService->loadContentTypeByIdentifier('user');
874
875
        $userCreate = $userService->newUserCreateStruct(
876
            'user',
877
            '[email protected]',
878
            'secret',
879
            'eng-US',
880
            $userType
881
        );
882
        /* END: Use Case */
883
884
        $this->assertSame($userType, $userCreate->contentType);
885
    }
886
887
    /**
888
     * Test for creating user with Active Directory login name.
889
     */
890
    public function testNewUserWithDomainName()
891
    {
892
        $repository = $this->getRepository();
893
        $userService = $repository->getUserService();
894
        $createdUser = $this->createUserVersion1(
895
            'ez-user-Domain\username-by-login',
896
            '[email protected]'
897
        );
898
        $loadedUser = $userService->loadUserByLogin('ez-user-Domain\username-by-login', Language::ALL);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...vice::loadUserByLogin() has been deprecated with message: since eZ Platform 2.5, will be dropped in the next major version as authentication may depend on various user providers. Use UserService::checkUserCredentials() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
899
900
        $this->assertEquals($createdUser, $loadedUser);
901
    }
902
903
    /**
904
     * Test for the createUser() method.
905
     *
906
     * @return \eZ\Publish\API\Repository\Values\User\User
907
     *
908
     * @see \eZ\Publish\API\Repository\UserService::createUser()
909
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
910
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserCreateStruct
911
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
912
     */
913
    public function testCreateUser()
914
    {
915
        /* BEGIN: Use Case */
916
        $user = $this->createUserVersion1();
917
        /* END: Use Case */
918
919
        $this->assertInstanceOf(
920
            '\\eZ\\Publish\\API\\Repository\\Values\\User\\User',
921
            $user
922
        );
923
924
        return $user;
925
    }
926
927
    /**
928
     * Test for the createUser() method.
929
     *
930
     * @param \eZ\Publish\API\Repository\Values\User\User $user
931
     *
932
     * @see \eZ\Publish\API\Repository\UserService::createUser()
933
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
934
     */
935
    public function testCreateUserSetsExpectedProperties(User $user)
936
    {
937
        $this->assertEquals(
938
            [
939
                'login' => 'user',
940
                'email' => '[email protected]',
941
                'mainLanguageCode' => 'eng-US',
942
            ],
943
            [
944
                'login' => $user->login,
945
                'email' => $user->email,
946
                'mainLanguageCode' => $user->contentInfo->mainLanguageCode,
947
            ]
948
        );
949
    }
950
951
    /**
952
     * Test for the createUser() method.
953
     *
954
     * @see \eZ\Publish\API\Repository\UserService::createUser()
955
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
956
     */
957
    public function testCreateUserWhenMissingField()
958
    {
959
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException::class);
960
961
        $repository = $this->getRepository();
962
963
        $editorsGroupId = $this->generateId('group', 13);
964
        /* BEGIN: Use Case */
965
        // $editorsGroupId is the ID of the "Editors" user group in an eZ
966
        // Publish demo installation
967
968
        $userService = $repository->getUserService();
969
970
        // Instantiate a create struct with mandatory properties
971
        $userCreate = $userService->newUserCreateStruct(
972
            'user',
973
            '[email protected]',
974
            'secret',
975
            'eng-US'
976
        );
977
978
        // Do not set the mandatory fields "first_name" and "last_name"
979
        //$userCreate->setField( 'first_name', 'Example' );
980
        //$userCreate->setField( 'last_name', 'User' );
981
982
        // Load parent group for the user
983
        $group = $userService->loadUserGroup($editorsGroupId);
984
985
        // This call will fail with a "ContentFieldValidationException", because the
986
        // mandatory fields "first_name" and "last_name" are not set.
987
        $userService->createUser($userCreate, [$group]);
988
        /* END: Use Case */
989
    }
990
991
    /**
992
     * Test for the createUser() method.
993
     *
994
     * @see \eZ\Publish\API\Repository\UserService::createUser()
995
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
996
     */
997
    public function testCreateUserThrowsInvalidArgumentExceptionOnFieldTypeNotAccept()
998
    {
999
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
1000
1001
        $repository = $this->getRepository();
1002
1003
        $editorsGroupId = $this->generateId('group', 13);
1004
        /* BEGIN: Use Case */
1005
        // $editorsGroupId is the ID of the "Editors" user group in an eZ
1006
        // Publish demo installation
1007
1008
        $userService = $repository->getUserService();
1009
1010
        // Instantiate a create struct with mandatory properties
1011
        $userCreate = $userService->newUserCreateStruct(
1012
            'user',
1013
            '[email protected]',
1014
            'secret',
1015
            'eng-US'
1016
        );
1017
1018
        // An object of stdClass is not a valid value for the field first_name
1019
        $userCreate->setField('first_name', new \stdClass());
1020
        $userCreate->setField('last_name', 'User');
1021
1022
        // Load parent group for the user
1023
        $group = $userService->loadUserGroup($editorsGroupId);
1024
1025
        // This call will fail with an "InvalidArgumentException", because the
1026
        // value for the firled "first_name" is not accepted by the field type.
1027
        $userService->createUser($userCreate, [$group]);
1028
        /* END: Use Case */
1029
    }
1030
1031
    /**
1032
     * Test for the createUser() method.
1033
     *
1034
     * @covers \eZ\Publish\API\Repository\UserService::createUser
1035
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1036
     */
1037
    public function testCreateUserThrowsInvalidArgumentException()
1038
    {
1039
        $repository = $this->getRepository();
1040
1041
        $editorsGroupId = $this->generateId('group', 13);
1042
        /* BEGIN: Use Case */
1043
        // $editorsGroupId is the ID of the "Editors" user group in an eZ
1044
        // Publish demo installation
1045
1046
        $userService = $repository->getUserService();
1047
1048
        // Instantiate a create struct with mandatory properties
1049
        $userCreate = $userService->newUserCreateStruct(
1050
            // admin is an existing login
1051
            'admin',
1052
            '[email protected]',
1053
            'secret',
1054
            'eng-US'
1055
        );
1056
1057
        $userCreate->setField('first_name', 'Example');
1058
        $userCreate->setField('last_name', 'User');
1059
1060
        // Load parent group for the user
1061
        $group = $userService->loadUserGroup($editorsGroupId);
1062
1063
        try {
1064
            // This call will fail with a "InvalidArgumentException", because the
1065
            // user with "admin" login already exists.
1066
            $userService->createUser($userCreate, [$group]);
1067
            /* END: Use Case */
1068
        } catch (ContentFieldValidationException $e) {
1069
            // Exception is caught, as there is no other way to check exception properties.
1070
            $this->assertValidationErrorOccurs($e, 'The user login \'%login%\' is used by another user. You must enter a unique login.');
1071
1072
            /* END: Use Case */
1073
            return;
1074
        }
1075
1076
        $this->fail('Expected ValidationError messages did not occur.');
1077
    }
1078
1079
    /**
1080
     * Test for the createUser() method.
1081
     *
1082
     * @return \eZ\Publish\API\Repository\Values\User\User
1083
     *
1084
     * @see \eZ\Publish\API\Repository\UserService::createUser()
1085
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
1086
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserCreateStruct
1087
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
1088
     */
1089
    public function testCreateUserInTransactionWithRollback()
1090
    {
1091
        $repository = $this->getRepository();
1092
        $userService = $repository->getUserService();
1093
1094
        /* BEGIN: Use Case */
1095
        $repository->beginTransaction();
1096
1097
        try {
1098
            $user = $this->createUserVersion1();
1099
        } catch (Exception $e) {
1100
            // Cleanup hanging transaction on error
1101
            $repository->rollback();
1102
            throw $e;
1103
        }
1104
1105
        $repository->rollback();
1106
1107
        try {
1108
            // Throws exception since creation of user was rolled back
1109
            $loadedUser = $userService->loadUser($user->id);
0 ignored issues
show
Unused Code introduced by
$loadedUser is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1110
        } catch (NotFoundException $e) {
1111
            return;
1112
        }
1113
        /* END: Use Case */
1114
1115
        $this->fail('User object still exists after rollback.');
1116
    }
1117
1118
    /**
1119
     * Test creating a user throwing NotFoundException.
1120
     *
1121
     * @covers \eZ\Publish\API\Repository\UserService::createUser
1122
     */
1123
    public function testCreateUserThrowsNotFoundException()
1124
    {
1125
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1126
1127
        $repository = $this->getRepository();
1128
        $userService = $repository->getUserService();
1129
1130
        $userCreateStruct = $userService->newUserCreateStruct('new_user', '[email protected]', 'password', 'eng-GB');
1131
        $userCreateStruct->setField('first_name', 'New');
1132
        $userCreateStruct->setField('last_name', 'User');
1133
1134
        $parentGroup = new UserGroup(
1135
            [
1136
                'content' => new Content(
1137
                    [
1138
                        'versionInfo' => new VersionInfo(
1139
                            [
1140
                                'contentInfo' => new ContentInfo(['id' => 123456]),
1141
                            ]
1142
                        ),
1143
                        'internalFields' => [],
1144
                    ]
1145
                ),
1146
            ]
1147
        );
1148
        $userService->createUser($userCreateStruct, [$parentGroup]);
1149
    }
1150
1151
    /**
1152
     * Test creating a user throwing UserPasswordValidationException when password doesn't follow specific rules.
1153
     *
1154
     * @covers \eZ\Publish\API\Repository\UserService::createUser
1155
     */
1156
    public function testCreateUserWithWeakPasswordThrowsUserPasswordValidationException()
1157
    {
1158
        $userContentType = $this->createUserContentTypeWithStrongPassword();
1159
1160
        try {
1161
            // This call will fail with a "UserPasswordValidationException" because the
1162
            // the password does not follow specified rules.
1163
            $this->createTestUserWithPassword('pass', $userContentType);
1164
        } catch (ContentFieldValidationException $e) {
1165
            // Exception is caught, as there is no other way to check exception properties.
1166
            $this->assertAllValidationErrorsOccur(
1167
                $e,
1168
                [
1169
                    'User password must include at least one special character',
1170
                    'User password must be at least %length% characters long',
1171
                    'User password must include at least one upper case letter',
1172
                    'User password must include at least one number',
1173
                ]
1174
            );
1175
1176
            return;
1177
        }
1178
1179
        $this->fail('Expected ValidationError messages did not occur.');
1180
    }
1181
1182
    /**
1183
     * Opposite test case for testCreateUserWithWeakPasswordThrowsUserPasswordValidationException.
1184
     *
1185
     * @covers \eZ\Publish\API\Repository\UserService::createUser
1186
     */
1187
    public function testCreateUserWithStrongPassword()
1188
    {
1189
        $userContentType = $this->createUserContentTypeWithStrongPassword();
1190
1191
        /* BEGIN: Use Case */
1192
        $user = $this->createTestUserWithPassword('H@xxi0r!', $userContentType);
1193
        /* END: Use Case */
1194
1195
        $this->assertInstanceOf(User::class, $user);
1196
    }
1197
1198
    /**
1199
     * Test for the loadUser() method.
1200
     *
1201
     * @see \eZ\Publish\API\Repository\UserService::loadUser()
1202
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1203
     */
1204
    public function testLoadUser()
1205
    {
1206
        $repository = $this->getRepository();
1207
1208
        $userService = $repository->getUserService();
1209
1210
        /* BEGIN: Use Case */
1211
        $user = $this->createUserVersion1();
1212
1213
        // Load the newly created user
1214
        $userReloaded = $userService->loadUser($user->id, Language::ALL);
1215
        /* END: Use Case */
1216
1217
        $this->assertEquals($user, $userReloaded);
1218
1219
        // User happens to also be a Content; isUser() should be true and isUserGroup() should be false
1220
        $this->assertTrue($userService->isUser($user), 'isUser() => false on a user');
1221
        $this->assertFalse($userService->isUserGroup($user), 'isUserGroup() => true on a user group');
1222
    }
1223
1224
    /**
1225
     * Test for the loadUser() method.
1226
     *
1227
     * @see \eZ\Publish\API\Repository\UserService::loadUser()
1228
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUser
1229
     */
1230
    public function testLoadUserThrowsNotFoundException()
1231
    {
1232
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1233
1234
        $repository = $this->getRepository();
1235
1236
        $nonExistingUserId = $this->generateId('user', self::DB_INT_MAX);
1237
        /* BEGIN: Use Case */
1238
        $userService = $repository->getUserService();
1239
1240
        // This call will fail with a "NotFoundException", because no user with
1241
        // an id equal to self::DB_INT_MAX should exist.
1242
        $userService->loadUser($nonExistingUserId);
1243
        /* END: Use Case */
1244
    }
1245
1246
    /**
1247
     * @see \eZ\Publish\API\Repository\UserService::checkUserCredentials()
1248
     * @depends \eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1249
     */
1250
    public function testCheckUserCredentialsValid(): void
1251
    {
1252
        $repository = $this->getRepository();
1253
1254
        $userService = $repository->getUserService();
1255
1256
        /* BEGIN: Use Case */
1257
        $user = $this->createUserVersion1();
1258
1259
        // Load the newly created user credentials
1260
        $credentialsValid = $userService->loadUserByCredentials($user, 'secret');
0 ignored issues
show
Bug introduced by
The method loadUserByCredentials() does not exist on eZ\Publish\API\Repository\UserService. Did you maybe mean loadUser()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
1261
        /* END: Use Case */
1262
1263
        $this->assertTrue($credentialsValid);
1264
    }
1265
1266
    /**
1267
     * @see \eZ\Publish\API\Repository\UserService::checkUserCredentials()
1268
     * @depends \eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1269
     */
1270
    public function testCheckUserCredentialsInvalid(): void
1271
    {
1272
        $repository = $this->getRepository();
1273
1274
        $userService = $repository->getUserService();
1275
1276
        /* BEGIN: Use Case */
1277
        $user = $this->createUserVersion1();
1278
1279
        // Load the newly created user credentials
1280
        $credentialsValid = $userService->loadUserByCredentials($user, '1234');
0 ignored issues
show
Bug introduced by
The method loadUserByCredentials() does not exist on eZ\Publish\API\Repository\UserService. Did you maybe mean loadUser()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
1281
        /* END: Use Case */
1282
1283
        $this->assertFalse($credentialsValid);
1284
    }
1285
1286
    /**
1287
     * Test for the loadUserByLogin() method.
1288
     *
1289
     * @see \eZ\Publish\API\Repository\UserService::loadUserByLogin()
1290
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1291
     */
1292
    public function testLoadUserByLogin()
1293
    {
1294
        $repository = $this->getRepository();
1295
1296
        $userService = $repository->getUserService();
1297
1298
        /* BEGIN: Use Case */
1299
        $user = $this->createUserVersion1('User');
1300
1301
        // Load the newly created user
1302
        $userReloaded = $userService->loadUserByLogin('User');
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...vice::loadUserByLogin() has been deprecated with message: since eZ Platform 2.5, will be dropped in the next major version as authentication may depend on various user providers. Use UserService::checkUserCredentials() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1303
        /* END: Use Case */
1304
1305
        $this->assertPropertiesCorrect(
1306
            [
1307
                'login' => $user->login,
1308
                'email' => $user->email,
1309
                'passwordHash' => $user->passwordHash,
1310
                'hashAlgorithm' => $user->hashAlgorithm,
1311
                'enabled' => $user->enabled,
1312
                'maxLogin' => $user->maxLogin,
1313
                'id' => $user->id,
1314
                'contentInfo' => $user->contentInfo,
1315
                'versionInfo' => $user->versionInfo,
1316
                'fields' => $user->fields,
1317
            ],
1318
            $userReloaded
1319
        );
1320
    }
1321
1322
    /**
1323
     * Test for the loadUserByLogin() method.
1324
     *
1325
     * @see \eZ\Publish\API\Repository\UserService::loadUserByLogin()
1326
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByLogin
1327
     */
1328
    public function testLoadUserByLoginThrowsNotFoundExceptionForUnknownLogin()
1329
    {
1330
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1331
1332
        $repository = $this->getRepository();
1333
1334
        $userService = $repository->getUserService();
1335
1336
        /* BEGIN: Use Case */
1337
        $this->createUserVersion1();
1338
1339
        // This call will fail with a "NotFoundException", because the given
1340
        // login/password combination does not exist.
1341
        $userService->loadUserByLogin('user42');
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...vice::loadUserByLogin() has been deprecated with message: since eZ Platform 2.5, will be dropped in the next major version as authentication may depend on various user providers. Use UserService::checkUserCredentials() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1342
        /* END: Use Case */
1343
    }
1344
1345
    /**
1346
     * Test for the loadUserByLogin() method.
1347
     *
1348
     * @see \eZ\Publish\API\Repository\UserService::loadUserByLogin()
1349
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByLogin
1350
     */
1351
    public function testLoadUserByLoginWorksForLoginWithWrongCase()
1352
    {
1353
        $repository = $this->getRepository();
1354
1355
        $userService = $repository->getUserService();
1356
1357
        /* BEGIN: Use Case */
1358
        $user = $this->createUserVersion1();
1359
1360
        // Lookup by user login should ignore casing
1361
        $userReloaded = $userService->loadUserByLogin('USER');
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...vice::loadUserByLogin() has been deprecated with message: since eZ Platform 2.5, will be dropped in the next major version as authentication may depend on various user providers. Use UserService::checkUserCredentials() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1362
        /* END: Use Case */
1363
1364
        $this->assertPropertiesCorrect(
1365
            [
1366
                'login' => $user->login,
1367
                'email' => $user->email,
1368
                'passwordHash' => $user->passwordHash,
1369
                'hashAlgorithm' => $user->hashAlgorithm,
1370
                'enabled' => $user->enabled,
1371
                'maxLogin' => $user->maxLogin,
1372
                'id' => $user->id,
1373
                'contentInfo' => $user->contentInfo,
1374
                'versionInfo' => $user->versionInfo,
1375
                'fields' => $user->fields,
1376
            ],
1377
            $userReloaded
1378
        );
1379
    }
1380
1381
    /**
1382
     * Test for the loadUserByLogin() method.
1383
     *
1384
     * In some cases people use email as login name, make sure system works as exepcted when asking for user by email.
1385
     *
1386
     * @see \eZ\Publish\API\Repository\UserService::loadUserByLogin()
1387
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByLogin
1388
     */
1389
    public function testLoadUserByLoginThrowsNotFoundExceptionForUnknownLoginByEmail()
1390
    {
1391
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1392
1393
        $repository = $this->getRepository();
1394
1395
        $userService = $repository->getUserService();
1396
1397
        /* BEGIN: Use Case */
1398
        $user = $this->createUserVersion1();
0 ignored issues
show
Unused Code introduced by
$user is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1399
1400
        // Lookup by user login by email should behave as normal
1401
        $userService->loadUserByLogin('[email protected]');
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...vice::loadUserByLogin() has been deprecated with message: since eZ Platform 2.5, will be dropped in the next major version as authentication may depend on various user providers. Use UserService::checkUserCredentials() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1402
        /* END: Use Case */
1403
    }
1404
1405
    /**
1406
     * Test for the loadUsersByEmail() method.
1407
     *
1408
     * @see \eZ\Publish\API\Repository\UserService::loadUsersByEmail()
1409
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1410
     */
1411
    public function testLoadUserByEmail()
1412
    {
1413
        $repository = $this->getRepository();
1414
1415
        $userService = $repository->getUserService();
1416
1417
        /* BEGIN: Use Case */
1418
        $user = $this->createUserVersion1();
1419
1420
        // Load the newly created user
1421
        $usersReloaded = $userService->loadUsersByEmail('[email protected]', Language::ALL);
1422
        /* END: Use Case */
1423
1424
        $this->assertEquals([$user], $usersReloaded);
1425
    }
1426
1427
    /**
1428
     * Test for the loadUsersByEmail() method.
1429
     *
1430
     * @see \eZ\Publish\API\Repository\UserService::loadUsersByEmail()
1431
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByEmail
1432
     */
1433
    public function testLoadUserByEmailReturnsEmptyInUnknownEmail()
1434
    {
1435
        $repository = $this->getRepository();
1436
1437
        $userService = $repository->getUserService();
1438
1439
        /* BEGIN: Use Case */
1440
        $this->createUserVersion1();
1441
1442
        // This call will return empty array, because the given
1443
        // login/password combination does not exist.
1444
        $emptyUserList = $userService->loadUsersByEmail('[email protected]');
1445
        /* END: Use Case */
1446
1447
        $this->assertEquals([], $emptyUserList);
1448
    }
1449
1450
    /**
1451
     * Test for the deleteUser() method.
1452
     *
1453
     * @see \eZ\Publish\API\Repository\UserService::deleteUser()
1454
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1455
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUser
1456
     */
1457
    public function testDeleteUser()
1458
    {
1459
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1460
1461
        $repository = $this->getRepository();
1462
1463
        $userService = $repository->getUserService();
1464
1465
        /* BEGIN: Use Case */
1466
        $user = $this->createUserVersion1();
1467
1468
        // Delete the currently created user
1469
        $userService->deleteUser($user);
1470
        /* END: Use Case */
1471
1472
        // We use the NotFoundException here to verify that the user not exists
1473
        $userService->loadUser($user->id);
1474
    }
1475
1476
    /**
1477
     * Test for the deleteUser() method.
1478
     *
1479
     * @covers \eZ\Publish\API\Repository\UserService::deleteUser()
1480
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1481
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUser
1482
     */
1483
    public function testDeleteUserDeletesRelatedBookmarks()
1484
    {
1485
        $repository = $this->getRepository();
1486
1487
        $userService = $repository->getUserService();
1488
        $locationService = $repository->getLocationService();
1489
        $bookmarkService = $repository->getBookmarkService();
1490
        /* BEGIN: Use Case */
1491
        $admin = $repository->getPermissionResolver()->getCurrentUserReference();
1492
1493
        $user = $this->createUserVersion1();
1494
1495
        $repository->getPermissionResolver()->setCurrentUserReference($user);
1496
1497
        $bookmarkService->createBookmark(
1498
            $locationService->loadLocation($this->generateId('location', 43))
1499
        );
1500
1501
        $repository->getPermissionResolver()->setCurrentUserReference($admin);
1502
        // Delete the currently created user
1503
        $userService->deleteUser($user);
1504
1505
        $repository->getPermissionResolver()->setCurrentUserReference($user);
1506
        /* END: Use Case */
1507
1508
        $this->assertEquals(0, $bookmarkService->loadBookmarks(0, 9999)->totalCount);
1509
    }
1510
1511
    /**
1512
     * Test for the newUserUpdateStruct() method.
1513
     *
1514
     * @see \eZ\Publish\API\Repository\UserService::newUserUpdateStruct()
1515
     */
1516
    public function testNewUserUpdateStruct()
1517
    {
1518
        $repository = $this->getRepository();
1519
1520
        /* BEGIN: Use Case */
1521
        $userService = $repository->getUserService();
1522
1523
        // Create a new update struct instance
1524
        $userUpdate = $userService->newUserUpdateStruct();
1525
        /* END: Use Case */
1526
1527
        $this->assertInstanceOf(
1528
            UserUpdateStruct::class,
1529
            $userUpdate
1530
        );
1531
1532
        $this->assertNull($userUpdate->contentUpdateStruct);
1533
        $this->assertNull($userUpdate->contentMetadataUpdateStruct);
1534
1535
        $this->assertPropertiesCorrect(
1536
            [
1537
                'email' => null,
1538
                'password' => null,
1539
                'enabled' => null,
1540
                'maxLogin' => null,
1541
            ],
1542
            $userUpdate
1543
        );
1544
    }
1545
1546
    /**
1547
     * Test for the updateUser() method.
1548
     *
1549
     * @return \eZ\Publish\API\Repository\Values\User\User
1550
     *
1551
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1552
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1553
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserUpdateStruct
1554
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1555
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
1556
     */
1557
    public function testUpdateUser()
1558
    {
1559
        $repository = $this->getRepository();
1560
1561
        $userService = $repository->getUserService();
1562
1563
        /* BEGIN: Use Case */
1564
        $user = $this->createUserVersion1();
1565
1566
        // Create a new update struct instance
1567
        $userUpdate = $userService->newUserUpdateStruct();
1568
1569
        // Set new values for password and maxLogin
1570
        $userUpdate->password = 'my-new-password';
1571
        $userUpdate->maxLogin = 42;
1572
        $userUpdate->enabled = false;
1573
1574
        // Updated the user record.
1575
        $userVersion2 = $userService->updateUser($user, $userUpdate);
1576
        /* END: Use Case */
1577
1578
        $this->assertInstanceOf(User::class, $userVersion2);
1579
1580
        return $userVersion2;
1581
    }
1582
1583
    /**
1584
     * Test for the updateUser() and loadUsersByEmail() method on change to email.
1585
     */
1586
    public function testUpdateUserEmail(): void
1587
    {
1588
        $repository = $this->getRepository();
1589
        $userService = $repository->getUserService();
1590
1591
        // Create a user
1592
        $user = $this->createUserVersion1();
1593
1594
        // Check we get what we expect (and implicit warmup any kind of cache)
1595
        $users = $userService->loadUsersByEmail('[email protected]');
1596
        $this->assertCount(0, $users);
1597
1598
        // Update user with the given email address
1599
        $userUpdate = $userService->newUserUpdateStruct();
1600
        $userUpdate->email = '[email protected]';
1601
        $updatedUser = $userService->updateUser($user, $userUpdate);
1602
        $this->assertInstanceOf(User::class, $updatedUser);
1603
1604
        // Check that we can load user by email
1605
        $users = $userService->loadUsersByEmail('[email protected]');
1606
        $this->assertCount(1, $users);
1607
        $this->assertInstanceOf(User::class, $users[0]);
1608
    }
1609
1610
    /**
1611
     * Test for the updateUser() method.
1612
     *
1613
     * @return \eZ\Publish\API\Repository\Values\User\User
1614
     *
1615
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1616
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1617
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserUpdateStruct
1618
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1619
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
1620
     */
1621
    public function testUpdateUserNoPassword()
1622
    {
1623
        $repository = $this->getRepository();
1624
        $userService = $repository->getUserService();
1625
1626
        /* BEGIN: Use Case */
1627
        $user = $this->createUserVersion1();
1628
1629
        // Create a new update struct instance
1630
        $userUpdate = $userService->newUserUpdateStruct();
1631
1632
        // Set new values for maxLogin, don't change password
1633
        $userUpdate->maxLogin = 43;
1634
        $userUpdate->enabled = false;
1635
1636
        // Updated the user record.
1637
        $userVersion2 = $userService->updateUser($user, $userUpdate);
1638
        /* END: Use Case */
1639
1640
        $this->assertInstanceOf(User::class, $user);
1641
1642
        $this->assertEquals(
1643
            [
1644
                'login' => $user->login,
1645
                'email' => $user->email,
1646
                'passwordHash' => $user->passwordHash,
1647
                'hashAlgorithm' => $user->hashAlgorithm,
1648
                'maxLogin' => 43,
1649
                'enabled' => false,
1650
            ],
1651
            [
1652
                'login' => $userVersion2->login,
1653
                'email' => $userVersion2->email,
1654
                'passwordHash' => $userVersion2->passwordHash,
1655
                'hashAlgorithm' => $userVersion2->hashAlgorithm,
1656
                'maxLogin' => $userVersion2->maxLogin,
1657
                'enabled' => $userVersion2->enabled,
1658
            ]
1659
        );
1660
    }
1661
1662
    /**
1663
     * Test for the updateUser() method.
1664
     *
1665
     * @param \eZ\Publish\API\Repository\Values\User\User $user
1666
     *
1667
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1668
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1669
     */
1670
    public function testUpdateUserUpdatesExpectedProperties(User $user)
1671
    {
1672
        $this->assertEquals(
1673
            [
1674
                'login' => 'user',
1675
                'email' => '[email protected]',
1676
                'maxLogin' => 42,
1677
                'enabled' => false,
1678
            ],
1679
            [
1680
                'login' => $user->login,
1681
                'email' => $user->email,
1682
                'maxLogin' => $user->maxLogin,
1683
                'enabled' => $user->enabled,
1684
            ]
1685
        );
1686
    }
1687
1688
    /**
1689
     * Test for the updateUser() method.
1690
     *
1691
     * @param \eZ\Publish\API\Repository\Values\User\User $user
1692
     *
1693
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1694
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1695
     */
1696
    public function testUpdateUserReturnsPublishedVersion(User $user)
1697
    {
1698
        $this->assertEquals(
1699
            APIVersionInfo::STATUS_PUBLISHED,
1700
            $user->getVersionInfo()->status
1701
        );
1702
    }
1703
1704
    /**
1705
     * Test for the updateUser() method.
1706
     *
1707
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1708
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1709
     */
1710
    public function testUpdateUserWithContentMetadataUpdateStruct()
1711
    {
1712
        $repository = $this->getRepository();
1713
1714
        $userService = $repository->getUserService();
1715
1716
        /* BEGIN: Use Case */
1717
        $user = $this->createUserVersion1();
1718
1719
        // Get the ContentService implementation
1720
        $contentService = $repository->getContentService();
1721
1722
        // Create a metadata update struct and change the remote id.
1723
        $metadataUpdate = $contentService->newContentMetadataUpdateStruct();
1724
        $metadataUpdate->remoteId = '85e10037d1ac0a00aa75443ced483e08';
1725
1726
        // Create a new update struct instance
1727
        $userUpdate = $userService->newUserUpdateStruct();
1728
1729
        // Set the metadata update struct.
1730
        $userUpdate->contentMetadataUpdateStruct = $metadataUpdate;
1731
1732
        // Updated the user record.
1733
        $userVersion2 = $userService->updateUser($user, $userUpdate);
1734
1735
        // The contentInfo->remoteId will be changed now.
1736
        $remoteId = $userVersion2->contentInfo->remoteId;
1737
        /* END: Use Case */
1738
1739
        $this->assertEquals('85e10037d1ac0a00aa75443ced483e08', $remoteId);
1740
    }
1741
1742
    /**
1743
     * Test for the updateUser() method.
1744
     *
1745
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1746
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1747
     */
1748
    public function testUpdateUserWithContentUpdateStruct()
1749
    {
1750
        $repository = $this->getRepository();
1751
1752
        $userService = $repository->getUserService();
1753
1754
        /* BEGIN: Use Case */
1755
        $user = $this->createUserVersion1();
1756
1757
        // Get the ContentService implementation
1758
        $contentService = $repository->getContentService();
1759
1760
        // Create a content update struct and change the remote id.
1761
        $contentUpdate = $contentService->newContentUpdateStruct();
1762
        $contentUpdate->setField('first_name', 'Hello', 'eng-US');
1763
        $contentUpdate->setField('last_name', 'World', 'eng-US');
1764
1765
        // Create a new update struct instance
1766
        $userUpdate = $userService->newUserUpdateStruct();
1767
1768
        // Set the content update struct.
1769
        $userUpdate->contentUpdateStruct = $contentUpdate;
1770
1771
        // Updated the user record.
1772
        $userVersion2 = $userService->updateUser($user, $userUpdate);
1773
1774
        $name = sprintf(
1775
            '%s %s',
1776
            $userVersion2->getFieldValue('first_name'),
1777
            $userVersion2->getFieldValue('last_name')
1778
        );
1779
        /* END: Use Case */
1780
1781
        $this->assertEquals('Hello World', $name);
1782
    }
1783
1784
    /**
1785
     * Test for the updateUser() method.
1786
     *
1787
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1788
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1789
     */
1790
    public function testUpdateUserWhenMissingField()
1791
    {
1792
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException::class);
1793
1794
        $repository = $this->getRepository();
1795
1796
        $userService = $repository->getUserService();
1797
1798
        /* BEGIN: Use Case */
1799
        $user = $this->createUserVersion1();
1800
1801
        // Get the ContentService implementation
1802
        $contentService = $repository->getContentService();
1803
1804
        // Create a content update struct and change the remote id.
1805
        $contentUpdate = $contentService->newContentUpdateStruct();
1806
        $contentUpdate->setField('first_name', null, 'eng-US');
1807
1808
        // Create a new update struct instance
1809
        $userUpdate = $userService->newUserUpdateStruct();
1810
1811
        // Set the content update struct.
1812
        $userUpdate->contentUpdateStruct = $contentUpdate;
1813
1814
        // This call will fail with a "ContentFieldValidationException" because the
1815
        // mandatory field "first_name" is set to an empty value.
1816
        $userService->updateUser($user, $userUpdate);
1817
1818
        /* END: Use Case */
1819
    }
1820
1821
    /**
1822
     * Test for the updateUser() method.
1823
     *
1824
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1825
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1826
     */
1827
    public function testUpdateUserThrowsInvalidArgumentExceptionOnFieldTypeNotAccept()
1828
    {
1829
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
1830
1831
        $repository = $this->getRepository();
1832
1833
        $userService = $repository->getUserService();
1834
1835
        /* BEGIN: Use Case */
1836
        $user = $this->createUserVersion1();
1837
1838
        // Get the ContentService implementation
1839
        $contentService = $repository->getContentService();
1840
1841
        $contentUpdate = $contentService->newContentUpdateStruct();
1842
        // An object of stdClass is not valid for the field first_name
1843
        $contentUpdate->setField('first_name', new \stdClass(), 'eng-US');
1844
1845
        // Create a new update struct instance
1846
        $userUpdate = $userService->newUserUpdateStruct();
1847
1848
        // Set the content update struct.
1849
        $userUpdate->contentUpdateStruct = $contentUpdate;
1850
1851
        // This call will fail with a "InvalidArgumentException" because the
1852
        // the field "first_name" does not accept the given value.
1853
        $userService->updateUser($user, $userUpdate);
1854
1855
        /* END: Use Case */
1856
    }
1857
1858
    /**
1859
     * Test updating a user throwing UserPasswordValidationException when password doesn't follow specified rules.
1860
     *
1861
     * @covers \eZ\Publish\API\Repository\UserService::updateUser
1862
     */
1863
    public function testUpdateUserWithWeakPasswordThrowsUserPasswordValidationException()
1864
    {
1865
        $userService = $this->getRepository()->getUserService();
1866
1867
        $user = $this->createTestUserWithPassword('H@xxxiR!_1', $this->createUserContentTypeWithStrongPassword());
1868
1869
        /* BEGIN: Use Case */
1870
        // Create a new update struct instance
1871
        $userUpdate = $userService->newUserUpdateStruct();
1872
        $userUpdate->password = 'pass';
1873
1874
        try {
1875
            // This call will fail with a "UserPasswordValidationException" because the
1876
            // the password does not follow specified rules
1877
            $userService->updateUser($user, $userUpdate);
1878
            /* END: Use Case */
1879
        } catch (ContentFieldValidationException $e) {
1880
            // Exception is caught, as there is no other way to check exception properties.
1881
            $this->assertValidationErrorOccurs($e, 'User password must include at least one special character');
1882
            $this->assertValidationErrorOccurs($e, 'User password must be at least %length% characters long');
1883
            $this->assertValidationErrorOccurs($e, 'User password must include at least one upper case letter');
1884
            $this->assertValidationErrorOccurs($e, 'User password must include at least one number');
1885
1886
            /* END: Use Case */
1887
            return;
1888
        }
1889
1890
        $this->fail('Expected ValidationError messages did not occur.');
1891
    }
1892
1893
    /**
1894
     * Opposite test case for testUpdateUserWithWeakPasswordThrowsUserPasswordValidationException.
1895
     *
1896
     * @covers \eZ\Publish\API\Repository\UserService::updateUser
1897
     */
1898
    public function testUpdateUserWithStrongPassword()
1899
    {
1900
        $userService = $this->getRepository()->getUserService();
1901
1902
        $user = $this->createTestUserWithPassword('H@xxxiR!_1', $this->createUserContentTypeWithStrongPassword());
1903
1904
        /* BEGIN: Use Case */
1905
        // Create a new update struct instance
1906
        $userUpdate = $userService->newUserUpdateStruct();
1907
        $userUpdate->password = 'H@xxxiR!_2';
1908
1909
        $user = $userService->updateUser($user, $userUpdate);
1910
        /* END: Use Case */
1911
1912
        $this->assertInstanceOf(User::class, $user);
1913
    }
1914
1915
    /**
1916
     * Test for the loadUserGroupsOfUser() method.
1917
     *
1918
     * @covers \eZ\Publish\API\Repository\UserService::loadUserGroupsOfUser
1919
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1920
     */
1921
    public function testLoadUserGroupsOfUser()
1922
    {
1923
        $repository = $this->getRepository();
1924
1925
        $userService = $repository->getUserService();
1926
1927
        /* BEGIN: Use Case */
1928
        $user = $this->createUserVersion1();
1929
1930
        // This array will contain the "Editors" user group name
1931
        $userGroupNames = [];
1932
        foreach ($userService->loadUserGroupsOfUser($user) as $userGroup) {
1933
            $this->assertInstanceOf(UserGroup::class, $userGroup);
1934
            $userGroupNames[] = $userGroup->getFieldValue('name');
1935
        }
1936
        /* END: Use Case */
1937
1938
        $this->assertEquals(['Editors'], $userGroupNames);
1939
    }
1940
1941
    /**
1942
     * Test for the loadUsersOfUserGroup() method.
1943
     *
1944
     * @covers \eZ\Publish\API\Repository\UserService::loadUsersOfUserGroup
1945
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1946
     */
1947
    public function testLoadUsersOfUserGroup()
1948
    {
1949
        $repository = $this->getRepository();
1950
        $userService = $repository->getUserService();
1951
1952
        $group = $userService->loadUserGroup($this->generateId('group', 13));
1953
1954
        /* BEGIN: Use Case */
1955
        $this->createUserVersion1();
1956
1957
        $this->refreshSearch($repository);
1958
1959
        // This array will contain the email of the newly created "Editor" user
1960
        $email = [];
1961
        foreach ($userService->loadUsersOfUserGroup($group) as $user) {
1962
            $this->assertInstanceOf(User::class, $user);
1963
            $email[] = $user->email;
1964
        }
1965
        /* END: Use Case */
1966
        $this->assertEquals(['[email protected]'], $email);
1967
    }
1968
1969
    /**
1970
     * Test for the assignUserToUserGroup() method.
1971
     *
1972
     * @see \eZ\Publish\API\Repository\UserService::assignUserToUserGroup()
1973
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroupsOfUser
1974
     */
1975
    public function testAssignUserToUserGroup()
1976
    {
1977
        $repository = $this->getRepository();
1978
        $userService = $repository->getUserService();
1979
1980
        $administratorGroupId = $this->generateId('group', 12);
1981
        /* BEGIN: Use Case */
1982
        // $administratorGroupId is the ID of the "Administrator" group in an
1983
        // eZ Publish demo installation
1984
1985
        $user = $this->createUserVersion1();
1986
1987
        // Assign group to newly created user
1988
        $userService->assignUserToUserGroup(
1989
            $user,
1990
            $userService->loadUserGroup($administratorGroupId)
1991
        );
1992
1993
        // This array will contain "Editors" and "Administrator users"
1994
        $userGroupNames = [];
1995
        foreach ($userService->loadUserGroupsOfUser($user) as $userGroup) {
1996
            $userGroupNames[] = $userGroup->getFieldValue('name');
1997
        }
1998
        /* END: Use Case */
1999
2000
        sort($userGroupNames, SORT_STRING);
2001
2002
        $this->assertEquals(
2003
            [
2004
                'Administrator users',
2005
                'Editors',
2006
            ],
2007
            $userGroupNames
2008
        );
2009
    }
2010
2011
    /**
2012
     * Test for the assignUserToUserGroup() method.
2013
     *
2014
     * @covers \eZ\Publish\API\Repository\UserService::assignUserToUserGroup
2015
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testAssignUserToUserGroup
2016
     */
2017
    public function testAssignUserToUserGroupThrowsInvalidArgumentException()
2018
    {
2019
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
2020
        $this->expectExceptionMessage('Argument \'user\' is invalid: User is already in the given User Group');
2021
2022
        $repository = $this->getRepository();
2023
        $userService = $repository->getUserService();
2024
2025
        $editorsGroupId = $this->generateId('group', 13);
2026
        /* BEGIN: Use Case */
2027
        $user = $this->createUserVersion1();
2028
        // $editorsGroupId is the ID of the "Editors" group in an
2029
        // eZ Publish demo installation
2030
2031
        // This call will fail with an "InvalidArgumentException", because the
2032
        // user is already assigned to the "Editors" group
2033
        $userService->assignUserToUserGroup(
2034
            $user,
2035
            $userService->loadUserGroup($editorsGroupId)
2036
        );
2037
        /* END: Use Case */
2038
    }
2039
2040
    /**
2041
     * Test for the unAssignUssrFromUserGroup() method.
2042
     *
2043
     * @see \eZ\Publish\API\Repository\UserService::unAssignUssrFromUserGroup()
2044
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroupsOfUser
2045
     */
2046
    public function testUnAssignUserFromUserGroup()
2047
    {
2048
        $repository = $this->getRepository();
2049
        $userService = $repository->getUserService();
2050
2051
        $editorsGroupId = $this->generateId('group', 13);
2052
        $anonymousGroupId = $this->generateId('group', 42);
2053
2054
        /* BEGIN: Use Case */
2055
        // $anonymousGroupId is the ID of the "Anonymous Users" group in an eZ
2056
        // Publish demo installation
2057
2058
        $user = $this->createUserVersion1();
2059
2060
        // Assign group to newly created user
2061
        $userService->assignUserToUserGroup(
2062
            $user,
2063
            $userService->loadUserGroup($anonymousGroupId)
2064
        );
2065
2066
        // Unassign user from "Editors" group
2067
        $userService->unAssignUserFromUserGroup(
2068
            $user,
2069
            $userService->loadUserGroup($editorsGroupId)
2070
        );
2071
2072
        // This array will contain "Anonymous Users"
2073
        $userGroupNames = [];
2074
        foreach ($userService->loadUserGroupsOfUser($user) as $userGroup) {
2075
            $userGroupNames[] = $userGroup->getFieldValue('name');
2076
        }
2077
        /* END: Use Case */
2078
2079
        $this->assertEquals(['Anonymous Users'], $userGroupNames);
2080
    }
2081
2082
    /**
2083
     * Test for the unAssignUserFromUserGroup() method.
2084
     *
2085
     * @see \eZ\Publish\API\Repository\UserService::unAssignUserFromUserGroup()
2086
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUnAssignUserFromUserGroup
2087
     */
2088
    public function testUnAssignUserFromUserGroupThrowsInvalidArgumentException()
2089
    {
2090
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
2091
2092
        $repository = $this->getRepository();
2093
        $userService = $repository->getUserService();
2094
2095
        $administratorGroupId = $this->generateId('group', 12);
2096
        /* BEGIN: Use Case */
2097
        $user = $this->createUserVersion1();
2098
        // $administratorGroupId is the ID of the "Administrator" group in an
2099
        // eZ Publish demo installation
2100
2101
        // This call will fail with an "InvalidArgumentException", because the
2102
        // user is not assigned to the "Administrator" group
2103
        $userService->unAssignUserFromUserGroup(
2104
            $user,
2105
            $userService->loadUserGroup($administratorGroupId)
2106
        );
2107
        /* END: Use Case */
2108
    }
2109
2110
    /**
2111
     * Test for the unAssignUserFromUserGroup() method removing user from the last group.
2112
     *
2113
     * @covers \eZ\Publish\API\Repository\UserService::unAssignUserFromUserGroup
2114
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUnAssignUserFromUserGroup
2115
     */
2116
    public function testUnAssignUserFromUserGroupThrowsBadStateArgumentException()
2117
    {
2118
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\BadStateException::class);
2119
        $this->expectExceptionMessage('Argument \'user\' has a bad state: User only has one User Group, cannot unassign from last group');
2120
2121
        $repository = $this->getRepository();
2122
        $userService = $repository->getUserService();
2123
2124
        $editorsGroupId = $this->generateId('group', 13);
2125
        /* BEGIN: Use Case */
2126
        $user = $this->createUserVersion1();
2127
2128
        // This call will fail with an "BadStateException", because the
2129
        // user has to be assigned to at least one group
2130
        $userService->unAssignUserFromUserGroup(
2131
            $user,
2132
            $userService->loadUserGroup($editorsGroupId)
2133
        );
2134
        /* END: Use Case */
2135
    }
2136
2137
    /**
2138
     * Test that multi-language logic for the loadUserGroup method respects prioritized language list.
2139
     *
2140
     * @covers \eZ\Publish\API\Repository\UserService::loadUserGroup
2141
     * @dataProvider getPrioritizedLanguageList
2142
     *
2143
     * @param string[] $prioritizedLanguages
2144
     * @param string|null $expectedLanguageCode language code of expected translation
2145
     */
2146
    public function testLoadUserGroupWithPrioritizedLanguagesList(
2147
        array $prioritizedLanguages,
2148
        $expectedLanguageCode
2149
    ) {
2150
        $repository = $this->getRepository();
2151
        $userService = $repository->getUserService();
2152
2153
        $userGroup = $this->createMultiLanguageUserGroup();
2154
        if ($expectedLanguageCode === null) {
2155
            $expectedLanguageCode = $userGroup->contentInfo->mainLanguageCode;
2156
        }
2157
2158
        $loadedUserGroup = $userService->loadUserGroup($userGroup->id, $prioritizedLanguages);
2159
2160
        self::assertEquals(
2161
            $loadedUserGroup->getName($expectedLanguageCode),
2162
            $loadedUserGroup->getName()
2163
        );
2164
        self::assertEquals(
2165
            $loadedUserGroup->getFieldValue('description', $expectedLanguageCode),
2166
            $loadedUserGroup->getFieldValue('description')
2167
        );
2168
    }
2169
2170
    /**
2171
     * Test that multi-language logic works correctly after updating user group main language.
2172
     *
2173
     * @covers \eZ\Publish\API\Repository\UserService::loadUserGroup
2174
     * @dataProvider getPrioritizedLanguageList
2175
     *
2176
     * @param string[] $prioritizedLanguages
2177
     * @param string|null $expectedLanguageCode language code of expected translation
2178
     */
2179
    public function testLoadUserGroupWithPrioritizedLanguagesListAfterMainLanguageUpdate(
2180
        array $prioritizedLanguages,
2181
        $expectedLanguageCode
2182
    ) {
2183
        $repository = $this->getRepository();
2184
        $userService = $repository->getUserService();
2185
        $contentService = $repository->getContentService();
2186
2187
        $userGroup = $this->createMultiLanguageUserGroup();
2188
2189
        $userGroupUpdateStruct = $userService->newUserGroupUpdateStruct();
2190
        $userGroupUpdateStruct->contentMetadataUpdateStruct = $contentService->newContentMetadataUpdateStruct();
2191
        $userGroupUpdateStruct->contentMetadataUpdateStruct->mainLanguageCode = 'eng-GB';
2192
        $userService->updateUserGroup($userGroup, $userGroupUpdateStruct);
2193
2194
        if ($expectedLanguageCode === null) {
2195
            $expectedLanguageCode = 'eng-GB';
2196
        }
2197
2198
        $loadedUserGroup = $userService->loadUserGroup($userGroup->id, $prioritizedLanguages);
2199
2200
        self::assertEquals(
2201
            $loadedUserGroup->getName($expectedLanguageCode),
2202
            $loadedUserGroup->getName()
2203
        );
2204
        self::assertEquals(
2205
            $loadedUserGroup->getFieldValue('description', $expectedLanguageCode),
2206
            $loadedUserGroup->getFieldValue('description')
2207
        );
2208
    }
2209
2210
    /**
2211
     * Test that multi-language logic for the loadSubUserGroups method respects prioritized language list.
2212
     *
2213
     * @covers \eZ\Publish\API\Repository\UserService::loadSubUserGroups
2214
     * @dataProvider getPrioritizedLanguageList
2215
     *
2216
     * @param string[] $prioritizedLanguages
2217
     * @param string|null $expectedLanguageCode language code of expected translation
2218
     */
2219
    public function testLoadSubUserGroupsWithPrioritizedLanguagesList(
2220
        array $prioritizedLanguages,
2221
        $expectedLanguageCode
2222
    ) {
2223
        $repository = $this->getRepository();
2224
        $userService = $repository->getUserService();
2225
2226
        // create main group for subgroups
2227
        $userGroup = $this->createMultiLanguageUserGroup(4);
2228
        if ($expectedLanguageCode === null) {
2229
            $expectedLanguageCode = $userGroup->contentInfo->mainLanguageCode;
2230
        }
2231
2232
        // create subgroups
2233
        $this->createMultiLanguageUserGroup($userGroup->id);
2234
        $this->createMultiLanguageUserGroup($userGroup->id);
2235
2236
        $userGroup = $userService->loadUserGroup($userGroup->id, $prioritizedLanguages);
2237
2238
        $subUserGroups = $userService->loadSubUserGroups($userGroup, 0, 2, $prioritizedLanguages);
2239
        foreach ($subUserGroups as $subUserGroup) {
2240
            self::assertEquals(
2241
                $subUserGroup->getName($expectedLanguageCode),
2242
                $subUserGroup->getName()
2243
            );
2244
            self::assertEquals(
2245
                $subUserGroup->getFieldValue('description', $expectedLanguageCode),
2246
                $subUserGroup->getFieldValue('description')
2247
            );
2248
        }
2249
    }
2250
2251
    /**
2252
     * Test that multi-language logic for the loadUser method respects prioritized language list.
2253
     *
2254
     * @covers \eZ\Publish\API\Repository\UserService::loadUser
2255
     * @dataProvider getPrioritizedLanguageList
2256
     *
2257
     * @param string[] $prioritizedLanguages
2258
     * @param string|null $expectedLanguageCode language code of expected translation
2259
     */
2260
    public function testLoadUserWithPrioritizedLanguagesList(
2261
        array $prioritizedLanguages,
2262
        $expectedLanguageCode
2263
    ) {
2264
        $repository = $this->getRepository();
2265
        $userService = $repository->getUserService();
2266
2267
        $user = $this->createMultiLanguageUser();
2268
        if ($expectedLanguageCode === null) {
2269
            $expectedLanguageCode = $user->contentInfo->mainLanguageCode;
2270
        }
2271
2272
        $loadedUser = $userService->loadUser($user->id, $prioritizedLanguages);
2273
2274
        self::assertEquals(
2275
            $loadedUser->getName($expectedLanguageCode),
2276
            $loadedUser->getName()
2277
        );
2278
2279
        foreach (['fist_name', 'last_name', 'signature'] as $fieldIdentifier) {
2280
            self::assertEquals(
2281
                $loadedUser->getFieldValue($fieldIdentifier, $expectedLanguageCode),
2282
                $loadedUser->getFieldValue($fieldIdentifier)
2283
            );
2284
        }
2285
    }
2286
2287
    /**
2288
     * Test that multi-language logic for the loadUser method works correctly after updating
2289
     * user content main language.
2290
     *
2291
     * @covers \eZ\Publish\API\Repository\UserService::loadUserGroup
2292
     * @dataProvider getPrioritizedLanguageList
2293
     *
2294
     * @param string[] $prioritizedLanguages
2295
     * @param string|null $expectedLanguageCode language code of expected translation
2296
     */
2297
    public function testLoadUserWithPrioritizedLanguagesListAfterMainLanguageUpdate(
2298
        array $prioritizedLanguages,
2299
        $expectedLanguageCode
2300
    ) {
2301
        $repository = $this->getRepository();
2302
        $userService = $repository->getUserService();
2303
        $contentService = $repository->getContentService();
2304
2305
        $user = $this->createMultiLanguageUser();
2306
        // sanity check
2307
        self::assertEquals($user->contentInfo->mainLanguageCode, 'eng-US');
2308
2309
        $userUpdateStruct = $userService->newUserUpdateStruct();
2310
        $userUpdateStruct->contentMetadataUpdateStruct = $contentService->newContentMetadataUpdateStruct();
2311
        $userUpdateStruct->contentMetadataUpdateStruct->mainLanguageCode = 'eng-GB';
2312
        $userService->updateUser($user, $userUpdateStruct);
2313
        if ($expectedLanguageCode === null) {
2314
            $expectedLanguageCode = 'eng-GB';
2315
        }
2316
2317
        $loadedUser = $userService->loadUser($user->id, $prioritizedLanguages);
2318
2319
        self::assertEquals(
2320
            $loadedUser->getName($expectedLanguageCode),
2321
            $loadedUser->getName()
2322
        );
2323
2324
        foreach (['fist_name', 'last_name', 'signature'] as $fieldIdentifier) {
2325
            self::assertEquals(
2326
                $loadedUser->getFieldValue($fieldIdentifier, $expectedLanguageCode),
2327
                $loadedUser->getFieldValue($fieldIdentifier)
2328
            );
2329
        }
2330
    }
2331
2332
    /**
2333
     * Test that multi-language logic for the loadUserByLogin method respects prioritized language list.
2334
     *
2335
     * @covers \eZ\Publish\API\Repository\UserService::loadUserByLogin
2336
     * @dataProvider getPrioritizedLanguageList
2337
     *
2338
     * @param string[] $prioritizedLanguages
2339
     * @param string|null $expectedLanguageCode language code of expected translation
2340
     */
2341
    public function testLoadUserByLoginWithPrioritizedLanguagesList(
2342
        array $prioritizedLanguages,
2343
        $expectedLanguageCode
2344
    ) {
2345
        $repository = $this->getRepository();
2346
        $userService = $repository->getUserService();
2347
        $user = $this->createMultiLanguageUser();
2348
2349
        // load, with prioritized languages, the newly created user
2350
        $loadedUser = $userService->loadUserByLogin($user->login, $prioritizedLanguages);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...vice::loadUserByLogin() has been deprecated with message: since eZ Platform 2.5, will be dropped in the next major version as authentication may depend on various user providers. Use UserService::checkUserCredentials() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
2351
        if ($expectedLanguageCode === null) {
2352
            $expectedLanguageCode = $loadedUser->contentInfo->mainLanguageCode;
2353
        }
2354
2355
        self::assertEquals(
2356
            $loadedUser->getName($expectedLanguageCode),
2357
            $loadedUser->getName()
2358
        );
2359
2360
        foreach (['first_name', 'last_name', 'signature'] as $fieldIdentifier) {
2361
            self::assertEquals(
2362
                $loadedUser->getFieldValue($fieldIdentifier, $expectedLanguageCode),
2363
                $loadedUser->getFieldValue($fieldIdentifier)
2364
            );
2365
        }
2366
    }
2367
2368
    /**
2369
     * Test that multi-language logic for the loadUsersByEmail method respects
2370
     * prioritized language list.
2371
     *
2372
     * @covers \eZ\Publish\API\Repository\UserService::loadUsersByEmail
2373
     * @dataProvider getPrioritizedLanguageList
2374
     *
2375
     * @param string[] $prioritizedLanguages
2376
     * @param string|null $expectedLanguageCode language code of expected translation
2377
     */
2378
    public function testLoadUsersByEmailWithPrioritizedLanguagesList(
2379
        array $prioritizedLanguages,
2380
        $expectedLanguageCode
2381
    ) {
2382
        $repository = $this->getRepository();
2383
        $userService = $repository->getUserService();
2384
        $user = $this->createMultiLanguageUser();
2385
2386
        // load, with prioritized languages, users by email
2387
        $loadedUsers = $userService->loadUsersByEmail($user->email, $prioritizedLanguages);
2388
2389
        foreach ($loadedUsers as $loadedUser) {
2390
            if ($expectedLanguageCode === null) {
2391
                $expectedLanguageCode = $loadedUser->contentInfo->mainLanguageCode;
2392
            }
2393
            self::assertEquals(
2394
                $loadedUser->getName($expectedLanguageCode),
2395
                $loadedUser->getName()
2396
            );
2397
2398
            foreach (['first_name', 'last_name', 'signature'] as $fieldIdentifier) {
2399
                self::assertEquals(
2400
                    $loadedUser->getFieldValue($fieldIdentifier, $expectedLanguageCode),
2401
                    $loadedUser->getFieldValue($fieldIdentifier)
2402
                );
2403
            }
2404
        }
2405
    }
2406
2407
    /**
2408
     * Test that multi-language logic for the loadUserGroupsOfUser method respects
2409
     * prioritized language list.
2410
     *
2411
     * @covers \eZ\Publish\API\Repository\UserService::loadUserGroupsOfUser
2412
     * @dataProvider getPrioritizedLanguageList
2413
     *
2414
     * @param string[] $prioritizedLanguages
2415
     * @param string|null $expectedLanguageCode language code of expected translation
2416
     */
2417
    public function testLoadUserGroupsOfUserWithPrioritizedLanguagesList(
2418
        array $prioritizedLanguages,
2419
        $expectedLanguageCode
2420
    ) {
2421
        $repository = $this->getRepository();
2422
        $userService = $repository->getUserService();
2423
        $userGroup = $this->createMultiLanguageUserGroup();
2424
        $user = $this->createMultiLanguageUser($userGroup->id);
2425
2426
        $userGroups = $userService->loadUserGroupsOfUser($user, 0, 25, $prioritizedLanguages);
2427
        foreach ($userGroups as $userGroup) {
2428
            self::assertEquals(
2429
                $userGroup->getName($expectedLanguageCode),
2430
                $userGroup->getName()
2431
            );
2432
            self::assertEquals(
2433
                $userGroup->getFieldValue('description', $expectedLanguageCode),
2434
                $userGroup->getFieldValue('description')
2435
            );
2436
        }
2437
    }
2438
2439
    /**
2440
     * Test that multi-language logic for the loadUsersOfUserGroup method respects
2441
     * prioritized language list.
2442
     *
2443
     * @covers \eZ\Publish\API\Repository\UserService::loadUsersOfUserGroup
2444
     * @dataProvider getPrioritizedLanguageList
2445
     *
2446
     * @param string[] $prioritizedLanguages
2447
     * @param string|null $expectedLanguageCode language code of expected translation
2448
     */
2449
    public function testLoadUsersOfUserGroupWithPrioritizedLanguagesList(
2450
        array $prioritizedLanguages,
2451
        $expectedLanguageCode
2452
    ) {
2453
        $repository = $this->getRepository();
2454
        $userService = $repository->getUserService();
2455
2456
        // create parent user group
2457
        $userGroup = $this->createMultiLanguageUserGroup();
2458
        // add two users to the created parent user group
2459
        $this->createMultiLanguageUser($userGroup->id);
2460
        $this->createMultiLanguageUser($userGroup->id);
2461
2462
        // test loading of users via user group with prioritized languages list
2463
        $users = $userService->loadUsersOfUserGroup($userGroup, 0, 25, $prioritizedLanguages);
2464
        foreach ($users as $user) {
2465
            if ($expectedLanguageCode === null) {
2466
                $expectedLanguageCode = $user->contentInfo->mainLanguageCode;
2467
            }
2468
            self::assertEquals(
2469
                $user->getName($expectedLanguageCode),
2470
                $user->getName()
2471
            );
2472
2473
            foreach (['first_name', 'last_name', 'signature'] as $fieldIdentifier) {
2474
                self::assertEquals(
2475
                    $user->getFieldValue($fieldIdentifier, $expectedLanguageCode),
2476
                    $user->getFieldValue($fieldIdentifier)
2477
                );
2478
            }
2479
        }
2480
    }
2481
2482
    /**
2483
     * Get prioritized languages list data.
2484
     *
2485
     * Test cases using this data provider should expect the following arguments:
2486
     * <code>
2487
     *   array $prioritizedLanguagesList
2488
     *   string $expectedLanguage (if null - use main language)
2489
     * </code>
2490
     *
2491
     * @return array
2492
     */
2493
    public function getPrioritizedLanguageList()
2494
    {
2495
        return [
2496
            [[], null],
2497
            [['eng-US'], 'eng-US'],
2498
            [['eng-GB'], 'eng-GB'],
2499
            [['eng-US', 'eng-GB'], 'eng-US'],
2500
            [['eng-GB', 'eng-US'], 'eng-GB'],
2501
            // use non-existent group as the first one
2502
            [['ger-DE'], null],
2503
            [['ger-DE', 'eng-GB'], 'eng-GB'],
2504
        ];
2505
    }
2506
2507
    /**
2508
     * @param int $parentGroupId
2509
     *
2510
     * @return \eZ\Publish\API\Repository\Values\User\UserGroup
2511
     */
2512
    private function createMultiLanguageUserGroup($parentGroupId = 4)
2513
    {
2514
        $repository = $this->getRepository();
2515
        $userService = $repository->getUserService();
2516
2517
        // create user group with multiple translations
2518
        $parentGroupId = $this->generateId('group', $parentGroupId);
2519
        $parentGroup = $userService->loadUserGroup($parentGroupId);
2520
2521
        $userGroupCreateStruct = $userService->newUserGroupCreateStruct('eng-US');
2522
        $userGroupCreateStruct->setField('name', 'US user group', 'eng-US');
2523
        $userGroupCreateStruct->setField('name', 'GB user group', 'eng-GB');
2524
        $userGroupCreateStruct->setField('description', 'US user group description', 'eng-US');
2525
        $userGroupCreateStruct->setField('description', 'GB user group description', 'eng-GB');
2526
        $userGroupCreateStruct->alwaysAvailable = true;
2527
2528
        return $userService->createUserGroup($userGroupCreateStruct, $parentGroup);
2529
    }
2530
2531
    /**
2532
     * Create a user group fixture in a variable named <b>$userGroup</b>,.
2533
     *
2534
     * @return \eZ\Publish\API\Repository\Values\User\UserGroup
2535
     */
2536
    private function createUserGroupVersion1()
2537
    {
2538
        $repository = $this->getRepository();
2539
2540
        $mainGroupId = $this->generateId('group', 4);
2541
        /* BEGIN: Inline */
2542
        // $mainGroupId is the ID of the main "Users" group
2543
2544
        $userService = $repository->getUserService();
2545
2546
        // Load main group
2547
        $parentUserGroup = $userService->loadUserGroup($mainGroupId);
2548
2549
        // Instantiate a new create struct
2550
        $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
2551
        $userGroupCreate->setField('name', 'Example Group');
2552
2553
        // Create the new user group
2554
        $userGroup = $userService->createUserGroup(
2555
            $userGroupCreate,
2556
            $parentUserGroup
2557
        );
2558
        /* END: Inline */
2559
2560
        return $userGroup;
2561
    }
2562
2563
    /**
2564
     * Create user with multiple translations of User Content fields.
2565
     *
2566
     * @param int $userGroupId User group ID (default 13 - Editors)
2567
     *
2568
     * @return \eZ\Publish\API\Repository\Values\User\User
2569
     */
2570
    private function createMultiLanguageUser($userGroupId = 13)
2571
    {
2572
        $repository = $this->getRepository();
2573
        $userService = $repository->getUserService();
2574
2575
        // Instantiate a create struct with mandatory properties
2576
        $randomLogin = md5(mt_rand() . time());
2577
        $userCreateStruct = $userService->newUserCreateStruct(
2578
            $randomLogin,
2579
            "{$randomLogin}@example.com",
2580
            'secret',
2581
            'eng-US'
2582
        );
2583
        $userCreateStruct->enabled = true;
2584
        $userCreateStruct->alwaysAvailable = true;
2585
2586
        // set field for each language
2587
        foreach (['eng-US', 'eng-GB'] as $languageCode) {
2588
            $userCreateStruct->setField('first_name', "{$languageCode} Example", $languageCode);
2589
            $userCreateStruct->setField('last_name', "{$languageCode} User", $languageCode);
2590
            $userCreateStruct->setField('signature', "{$languageCode} signature", $languageCode);
2591
        }
2592
2593
        // Load parent group for the user
2594
        $group = $userService->loadUserGroup($userGroupId);
2595
2596
        // Create a new user
2597
        return $userService->createUser($userCreateStruct, [$group]);
2598
    }
2599
2600
    /**
2601
     * Test for the createUser() method.
2602
     *
2603
     * @see \eZ\Publish\API\Repository\UserService::createUser()
2604
     */
2605
    public function testCreateUserInvalidPasswordHashTypeThrowsException()
2606
    {
2607
        $repository = $this->getRepository();
2608
        $eventUserService = $repository->getUserService();
2609
2610
        // Instantiate a create struct with mandatory properties.
2611
        $createStruct = $eventUserService->newUserCreateStruct(
2612
            'user',
2613
            '[email protected]',
2614
            'secret',
2615
            'eng-US'
2616
        );
2617
2618
        // Set some fields required by the user ContentType.
2619
        $createStruct->setField('first_name', 'Example');
2620
        $createStruct->setField('last_name', 'User');
2621
2622
        // Get User fieldType.
2623
        $userFieldDef = null;
2624
        foreach ($createStruct->fields as $field) {
2625
            if ($field->fieldTypeIdentifier === 'ezuser') {
2626
                $userFieldDef = $field;
2627
                break;
2628
            }
2629
        }
2630
2631
        if (!$userFieldDef) {
2632
            $this->fail('User FieldType not found in userCreateStruct!');
2633
        }
2634
2635
        /** @var \eZ\Publish\Core\FieldType\User\Value $userValue */
2636
        $userValue = $userFieldDef->value;
2637
2638
        // Set not supported hash type.
2639
        $userValue->passwordHashType = 42424242;
2640
2641
        $this->expectException(InvalidArgumentException::class);
2642
        $this->expectExceptionMessage("Argument 'hashType' is invalid: Password hash type '42424242' is not recognized");
2643
2644
        // Create a new user instance.
2645
        // 13 is ID of the "Editors" user group in an eZ Publish demo installation.
2646
        $eventUserService->createUser($createStruct, [$eventUserService->loadUserGroup(13)]);
2647
    }
2648
2649
    /**
2650
     * Test loading User by Token.
2651
     *
2652
     * @covers \eZ\Publish\API\Repository\UserService::loadUserByToken
2653
     */
2654
    public function testLoadUserByToken()
2655
    {
2656
        $repository = $this->getRepository();
2657
        $userService = $repository->getUserService();
2658
2659
        $user = $this->createUserVersion1();
2660
2661
        $userTokenUpdateStruct = new UserTokenUpdateStruct();
2662
        $userTokenUpdateStruct->hashKey = md5('hash');
2663
        $userTokenUpdateStruct->time = (new DateTime())->add(new DateInterval('PT10S'));
2664
2665
        $userService->updateUserToken($user, $userTokenUpdateStruct);
2666
2667
        $loadedUser = $userService->loadUserByToken($userTokenUpdateStruct->hashKey, Language::ALL);
2668
        self::assertEquals($user, $loadedUser);
2669
2670
        return $userTokenUpdateStruct->hashKey;
2671
    }
2672
2673
    /**
2674
     * Test trying to load User by invalid Token.
2675
     *
2676
     * @covers \eZ\Publish\API\Repository\UserService::loadUserByToken
2677
     */
2678
    public function testLoadUserByTokenThrowsNotFoundException()
2679
    {
2680
        $this->expectException(NotFoundException::class);
2681
2682
        $repository = $this->getRepository();
2683
        $userService = $repository->getUserService();
2684
2685
        $user = $this->createUserVersion1();
2686
2687
        $userTokenUpdateStruct = new UserTokenUpdateStruct();
2688
        $userTokenUpdateStruct->hashKey = md5('hash');
2689
        $userTokenUpdateStruct->time = new DateTime();
2690
2691
        $userService->updateUserToken($user, $userTokenUpdateStruct);
2692
2693
        $userService->loadUserByToken('not_existing_token');
2694
    }
2695
2696
    /**
2697
     * Test updating User Token.
2698
     *
2699
     * @covers \eZ\Publish\API\Repository\UserService::updateUserToken()
2700
     *
2701
     * @depends testLoadUserByToken
2702
     *
2703
     * @param string $originalUserToken
2704
     */
2705
    public function testUpdateUserToken($originalUserToken)
2706
    {
2707
        $repository = $this->getRepository(false);
2708
        $userService = $repository->getUserService();
2709
2710
        $user = $userService->loadUserByToken($originalUserToken);
2711
2712
        $userTokenUpdateStruct = new UserTokenUpdateStruct();
2713
        $userTokenUpdateStruct->hashKey = md5('my_updated_hash');
2714
        $userTokenUpdateStruct->time = (new DateTime())->add(new DateInterval('PT10S'));
2715
2716
        $userService->updateUserToken($user, $userTokenUpdateStruct);
2717
2718
        $loadedUser = $userService->loadUserByToken($userTokenUpdateStruct->hashKey);
2719
        self::assertEquals($user, $loadedUser);
2720
    }
2721
2722
    /**
2723
     * Test invalidating (expiring) User Token.
2724
     *
2725
     * @covers \eZ\Publish\API\Repository\UserService::expireUserToken()
2726
     *
2727
     * @depends testLoadUserByToken
2728
     *
2729
     * @param string $userToken
2730
     */
2731
    public function testExpireUserToken($userToken)
2732
    {
2733
        $this->expectException(NotFoundException::class);
2734
2735
        $repository = $this->getRepository(false);
2736
        $userService = $repository->getUserService();
2737
2738
        // sanity check
2739
        $userService->loadUserByToken($userToken);
2740
2741
        $userService->expireUserToken($userToken);
2742
2743
        // should throw NotFoundException now
2744
        $userService->loadUserByToken($userToken);
2745
    }
2746
2747
    /**
2748
     * @covers \eZ\Publish\API\Repository\UserService::validatePassword()
2749
     */
2750
    public function testValidatePasswordWithDefaultContext()
2751
    {
2752
        $userService = $this->getRepository()->getUserService();
2753
2754
        /* BEGIN: Use Case */
2755
        $errors = $userService->validatePassword('pass');
2756
        /* END: Use Case */
2757
2758
        $this->assertEmpty($errors);
2759
    }
2760
2761
    /**
2762
     * @covers \eZ\Publish\API\Repository\UserService::validatePassword()
2763
     * @dataProvider dataProviderForValidatePassword
2764
     */
2765
    public function testValidatePassword(string $password, array $expectedErrors)
2766
    {
2767
        $userService = $this->getRepository()->getUserService();
2768
        $contentType = $this->createUserContentTypeWithStrongPassword();
2769
2770
        /* BEGIN: Use Case */
2771
        $context = new PasswordValidationContext([
2772
            'contentType' => $contentType,
2773
        ]);
2774
2775
        $actualErrors = $userService->validatePassword($password, $context);
2776
        /* END: Use Case */
2777
2778
        $this->assertEquals($expectedErrors, $actualErrors);
2779
    }
2780
2781
    public function testValidatePasswordReturnsErrorWhenOldPasswordIsReused(): void
2782
    {
2783
        $password = 'P@blish123!';
2784
2785
        $userService = $this->getRepository()->getUserService();
2786
        // Password expiration needs to be enabled
2787
        $contentType = $this->createUserContentTypeWithPasswordExpirationDate();
2788
2789
        $user = $this->createTestUserWithPassword($password, $contentType);
2790
2791
        $context = new PasswordValidationContext([
2792
            'contentType' => $contentType,
2793
            'user' => $user,
2794
        ]);
2795
2796
        $actualErrors = $userService->validatePassword($password, $context);
2797
2798
        $this->assertEquals(
2799
            [new ValidationError('New password cannot be the same as old password', null, [], 'password')],
2800
            $actualErrors
2801
        );
2802
    }
2803
2804
    /**
2805
     * Data provider for testValidatePassword.
2806
     *
2807
     * @return array
2808
     */
2809
    public function dataProviderForValidatePassword(): array
2810
    {
2811
        return [
2812
            [
2813
                'pass',
2814
                [
2815
                    new ValidationError('User password must be at least %length% characters long', null, [
2816
                        '%length%' => 8,
2817
                    ], 'password'),
2818
                    new ValidationError('User password must include at least one upper case letter', null, [], 'password'),
2819
                    new ValidationError('User password must include at least one number', null, [], 'password'),
2820
                    new ValidationError('User password must include at least one special character', null, [], 'password'),
2821
                ],
2822
            ],
2823
            [
2824
                'H@xxxi0R!!!',
2825
                [],
2826
            ],
2827
        ];
2828
    }
2829
2830
    public function testGetPasswordInfo(): void
2831
    {
2832
        $userService = $this->getRepository()->getUserService();
2833
        $contentType = $this->createUserContentTypeWithPasswordExpirationDate(
2834
            self::EXAMPLE_PASSWORD_TTL,
2835
            self::EXAMPLE_PASSWORD_TTL_WARNING
2836
        );
2837
2838
        $user = $this->createTestUser($contentType);
2839
2840
        /* BEGIN: Use Case */
2841
        $passwordInfo = $userService->getPasswordInfo($user);
2842
        /* END: Use Case */
2843
2844
        $passwordUpdatedAt = $user->passwordUpdatedAt;
2845
        if ($passwordUpdatedAt instanceof DateTime) {
2846
            $passwordUpdatedAt = DateTimeImmutable::createFromFormat(DateTime::ATOM, $passwordUpdatedAt->format(DateTime::ATOM));
2847
        }
2848
2849
        $expectedPasswordExpirationDate = $passwordUpdatedAt->add(
2850
            new DateInterval(sprintf('P%dD', self::EXAMPLE_PASSWORD_TTL))
2851
        );
2852
2853
        $expectedPasswordExpirationWarningDate = $passwordUpdatedAt->add(
2854
            new DateInterval(sprintf('P%dD', self::EXAMPLE_PASSWORD_TTL - self::EXAMPLE_PASSWORD_TTL_WARNING))
2855
        );
2856
2857
        $this->assertEquals(new PasswordInfo(
2858
            $expectedPasswordExpirationDate,
2859
            $expectedPasswordExpirationWarningDate
2860
        ), $passwordInfo);
2861
    }
2862
2863
    public function testGetPasswordInfoIfExpirationIsDisabled(): void
2864
    {
2865
        $userService = $this->getRepository()->getUserService();
2866
        $contentType = $this->createUserContentTypeWithPasswordExpirationDate(null, null);
2867
2868
        $user = $this->createTestUser($contentType);
2869
2870
        /* BEGIN: Use Case */
2871
        $passwordInfo = $userService->getPasswordInfo($user);
2872
        /* END: Use Case */
2873
2874
        $this->assertEquals(new PasswordInfo(), $passwordInfo);
2875
    }
2876
2877
    public function testGetPasswordInfoIfExpirationWarningIsDisabled(): void
2878
    {
2879
        $userService = $this->getRepository()->getUserService();
2880
        $contentType = $this->createUserContentTypeWithPasswordExpirationDate(self::EXAMPLE_PASSWORD_TTL, null);
2881
2882
        $user = $this->createTestUser($contentType);
2883
2884
        /* BEGIN: Use Case */
2885
        $passwordInfo = $userService->getPasswordInfo($user);
2886
        /* END: Use Case */
2887
2888
        $passwordUpdatedAt = $user->passwordUpdatedAt;
2889
        if ($passwordUpdatedAt instanceof DateTime) {
2890
            $passwordUpdatedAt = DateTimeImmutable::createFromFormat(DateTime::ATOM, $passwordUpdatedAt->format(DateTime::ATOM));
2891
        }
2892
2893
        $expectedPasswordExpirationDate = $passwordUpdatedAt->add(
2894
            new DateInterval(sprintf('P%dD', self::EXAMPLE_PASSWORD_TTL))
2895
        );
2896
2897
        $this->assertEquals(new PasswordInfo($expectedPasswordExpirationDate, null), $passwordInfo);
2898
    }
2899
2900
    public function createTestUser(ContentType $contentType): User
2901
    {
2902
        return $this->createTestUserWithPassword(self::EXAMPLE_PASSWORD, $contentType);
2903
    }
2904
2905
    /**
2906
     * Creates a user with given password.
2907
     *
2908
     * @param string $password
2909
     * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType
2910
     *
2911
     * @return \eZ\Publish\API\Repository\Values\User\User
2912
     */
2913
    private function createTestUserWithPassword(string $password, ContentType $contentType): User
2914
    {
2915
        $userService = $this->getRepository()->getUserService();
2916
        // ID of the "Editors" user group in an eZ Publish demo installation
2917
        $editorsGroupId = 13;
2918
2919
        // Instantiate a create struct with mandatory properties
2920
        $userCreate = $userService->newUserCreateStruct(
2921
            'johndoe',
2922
            '[email protected]',
2923
            $password,
2924
            'eng-US',
2925
            $contentType
2926
        );
2927
        $userCreate->enabled = true;
2928
        $userCreate->setField('first_name', 'John');
2929
        $userCreate->setField('last_name', 'Doe');
2930
2931
        return $userService->createUser($userCreate, [
2932
            $userService->loadUserGroup($editorsGroupId),
2933
        ]);
2934
    }
2935
2936
    /**
2937
     * Creates the User Content Type with password constraints.
2938
     *
2939
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
2940
     */
2941
    private function createUserContentTypeWithStrongPassword(): ContentType
2942
    {
2943
        return $this->createUserContentTypeWithAccountSettings('user-with-strong-password', null, [
2944
            'PasswordValueValidator' => [
2945
                'requireAtLeastOneUpperCaseCharacter' => 1,
2946
                'requireAtLeastOneLowerCaseCharacter' => 1,
2947
                'requireAtLeastOneNumericCharacter' => 1,
2948
                'requireAtLeastOneNonAlphanumericCharacter' => 1,
2949
                'requireNewPassword' => 1,
2950
                'minLength' => 8,
2951
            ],
2952
        ]);
2953
    }
2954
2955
    private function createUserContentTypeWithPasswordExpirationDate(
2956
        ?int $passwordTTL = self::EXAMPLE_PASSWORD_TTL,
2957
        ?int $passwordTTLWarning = self::EXAMPLE_PASSWORD_TTL_WARNING
2958
    ): ContentType {
2959
        return $this->createUserContentTypeWithAccountSettings('password-expiration', [
2960
            'PasswordTTL' => $passwordTTL,
2961
            'PasswordTTLWarning' => $passwordTTLWarning,
2962
        ]);
2963
    }
2964
2965
    private function createUserContentTypeWithAccountSettings(
2966
        string $identifier,
2967
        ?array $fieldSetting = null,
2968
        ?array $validatorConfiguration = null
2969
    ): ContentType {
2970
        $repository = $this->getRepository();
2971
2972
        $contentTypeService = $repository->getContentTypeService();
2973
        $permissionResolver = $repository->getPermissionResolver();
2974
2975
        $typeCreate = $contentTypeService->newContentTypeCreateStruct($identifier);
2976
        $typeCreate->mainLanguageCode = 'eng-GB';
2977
        $typeCreate->urlAliasSchema = 'url|scheme';
2978
        $typeCreate->nameSchema = 'name|scheme';
2979
        $typeCreate->names = [
2980
            'eng-GB' => 'User: ' . $identifier,
2981
        ];
2982
        $typeCreate->descriptions = [
2983
            'eng-GB' => '',
2984
        ];
2985
        $typeCreate->creatorId = $this->generateId('user', $permissionResolver->getCurrentUserReference()->getUserId());
2986
        $typeCreate->creationDate = $this->createDateTime();
2987
2988
        $firstNameFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('first_name', 'ezstring');
2989
        $firstNameFieldCreate->names = [
2990
            'eng-GB' => 'First name',
2991
        ];
2992
        $firstNameFieldCreate->descriptions = [
2993
            'eng-GB' => '',
2994
        ];
2995
        $firstNameFieldCreate->fieldGroup = 'default';
2996
        $firstNameFieldCreate->position = 1;
2997
        $firstNameFieldCreate->isTranslatable = false;
2998
        $firstNameFieldCreate->isRequired = true;
2999
        $firstNameFieldCreate->isInfoCollector = false;
3000
        $firstNameFieldCreate->validatorConfiguration = [
3001
            'StringLengthValidator' => [
3002
                'minStringLength' => 0,
3003
                'maxStringLength' => 0,
3004
            ],
3005
        ];
3006
        $firstNameFieldCreate->fieldSettings = [];
3007
        $firstNameFieldCreate->isSearchable = true;
3008
        $firstNameFieldCreate->defaultValue = '';
3009
3010
        $typeCreate->addFieldDefinition($firstNameFieldCreate);
3011
3012
        $lastNameFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('last_name', 'ezstring');
3013
        $lastNameFieldCreate->names = [
3014
            'eng-GB' => 'Last name',
3015
        ];
3016
        $lastNameFieldCreate->descriptions = [
3017
            'eng-GB' => '',
3018
        ];
3019
        $lastNameFieldCreate->fieldGroup = 'default';
3020
        $lastNameFieldCreate->position = 2;
3021
        $lastNameFieldCreate->isTranslatable = false;
3022
        $lastNameFieldCreate->isRequired = true;
3023
        $lastNameFieldCreate->isInfoCollector = false;
3024
        $lastNameFieldCreate->validatorConfiguration = [
3025
            'StringLengthValidator' => [
3026
                'minStringLength' => 0,
3027
                'maxStringLength' => 0,
3028
            ],
3029
        ];
3030
        $lastNameFieldCreate->fieldSettings = [];
3031
        $lastNameFieldCreate->isSearchable = true;
3032
        $lastNameFieldCreate->defaultValue = '';
3033
3034
        $typeCreate->addFieldDefinition($lastNameFieldCreate);
3035
3036
        $accountFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct('account', 'ezuser');
3037
        $accountFieldCreateStruct->names = [
3038
            'eng-GB' => 'User account',
3039
        ];
3040
        $accountFieldCreateStruct->descriptions = [
3041
            'eng-GB' => '',
3042
        ];
3043
        $accountFieldCreateStruct->fieldGroup = 'default';
3044
        $accountFieldCreateStruct->position = 3;
3045
        $accountFieldCreateStruct->isTranslatable = false;
3046
        $accountFieldCreateStruct->isRequired = true;
3047
        $accountFieldCreateStruct->isInfoCollector = false;
3048
        $accountFieldCreateStruct->validatorConfiguration = $validatorConfiguration;
3049
        $accountFieldCreateStruct->fieldSettings = $fieldSetting;
3050
        $accountFieldCreateStruct->isSearchable = false;
3051
        $accountFieldCreateStruct->defaultValue = null;
3052
3053
        $typeCreate->addFieldDefinition($accountFieldCreateStruct);
3054
3055
        $contentTypeDraft = $contentTypeService->createContentType($typeCreate, [
3056
            $contentTypeService->loadContentTypeGroupByIdentifier('Users'),
3057
        ]);
3058
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
3059
3060
        return $contentTypeService->loadContentTypeByIdentifier($identifier);
3061
    }
3062
}
3063