Completed
Push — master ( d4542d...320f13 )
by
unknown
21s queued 10s
created

testGetPasswordInfoIfExpirationWarningIsDisabled()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 22
rs 9.568
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the UserServiceTest class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\API\Repository\Tests;
10
11
use DateInterval;
12
use DateTime;
13
use DateTimeImmutable;
14
use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException;
15
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
16
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
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
use ReflectionClass;
32
33
/**
34
 * Test case for operations in the UserService using in memory storage.
35
 *
36
 * @see eZ\Publish\API\Repository\UserService
37
 * @group integration
38
 * @group user
39
 */
40
class UserServiceTest extends BaseTest
41
{
42
    // Example password matching default rules
43
    private const EXAMPLE_PASSWORD = 'P@ssword123!';
44
45
    private const EXAMPLE_PASSWORD_TTL = 30;
46
    private const EXAMPLE_PASSWORD_TTL_WARNING = 14;
47
48
    /**
49
     * Test for the loadUserGroup() method.
50
     *
51
     * @see \eZ\Publish\API\Repository\UserService::loadUserGroup()
52
     */
53
    public function testLoadUserGroup()
54
    {
55
        $repository = $this->getRepository();
56
57
        $mainGroupId = $this->generateId('group', 4);
58
        /* BEGIN: Use Case */
59
        // $mainGroupId is the ID of the main "Users" group
60
61
        $userService = $repository->getUserService();
62
63
        $userGroup = $userService->loadUserGroup($mainGroupId);
64
        /* END: Use Case */
65
66
        $this->assertInstanceOf(UserGroup::class, $userGroup);
67
68
        // User group happens to also be a Content; isUserGroup() should be true and isUser() should be false
69
        $this->assertTrue($userService->isUserGroup($userGroup), 'isUserGroup() => false on a user group');
70
        $this->assertFalse($userService->isUser($userGroup), 'isUser() => true on a user group');
71
        $this->assertSame(0, $userGroup->parentId, 'parentId should be equal `0` because it is top level node');
72
    }
73
74
    /**
75
     * Test for the loadUserGroup() method to ensure that DomainUserGroupObject is created properly even if a user
76
     * has no access to parent of UserGroup.
77
     *
78
     * @see \eZ\Publish\API\Repository\UserService::loadUserGroup()
79
     */
80
    public function testLoadUserGroupWithNoAccessToParent()
81
    {
82
        $repository = $this->getRepository();
83
84
        $mainGroupId = $this->generateId('group', 4);
85
        /* BEGIN: Use Case */
86
        // $mainGroupId is the ID of the main "Users" group
87
88
        $userService = $repository->getUserService();
89
90
        $user = $this->createUserWithPolicies(
91
            'user',
92
            [
93
                ['module' => 'content', 'function' => 'read'],
94
            ],
95
            new SubtreeLimitation(['limitationValues' => ['/1/5']])
96
        );
97
        $repository->getPermissionResolver()->setCurrentUserReference($user);
98
99
        $userGroup = $userService->loadUserGroup($mainGroupId);
100
        /* END: Use Case */
101
102
        $this->assertInstanceOf(UserGroup::class, $userGroup);
103
104
        // User group happens to also be a Content; isUserGroup() should be true and isUser() should be false
105
        $this->assertTrue($userService->isUserGroup($userGroup), 'isUserGroup() => false on a user group');
106
        $this->assertFalse($userService->isUser($userGroup), 'isUser() => true on a user group');
107
        $this->assertSame(0, $userGroup->parentId, 'parentId should be equal `0` because it is top level node');
108
    }
109
110
    /**
111
     * Test for the loadUserGroup() method.
112
     *
113
     * @see \eZ\Publish\API\Repository\UserService::loadUserGroup()
114
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
115
     */
116
    public function testLoadUserGroupThrowsNotFoundException()
117
    {
118
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
119
120
        $repository = $this->getRepository();
121
122
        $nonExistingGroupId = $this->generateId('group', self::DB_INT_MAX);
123
        /* BEGIN: Use Case */
124
        $userService = $repository->getUserService();
125
126
        // This call will fail with a NotFoundException
127
        $userService->loadUserGroup($nonExistingGroupId);
128
        /* END: Use Case */
129
    }
130
131
    /**
132
     * Test for the loadSubUserGroups() method.
133
     *
134
     * @see \eZ\Publish\API\Repository\UserService::loadSubUserGroups()
135
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
136
     */
137
    public function testLoadSubUserGroups()
138
    {
139
        $repository = $this->getRepository();
140
141
        $mainGroupId = $this->generateId('group', 4);
142
        /* BEGIN: Use Case */
143
        // $mainGroupId is the ID of the main "Users" group
144
145
        $userService = $repository->getUserService();
146
147
        $userGroup = $userService->loadUserGroup($mainGroupId);
148
149
        $subUserGroups = $userService->loadSubUserGroups($userGroup);
150
        foreach ($subUserGroups as $subUserGroup) {
151
            // Do something with the $subUserGroup
152
            $this->assertInstanceOf(UserGroup::class, $subUserGroup);
153
        }
154
        /* END: Use Case */
155
    }
156
157
    /**
158
     * Test loading sub groups throwing NotFoundException.
159
     *
160
     * @covers \eZ\Publish\API\Repository\UserService::loadSubUserGroups
161
     */
162
    public function testLoadSubUserGroupsThrowsNotFoundException()
163
    {
164
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
165
166
        $repository = $this->getRepository();
167
        $userService = $repository->getUserService();
168
169
        $parentGroup = new UserGroup(
170
            [
171
                'content' => new Content(
172
                    [
173
                        'versionInfo' => new VersionInfo(
174
                            [
175
                                'contentInfo' => new ContentInfo(
176
                                    ['id' => 123456]
177
                                ),
178
                            ]
179
                        ),
180
                        'internalFields' => [],
181
                    ]
182
                ),
183
            ]
184
        );
185
        $userService->loadSubUserGroups($parentGroup);
186
    }
187
188
    /**
189
     * Test for the newUserGroupCreateStruct() method.
190
     *
191
     * @return \eZ\Publish\API\Repository\Values\User\UserGroupCreateStruct
192
     *
193
     * @see \eZ\Publish\API\Repository\UserService::newUserGroupCreateStruct()
194
     * @depends eZ\Publish\API\Repository\Tests\ContentTypeServiceTest::testLoadContentTypeByIdentifier
195
     */
196
    public function testNewUserGroupCreateStruct()
197
    {
198
        $repository = $this->getRepository();
199
200
        /* BEGIN: Use Case */
201
        $userService = $repository->getUserService();
202
203
        $groupCreate = $userService->newUserGroupCreateStruct('eng-US');
204
        /* END: Use Case */
205
206
        $this->assertInstanceOf(
207
            '\\eZ\\Publish\\API\\Repository\\Values\\User\\UserGroupCreateStruct',
208
            $groupCreate
209
        );
210
211
        return $groupCreate;
212
    }
213
214
    /**
215
     * Test for the newUserGroupCreateStruct() method.
216
     *
217
     * @param \eZ\Publish\API\Repository\Values\User\UserGroupCreateStruct $groupCreate
218
     *
219
     * @see \eZ\Publish\API\Repository\UserService::newUserGroupCreateStruct()
220
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupCreateStruct
221
     */
222
    public function testNewUserGroupCreateStructSetsMainLanguageCode($groupCreate)
223
    {
224
        $this->assertEquals('eng-US', $groupCreate->mainLanguageCode);
225
    }
226
227
    /**
228
     * Test for the newUserGroupCreateStruct() method.
229
     *
230
     * @param \eZ\Publish\API\Repository\Values\User\UserGroupCreateStruct $groupCreate
231
     *
232
     * @see \eZ\Publish\API\Repository\UserService::newUserGroupCreateStruct()
233
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupCreateStruct
234
     */
235
    public function testNewUserGroupCreateStructSetsContentType($groupCreate)
236
    {
237
        $this->assertInstanceOf(
238
            '\\eZ\\Publish\\API\\Repository\\Values\\ContentType\\ContentType',
239
            $groupCreate->contentType
240
        );
241
    }
242
243
    /**
244
     * Test for the newUserGroupCreateStruct() method.
245
     *
246
     * @see \eZ\Publish\API\Repository\UserService::newUserGroupCreateStruct($mainLanguageCode, $contentType)
247
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupCreateStruct
248
     * @depends eZ\Publish\API\Repository\Tests\ContentTypeServiceTest::testLoadContentTypeByIdentifier
249
     */
250
    public function testNewUserGroupCreateStructWithSecondParameter()
251
    {
252
        if ($this->isVersion4()) {
253
            $this->markTestSkipped('This test is only relevant for eZ Publish versions > 4');
254
        }
255
256
        $repository = $this->getRepository();
257
258
        /* BEGIN: Use Case */
259
        $contentTypeService = $repository->getContentTypeService();
260
        $userService = $repository->getUserService();
261
262
        // Load the default ContentType for user groups
263
        $groupType = $contentTypeService->loadContentTypeByIdentifier('user_group');
264
265
        // Instantiate a new group create struct
266
        $groupCreate = $userService->newUserGroupCreateStruct(
267
            'eng-US',
268
            $groupType
269
        );
270
        /* END: Use Case */
271
272
        $this->assertSame($groupType, $groupCreate->contentType);
273
    }
274
275
    /**
276
     * Test for the createUserGroup() method.
277
     *
278
     * @return \eZ\Publish\API\Repository\Values\User\UserGroup
279
     *
280
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
281
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupCreateStruct
282
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
283
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
284
     */
285
    public function testCreateUserGroup()
286
    {
287
        /* BEGIN: Use Case */
288
        $userGroup = $this->createUserGroupVersion1();
289
        /* END: Use Case */
290
291
        $this->assertInstanceOf(
292
            UserGroup::class,
293
            $userGroup
294
        );
295
296
        $versionInfo = $userGroup->getVersionInfo();
297
298
        $this->assertEquals(APIVersionInfo::STATUS_PUBLISHED, $versionInfo->status);
299
        $this->assertEquals(1, $versionInfo->versionNo);
300
301
        return $userGroup;
302
    }
303
304
    /**
305
     * Test for the createUserGroup() method.
306
     *
307
     * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup
308
     *
309
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
310
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
311
     */
312
    public function testCreateUserGroupSetsExpectedProperties($userGroup)
313
    {
314
        $this->assertEquals(
315
            [
316
                'parentId' => $this->generateId('group', 4),
317
            ],
318
            [
319
                'parentId' => $userGroup->parentId,
320
            ]
321
        );
322
    }
323
324
    /**
325
     * Test for the createUserGroup() method.
326
     *
327
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
328
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
329
     */
330
    public function testCreateUserGroupThrowsInvalidArgumentException()
331
    {
332
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
333
334
        $repository = $this->getRepository();
335
336
        $mainGroupId = $this->generateId('group', 4);
337
        /* BEGIN: Use Case */
338
        // $mainGroupId is the ID of the main "Users" group
339
340
        $userService = $repository->getUserService();
341
342
        // Load main group
343
        $parentUserGroup = $userService->loadUserGroup($mainGroupId);
344
345
        // Instantiate a new create struct
346
        $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
347
        $userGroupCreate->setField('name', 'Example Group');
348
        $userGroupCreate->remoteId = '5f7f0bdb3381d6a461d8c29ff53d908f';
349
350
        // This call will fail with an "InvalidArgumentException", because the
351
        // specified remoteId is already used for the "Members" user group.
352
        $userService->createUserGroup(
353
            $userGroupCreate,
354
            $parentUserGroup
355
        );
356
        /* END: Use Case */
357
    }
358
359
    /**
360
     * Test for the createUserGroup() method.
361
     *
362
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
363
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
364
     */
365
    public function testCreateUserGroupThrowsInvalidArgumentExceptionFieldTypeNotAccept()
366
    {
367
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
368
369
        $repository = $this->getRepository();
370
371
        $mainGroupId = $this->generateId('group', 4);
372
        /* BEGIN: Use Case */
373
        // $mainGroupId is the ID of the main "Users" group
374
375
        $userService = $repository->getUserService();
376
377
        // Load main group
378
        $parentUserGroup = $userService->loadUserGroup($mainGroupId);
379
380
        // Instantiate a new create struct
381
        $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
382
        $userGroupCreate->setField('name', new \stdClass());
383
384
        // This call will fail with an "InvalidArgumentException", because the
385
        // specified remoteId is already used for the "Members" user group.
386
        $userService->createUserGroup(
387
            $userGroupCreate,
388
            $parentUserGroup
389
        );
390
        /* END: Use Case */
391
    }
392
393
    /**
394
     * Test for the createUserGroup() method.
395
     *
396
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
397
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
398
     */
399
    public function testCreateUserGroupWhenMissingField()
400
    {
401
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException::class);
402
403
        $repository = $this->getRepository();
404
405
        $mainGroupId = $this->generateId('group', 4);
406
        /* BEGIN: Use Case */
407
        // $mainGroupId is the ID of the main "Users" group
408
409
        $userService = $repository->getUserService();
410
411
        // Load main group
412
        $parentUserGroup = $userService->loadUserGroup($mainGroupId);
413
414
        // Instantiate a new create struct
415
        $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
416
417
        // This call will fail with a "ContentFieldValidationException", because the
418
        // only mandatory field "name" is not set.
419
        $userService->createUserGroup($userGroupCreate, $parentUserGroup);
420
        /* END: Use Case */
421
    }
422
423
    /**
424
     * Test for the createUserGroup() method.
425
     *
426
     * @return \eZ\Publish\API\Repository\Values\User\UserGroup
427
     *
428
     * @see \eZ\Publish\API\Repository\UserService::createUserGroup()
429
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupCreateStruct
430
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
431
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
432
     */
433
    public function testCreateUserGroupInTransactionWithRollback()
434
    {
435
        $repository = $this->getRepository();
436
437
        $mainGroupId = $this->generateId('group', 4);
438
        /* BEGIN: Use Case */
439
        // $mainGroupId is the ID of the main "Users" group
440
441
        $userService = $repository->getUserService();
442
443
        $repository->beginTransaction();
444
445
        try {
446
            // Load main group
447
            $parentUserGroup = $userService->loadUserGroup($mainGroupId);
448
449
            // Instantiate a new create struct
450
            $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
451
            $userGroupCreate->setField('name', 'Example Group');
452
453
            // Create the new user group
454
            $createdUserGroupId = $userService->createUserGroup(
455
                $userGroupCreate,
456
                $parentUserGroup
457
            )->id;
458
        } catch (Exception $e) {
459
            // Cleanup hanging transaction on error
460
            $repository->rollback();
461
            throw $e;
462
        }
463
464
        $repository->rollback();
465
466
        try {
467
            // Throws exception since creation of user group was rolled back
468
            $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...
469
        } catch (NotFoundException $e) {
470
            return;
471
        }
472
        /* END: Use Case */
473
474
        $this->fail('User group object still exists after rollback.');
475
    }
476
477
    /**
478
     * Test for the deleteUserGroup() method.
479
     *
480
     * @see \eZ\Publish\API\Repository\UserService::deleteUserGroup()
481
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
482
     */
483
    public function testDeleteUserGroup()
484
    {
485
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
486
487
        $repository = $this->getRepository();
488
        $userService = $repository->getUserService();
489
490
        /* BEGIN: Use Case */
491
        $userGroup = $this->createUserGroupVersion1();
492
493
        // Delete the currently created user group again
494
        $userService->deleteUserGroup($userGroup);
495
        /* END: Use Case */
496
497
        // We use the NotFoundException here for verification
498
        $userService->loadUserGroup($userGroup->id);
499
    }
500
501
    /**
502
     * Test deleting user group throwing NotFoundException.
503
     *
504
     * @covers \eZ\Publish\API\Repository\UserService::deleteUserGroup
505
     */
506
    public function testDeleteUserGroupThrowsNotFoundException()
507
    {
508
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
509
510
        $repository = $this->getRepository();
511
        $userService = $repository->getUserService();
512
513
        $userGroup = new UserGroup(
514
            [
515
                'content' => new Content(
516
                    [
517
                        'versionInfo' => new VersionInfo(
518
                            ['contentInfo' => new ContentInfo(['id' => 123456])]
519
                        ),
520
                        'internalFields' => [],
521
                    ]
522
                ),
523
            ]
524
        );
525
        $userService->deleteUserGroup($userGroup);
526
    }
527
528
    /**
529
     * Test for the moveUserGroup() method.
530
     *
531
     * @see \eZ\Publish\API\Repository\UserService::moveUserGroup()
532
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
533
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadSubUserGroups
534
     */
535
    public function testMoveUserGroup()
536
    {
537
        $repository = $this->getRepository();
538
        $userService = $repository->getUserService();
539
540
        $membersGroupId = $this->generateId('group', 13);
541
        /* BEGIN: Use Case */
542
        // $membersGroupId is the ID of the "Members" user group in an eZ
543
        // Publish demo installation
544
545
        $userGroup = $this->createUserGroupVersion1();
546
547
        // Load the new parent group
548
        $membersUserGroup = $userService->loadUserGroup($membersGroupId);
549
550
        // Move user group from "Users" to "Members"
551
        $userService->moveUserGroup($userGroup, $membersUserGroup);
552
553
        // Reload the user group to get an updated $parentId
554
        $userGroup = $userService->loadUserGroup($userGroup->id);
555
556
        $this->refreshSearch($repository);
557
558
        // The returned array will no contain $userGroup
559
        $subUserGroups = $userService->loadSubUserGroups(
560
            $membersUserGroup
561
        );
562
        /* END: Use Case */
563
564
        $subUserGroupIds = array_map(
565
            function ($content) {
566
                return $content->id;
567
            },
568
            $subUserGroups
569
        );
570
571
        $this->assertEquals($membersGroupId, $userGroup->parentId);
572
        $this->assertEquals([$userGroup->id], $subUserGroupIds);
573
    }
574
575
    /**
576
     * Test moving a user group below another group throws NotFoundException.
577
     *
578
     * @covers \eZ\Publish\API\Repository\UserService::moveUserGroup
579
     */
580
    public function testMoveUserGroupThrowsNotFoundException()
581
    {
582
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
583
584
        $repository = $this->getRepository();
585
        $userService = $repository->getUserService();
586
587
        $userGroupToMove = new UserGroup(
588
            [
589
                'content' => new Content(
590
                    [
591
                        'versionInfo' => new VersionInfo(
592
                            ['contentInfo' => new ContentInfo(['id' => 123456])]
593
                        ),
594
                        'internalFields' => [],
595
                    ]
596
                ),
597
            ]
598
        );
599
        $parentUserGroup = new UserGroup(
600
            [
601
                'content' => new Content(
602
                    [
603
                        'versionInfo' => new VersionInfo(
604
                            ['contentInfo' => new ContentInfo(['id' => 123455])]
605
                        ),
606
                        'internalFields' => [],
607
                    ]
608
                ),
609
            ]
610
        );
611
        $userService->moveUserGroup($userGroupToMove, $parentUserGroup);
612
    }
613
614
    /**
615
     * Test for the newUserGroupUpdateStruct() method.
616
     *
617
     * @covers \eZ\Publish\API\Repository\UserService::newUserGroupUpdateStruct
618
     */
619
    public function testNewUserGroupUpdateStruct()
620
    {
621
        $repository = $this->getRepository();
622
623
        /* BEGIN: Use Case */
624
        $userService = $repository->getUserService();
625
626
        $groupUpdate = $userService->newUserGroupUpdateStruct();
627
        /* END: Use Case */
628
629
        $this->assertInstanceOf(
630
            UserGroupUpdateStruct::class,
631
            $groupUpdate
632
        );
633
634
        $this->assertNull($groupUpdate->contentUpdateStruct);
635
        $this->assertNull($groupUpdate->contentMetadataUpdateStruct);
636
    }
637
638
    /**
639
     * Test for the updateUserGroup() method.
640
     *
641
     * @see \eZ\Publish\API\Repository\UserService::updateUserGroup()
642
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUserGroup
643
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserGroupUpdateStruct
644
     */
645
    public function testUpdateUserGroup()
646
    {
647
        $repository = $this->getRepository();
648
        $userService = $repository->getUserService();
649
650
        /* BEGIN: Use Case */
651
        $userGroup = $this->createUserGroupVersion1();
652
653
        // Create a group update struct and change nothing
654
        $groupUpdate = $userService->newUserGroupUpdateStruct();
655
656
        // This update will do nothing
657
        $userGroup = $userService->updateUserGroup(
658
            $userGroup,
659
            $groupUpdate
660
        );
661
        /* END: Use Case */
662
663
        $this->assertInstanceOf(
664
            UserGroup::class,
665
            $userGroup
666
        );
667
668
        $this->assertEquals(1, $userGroup->getVersionInfo()->versionNo);
669
    }
670
671
    /**
672
     * Test for the updateUserGroup() method.
673
     *
674
     * @see \eZ\Publish\API\Repository\UserService::updateUserGroup()
675
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUserGroup
676
     */
677
    public function testUpdateUserGroupWithSubContentUpdateStruct()
678
    {
679
        $repository = $this->getRepository();
680
        $userService = $repository->getUserService();
681
682
        /* BEGIN: Use Case */
683
        $userGroup = $this->createUserGroupVersion1();
684
685
        // Load the content service
686
        $contentService = $repository->getContentService();
687
688
        // Create a content update struct and update the group name
689
        $contentUpdate = $contentService->newContentUpdateStruct();
690
        $contentUpdate->setField('name', 'Sindelfingen', 'eng-US');
691
692
        // Create a group update struct and set content update struct
693
        $groupUpdate = $userService->newUserGroupUpdateStruct();
694
        $groupUpdate->contentUpdateStruct = $contentUpdate;
695
696
        // This will update the name and the increment the group version number
697
        $userGroup = $userService->updateUserGroup(
698
            $userGroup,
699
            $groupUpdate
700
        );
701
        /* END: Use Case */
702
703
        $this->assertEquals('Sindelfingen', $userGroup->getFieldValue('name', 'eng-US'));
704
705
        $versionInfo = $userGroup->getVersionInfo();
706
707
        $this->assertEquals(APIVersionInfo::STATUS_PUBLISHED, $versionInfo->status);
708
        $this->assertEquals(2, $versionInfo->versionNo);
709
    }
710
711
    /**
712
     * Test for the updateUserGroup() method.
713
     *
714
     * @see \eZ\Publish\API\Repository\UserService::updateUserGroup()
715
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUserGroup
716
     */
717
    public function testUpdateUserGroupWithSubContentMetadataUpdateStruct()
718
    {
719
        $repository = $this->getRepository();
720
        $userService = $repository->getUserService();
721
722
        /* BEGIN: Use Case */
723
        $userGroup = $this->createUserGroupVersion1();
724
725
        // Load the content service
726
        $contentService = $repository->getContentService();
727
728
        // Create a metadata update struct and change the remoteId
729
        $metadataUpdate = $contentService->newContentMetadataUpdateStruct();
730
        $metadataUpdate->remoteId = '3c61299780663bafa3af2101e52125da';
731
732
        // Create a group update struct and set content update struct
733
        $groupUpdate = $userService->newUserGroupUpdateStruct();
734
        $groupUpdate->contentMetadataUpdateStruct = $metadataUpdate;
735
736
        // This will update the name and the increment the group version number
737
        $userGroup = $userService->updateUserGroup(
738
            $userGroup,
739
            $groupUpdate
740
        );
741
        /* END: Use Case */
742
743
        $this->assertEquals(
744
            '3c61299780663bafa3af2101e52125da',
745
            $userGroup->contentInfo->remoteId
746
        );
747
748
        $versionInfo = $userGroup->getVersionInfo();
749
750
        $this->assertEquals(APIVersionInfo::STATUS_PUBLISHED, $versionInfo->status);
751
        $this->assertEquals(1, $versionInfo->versionNo);
752
    }
753
754
    /**
755
     * Test for the updateUserGroup() method.
756
     *
757
     * @see \eZ\Publish\API\Repository\UserService::updateUserGroup()
758
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUserGroup
759
     */
760
    public function testUpdateUserGroupThrowsInvalidArgumentExceptionOnFieldTypeNotAccept()
761
    {
762
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
763
764
        $repository = $this->getRepository();
765
        $userService = $repository->getUserService();
766
767
        /* BEGIN: Use Case */
768
        $userGroup = $this->createUserGroupVersion1();
769
770
        // Load the content service
771
        $contentService = $repository->getContentService();
772
773
        // Create a content update struct and update the group name
774
        $contentUpdate = $contentService->newContentUpdateStruct();
775
        // An object of stdClass is not accepted as a value by the field "name"
776
        $contentUpdate->setField('name', new \stdClass(), 'eng-US');
777
778
        // Create a group update struct and set content update struct
779
        $groupUpdate = $userService->newUserGroupUpdateStruct();
780
        $groupUpdate->contentUpdateStruct = $contentUpdate;
781
782
        // This call will fail with an InvalidArgumentException, because the
783
        // field "name" does not accept the given value
784
        $userService->updateUserGroup($userGroup, $groupUpdate);
785
        /* END: Use Case */
786
    }
787
788
    /**
789
     * Test for the newUserCreateStruct() method.
790
     *
791
     * @see \eZ\Publish\API\Repository\UserService::newUserCreateStruct()
792
     */
793
    public function testNewUserCreateStruct()
794
    {
795
        $repository = $this->getRepository();
796
797
        /* BEGIN: Use Case */
798
        $userService = $repository->getUserService();
799
800
        $userCreate = $userService->newUserCreateStruct(
801
            'user',
802
            '[email protected]',
803
            'secret',
804
            'eng-US'
805
        );
806
        /* END: Use Case */
807
808
        $this->assertInstanceOf(
809
            '\\eZ\\Publish\\API\\Repository\\Values\\User\\UserCreateStruct',
810
            $userCreate
811
        );
812
813
        return $userCreate;
814
    }
815
816
    /**
817
     * Test updating a user group throws ContentFieldValidationException.
818
     *
819
     * @covers \eZ\Publish\API\Repository\UserService::updateUserGroup
820
     */
821
    public function testUpdateUserGroupThrowsContentFieldValidationExceptionOnRequiredFieldEmpty()
822
    {
823
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException::class);
824
825
        $repository = $this->getRepository();
826
        $userService = $repository->getUserService();
827
        $contentService = $repository->getContentService();
828
829
        $userGroup = $userService->loadUserGroup(42);
830
        $userGroupUpdateStruct = $userService->newUserGroupUpdateStruct();
831
        $userGroupUpdateStruct->contentUpdateStruct = $contentService->newContentUpdateStruct();
832
        $userGroupUpdateStruct->contentUpdateStruct->setField('name', '', 'eng-US');
833
834
        $userService->updateUserGroup($userGroup, $userGroupUpdateStruct);
835
    }
836
837
    /**
838
     * Test for the newUserCreateStruct() method.
839
     *
840
     * @param \eZ\Publish\API\Repository\Values\User\UserCreateStruct $userCreate
841
     *
842
     * @see \eZ\Publish\API\Repository\UserService::newUserCreateStruct()
843
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserCreateStruct
844
     */
845
    public function testNewUserCreateStructSetsExpectedProperties($userCreate)
846
    {
847
        $this->assertEquals(
848
            [
849
                'login' => 'user',
850
                'email' => '[email protected]',
851
                'password' => 'secret',
852
                'mainLanguageCode' => 'eng-US',
853
            ],
854
            [
855
                'login' => $userCreate->login,
856
                'email' => $userCreate->email,
857
                'password' => $userCreate->password,
858
                'mainLanguageCode' => $userCreate->mainLanguageCode,
859
            ]
860
        );
861
    }
862
863
    /**
864
     * Test for the newUserCreateStruct() method.
865
     *
866
     * @see \eZ\Publish\API\Repository\UserService::newUserCreateStruct($login, $email, $password, $mainLanguageCode, $contentType)
867
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserCreateStruct
868
     * @depends eZ\Publish\API\Repository\Tests\ContentTypeServiceTest::testLoadContentTypeByIdentifier
869
     */
870
    public function testNewUserCreateStructWithFifthParameter()
871
    {
872
        if ($this->isVersion4()) {
873
            $this->markTestSkipped('This test is only relevant for eZ Publish versions > 4');
874
        }
875
876
        $repository = $this->getRepository();
877
878
        /* BEGIN: Use Case */
879
        $contentTypeService = $repository->getContentTypeService();
880
        $userService = $repository->getUserService();
881
882
        $userType = $contentTypeService->loadContentTypeByIdentifier('user');
883
884
        $userCreate = $userService->newUserCreateStruct(
885
            'user',
886
            '[email protected]',
887
            'secret',
888
            'eng-US',
889
            $userType
890
        );
891
        /* END: Use Case */
892
893
        $this->assertSame($userType, $userCreate->contentType);
894
    }
895
896
    /**
897
     * Test for creating user with Active Directory login name.
898
     */
899
    public function testNewUserWithDomainName()
900
    {
901
        $repository = $this->getRepository();
902
        $userService = $repository->getUserService();
903
        $createdUser = $this->createUserVersion1('ez-user-Domain\username-by-login');
904
        $loadedUser = $userService->loadUserByLogin('ez-user-Domain\username-by-login');
905
906
        $this->assertEquals($createdUser, $loadedUser);
907
    }
908
909
    /**
910
     * Test for the createUser() method.
911
     *
912
     * @return \eZ\Publish\API\Repository\Values\User\User
913
     *
914
     * @see \eZ\Publish\API\Repository\UserService::createUser()
915
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
916
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserCreateStruct
917
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
918
     */
919
    public function testCreateUser()
920
    {
921
        /* BEGIN: Use Case */
922
        $user = $this->createUserVersion1();
923
        /* END: Use Case */
924
925
        $this->assertInstanceOf(
926
            '\\eZ\\Publish\\API\\Repository\\Values\\User\\User',
927
            $user
928
        );
929
930
        return $user;
931
    }
932
933
    /**
934
     * Test for the createUser() method.
935
     *
936
     * @param \eZ\Publish\API\Repository\Values\User\User $user
937
     *
938
     * @see \eZ\Publish\API\Repository\UserService::createUser()
939
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
940
     */
941
    public function testCreateUserSetsExpectedProperties(User $user)
942
    {
943
        $this->assertEquals(
944
            [
945
                'login' => 'user',
946
                'email' => '[email protected]',
947
                'mainLanguageCode' => 'eng-US',
948
            ],
949
            [
950
                'login' => $user->login,
951
                'email' => $user->email,
952
                'mainLanguageCode' => $user->contentInfo->mainLanguageCode,
953
            ]
954
        );
955
    }
956
957
    /**
958
     * Test for the createUser() method.
959
     *
960
     * @see \eZ\Publish\API\Repository\UserService::createUser()
961
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
962
     */
963
    public function testCreateUserWhenMissingField()
964
    {
965
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException::class);
966
967
        $repository = $this->getRepository();
968
969
        $editorsGroupId = $this->generateId('group', 13);
970
        /* BEGIN: Use Case */
971
        // $editorsGroupId is the ID of the "Editors" user group in an eZ
972
        // Publish demo installation
973
974
        $userService = $repository->getUserService();
975
976
        // Instantiate a create struct with mandatory properties
977
        $userCreate = $userService->newUserCreateStruct(
978
            'user',
979
            '[email protected]',
980
            'secret',
981
            'eng-US'
982
        );
983
984
        // Do not set the mandatory fields "first_name" and "last_name"
985
        //$userCreate->setField( 'first_name', 'Example' );
986
        //$userCreate->setField( 'last_name', 'User' );
987
988
        // Load parent group for the user
989
        $group = $userService->loadUserGroup($editorsGroupId);
990
991
        // This call will fail with a "ContentFieldValidationException", because the
992
        // mandatory fields "first_name" and "last_name" are not set.
993
        $userService->createUser($userCreate, [$group]);
994
        /* END: Use Case */
995
    }
996
997
    /**
998
     * Test for the createUser() method.
999
     *
1000
     * @see \eZ\Publish\API\Repository\UserService::createUser()
1001
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1002
     */
1003
    public function testCreateUserThrowsInvalidArgumentExceptionOnFieldTypeNotAccept()
1004
    {
1005
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
1006
1007
        $repository = $this->getRepository();
1008
1009
        $editorsGroupId = $this->generateId('group', 13);
1010
        /* BEGIN: Use Case */
1011
        // $editorsGroupId is the ID of the "Editors" user group in an eZ
1012
        // Publish demo installation
1013
1014
        $userService = $repository->getUserService();
1015
1016
        // Instantiate a create struct with mandatory properties
1017
        $userCreate = $userService->newUserCreateStruct(
1018
            'user',
1019
            '[email protected]',
1020
            'secret',
1021
            'eng-US'
1022
        );
1023
1024
        // An object of stdClass is not a valid value for the field first_name
1025
        $userCreate->setField('first_name', new \stdClass());
1026
        $userCreate->setField('last_name', 'User');
1027
1028
        // Load parent group for the user
1029
        $group = $userService->loadUserGroup($editorsGroupId);
1030
1031
        // This call will fail with an "InvalidArgumentException", because the
1032
        // value for the firled "first_name" is not accepted by the field type.
1033
        $userService->createUser($userCreate, [$group]);
1034
        /* END: Use Case */
1035
    }
1036
1037
    /**
1038
     * Test for the createUser() method.
1039
     *
1040
     * @covers \eZ\Publish\API\Repository\UserService::createUser
1041
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1042
     */
1043
    public function testCreateUserThrowsInvalidArgumentException()
1044
    {
1045
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
1046
        $this->expectExceptionMessage('Argument \'userCreateStruct\' is invalid: User with provided login already exists');
1047
1048
        $repository = $this->getRepository();
1049
1050
        $editorsGroupId = $this->generateId('group', 13);
1051
        /* BEGIN: Use Case */
1052
        // $editorsGroupId is the ID of the "Editors" user group in an eZ
1053
        // Publish demo installation
1054
1055
        $userService = $repository->getUserService();
1056
1057
        // Instantiate a create struct with mandatory properties
1058
        $userCreate = $userService->newUserCreateStruct(
1059
            // admin is an existing login
1060
            'admin',
1061
            '[email protected]',
1062
            'secret',
1063
            'eng-US'
1064
        );
1065
1066
        $userCreate->setField('first_name', 'Example');
1067
        $userCreate->setField('last_name', 'User');
1068
1069
        // Load parent group for the user
1070
        $group = $userService->loadUserGroup($editorsGroupId);
1071
1072
        // This call will fail with a "InvalidArgumentException", because the
1073
        // user with "admin" login already exists.
1074
        $userService->createUser($userCreate, [$group]);
1075
        /* END: Use Case */
1076
    }
1077
1078
    /**
1079
     * Test for the createUser() method.
1080
     *
1081
     * @return \eZ\Publish\API\Repository\Values\User\User
1082
     *
1083
     * @see \eZ\Publish\API\Repository\UserService::createUser()
1084
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroup
1085
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserCreateStruct
1086
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
1087
     */
1088
    public function testCreateUserInTransactionWithRollback()
1089
    {
1090
        $repository = $this->getRepository();
1091
        $userService = $repository->getUserService();
1092
1093
        /* BEGIN: Use Case */
1094
        $repository->beginTransaction();
1095
1096
        try {
1097
            $user = $this->createUserVersion1();
1098
        } catch (Exception $e) {
1099
            // Cleanup hanging transaction on error
1100
            $repository->rollback();
1101
            throw $e;
1102
        }
1103
1104
        $repository->rollback();
1105
1106
        try {
1107
            // Throws exception since creation of user was rolled back
1108
            $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...
1109
        } catch (NotFoundException $e) {
1110
            return;
1111
        }
1112
        /* END: Use Case */
1113
1114
        $this->fail('User object still exists after rollback.');
1115
    }
1116
1117
    /**
1118
     * Test creating a user throwing NotFoundException.
1119
     *
1120
     * @covers \eZ\Publish\API\Repository\UserService::createUser
1121
     */
1122
    public function testCreateUserThrowsNotFoundException()
1123
    {
1124
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1125
1126
        $repository = $this->getRepository();
1127
        $userService = $repository->getUserService();
1128
1129
        $userCreateStruct = $userService->newUserCreateStruct('new_user', '[email protected]', 'password', 'eng-GB');
1130
        $userCreateStruct->setField('first_name', 'New');
1131
        $userCreateStruct->setField('last_name', 'User');
1132
1133
        $parentGroup = new UserGroup(
1134
            [
1135
                'content' => new Content(
1136
                    [
1137
                        'versionInfo' => new VersionInfo(
1138
                            [
1139
                                'contentInfo' => new ContentInfo(['id' => 123456]),
1140
                            ]
1141
                        ),
1142
                        'internalFields' => [],
1143
                    ]
1144
                ),
1145
            ]
1146
        );
1147
        $userService->createUser($userCreateStruct, [$parentGroup]);
1148
    }
1149
1150
    /**
1151
     * Test creating a user throwing UserPasswordValidationException when password doesn't follow specific rules.
1152
     *
1153
     * @covers \eZ\Publish\API\Repository\UserService::createUser
1154
     */
1155
    public function testCreateUserWithWeakPasswordThrowsUserPasswordValidationException()
1156
    {
1157
        $this->expectException(\eZ\Publish\Core\Base\Exceptions\UserPasswordValidationException::class);
1158
        $this->expectExceptionMessage('Argument \'password\' is invalid: Password doesn\'t match the following rules: User password must be at least 8 characters long, User password must include at least one upper case letter, User password must include at least one number, User password must include at least one special character');
1159
1160
        $userContentType = $this->createUserContentTypeWithStrongPassword();
1161
1162
        /* BEGIN: Use Case */
1163
        // This call will fail with a "UserPasswordValidationException" because the
1164
        // the password does not follow specified rules.
1165
        $this->createTestUserWithPassword('pass', $userContentType);
1166
        /* END: Use Case */
1167
    }
1168
1169
    /**
1170
     * Opposite test case for testCreateUserWithWeakPasswordThrowsUserPasswordValidationException.
1171
     *
1172
     * @covers \eZ\Publish\API\Repository\UserService::createUser
1173
     */
1174
    public function testCreateUserWithStrongPassword()
1175
    {
1176
        $userContentType = $this->createUserContentTypeWithStrongPassword();
1177
1178
        /* BEGIN: Use Case */
1179
        $user = $this->createTestUserWithPassword('H@xxi0r!', $userContentType);
1180
        /* END: Use Case */
1181
1182
        $this->assertInstanceOf(User::class, $user);
1183
    }
1184
1185
    /**
1186
     * Test for the loadUser() method.
1187
     *
1188
     * @see \eZ\Publish\API\Repository\UserService::loadUser()
1189
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1190
     */
1191
    public function testLoadUser()
1192
    {
1193
        $repository = $this->getRepository();
1194
1195
        $userService = $repository->getUserService();
1196
1197
        /* BEGIN: Use Case */
1198
        $user = $this->createUserVersion1();
1199
1200
        // Load the newly created user
1201
        $userReloaded = $userService->loadUser($user->id);
1202
        /* END: Use Case */
1203
1204
        $this->assertEquals($user, $userReloaded);
1205
1206
        // User happens to also be a Content; isUser() should be true and isUserGroup() should be false
1207
        $this->assertTrue($userService->isUser($user), 'isUser() => false on a user');
1208
        $this->assertFalse($userService->isUserGroup($user), 'isUserGroup() => true on a user group');
1209
    }
1210
1211
    /**
1212
     * Test for the loadUser() method.
1213
     *
1214
     * @see \eZ\Publish\API\Repository\UserService::loadUser()
1215
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUser
1216
     */
1217
    public function testLoadUserThrowsNotFoundException()
1218
    {
1219
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1220
1221
        $repository = $this->getRepository();
1222
1223
        $nonExistingUserId = $this->generateId('user', self::DB_INT_MAX);
1224
        /* BEGIN: Use Case */
1225
        $userService = $repository->getUserService();
1226
1227
        // This call will fail with a "NotFoundException", because no user with
1228
        // an id equal to self::DB_INT_MAX should exist.
1229
        $userService->loadUser($nonExistingUserId);
1230
        /* END: Use Case */
1231
    }
1232
1233
    /**
1234
     * Test for the loadAnonymousUser() method.
1235
     *
1236
     * @see \eZ\Publish\API\Repository\UserService::loadAnonymousUser()
1237
     */
1238
    public function testLoadAnonymousUser()
1239
    {
1240
        $repository = $this->getRepository();
1241
1242
        $anonymousUserId = $this->generateId('user', 10);
1243
        /* BEGIN: Use Case */
1244
        // $anonymousUserId is the ID of the "Anonymous" user in a eZ
1245
        // Publish demo installation.
1246
        $userService = $repository->getUserService();
1247
1248
        // Load default anonymous user available in each eZ Publish installation
1249
        $anonymousUser = $userService->loadUser($anonymousUserId);
1250
        /* END: Use Case */
1251
1252
        $this->assertInstanceOf(
1253
            '\\eZ\\Publish\\API\\Repository\\Values\\User\\User',
1254
            $anonymousUser
1255
        );
1256
1257
        $this->assertEquals('anonymous', $anonymousUser->login);
1258
    }
1259
1260
    /**
1261
     * Test for the loadUserByCredentials() method.
1262
     *
1263
     * @see \eZ\Publish\API\Repository\UserService::loadUserByCredentials()
1264
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1265
     */
1266
    public function testLoadUserByCredentials()
1267
    {
1268
        $repository = $this->getRepository();
1269
1270
        $userService = $repository->getUserService();
1271
1272
        /* BEGIN: Use Case */
1273
        $user = $this->createUserVersion1();
1274
1275
        // Load the newly created user
1276
        $userReloaded = $userService->loadUserByCredentials('user', 'secret');
1277
        /* END: Use Case */
1278
1279
        $this->assertEquals($user, $userReloaded);
1280
    }
1281
1282
    /**
1283
     * Test for the loadUserByCredentials() method.
1284
     *
1285
     * @see \eZ\Publish\API\Repository\UserService::loadUserByCredentials()
1286
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByCredentials
1287
     */
1288
    public function testLoadUserByCredentialsThrowsNotFoundExceptionForUnknownPassword()
1289
    {
1290
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1291
1292
        $repository = $this->getRepository();
1293
1294
        $userService = $repository->getUserService();
1295
1296
        /* BEGIN: Use Case */
1297
        $this->createUserVersion1();
1298
1299
        // This call will fail with a "NotFoundException", because the given
1300
        // login/password combination does not exist.
1301
        $userService->loadUserByCredentials('user', 'SeCrEt');
1302
        /* END: Use Case */
1303
    }
1304
1305
    /**
1306
     * Test for the loadUserByCredentials() method.
1307
     *
1308
     * @see \eZ\Publish\API\Repository\UserService::loadUserByCredentials()
1309
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByCredentials
1310
     */
1311
    public function testLoadUserByCredentialsThrowsNotFoundExceptionForUnknownPasswordEmtpy()
1312
    {
1313
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1314
1315
        $repository = $this->getRepository();
1316
1317
        $userService = $repository->getUserService();
1318
1319
        /* BEGIN: Use Case */
1320
        $this->createUserVersion1();
1321
1322
        // This call will fail with a "NotFoundException", because the given
1323
        // login/password combination does not exist.
1324
        $userService->loadUserByCredentials('user', '');
1325
        /* END: Use Case */
1326
    }
1327
1328
    /**
1329
     * Test for the loadUserByCredentials() method.
1330
     *
1331
     * @see \eZ\Publish\API\Repository\UserService::loadUserByCredentials()
1332
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByCredentials
1333
     */
1334
    public function testLoadUserByCredentialsThrowsNotFoundExceptionForUnknownLogin()
1335
    {
1336
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1337
1338
        $repository = $this->getRepository();
1339
1340
        $userService = $repository->getUserService();
1341
1342
        /* BEGIN: Use Case */
1343
        $this->createUserVersion1();
1344
1345
        // This call will fail with a "NotFoundException", because the given
1346
        // login/password combination does not exist.
1347
        $userService->loadUserByCredentials('üser', 'secret');
1348
        /* END: Use Case */
1349
    }
1350
1351
    /**
1352
     * Test for the loadUserByCredentials() method.
1353
     *
1354
     * @see \eZ\Publish\API\Repository\UserService::loadUserByCredentials()
1355
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByCredentials
1356
     */
1357
    public function testLoadUserByCredentialsThrowsInvalidArgumentValueForEmptyLogin()
1358
    {
1359
        $this->expectException(\eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue::class);
1360
1361
        $repository = $this->getRepository();
1362
1363
        $userService = $repository->getUserService();
1364
1365
        /* BEGIN: Use Case */
1366
        $this->createUserVersion1();
1367
1368
        // This call will fail with a "InvalidArgumentValue", because the given
1369
        // login is empty.
1370
        $userService->loadUserByCredentials('', 'secret');
1371
        /* END: Use Case */
1372
    }
1373
1374
    /**
1375
     * Test for the loadUserByLogin() method.
1376
     *
1377
     * @see \eZ\Publish\API\Repository\UserService::loadUserByLogin()
1378
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1379
     */
1380
    public function testLoadUserByLogin()
1381
    {
1382
        $repository = $this->getRepository();
1383
1384
        $userService = $repository->getUserService();
1385
1386
        /* BEGIN: Use Case */
1387
        $user = $this->createUserVersion1('User');
1388
1389
        // Load the newly created user
1390
        $userReloaded = $userService->loadUserByLogin('User');
1391
        /* END: Use Case */
1392
1393
        $this->assertPropertiesCorrect(
1394
            [
1395
                'login' => $user->login,
1396
                'email' => $user->email,
1397
                'passwordHash' => $user->passwordHash,
1398
                'hashAlgorithm' => $user->hashAlgorithm,
1399
                'enabled' => $user->enabled,
1400
                'maxLogin' => $user->maxLogin,
1401
                'id' => $user->id,
1402
                'contentInfo' => $user->contentInfo,
1403
                'versionInfo' => $user->versionInfo,
1404
                'fields' => $user->fields,
1405
            ],
1406
            $userReloaded
1407
        );
1408
    }
1409
1410
    /**
1411
     * Test for the loadUserByLogin() method.
1412
     *
1413
     * @see \eZ\Publish\API\Repository\UserService::loadUserByLogin()
1414
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByLogin
1415
     */
1416
    public function testLoadUserByLoginThrowsNotFoundExceptionForUnknownLogin()
1417
    {
1418
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1419
1420
        $repository = $this->getRepository();
1421
1422
        $userService = $repository->getUserService();
1423
1424
        /* BEGIN: Use Case */
1425
        $this->createUserVersion1();
1426
1427
        // This call will fail with a "NotFoundException", because the given
1428
        // login/password combination does not exist.
1429
        $userService->loadUserByLogin('user42');
1430
        /* END: Use Case */
1431
    }
1432
1433
    /**
1434
     * Test for the loadUserByLogin() method.
1435
     *
1436
     * @see \eZ\Publish\API\Repository\UserService::loadUserByLogin()
1437
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByLogin
1438
     */
1439
    public function testLoadUserByLoginWorksForLoginWithWrongCase()
1440
    {
1441
        $repository = $this->getRepository();
1442
1443
        $userService = $repository->getUserService();
1444
1445
        /* BEGIN: Use Case */
1446
        $user = $this->createUserVersion1();
1447
1448
        // Lookup by user login should ignore casing
1449
        $userReloaded = $userService->loadUserByLogin('USER');
1450
        /* END: Use Case */
1451
1452
        $this->assertPropertiesCorrect(
1453
            [
1454
                'login' => $user->login,
1455
                'email' => $user->email,
1456
                'passwordHash' => $user->passwordHash,
1457
                'hashAlgorithm' => $user->hashAlgorithm,
1458
                'enabled' => $user->enabled,
1459
                'maxLogin' => $user->maxLogin,
1460
                'id' => $user->id,
1461
                'contentInfo' => $user->contentInfo,
1462
                'versionInfo' => $user->versionInfo,
1463
                'fields' => $user->fields,
1464
            ],
1465
            $userReloaded
1466
        );
1467
    }
1468
1469
    /**
1470
     * Test for the loadUserByLogin() method.
1471
     *
1472
     * In some cases people use email as login name, make sure system works as exepcted when asking for user by email.
1473
     *
1474
     * @see \eZ\Publish\API\Repository\UserService::loadUserByLogin()
1475
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByLogin
1476
     */
1477
    public function testLoadUserByLoginThrowsNotFoundExceptionForUnknownLoginByEmail()
1478
    {
1479
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1480
1481
        $repository = $this->getRepository();
1482
1483
        $userService = $repository->getUserService();
1484
1485
        /* BEGIN: Use Case */
1486
        $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...
1487
1488
        // Lookup by user login by email should behave as normal
1489
        $userService->loadUserByLogin('[email protected]');
1490
        /* END: Use Case */
1491
    }
1492
1493
    /**
1494
     * Test for the loadUsersByEmail() method.
1495
     *
1496
     * @see \eZ\Publish\API\Repository\UserService::loadUsersByEmail()
1497
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1498
     */
1499
    public function testLoadUserByEmail()
1500
    {
1501
        $repository = $this->getRepository();
1502
1503
        $userService = $repository->getUserService();
1504
1505
        /* BEGIN: Use Case */
1506
        $user = $this->createUserVersion1();
1507
1508
        // Load the newly created user
1509
        $usersReloaded = $userService->loadUsersByEmail('[email protected]');
1510
        /* END: Use Case */
1511
1512
        $this->assertEquals([$user], $usersReloaded);
1513
    }
1514
1515
    /**
1516
     * Test for the loadUsersByEmail() method.
1517
     *
1518
     * @see \eZ\Publish\API\Repository\UserService::loadUsersByEmail()
1519
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByEmail
1520
     */
1521
    public function testLoadUserByEmailReturnsEmptyInUnknownEmail()
1522
    {
1523
        $repository = $this->getRepository();
1524
1525
        $userService = $repository->getUserService();
1526
1527
        /* BEGIN: Use Case */
1528
        $this->createUserVersion1();
1529
1530
        // This call will return empty array, because the given
1531
        // login/password combination does not exist.
1532
        $emptyUserList = $userService->loadUsersByEmail('[email protected]');
1533
        /* END: Use Case */
1534
1535
        $this->assertEquals([], $emptyUserList);
1536
    }
1537
1538
    /**
1539
     * Test for the deleteUser() method.
1540
     *
1541
     * @see \eZ\Publish\API\Repository\UserService::deleteUser()
1542
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1543
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUser
1544
     */
1545
    public function testDeleteUser()
1546
    {
1547
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
1548
1549
        $repository = $this->getRepository();
1550
1551
        $userService = $repository->getUserService();
1552
1553
        /* BEGIN: Use Case */
1554
        $user = $this->createUserVersion1();
1555
1556
        // Delete the currently created user
1557
        $userService->deleteUser($user);
1558
        /* END: Use Case */
1559
1560
        // We use the NotFoundException here to verify that the user not exists
1561
        $userService->loadUser($user->id);
1562
    }
1563
1564
    /**
1565
     * Test for the deleteUser() method.
1566
     *
1567
     * @covers \eZ\Publish\API\Repository\UserService::deleteUser()
1568
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1569
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUser
1570
     */
1571
    public function testDeleteUserDeletesRelatedBookmarks()
1572
    {
1573
        $repository = $this->getRepository();
1574
1575
        $userService = $repository->getUserService();
1576
        $locationService = $repository->getLocationService();
1577
        $bookmarkService = $repository->getBookmarkService();
1578
        /* BEGIN: Use Case */
1579
        $admin = $repository->getPermissionResolver()->getCurrentUserReference();
1580
1581
        $user = $this->createUserVersion1();
1582
1583
        $repository->getPermissionResolver()->setCurrentUserReference($user);
1584
1585
        $bookmarkService->createBookmark(
1586
            $locationService->loadLocation($this->generateId('location', 43))
1587
        );
1588
1589
        $repository->getPermissionResolver()->setCurrentUserReference($admin);
1590
        // Delete the currently created user
1591
        $userService->deleteUser($user);
1592
1593
        $repository->getPermissionResolver()->setCurrentUserReference($user);
1594
        /* END: Use Case */
1595
1596
        $this->assertEquals(0, $bookmarkService->loadBookmarks(0, 9999)->totalCount);
1597
    }
1598
1599
    /**
1600
     * Test for the newUserUpdateStruct() method.
1601
     *
1602
     * @see \eZ\Publish\API\Repository\UserService::newUserUpdateStruct()
1603
     */
1604
    public function testNewUserUpdateStruct()
1605
    {
1606
        $repository = $this->getRepository();
1607
1608
        /* BEGIN: Use Case */
1609
        $userService = $repository->getUserService();
1610
1611
        // Create a new update struct instance
1612
        $userUpdate = $userService->newUserUpdateStruct();
1613
        /* END: Use Case */
1614
1615
        $this->assertInstanceOf(
1616
            UserUpdateStruct::class,
1617
            $userUpdate
1618
        );
1619
1620
        $this->assertNull($userUpdate->contentUpdateStruct);
1621
        $this->assertNull($userUpdate->contentMetadataUpdateStruct);
1622
1623
        $this->assertPropertiesCorrect(
1624
            [
1625
                'email' => null,
1626
                'password' => null,
1627
                'enabled' => null,
1628
                'maxLogin' => null,
1629
            ],
1630
            $userUpdate
1631
        );
1632
    }
1633
1634
    /**
1635
     * Test for the updateUser() method.
1636
     *
1637
     * @return \eZ\Publish\API\Repository\Values\User\User
1638
     *
1639
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1640
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1641
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserUpdateStruct
1642
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1643
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
1644
     */
1645
    public function testUpdateUser()
1646
    {
1647
        $repository = $this->getRepository();
1648
1649
        $userService = $repository->getUserService();
1650
1651
        /* BEGIN: Use Case */
1652
        $user = $this->createUserVersion1();
1653
1654
        // Create a new update struct instance
1655
        $userUpdate = $userService->newUserUpdateStruct();
1656
1657
        // Set new values for password and maxLogin
1658
        $userUpdate->password = 'my-new-password';
1659
        $userUpdate->maxLogin = 42;
1660
        $userUpdate->enabled = false;
1661
1662
        // Updated the user record.
1663
        $userVersion2 = $userService->updateUser($user, $userUpdate);
1664
        /* END: Use Case */
1665
1666
        $this->assertInstanceOf(User::class, $userVersion2);
1667
1668
        return $userVersion2;
1669
    }
1670
1671
    /**
1672
     * Test for the updateUser() and loadUsersByEmail() method on change to email.
1673
     */
1674
    public function testUpdateUserEmail(): void
1675
    {
1676
        $repository = $this->getRepository();
1677
        $userService = $repository->getUserService();
1678
1679
        // Create a user
1680
        $user = $this->createUserVersion1();
1681
1682
        // Check we get what we expect (and implicit warmup any kind of cache)
1683
        $users = $userService->loadUsersByEmail('[email protected]');
1684
        $this->assertCount(0, $users);
1685
1686
        // Update user with the given email address
1687
        $userUpdate = $userService->newUserUpdateStruct();
1688
        $userUpdate->email = '[email protected]';
1689
        $updatedUser = $userService->updateUser($user, $userUpdate);
1690
        $this->assertInstanceOf(User::class, $updatedUser);
1691
1692
        // Check that we can load user by email
1693
        $users = $userService->loadUsersByEmail('[email protected]');
1694
        $this->assertCount(1, $users);
1695
        $this->assertInstanceOf(User::class, $users[0]);
1696
    }
1697
1698
    /**
1699
     * Test for the updateUser() method.
1700
     *
1701
     * @return \eZ\Publish\API\Repository\Values\User\User
1702
     *
1703
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1704
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
1705
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testNewUserUpdateStruct
1706
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1707
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
1708
     */
1709
    public function testUpdateUserNoPassword()
1710
    {
1711
        $repository = $this->getRepository();
1712
        $eventUserService = $repository->getUserService();
1713
1714
        $eventUserServiceReflection = new ReflectionClass($eventUserService);
1715
        $userServiceProperty = $eventUserServiceReflection->getProperty('innerService');
1716
        $userServiceProperty->setAccessible(true);
1717
        $userService = $userServiceProperty->getValue($eventUserService);
1718
1719
        $userServiceReflection = new ReflectionClass($userService);
1720
        $settingsProperty = $userServiceReflection->getProperty('settings');
1721
        $settingsProperty->setAccessible(true);
1722
        $settingsProperty->setValue(
1723
            $userService,
1724
            [
1725
                'hashType' => User::PASSWORD_HASH_MD5_USER,
0 ignored issues
show
Deprecated Code introduced by
The constant eZ\Publish\API\Repositor...:PASSWORD_HASH_MD5_USER has been deprecated with message: since 6.13

This class constant 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 constant will be removed from the class and what other constant to use instead.

Loading history...
1726
            ] + $settingsProperty->getValue($userService)
1727
        );
1728
1729
        /* BEGIN: Use Case */
1730
        $user = $this->createUserVersion1();
1731
1732
        $settingsProperty->setValue(
1733
            $userService,
1734
            [
1735
                'hashType' => User::PASSWORD_HASH_PHP_DEFAULT,
1736
            ] + $settingsProperty->getValue($userService)
1737
        );
1738
1739
        // Create a new update struct instance
1740
        $userUpdate = $userService->newUserUpdateStruct();
1741
1742
        // Set new values for maxLogin, don't change password
1743
        $userUpdate->maxLogin = 43;
1744
        $userUpdate->enabled = false;
1745
1746
        // Updated the user record.
1747
        $userVersion2 = $userService->updateUser($user, $userUpdate);
1748
        /* END: Use Case */
1749
1750
        $this->assertInstanceOf(User::class, $user);
1751
1752
        $this->assertEquals(
1753
            [
1754
                'login' => $user->login,
1755
                'email' => $user->email,
1756
                'passwordHash' => $user->passwordHash,
1757
                'hashAlgorithm' => $user->hashAlgorithm,
1758
                'maxLogin' => 43,
1759
                'enabled' => false,
1760
            ],
1761
            [
1762
                'login' => $userVersion2->login,
1763
                'email' => $userVersion2->email,
1764
                'passwordHash' => $userVersion2->passwordHash,
1765
                'hashAlgorithm' => $userVersion2->hashAlgorithm,
1766
                'maxLogin' => $userVersion2->maxLogin,
1767
                'enabled' => $userVersion2->enabled,
1768
            ]
1769
        );
1770
    }
1771
1772
    /**
1773
     * Test for the updateUser() method.
1774
     *
1775
     * @param \eZ\Publish\API\Repository\Values\User\User $user
1776
     *
1777
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1778
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1779
     */
1780
    public function testUpdateUserUpdatesExpectedProperties(User $user)
1781
    {
1782
        $this->assertEquals(
1783
            [
1784
                'login' => 'user',
1785
                'email' => '[email protected]',
1786
                'maxLogin' => 42,
1787
                'enabled' => false,
1788
            ],
1789
            [
1790
                'login' => $user->login,
1791
                'email' => $user->email,
1792
                'maxLogin' => $user->maxLogin,
1793
                'enabled' => $user->enabled,
1794
            ]
1795
        );
1796
    }
1797
1798
    /**
1799
     * Test for the updateUser() method.
1800
     *
1801
     * @param \eZ\Publish\API\Repository\Values\User\User $user
1802
     *
1803
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1804
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1805
     */
1806
    public function testUpdateUserReturnsPublishedVersion(User $user)
1807
    {
1808
        $this->assertEquals(
1809
            APIVersionInfo::STATUS_PUBLISHED,
1810
            $user->getVersionInfo()->status
1811
        );
1812
    }
1813
1814
    /**
1815
     * Test for the updateUser() method.
1816
     *
1817
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1818
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1819
     */
1820
    public function testUpdateUserWithContentMetadataUpdateStruct()
1821
    {
1822
        $repository = $this->getRepository();
1823
1824
        $userService = $repository->getUserService();
1825
1826
        /* BEGIN: Use Case */
1827
        $user = $this->createUserVersion1();
1828
1829
        // Get the ContentService implementation
1830
        $contentService = $repository->getContentService();
1831
1832
        // Create a metadata update struct and change the remote id.
1833
        $metadataUpdate = $contentService->newContentMetadataUpdateStruct();
1834
        $metadataUpdate->remoteId = '85e10037d1ac0a00aa75443ced483e08';
1835
1836
        // Create a new update struct instance
1837
        $userUpdate = $userService->newUserUpdateStruct();
1838
1839
        // Set the metadata update struct.
1840
        $userUpdate->contentMetadataUpdateStruct = $metadataUpdate;
1841
1842
        // Updated the user record.
1843
        $userVersion2 = $userService->updateUser($user, $userUpdate);
1844
1845
        // The contentInfo->remoteId will be changed now.
1846
        $remoteId = $userVersion2->contentInfo->remoteId;
1847
        /* END: Use Case */
1848
1849
        $this->assertEquals('85e10037d1ac0a00aa75443ced483e08', $remoteId);
1850
    }
1851
1852
    /**
1853
     * Test for the updateUser() method.
1854
     *
1855
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1856
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1857
     */
1858
    public function testUpdateUserWithContentUpdateStruct()
1859
    {
1860
        $repository = $this->getRepository();
1861
1862
        $userService = $repository->getUserService();
1863
1864
        /* BEGIN: Use Case */
1865
        $user = $this->createUserVersion1();
1866
1867
        // Get the ContentService implementation
1868
        $contentService = $repository->getContentService();
1869
1870
        // Create a content update struct and change the remote id.
1871
        $contentUpdate = $contentService->newContentUpdateStruct();
1872
        $contentUpdate->setField('first_name', 'Hello', 'eng-US');
1873
        $contentUpdate->setField('last_name', 'World', 'eng-US');
1874
1875
        // Create a new update struct instance
1876
        $userUpdate = $userService->newUserUpdateStruct();
1877
1878
        // Set the content update struct.
1879
        $userUpdate->contentUpdateStruct = $contentUpdate;
1880
1881
        // Updated the user record.
1882
        $userVersion2 = $userService->updateUser($user, $userUpdate);
1883
1884
        $name = sprintf(
1885
            '%s %s',
1886
            $userVersion2->getFieldValue('first_name'),
1887
            $userVersion2->getFieldValue('last_name')
1888
        );
1889
        /* END: Use Case */
1890
1891
        $this->assertEquals('Hello World', $name);
1892
    }
1893
1894
    /**
1895
     * Test for the updateUser() method.
1896
     *
1897
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1898
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1899
     */
1900
    public function testUpdateUserWhenMissingField()
1901
    {
1902
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException::class);
1903
1904
        $repository = $this->getRepository();
1905
1906
        $userService = $repository->getUserService();
1907
1908
        /* BEGIN: Use Case */
1909
        $user = $this->createUserVersion1();
1910
1911
        // Get the ContentService implementation
1912
        $contentService = $repository->getContentService();
1913
1914
        // Create a content update struct and change the remote id.
1915
        $contentUpdate = $contentService->newContentUpdateStruct();
1916
        $contentUpdate->setField('first_name', null, 'eng-US');
1917
1918
        // Create a new update struct instance
1919
        $userUpdate = $userService->newUserUpdateStruct();
1920
1921
        // Set the content update struct.
1922
        $userUpdate->contentUpdateStruct = $contentUpdate;
1923
1924
        // This call will fail with a "ContentFieldValidationException" because the
1925
        // mandatory field "first_name" is set to an empty value.
1926
        $userService->updateUser($user, $userUpdate);
1927
1928
        /* END: Use Case */
1929
    }
1930
1931
    /**
1932
     * Test for the updateUser() method.
1933
     *
1934
     * @see \eZ\Publish\API\Repository\UserService::updateUser()
1935
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUpdateUser
1936
     */
1937
    public function testUpdateUserThrowsInvalidArgumentExceptionOnFieldTypeNotAccept()
1938
    {
1939
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
1940
1941
        $repository = $this->getRepository();
1942
1943
        $userService = $repository->getUserService();
1944
1945
        /* BEGIN: Use Case */
1946
        $user = $this->createUserVersion1();
1947
1948
        // Get the ContentService implementation
1949
        $contentService = $repository->getContentService();
1950
1951
        $contentUpdate = $contentService->newContentUpdateStruct();
1952
        // An object of stdClass is not valid for the field first_name
1953
        $contentUpdate->setField('first_name', new \stdClass(), 'eng-US');
1954
1955
        // Create a new update struct instance
1956
        $userUpdate = $userService->newUserUpdateStruct();
1957
1958
        // Set the content update struct.
1959
        $userUpdate->contentUpdateStruct = $contentUpdate;
1960
1961
        // This call will fail with a "InvalidArgumentException" because the
1962
        // the field "first_name" does not accept the given value.
1963
        $userService->updateUser($user, $userUpdate);
1964
1965
        /* END: Use Case */
1966
    }
1967
1968
    /**
1969
     * Test updating a user throwing UserPasswordValidationException when password doesn't follow specified rules.
1970
     *
1971
     * @covers \eZ\Publish\API\Repository\UserService::updateUser
1972
     */
1973
    public function testUpdateUserWithWeakPasswordThrowsUserPasswordValidationException()
1974
    {
1975
        $this->expectException(\eZ\Publish\Core\Base\Exceptions\UserPasswordValidationException::class);
1976
        $this->expectExceptionMessage('Argument \'password\' is invalid: Password doesn\'t match the following rules: User password must be at least 8 characters long, User password must include at least one upper case letter, User password must include at least one number, User password must include at least one special character');
1977
1978
        $userService = $this->getRepository()->getUserService();
1979
1980
        $user = $this->createTestUserWithPassword('H@xxxiR!_1', $this->createUserContentTypeWithStrongPassword());
1981
1982
        /* BEGIN: Use Case */
1983
        // Create a new update struct instance
1984
        $userUpdate = $userService->newUserUpdateStruct();
1985
        $userUpdate->password = 'pass';
1986
1987
        // This call will fail with a "UserPasswordValidationException" because the
1988
        // the password does not follow specified rules
1989
        $userService->updateUser($user, $userUpdate);
1990
        /* END: Use Case */
1991
    }
1992
1993
    /**
1994
     * Opposite test case for testUpdateUserWithWeakPasswordThrowsUserPasswordValidationException.
1995
     *
1996
     * @covers \eZ\Publish\API\Repository\UserService::updateUser
1997
     */
1998
    public function testUpdateUserWithStrongPassword()
1999
    {
2000
        $userService = $this->getRepository()->getUserService();
2001
2002
        $user = $this->createTestUserWithPassword('H@xxxiR!_1', $this->createUserContentTypeWithStrongPassword());
2003
2004
        /* BEGIN: Use Case */
2005
        // Create a new update struct instance
2006
        $userUpdate = $userService->newUserUpdateStruct();
2007
        $userUpdate->password = 'H@xxxiR!_2';
2008
2009
        $user = $userService->updateUser($user, $userUpdate);
2010
        /* END: Use Case */
2011
2012
        $this->assertInstanceOf(User::class, $user);
2013
    }
2014
2015
    /**
2016
     * Test for the loadUserGroupsOfUser() method.
2017
     *
2018
     * @covers \eZ\Publish\API\Repository\UserService::loadUserGroupsOfUser
2019
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
2020
     */
2021
    public function testLoadUserGroupsOfUser()
2022
    {
2023
        $repository = $this->getRepository();
2024
2025
        $userService = $repository->getUserService();
2026
2027
        /* BEGIN: Use Case */
2028
        $user = $this->createUserVersion1();
2029
2030
        // This array will contain the "Editors" user group name
2031
        $userGroupNames = [];
2032
        foreach ($userService->loadUserGroupsOfUser($user) as $userGroup) {
2033
            $this->assertInstanceOf(UserGroup::class, $userGroup);
2034
            $userGroupNames[] = $userGroup->getFieldValue('name');
2035
        }
2036
        /* END: Use Case */
2037
2038
        $this->assertEquals(['Editors'], $userGroupNames);
2039
    }
2040
2041
    /**
2042
     * Test for the loadUsersOfUserGroup() method.
2043
     *
2044
     * @covers \eZ\Publish\API\Repository\UserService::loadUsersOfUserGroup
2045
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testCreateUser
2046
     */
2047
    public function testLoadUsersOfUserGroup()
2048
    {
2049
        $repository = $this->getRepository();
2050
        $userService = $repository->getUserService();
2051
2052
        $group = $userService->loadUserGroup($this->generateId('group', 13));
2053
2054
        /* BEGIN: Use Case */
2055
        $this->createUserVersion1();
2056
2057
        $this->refreshSearch($repository);
2058
2059
        // This array will contain the email of the newly created "Editor" user
2060
        $email = [];
2061
        foreach ($userService->loadUsersOfUserGroup($group) as $user) {
2062
            $this->assertInstanceOf(User::class, $user);
2063
            $email[] = $user->email;
2064
        }
2065
        /* END: Use Case */
2066
        $this->assertEquals(['[email protected]'], $email);
2067
    }
2068
2069
    /**
2070
     * Test for the assignUserToUserGroup() method.
2071
     *
2072
     * @see \eZ\Publish\API\Repository\UserService::assignUserToUserGroup()
2073
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroupsOfUser
2074
     */
2075
    public function testAssignUserToUserGroup()
2076
    {
2077
        $repository = $this->getRepository();
2078
        $userService = $repository->getUserService();
2079
2080
        $administratorGroupId = $this->generateId('group', 12);
2081
        /* BEGIN: Use Case */
2082
        // $administratorGroupId is the ID of the "Administrator" group in an
2083
        // eZ Publish demo installation
2084
2085
        $user = $this->createUserVersion1();
2086
2087
        // Assign group to newly created user
2088
        $userService->assignUserToUserGroup(
2089
            $user,
2090
            $userService->loadUserGroup($administratorGroupId)
2091
        );
2092
2093
        // This array will contain "Editors" and "Administrator users"
2094
        $userGroupNames = [];
2095
        foreach ($userService->loadUserGroupsOfUser($user) as $userGroup) {
2096
            $userGroupNames[] = $userGroup->getFieldValue('name');
2097
        }
2098
        /* END: Use Case */
2099
2100
        sort($userGroupNames, SORT_STRING);
2101
2102
        $this->assertEquals(
2103
            [
2104
                'Administrator users',
2105
                'Editors',
2106
            ],
2107
            $userGroupNames
2108
        );
2109
    }
2110
2111
    /**
2112
     * Test for the assignUserToUserGroup() method.
2113
     *
2114
     * @covers \eZ\Publish\API\Repository\UserService::assignUserToUserGroup
2115
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testAssignUserToUserGroup
2116
     */
2117
    public function testAssignUserToUserGroupThrowsInvalidArgumentException()
2118
    {
2119
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
2120
        $this->expectExceptionMessage('Argument \'user\' is invalid: user is already in the given user group');
2121
2122
        $repository = $this->getRepository();
2123
        $userService = $repository->getUserService();
2124
2125
        $editorsGroupId = $this->generateId('group', 13);
2126
        /* BEGIN: Use Case */
2127
        $user = $this->createUserVersion1();
2128
        // $editorsGroupId is the ID of the "Editors" group in an
2129
        // eZ Publish demo installation
2130
2131
        // This call will fail with an "InvalidArgumentException", because the
2132
        // user is already assigned to the "Editors" group
2133
        $userService->assignUserToUserGroup(
2134
            $user,
2135
            $userService->loadUserGroup($editorsGroupId)
2136
        );
2137
        /* END: Use Case */
2138
    }
2139
2140
    /**
2141
     * Test for the unAssignUssrFromUserGroup() method.
2142
     *
2143
     * @see \eZ\Publish\API\Repository\UserService::unAssignUssrFromUserGroup()
2144
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserGroupsOfUser
2145
     */
2146
    public function testUnAssignUserFromUserGroup()
2147
    {
2148
        $repository = $this->getRepository();
2149
        $userService = $repository->getUserService();
2150
2151
        $editorsGroupId = $this->generateId('group', 13);
2152
        $anonymousGroupId = $this->generateId('group', 42);
2153
2154
        /* BEGIN: Use Case */
2155
        // $anonymousGroupId is the ID of the "Anonymous Users" group in an eZ
2156
        // Publish demo installation
2157
2158
        $user = $this->createUserVersion1();
2159
2160
        // Assign group to newly created user
2161
        $userService->assignUserToUserGroup(
2162
            $user,
2163
            $userService->loadUserGroup($anonymousGroupId)
2164
        );
2165
2166
        // Unassign user from "Editors" group
2167
        $userService->unAssignUserFromUserGroup(
2168
            $user,
2169
            $userService->loadUserGroup($editorsGroupId)
2170
        );
2171
2172
        // This array will contain "Anonymous Users"
2173
        $userGroupNames = [];
2174
        foreach ($userService->loadUserGroupsOfUser($user) as $userGroup) {
2175
            $userGroupNames[] = $userGroup->getFieldValue('name');
2176
        }
2177
        /* END: Use Case */
2178
2179
        $this->assertEquals(['Anonymous Users'], $userGroupNames);
2180
    }
2181
2182
    /**
2183
     * Test for the unAssignUserFromUserGroup() method.
2184
     *
2185
     * @see \eZ\Publish\API\Repository\UserService::unAssignUserFromUserGroup()
2186
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUnAssignUserFromUserGroup
2187
     */
2188
    public function testUnAssignUserFromUserGroupThrowsInvalidArgumentException()
2189
    {
2190
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
2191
2192
        $repository = $this->getRepository();
2193
        $userService = $repository->getUserService();
2194
2195
        $administratorGroupId = $this->generateId('group', 12);
2196
        /* BEGIN: Use Case */
2197
        $user = $this->createUserVersion1();
2198
        // $administratorGroupId is the ID of the "Administrator" group in an
2199
        // eZ Publish demo installation
2200
2201
        // This call will fail with an "InvalidArgumentException", because the
2202
        // user is not assigned to the "Administrator" group
2203
        $userService->unAssignUserFromUserGroup(
2204
            $user,
2205
            $userService->loadUserGroup($administratorGroupId)
2206
        );
2207
        /* END: Use Case */
2208
    }
2209
2210
    /**
2211
     * Test for the unAssignUserFromUserGroup() method removing user from the last group.
2212
     *
2213
     * @covers \eZ\Publish\API\Repository\UserService::unAssignUserFromUserGroup
2214
     * @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testUnAssignUserFromUserGroup
2215
     */
2216
    public function testUnAssignUserFromUserGroupThrowsBadStateArgumentException()
2217
    {
2218
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\BadStateException::class);
2219
        $this->expectExceptionMessage('Argument \'user\' has a bad state: user only has one user group, cannot unassign from last group');
2220
2221
        $repository = $this->getRepository();
2222
        $userService = $repository->getUserService();
2223
2224
        $editorsGroupId = $this->generateId('group', 13);
2225
        /* BEGIN: Use Case */
2226
        $user = $this->createUserVersion1();
2227
2228
        // This call will fail with an "BadStateException", because the
2229
        // user has to be assigned to at least one group
2230
        $userService->unAssignUserFromUserGroup(
2231
            $user,
2232
            $userService->loadUserGroup($editorsGroupId)
2233
        );
2234
        /* END: Use Case */
2235
    }
2236
2237
    /**
2238
     * Test that multi-language logic for the loadUserGroup method respects prioritized language list.
2239
     *
2240
     * @covers \eZ\Publish\API\Repository\UserService::loadUserGroup
2241
     * @dataProvider getPrioritizedLanguageList
2242
     * @param string[] $prioritizedLanguages
2243
     * @param string|null $expectedLanguageCode language code of expected translation
2244
     */
2245
    public function testLoadUserGroupWithPrioritizedLanguagesList(
2246
        array $prioritizedLanguages,
2247
        $expectedLanguageCode
2248
    ) {
2249
        $repository = $this->getRepository();
2250
        $userService = $repository->getUserService();
2251
2252
        $userGroup = $this->createMultiLanguageUserGroup();
2253
        if ($expectedLanguageCode === null) {
2254
            $expectedLanguageCode = $userGroup->contentInfo->mainLanguageCode;
2255
        }
2256
2257
        $loadedUserGroup = $userService->loadUserGroup($userGroup->id, $prioritizedLanguages);
2258
2259
        self::assertEquals(
2260
            $loadedUserGroup->getName($expectedLanguageCode),
2261
            $loadedUserGroup->getName()
2262
        );
2263
        self::assertEquals(
2264
            $loadedUserGroup->getFieldValue('description', $expectedLanguageCode),
2265
            $loadedUserGroup->getFieldValue('description')
2266
        );
2267
    }
2268
2269
    /**
2270
     * Test that multi-language logic works correctly after updating user group main language.
2271
     *
2272
     * @covers \eZ\Publish\API\Repository\UserService::loadUserGroup
2273
     * @dataProvider getPrioritizedLanguageList
2274
     * @param string[] $prioritizedLanguages
2275
     * @param string|null $expectedLanguageCode language code of expected translation
2276
     */
2277
    public function testLoadUserGroupWithPrioritizedLanguagesListAfterMainLanguageUpdate(
2278
        array $prioritizedLanguages,
2279
        $expectedLanguageCode
2280
    ) {
2281
        $repository = $this->getRepository();
2282
        $userService = $repository->getUserService();
2283
        $contentService = $repository->getContentService();
2284
2285
        $userGroup = $this->createMultiLanguageUserGroup();
2286
2287
        $userGroupUpdateStruct = $userService->newUserGroupUpdateStruct();
2288
        $userGroupUpdateStruct->contentMetadataUpdateStruct = $contentService->newContentMetadataUpdateStruct();
2289
        $userGroupUpdateStruct->contentMetadataUpdateStruct->mainLanguageCode = 'eng-GB';
2290
        $userService->updateUserGroup($userGroup, $userGroupUpdateStruct);
2291
2292
        if ($expectedLanguageCode === null) {
2293
            $expectedLanguageCode = 'eng-GB';
2294
        }
2295
2296
        $loadedUserGroup = $userService->loadUserGroup($userGroup->id, $prioritizedLanguages);
2297
2298
        self::assertEquals(
2299
            $loadedUserGroup->getName($expectedLanguageCode),
2300
            $loadedUserGroup->getName()
2301
        );
2302
        self::assertEquals(
2303
            $loadedUserGroup->getFieldValue('description', $expectedLanguageCode),
2304
            $loadedUserGroup->getFieldValue('description')
2305
        );
2306
    }
2307
2308
    /**
2309
     * Test that multi-language logic for the loadSubUserGroups method respects prioritized language list.
2310
     *
2311
     * @covers \eZ\Publish\API\Repository\UserService::loadSubUserGroups
2312
     * @dataProvider getPrioritizedLanguageList
2313
     * @param string[] $prioritizedLanguages
2314
     * @param string|null $expectedLanguageCode language code of expected translation
2315
     */
2316
    public function testLoadSubUserGroupsWithPrioritizedLanguagesList(
2317
        array $prioritizedLanguages,
2318
        $expectedLanguageCode
2319
    ) {
2320
        $repository = $this->getRepository();
2321
        $userService = $repository->getUserService();
2322
2323
        // create main group for subgroups
2324
        $userGroup = $this->createMultiLanguageUserGroup(4);
2325
        if ($expectedLanguageCode === null) {
2326
            $expectedLanguageCode = $userGroup->contentInfo->mainLanguageCode;
2327
        }
2328
2329
        // create subgroups
2330
        $this->createMultiLanguageUserGroup($userGroup->id);
2331
        $this->createMultiLanguageUserGroup($userGroup->id);
2332
2333
        $userGroup = $userService->loadUserGroup($userGroup->id, $prioritizedLanguages);
2334
2335
        $subUserGroups = $userService->loadSubUserGroups($userGroup, 0, 2, $prioritizedLanguages);
2336
        foreach ($subUserGroups as $subUserGroup) {
2337
            self::assertEquals(
2338
                $subUserGroup->getName($expectedLanguageCode),
2339
                $subUserGroup->getName()
2340
            );
2341
            self::assertEquals(
2342
                $subUserGroup->getFieldValue('description', $expectedLanguageCode),
2343
                $subUserGroup->getFieldValue('description')
2344
            );
2345
        }
2346
    }
2347
2348
    /**
2349
     * Test that multi-language logic for the loadUser method respects prioritized language list.
2350
     *
2351
     * @covers \eZ\Publish\API\Repository\UserService::loadUser
2352
     * @dataProvider getPrioritizedLanguageList
2353
     * @param string[] $prioritizedLanguages
2354
     * @param string|null $expectedLanguageCode language code of expected translation
2355
     */
2356
    public function testLoadUserWithPrioritizedLanguagesList(
2357
        array $prioritizedLanguages,
2358
        $expectedLanguageCode
2359
    ) {
2360
        $repository = $this->getRepository();
2361
        $userService = $repository->getUserService();
2362
2363
        $user = $this->createMultiLanguageUser();
2364
        if ($expectedLanguageCode === null) {
2365
            $expectedLanguageCode = $user->contentInfo->mainLanguageCode;
2366
        }
2367
2368
        $loadedUser = $userService->loadUser($user->id, $prioritizedLanguages);
2369
2370
        self::assertEquals(
2371
            $loadedUser->getName($expectedLanguageCode),
2372
            $loadedUser->getName()
2373
        );
2374
2375
        foreach (['fist_name', 'last_name', 'signature'] as $fieldIdentifier) {
2376
            self::assertEquals(
2377
                $loadedUser->getFieldValue($fieldIdentifier, $expectedLanguageCode),
2378
                $loadedUser->getFieldValue($fieldIdentifier)
2379
            );
2380
        }
2381
    }
2382
2383
    /**
2384
     * Test that multi-language logic for the loadUser method works correctly after updating
2385
     * user content main language.
2386
     *
2387
     * @covers \eZ\Publish\API\Repository\UserService::loadUserGroup
2388
     * @dataProvider getPrioritizedLanguageList
2389
     * @param string[] $prioritizedLanguages
2390
     * @param string|null $expectedLanguageCode language code of expected translation
2391
     */
2392
    public function testLoadUserWithPrioritizedLanguagesListAfterMainLanguageUpdate(
2393
        array $prioritizedLanguages,
2394
        $expectedLanguageCode
2395
    ) {
2396
        $repository = $this->getRepository();
2397
        $userService = $repository->getUserService();
2398
        $contentService = $repository->getContentService();
2399
2400
        $user = $this->createMultiLanguageUser();
2401
        // sanity check
2402
        self::assertEquals($user->contentInfo->mainLanguageCode, 'eng-US');
2403
2404
        $userUpdateStruct = $userService->newUserUpdateStruct();
2405
        $userUpdateStruct->contentMetadataUpdateStruct = $contentService->newContentMetadataUpdateStruct();
2406
        $userUpdateStruct->contentMetadataUpdateStruct->mainLanguageCode = 'eng-GB';
2407
        $userService->updateUser($user, $userUpdateStruct);
2408
        if ($expectedLanguageCode === null) {
2409
            $expectedLanguageCode = 'eng-GB';
2410
        }
2411
2412
        $loadedUser = $userService->loadUser($user->id, $prioritizedLanguages);
2413
2414
        self::assertEquals(
2415
            $loadedUser->getName($expectedLanguageCode),
2416
            $loadedUser->getName()
2417
        );
2418
2419
        foreach (['fist_name', 'last_name', 'signature'] as $fieldIdentifier) {
2420
            self::assertEquals(
2421
                $loadedUser->getFieldValue($fieldIdentifier, $expectedLanguageCode),
2422
                $loadedUser->getFieldValue($fieldIdentifier)
2423
            );
2424
        }
2425
    }
2426
2427
    /**
2428
     * Test that multi-language logic for the loadUserByLogin method respects prioritized language list.
2429
     *
2430
     * @covers \eZ\Publish\API\Repository\UserService::loadUserByLogin
2431
     * @dataProvider getPrioritizedLanguageList
2432
     * @param string[] $prioritizedLanguages
2433
     * @param string|null $expectedLanguageCode language code of expected translation
2434
     */
2435
    public function testLoadUserByLoginWithPrioritizedLanguagesList(
2436
        array $prioritizedLanguages,
2437
        $expectedLanguageCode
2438
    ) {
2439
        $repository = $this->getRepository();
2440
        $userService = $repository->getUserService();
2441
        $user = $this->createMultiLanguageUser();
2442
2443
        // load, with prioritized languages, the newly created user
2444
        $loadedUser = $userService->loadUserByLogin($user->login, $prioritizedLanguages);
2445
        if ($expectedLanguageCode === null) {
2446
            $expectedLanguageCode = $loadedUser->contentInfo->mainLanguageCode;
2447
        }
2448
2449
        self::assertEquals(
2450
            $loadedUser->getName($expectedLanguageCode),
2451
            $loadedUser->getName()
2452
        );
2453
2454
        foreach (['first_name', 'last_name', 'signature'] as $fieldIdentifier) {
2455
            self::assertEquals(
2456
                $loadedUser->getFieldValue($fieldIdentifier, $expectedLanguageCode),
2457
                $loadedUser->getFieldValue($fieldIdentifier)
2458
            );
2459
        }
2460
    }
2461
2462
    /**
2463
     * Test that multi-language logic for the loadUserByCredentials method respects
2464
     * prioritized language list.
2465
     *
2466
     * @covers \eZ\Publish\API\Repository\UserService::loadUserByCredentials
2467
     * @dataProvider getPrioritizedLanguageList
2468
     * @param string[] $prioritizedLanguages
2469
     * @param string|null $expectedLanguageCode language code of expected translation
2470
     */
2471
    public function testLoadUserByCredentialsWithPrioritizedLanguagesList(
2472
        array $prioritizedLanguages,
2473
        $expectedLanguageCode
2474
    ) {
2475
        $repository = $this->getRepository();
2476
        $userService = $repository->getUserService();
2477
        $user = $this->createMultiLanguageUser();
2478
2479
        // load, with prioritized languages, the newly created user
2480
        $loadedUser = $userService->loadUserByCredentials(
2481
            $user->login,
2482
            'secret',
2483
            $prioritizedLanguages
2484
        );
2485
        if ($expectedLanguageCode === null) {
2486
            $expectedLanguageCode = $loadedUser->contentInfo->mainLanguageCode;
2487
        }
2488
2489
        self::assertEquals(
2490
            $loadedUser->getName($expectedLanguageCode),
2491
            $loadedUser->getName()
2492
        );
2493
2494
        foreach (['first_name', 'last_name', 'signature'] as $fieldIdentifier) {
2495
            self::assertEquals(
2496
                $loadedUser->getFieldValue($fieldIdentifier, $expectedLanguageCode),
2497
                $loadedUser->getFieldValue($fieldIdentifier)
2498
            );
2499
        }
2500
    }
2501
2502
    /**
2503
     * Test that multi-language logic for the loadUsersByEmail method respects
2504
     * prioritized language list.
2505
     *
2506
     * @covers \eZ\Publish\API\Repository\UserService::loadUsersByEmail
2507
     * @dataProvider getPrioritizedLanguageList
2508
     * @param string[] $prioritizedLanguages
2509
     * @param string|null $expectedLanguageCode language code of expected translation
2510
     */
2511
    public function testLoadUsersByEmailWithPrioritizedLanguagesList(
2512
        array $prioritizedLanguages,
2513
        $expectedLanguageCode
2514
    ) {
2515
        $repository = $this->getRepository();
2516
        $userService = $repository->getUserService();
2517
        $user = $this->createMultiLanguageUser();
2518
2519
        // load, with prioritized languages, users by email
2520
        $loadedUsers = $userService->loadUsersByEmail($user->email, $prioritizedLanguages);
2521
2522
        foreach ($loadedUsers as $loadedUser) {
2523
            if ($expectedLanguageCode === null) {
2524
                $expectedLanguageCode = $loadedUser->contentInfo->mainLanguageCode;
2525
            }
2526
            self::assertEquals(
2527
                $loadedUser->getName($expectedLanguageCode),
2528
                $loadedUser->getName()
2529
            );
2530
2531
            foreach (['first_name', 'last_name', 'signature'] as $fieldIdentifier) {
2532
                self::assertEquals(
2533
                    $loadedUser->getFieldValue($fieldIdentifier, $expectedLanguageCode),
2534
                    $loadedUser->getFieldValue($fieldIdentifier)
2535
                );
2536
            }
2537
        }
2538
    }
2539
2540
    /**
2541
     * Test that multi-language logic for the loadUserGroupsOfUser method respects
2542
     * prioritized language list.
2543
     *
2544
     * @covers \eZ\Publish\API\Repository\UserService::loadUserGroupsOfUser
2545
     * @dataProvider getPrioritizedLanguageList
2546
     * @param string[] $prioritizedLanguages
2547
     * @param string|null $expectedLanguageCode language code of expected translation
2548
     */
2549
    public function testLoadUserGroupsOfUserWithPrioritizedLanguagesList(
2550
        array $prioritizedLanguages,
2551
        $expectedLanguageCode
2552
    ) {
2553
        $repository = $this->getRepository();
2554
        $userService = $repository->getUserService();
2555
        $userGroup = $this->createMultiLanguageUserGroup();
2556
        $user = $this->createMultiLanguageUser($userGroup->id);
2557
2558
        $userGroups = $userService->loadUserGroupsOfUser($user, 0, 25, $prioritizedLanguages);
2559
        foreach ($userGroups as $userGroup) {
2560
            self::assertEquals(
2561
                $userGroup->getName($expectedLanguageCode),
2562
                $userGroup->getName()
2563
            );
2564
            self::assertEquals(
2565
                $userGroup->getFieldValue('description', $expectedLanguageCode),
2566
                $userGroup->getFieldValue('description')
2567
            );
2568
        }
2569
    }
2570
2571
    /**
2572
     * Test that multi-language logic for the loadUsersOfUserGroup method respects
2573
     * prioritized language list.
2574
     *
2575
     * @covers \eZ\Publish\API\Repository\UserService::loadUsersOfUserGroup
2576
     * @dataProvider getPrioritizedLanguageList
2577
     * @param string[] $prioritizedLanguages
2578
     * @param string|null $expectedLanguageCode language code of expected translation
2579
     */
2580
    public function testLoadUsersOfUserGroupWithPrioritizedLanguagesList(
2581
        array $prioritizedLanguages,
2582
        $expectedLanguageCode
2583
    ) {
2584
        $repository = $this->getRepository();
2585
        $userService = $repository->getUserService();
2586
2587
        // create parent user group
2588
        $userGroup = $this->createMultiLanguageUserGroup();
2589
        // add two users to the created parent user group
2590
        $this->createMultiLanguageUser($userGroup->id);
2591
        $this->createMultiLanguageUser($userGroup->id);
2592
2593
        // test loading of users via user group with prioritized languages list
2594
        $users = $userService->loadUsersOfUserGroup($userGroup, 0, 25, $prioritizedLanguages);
2595
        foreach ($users as $user) {
2596
            if ($expectedLanguageCode === null) {
2597
                $expectedLanguageCode = $user->contentInfo->mainLanguageCode;
2598
            }
2599
            self::assertEquals(
2600
                $user->getName($expectedLanguageCode),
2601
                $user->getName()
2602
            );
2603
2604
            foreach (['first_name', 'last_name', 'signature'] as $fieldIdentifier) {
2605
                self::assertEquals(
2606
                    $user->getFieldValue($fieldIdentifier, $expectedLanguageCode),
2607
                    $user->getFieldValue($fieldIdentifier)
2608
                );
2609
            }
2610
        }
2611
    }
2612
2613
    /**
2614
     * Get prioritized languages list data.
2615
     *
2616
     * Test cases using this data provider should expect the following arguments:
2617
     * <code>
2618
     *   array $prioritizedLanguagesList
2619
     *   string $expectedLanguage (if null - use main language)
2620
     * </code>
2621
     *
2622
     * @return array
2623
     */
2624
    public function getPrioritizedLanguageList()
2625
    {
2626
        return [
2627
            [[], null],
2628
            [['eng-US'], 'eng-US'],
2629
            [['eng-GB'], 'eng-GB'],
2630
            [['eng-US', 'eng-GB'], 'eng-US'],
2631
            [['eng-GB', 'eng-US'], 'eng-GB'],
2632
            // use non-existent group as the first one
2633
            [['ger-DE'], null],
2634
            [['ger-DE', 'eng-GB'], 'eng-GB'],
2635
        ];
2636
    }
2637
2638
    /**
2639
     * @param int $parentGroupId
2640
     * @return \eZ\Publish\API\Repository\Values\User\UserGroup
2641
     */
2642
    private function createMultiLanguageUserGroup($parentGroupId = 4)
2643
    {
2644
        $repository = $this->getRepository();
2645
        $userService = $repository->getUserService();
2646
2647
        // create user group with multiple translations
2648
        $parentGroupId = $this->generateId('group', $parentGroupId);
2649
        $parentGroup = $userService->loadUserGroup($parentGroupId);
2650
2651
        $userGroupCreateStruct = $userService->newUserGroupCreateStruct('eng-US');
2652
        $userGroupCreateStruct->setField('name', 'US user group', 'eng-US');
2653
        $userGroupCreateStruct->setField('name', 'GB user group', 'eng-GB');
2654
        $userGroupCreateStruct->setField('description', 'US user group description', 'eng-US');
2655
        $userGroupCreateStruct->setField('description', 'GB user group description', 'eng-GB');
2656
        $userGroupCreateStruct->alwaysAvailable = true;
2657
2658
        return $userService->createUserGroup($userGroupCreateStruct, $parentGroup);
2659
    }
2660
2661
    /**
2662
     * Create a user group fixture in a variable named <b>$userGroup</b>,.
2663
     *
2664
     * @return \eZ\Publish\API\Repository\Values\User\UserGroup
2665
     */
2666
    private function createUserGroupVersion1()
2667
    {
2668
        $repository = $this->getRepository();
2669
2670
        $mainGroupId = $this->generateId('group', 4);
2671
        /* BEGIN: Inline */
2672
        // $mainGroupId is the ID of the main "Users" group
2673
2674
        $userService = $repository->getUserService();
2675
2676
        // Load main group
2677
        $parentUserGroup = $userService->loadUserGroup($mainGroupId);
2678
2679
        // Instantiate a new create struct
2680
        $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
2681
        $userGroupCreate->setField('name', 'Example Group');
2682
2683
        // Create the new user group
2684
        $userGroup = $userService->createUserGroup(
2685
            $userGroupCreate,
2686
            $parentUserGroup
2687
        );
2688
        /* END: Inline */
2689
2690
        return $userGroup;
2691
    }
2692
2693
    /**
2694
     * Create user with multiple translations of User Content fields.
2695
     *
2696
     * @param int $userGroupId User group ID (default 13 - Editors)
2697
     *
2698
     * @return \eZ\Publish\API\Repository\Values\User\User
2699
     */
2700
    private function createMultiLanguageUser($userGroupId = 13)
2701
    {
2702
        $repository = $this->getRepository();
2703
        $userService = $repository->getUserService();
2704
2705
        // Instantiate a create struct with mandatory properties
2706
        $randomLogin = md5(mt_rand() . time());
2707
        $userCreateStruct = $userService->newUserCreateStruct(
2708
            $randomLogin,
2709
            "{$randomLogin}@example.com",
2710
            'secret',
2711
            'eng-US'
2712
        );
2713
        $userCreateStruct->enabled = true;
2714
        $userCreateStruct->alwaysAvailable = true;
2715
2716
        // set field for each language
2717
        foreach (['eng-US', 'eng-GB'] as $languageCode) {
2718
            $userCreateStruct->setField('first_name', "{$languageCode} Example", $languageCode);
2719
            $userCreateStruct->setField('last_name', "{$languageCode} User", $languageCode);
2720
            $userCreateStruct->setField('signature', "{$languageCode} signature", $languageCode);
2721
        }
2722
2723
        // Load parent group for the user
2724
        $group = $userService->loadUserGroup($userGroupId);
2725
2726
        // Create a new user
2727
        return $userService->createUser($userCreateStruct, [$group]);
2728
    }
2729
2730
    /**
2731
     * Test for the createUser() method.
2732
     *
2733
     * @see \eZ\Publish\API\Repository\UserService::createUser()
2734
     */
2735
    public function testCreateUserInvalidPasswordHashTypeThrowsException()
2736
    {
2737
        $this->expectException(InvalidArgumentException::class);
2738
        $this->expectExceptionMessage("Argument 'type' is invalid: Password hash type '42424242' is not recognized");
2739
2740
        $repository = $this->getRepository();
2741
        $eventUserService = $repository->getUserService();
2742
2743
        $eventUserServiceReflection = new ReflectionClass($eventUserService);
2744
        $userServiceProperty = $eventUserServiceReflection->getProperty('innerService');
2745
        $userServiceProperty->setAccessible(true);
2746
        $userService = $userServiceProperty->getValue($eventUserService);
2747
2748
        $userServiceReflection = new ReflectionClass($userService);
2749
        $settingsProperty = $userServiceReflection->getProperty('settings');
2750
        $settingsProperty->setAccessible(true);
2751
2752
        $defaultUserServiceSettings = $settingsProperty->getValue($userService);
2753
2754
        /* BEGIN: Use Case */
2755
        $settingsProperty->setValue(
2756
            $userService,
2757
            [
2758
                'hashType' => 42424242, // Non-existing hash type
2759
            ] + $settingsProperty->getValue($userService)
2760
        );
2761
2762
        try {
2763
            $this->createUserVersion1();
2764
        } catch (InvalidArgumentException $e) {
2765
            // Reset to default settings, so we don't break other tests
2766
            $settingsProperty->setValue($userService, $defaultUserServiceSettings);
2767
2768
            throw $e;
2769
        }
2770
        /* END: Use Case */
2771
2772
        // Reset to default settings, so we don't break other tests
2773
        $settingsProperty->setValue($userService, $defaultUserServiceSettings);
2774
    }
2775
2776
    /**
2777
     * Test loading User by Token.
2778
     *
2779
     * @covers \eZ\Publish\API\Repository\UserService::loadUserByToken
2780
     */
2781
    public function testLoadUserByToken()
2782
    {
2783
        $repository = $this->getRepository();
2784
        $userService = $repository->getUserService();
2785
2786
        $user = $this->createUserVersion1();
2787
2788
        $userTokenUpdateStruct = new UserTokenUpdateStruct();
2789
        $userTokenUpdateStruct->hashKey = md5('hash');
2790
        $userTokenUpdateStruct->time = new DateTime();
2791
2792
        $userService->updateUserToken($user, $userTokenUpdateStruct);
2793
2794
        $loadedUser = $userService->loadUserByToken($userTokenUpdateStruct->hashKey);
2795
        self::assertEquals($user, $loadedUser);
2796
2797
        return $userTokenUpdateStruct->hashKey;
2798
    }
2799
2800
    /**
2801
     * Test trying to load User by invalid Token.
2802
     *
2803
     * @covers \eZ\Publish\API\Repository\UserService::loadUserByToken
2804
     */
2805
    public function testLoadUserByTokenThrowsNotFoundException()
2806
    {
2807
        $this->expectException(NotFoundException::class);
2808
2809
        $repository = $this->getRepository();
2810
        $userService = $repository->getUserService();
2811
2812
        $user = $this->createUserVersion1();
2813
2814
        $userTokenUpdateStruct = new UserTokenUpdateStruct();
2815
        $userTokenUpdateStruct->hashKey = md5('hash');
2816
        $userTokenUpdateStruct->time = new DateTime();
2817
2818
        $userService->updateUserToken($user, $userTokenUpdateStruct);
2819
2820
        $userService->loadUserByToken('not_existing_token');
2821
    }
2822
2823
    /**
2824
     * Test updating User Token.
2825
     *
2826
     * @covers \eZ\Publish\API\Repository\UserService::updateUserToken()
2827
     *
2828
     * @depends testLoadUserByToken
2829
     *
2830
     * @param string $originalUserToken
2831
     */
2832
    public function testUpdateUserToken($originalUserToken)
2833
    {
2834
        $repository = $this->getRepository(false);
2835
        $userService = $repository->getUserService();
2836
2837
        $user = $userService->loadUserByToken($originalUserToken);
2838
2839
        $userTokenUpdateStruct = new UserTokenUpdateStruct();
2840
        $userTokenUpdateStruct->hashKey = md5('my_updated_hash');
2841
        $userTokenUpdateStruct->time = new DateTime();
2842
2843
        $userService->updateUserToken($user, $userTokenUpdateStruct);
2844
2845
        $loadedUser = $userService->loadUserByToken($userTokenUpdateStruct->hashKey);
2846
        self::assertEquals($user, $loadedUser);
2847
    }
2848
2849
    /**
2850
     * Test invalidating (expiring) User Token.
2851
     *
2852
     * @covers \eZ\Publish\API\Repository\UserService::expireUserToken()
2853
     *
2854
     * @depends testLoadUserByToken
2855
     *
2856
     * @param string $userToken
2857
     */
2858
    public function testExpireUserToken($userToken)
2859
    {
2860
        $this->expectException(NotFoundException::class);
2861
2862
        $repository = $this->getRepository(false);
2863
        $userService = $repository->getUserService();
2864
2865
        // sanity check
2866
        $userService->loadUserByToken($userToken);
2867
2868
        $userService->expireUserToken($userToken);
2869
2870
        // should throw NotFoundException now
2871
        $userService->loadUserByToken($userToken);
2872
    }
2873
2874
    /**
2875
     * @covers \eZ\Publish\API\Repository\UserService::validatePassword()
2876
     */
2877
    public function testValidatePasswordWithDefaultContext()
2878
    {
2879
        $userService = $this->getRepository()->getUserService();
2880
2881
        /* BEGIN: Use Case */
2882
        $errors = $userService->validatePassword('pass');
2883
        /* END: Use Case */
2884
2885
        $this->assertEmpty($errors);
2886
    }
2887
2888
    /**
2889
     * @covers \eZ\Publish\API\Repository\UserService::validatePassword()
2890
     * @dataProvider dataProviderForValidatePassword
2891
     */
2892
    public function testValidatePassword(string $password, array $expectedErrorr)
2893
    {
2894
        $userService = $this->getRepository()->getUserService();
2895
        $contentType = $this->createUserContentTypeWithStrongPassword();
2896
2897
        /* BEGIN: Use Case */
2898
        $context = new PasswordValidationContext([
2899
            'contentType' => $contentType,
2900
        ]);
2901
2902
        $actualErrors = $userService->validatePassword($password, $context);
2903
        /* END: Use Case */
2904
2905
        $this->assertEquals($expectedErrorr, $actualErrors);
2906
    }
2907
2908
    /**
2909
     * Data provider for testValidatePassword.
2910
     *
2911
     * @return array
2912
     */
2913
    public function dataProviderForValidatePassword(): array
2914
    {
2915
        return [
2916
            [
2917
                'pass',
2918
                [
2919
                    new ValidationError('User password must be at least %length% characters long', null, [
2920
                        '%length%' => 8,
2921
                    ], 'password'),
2922
                    new ValidationError('User password must include at least one upper case letter', null, [], 'password'),
2923
                    new ValidationError('User password must include at least one number', null, [], 'password'),
2924
                    new ValidationError('User password must include at least one special character', null, [], 'password'),
2925
                ],
2926
            ],
2927
            [
2928
                'H@xxxi0R!!!',
2929
                [],
2930
            ],
2931
        ];
2932
    }
2933
2934
    public function testGetPasswordInfo(): void
2935
    {
2936
        $userService = $this->getRepository()->getUserService();
2937
        $contentType = $this->createUserContentTypeWithPasswordExpirationDate(
2938
            self::EXAMPLE_PASSWORD_TTL,
2939
            self::EXAMPLE_PASSWORD_TTL_WARNING
2940
        );
2941
2942
        $user = $this->createTestUser($contentType);
2943
2944
        /* BEGIN: Use Case */
2945
        $passwordInfo = $userService->getPasswordInfo($user);
2946
        /* END: Use Case */
2947
2948
        $passwordUpdatedAt = $user->passwordUpdatedAt;
2949
        if ($passwordUpdatedAt instanceof DateTime) {
2950
            $passwordUpdatedAt = DateTimeImmutable::createFromFormat(DateTime::ATOM, $passwordUpdatedAt->format(DateTime::ATOM));
2951
        }
2952
2953
        $expectedPasswordExpirationDate = $passwordUpdatedAt->add(
2954
            new DateInterval(sprintf('P%dD', self::EXAMPLE_PASSWORD_TTL))
2955
        );
2956
2957
        $expectedPasswordExpirationWarningDate = $passwordUpdatedAt->add(
2958
            new DateInterval(sprintf('P%dD', self::EXAMPLE_PASSWORD_TTL - self::EXAMPLE_PASSWORD_TTL_WARNING))
2959
        );
2960
2961
        $this->assertEquals(new PasswordInfo(
2962
            $expectedPasswordExpirationDate,
2963
            $expectedPasswordExpirationWarningDate
2964
        ), $passwordInfo);
2965
    }
2966
2967
    public function testGetPasswordInfoIfExpirationIsDisabled(): void
2968
    {
2969
        $userService = $this->getRepository()->getUserService();
2970
        $contentType = $this->createUserContentTypeWithPasswordExpirationDate(null, null);
2971
2972
        $user = $this->createTestUser($contentType);
2973
2974
        /* BEGIN: Use Case */
2975
        $passwordInfo = $userService->getPasswordInfo($user);
2976
        /* END: Use Case */
2977
2978
        $this->assertEquals(new PasswordInfo(), $passwordInfo);
2979
    }
2980
2981
    public function testGetPasswordInfoIfExpirationWarningIsDisabled(): void
2982
    {
2983
        $userService = $this->getRepository()->getUserService();
2984
        $contentType = $this->createUserContentTypeWithPasswordExpirationDate(self::EXAMPLE_PASSWORD_TTL, null);
2985
2986
        $user = $this->createTestUser($contentType);
2987
2988
        /* BEGIN: Use Case */
2989
        $passwordInfo = $userService->getPasswordInfo($user);
2990
        /* END: Use Case */
2991
2992
        $passwordUpdatedAt = $user->passwordUpdatedAt;
2993
        if ($passwordUpdatedAt instanceof DateTime) {
2994
            $passwordUpdatedAt = DateTimeImmutable::createFromFormat(DateTime::ATOM, $passwordUpdatedAt->format(DateTime::ATOM));
2995
        }
2996
2997
        $expectedPasswordExpirationDate = $passwordUpdatedAt->add(
2998
            new DateInterval(sprintf('P%dD', self::EXAMPLE_PASSWORD_TTL))
2999
        );
3000
3001
        $this->assertEquals(new PasswordInfo($expectedPasswordExpirationDate, null), $passwordInfo);
3002
    }
3003
3004
    public function createTestUser(ContentType $contentType): User
3005
    {
3006
        return $this->createTestUserWithPassword(self::EXAMPLE_PASSWORD, $contentType);
3007
    }
3008
3009
    /**
3010
     * Creates a user with given password.
3011
     *
3012
     * @param string $password
3013
     * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType
3014
     *
3015
     * @return \eZ\Publish\API\Repository\Values\User\User
3016
     */
3017
    private function createTestUserWithPassword(string $password, ContentType $contentType): User
3018
    {
3019
        $userService = $this->getRepository()->getUserService();
3020
        // ID of the "Editors" user group in an eZ Publish demo installation
3021
        $editorsGroupId = 13;
3022
3023
        // Instantiate a create struct with mandatory properties
3024
        $userCreate = $userService->newUserCreateStruct(
3025
            'johndoe',
3026
            '[email protected]',
3027
            $password,
3028
            'eng-US',
3029
            $contentType
3030
        );
3031
        $userCreate->enabled = true;
3032
        $userCreate->setField('first_name', 'John');
3033
        $userCreate->setField('last_name', 'Doe');
3034
3035
        return $userService->createUser($userCreate, [
3036
            $userService->loadUserGroup($editorsGroupId),
3037
        ]);
3038
    }
3039
3040
    /**
3041
     * Creates the User Content Type with password constraints.
3042
     *
3043
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
3044
     */
3045
    private function createUserContentTypeWithStrongPassword(): ContentType
3046
    {
3047
        return $this->createUserContentTypeWithAccountSettings('user-with-strong-password', null, [
3048
            'PasswordValueValidator' => [
3049
                'requireAtLeastOneUpperCaseCharacter' => 1,
3050
                'requireAtLeastOneLowerCaseCharacter' => 1,
3051
                'requireAtLeastOneNumericCharacter' => 1,
3052
                'requireAtLeastOneNonAlphanumericCharacter' => 1,
3053
                'minLength' => 8,
3054
            ],
3055
        ]);
3056
    }
3057
3058
    private function createUserContentTypeWithPasswordExpirationDate(
3059
        ?int $passwordTTL = self::EXAMPLE_PASSWORD_TTL,
3060
        ?int $passwordTTLWarning = self::EXAMPLE_PASSWORD_TTL_WARNING
3061
    ): ContentType {
3062
        return $this->createUserContentTypeWithAccountSettings('password-expiration', [
3063
            'PasswordTTL' => $passwordTTL,
3064
            'PasswordTTLWarning' => $passwordTTLWarning,
3065
        ]);
3066
    }
3067
3068
    private function createUserContentTypeWithAccountSettings(
3069
        string $identifier,
3070
        ?array $fieldSetting = null,
3071
        ?array $validatorConfiguration = null
3072
    ): ContentType {
3073
        $repository = $this->getRepository();
3074
3075
        $contentTypeService = $repository->getContentTypeService();
3076
3077
        $typeCreate = $contentTypeService->newContentTypeCreateStruct($identifier);
3078
        $typeCreate->mainLanguageCode = 'eng-GB';
3079
        $typeCreate->urlAliasSchema = 'url|scheme';
3080
        $typeCreate->nameSchema = 'name|scheme';
3081
        $typeCreate->names = [
3082
            'eng-GB' => 'User: ' . $identifier,
3083
        ];
3084
        $typeCreate->descriptions = [
3085
            'eng-GB' => '',
3086
        ];
3087
        $typeCreate->creatorId = $this->generateId('user', $repository->getPermissionResolver()->getCurrentUserReference()->getUserId());
3088
        $typeCreate->creationDate = $this->createDateTime();
3089
3090
        $firstNameFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('first_name', 'ezstring');
3091
        $firstNameFieldCreate->names = [
3092
            'eng-GB' => 'First name',
3093
        ];
3094
        $firstNameFieldCreate->descriptions = [
3095
            'eng-GB' => '',
3096
        ];
3097
        $firstNameFieldCreate->fieldGroup = 'default';
3098
        $firstNameFieldCreate->position = 1;
3099
        $firstNameFieldCreate->isTranslatable = false;
3100
        $firstNameFieldCreate->isRequired = true;
3101
        $firstNameFieldCreate->isInfoCollector = false;
3102
        $firstNameFieldCreate->validatorConfiguration = [
3103
            'StringLengthValidator' => [
3104
                'minStringLength' => 0,
3105
                'maxStringLength' => 0,
3106
            ],
3107
        ];
3108
        $firstNameFieldCreate->fieldSettings = [];
3109
        $firstNameFieldCreate->isSearchable = true;
3110
        $firstNameFieldCreate->defaultValue = '';
3111
3112
        $typeCreate->addFieldDefinition($firstNameFieldCreate);
3113
3114
        $lastNameFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct('last_name', 'ezstring');
3115
        $lastNameFieldCreate->names = [
3116
            'eng-GB' => 'Last name',
3117
        ];
3118
        $lastNameFieldCreate->descriptions = [
3119
            'eng-GB' => '',
3120
        ];
3121
        $lastNameFieldCreate->fieldGroup = 'default';
3122
        $lastNameFieldCreate->position = 2;
3123
        $lastNameFieldCreate->isTranslatable = false;
3124
        $lastNameFieldCreate->isRequired = true;
3125
        $lastNameFieldCreate->isInfoCollector = false;
3126
        $lastNameFieldCreate->validatorConfiguration = [
3127
            'StringLengthValidator' => [
3128
                'minStringLength' => 0,
3129
                'maxStringLength' => 0,
3130
            ],
3131
        ];
3132
        $lastNameFieldCreate->fieldSettings = [];
3133
        $lastNameFieldCreate->isSearchable = true;
3134
        $lastNameFieldCreate->defaultValue = '';
3135
3136
        $typeCreate->addFieldDefinition($lastNameFieldCreate);
3137
3138
        $accountFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct('account', 'ezuser');
3139
        $accountFieldCreateStruct->names = [
3140
            'eng-GB' => 'User account',
3141
        ];
3142
        $accountFieldCreateStruct->descriptions = [
3143
            'eng-GB' => '',
3144
        ];
3145
        $accountFieldCreateStruct->fieldGroup = 'default';
3146
        $accountFieldCreateStruct->position = 3;
3147
        $accountFieldCreateStruct->isTranslatable = false;
3148
        $accountFieldCreateStruct->isRequired = true;
3149
        $accountFieldCreateStruct->isInfoCollector = false;
3150
        $accountFieldCreateStruct->validatorConfiguration = $validatorConfiguration;
3151
        $accountFieldCreateStruct->fieldSettings = $fieldSetting;
3152
        $accountFieldCreateStruct->isSearchable = false;
3153
        $accountFieldCreateStruct->defaultValue = null;
3154
3155
        $typeCreate->addFieldDefinition($accountFieldCreateStruct);
3156
3157
        $contentTypeDraft = $contentTypeService->createContentType($typeCreate, [
3158
            $contentTypeService->loadContentTypeGroupByIdentifier('Users'),
3159
        ]);
3160
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
3161
3162
        return $contentTypeService->loadContentTypeByIdentifier($identifier);
3163
    }
3164
}
3165