Completed
Push — 6.13.7 ( b1546d )
by
unknown
14:00
created

BaseTest::assertStructPropertiesCorrect()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
c 0
b 0
f 0
cc 4
nc 6
nop 3
rs 9.7998
1
<?php
2
3
/**
4
 * File containing the BaseTest 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 Doctrine\DBAL\Connection;
12
use eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException;
13
use eZ\Publish\API\Repository\Exceptions\ForbiddenException;
14
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
15
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
16
use eZ\Publish\API\Repository\Tests\PHPUnitConstraint\AllValidationErrorsOccur as PHPUnitConstraintAllValidationErrorsOccur;
17
use eZ\Publish\API\Repository\Tests\PHPUnitConstraint\ValidationErrorOccurs as PHPUnitConstraintValidationErrorOccurs;
18
use eZ\Publish\API\Repository\Tests\SetupFactory\Legacy;
19
use eZ\Publish\API\Repository\Values\Content\Content;
20
use eZ\Publish\API\Repository\Values\Content\Language;
21
use eZ\Publish\API\Repository\Values\User\User;
22
use EzSystems\EzPlatformSolrSearchEngine\Tests\SetupFactory\LegacySetupFactory as LegacySolrSetupFactory;
23
use PHPUnit\Framework\TestCase;
24
use eZ\Publish\API\Repository\Repository;
25
use eZ\Publish\API\Repository\Values\ValueObject;
26
use eZ\Publish\API\Repository\Values\User\Limitation\RoleLimitation;
27
use eZ\Publish\API\Repository\Values\User\Limitation\SubtreeLimitation;
28
use eZ\Publish\API\Repository\Values\User\UserGroup;
29
use DateTime;
30
use ArrayObject;
31
use Exception;
32
use PDOException;
33
34
/**
35
 * Base class for api specific tests.
36
 */
37
abstract class BaseTest extends TestCase
38
{
39
    /**
40
     * Maximum integer number accepted by the different backends.
41
     */
42
    const DB_INT_MAX = 2147483647;
43
44
    /** @var \eZ\Publish\API\Repository\Tests\SetupFactory */
45
    private $setupFactory;
46
47
    /** @var \eZ\Publish\API\Repository\Repository */
48
    private $repository;
49
50
    protected function setUp(): void
51
    {
52
        parent::setUp();
53
54
        try {
55
            // Use setup factory instance here w/o clearing data in case test don't need to
56
            $this->getSetupFactory()->getRepository(false);
57
        } catch (PDOException $e) {
58
            $this->fail(
59
                'The communication with the database cannot be established. ' .
60
                "This is required in order to perform the tests.\n\n" .
61
                'Exception: ' . $e
62
            );
63
        } catch (Exception $e) {
64
            $this->fail(
65
                'Cannot create a repository with predefined user. ' .
66
                'Check the UserService or RoleService implementation. ' .
67
                PHP_EOL . PHP_EOL .
68
                'Exception: ' . $e
69
            );
70
        }
71
    }
72
73
    /**
74
     * Resets the temporary used repository between each test run.
75
     */
76
    protected function tearDown(): void
77
    {
78
        $this->repository = null;
79
        parent::tearDown();
80
    }
81
82
    /**
83
     * Returns the ID generator, fitting to the repository implementation.
84
     *
85
     * @return \eZ\Publish\API\Repository\Tests\IdManager
86
     */
87
    protected function getIdManager()
88
    {
89
        return $this->getSetupFactory()->getIdManager();
90
    }
91
92
    /**
93
     * Generates a repository specific ID value.
94
     *
95
     * @param string $type
96
     * @param mixed $rawId
97
     *
98
     * @return mixed
99
     */
100
    protected function generateId($type, $rawId)
101
    {
102
        return $this->getIdManager()->generateId($type, $rawId);
103
    }
104
105
    /**
106
     * Parses a repository specific ID value.
107
     *
108
     * @param string $type
109
     * @param mixed $id
110
     *
111
     * @return mixed
112
     */
113
    protected function parseId($type, $id)
114
    {
115
        return $this->getIdManager()->parseId($type, $id);
116
    }
117
118
    /**
119
     * Returns a config setting provided by the setup factory.
120
     *
121
     * @param string $configKey
122
     *
123
     * @return mixed
124
     */
125
    protected function getConfigValue($configKey)
126
    {
127
        return $this->getSetupFactory()->getConfigValue($configKey);
128
    }
129
130
    /**
131
     * Tests if the currently tested api is based on a V4 implementation.
132
     *
133
     * @return bool
134
     */
135
    protected function isVersion4()
136
    {
137
        return isset($_ENV['backendVersion']) && '4' === $_ENV['backendVersion'];
138
    }
139
140
    /**
141
     * @param bool $initialInitializeFromScratch Only has an effect if set in first call within a test
142
     *
143
     * @return \eZ\Publish\API\Repository\Repository
144
     */
145
    protected function getRepository($initialInitializeFromScratch = true)
146
    {
147
        if (null === $this->repository) {
148
            $this->repository = $this->getSetupFactory()->getRepository($initialInitializeFromScratch);
149
        }
150
151
        return $this->repository;
152
    }
153
154
    /**
155
     * @return \eZ\Publish\API\Repository\Tests\SetupFactory
156
     */
157
    protected function getSetupFactory()
158
    {
159
        if (null === $this->setupFactory) {
160
            if (false === ($setupClass = getenv('setupFactory'))) {
161
                $setupClass = Legacy::class;
162
                putenv("setupFactory=${setupClass}");
163
            }
164
165
            if (false === ($fixtureDir = getenv('fixtureDir'))) {
166
                putenv('fixtureDir=Legacy');
167
            }
168
169
            if (false === class_exists($setupClass)) {
170
                throw new \ErrorException(
171
                    sprintf(
172
                        'Environment variable "setupFactory" does not reference an existing class: %s. Did you forget to install an package dependency?',
173
                        $setupClass
174
                    )
175
                );
176
            }
177
178
            $this->setupFactory = new $setupClass();
179
        }
180
181
        return $this->setupFactory;
182
    }
183
184
    /**
185
     * Asserts that properties given in $expectedValues are correctly set in
186
     * $actualObject.
187
     *
188
     * @param mixed[] $expectedValues
189
     * @param \eZ\Publish\API\Repository\Values\ValueObject $actualObject
190
     */
191
    protected function assertPropertiesCorrect(array $expectedValues, ValueObject $actualObject)
192
    {
193
        foreach ($expectedValues as $propertyName => $propertyValue) {
194
            if ($propertyValue instanceof ValueObject) {
195
                $this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName);
196
            } elseif (is_array($propertyValue)) {
197
                foreach ($propertyValue as $key => $value) {
198
                    if ($value instanceof ValueObject) {
199
                        $this->assertStructPropertiesCorrect($value, $actualObject->$propertyName[$key]);
200
                    } else {
201
                        $this->assertPropertiesEqual("$propertyName\[$key\]", $value, $actualObject->$propertyName[$key]);
202
                    }
203
                }
204
            } else {
205
                $this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName);
206
            }
207
        }
208
    }
209
210
    /**
211
     * Asserts that properties given in $expectedValues are correctly set in
212
     * $actualObject.
213
     *
214
     * If the property type is array, it will be sorted before comparison.
215
     *
216
     * @TODO: introduced because of randomly failing tests, ref: https://jira.ez.no/browse/EZP-21734
217
     *
218
     * @param mixed[] $expectedValues
219
     * @param \eZ\Publish\API\Repository\Values\ValueObject $actualObject
220
     */
221
    protected function assertPropertiesCorrectUnsorted(array $expectedValues, ValueObject $actualObject)
222
    {
223
        foreach ($expectedValues as $propertyName => $propertyValue) {
224
            if ($propertyValue instanceof ValueObject) {
225
                $this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName);
226
            } else {
227
                $this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName, true);
228
            }
229
        }
230
    }
231
232
    /**
233
     * Asserts all properties from $expectedValues are correctly set in
234
     * $actualObject. Additional (virtual) properties can be asserted using
235
     * $additionalProperties.
236
     *
237
     * @param \eZ\Publish\API\Repository\Values\ValueObject $expectedValues
238
     * @param \eZ\Publish\API\Repository\Values\ValueObject $actualObject
239
     * @param array $propertyNames
0 ignored issues
show
Bug introduced by
There is no parameter named $propertyNames. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
240
     */
241
    protected function assertStructPropertiesCorrect(ValueObject $expectedValues, ValueObject $actualObject, array $additionalProperties = [])
242
    {
243
        foreach ($expectedValues as $propertyName => $propertyValue) {
0 ignored issues
show
Bug introduced by
The expression $expectedValues of type object<eZ\Publish\API\Re...ory\Values\ValueObject> is not traversable.
Loading history...
244
            if ($propertyValue instanceof ValueObject) {
245
                $this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName);
246
            } else {
247
                $this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName);
248
            }
249
        }
250
251
        foreach ($additionalProperties as $propertyName) {
252
            $this->assertPropertiesEqual($propertyName, $expectedValues->$propertyName, $actualObject->$propertyName);
253
        }
254
    }
255
256
    /**
257
     * @see \eZ\Publish\API\Repository\Tests\BaseTest::assertPropertiesCorrectUnsorted()
258
     *
259
     * @param array $items An array of scalar values
260
     */
261
    private function sortItems(array &$items)
262
    {
263
        $sorter = function ($a, $b) {
264
            if (!is_scalar($a) || !is_scalar($b)) {
265
                $this->fail('Wrong usage: method ' . __METHOD__ . ' accepts only an array of scalar values');
266
            }
267
268
            return strcmp($a, $b);
269
        };
270
        usort($items, $sorter);
271
    }
272
273
    private function assertPropertiesEqual($propertyName, $expectedValue, $actualValue, $sortArray = false)
274
    {
275
        if ($expectedValue instanceof ArrayObject) {
276
            $expectedValue = $expectedValue->getArrayCopy();
277
        } elseif ($expectedValue instanceof DateTime) {
278
            $expectedValue = $expectedValue->format(DateTime::RFC850);
279
        }
280
        if ($actualValue instanceof ArrayObject) {
281
            $actualValue = $actualValue->getArrayCopy();
282
        } elseif ($actualValue instanceof DateTime) {
283
            $actualValue = $actualValue->format(DateTime::RFC850);
284
        }
285
286
        if ($sortArray && is_array($actualValue) && is_array($expectedValue)) {
287
            $this->sortItems($actualValue);
288
            $this->sortItems($expectedValue);
289
        }
290
291
        $this->assertEquals(
292
            $expectedValue,
293
            $actualValue,
294
            sprintf('Object property "%s" incorrect.', $propertyName)
295
        );
296
    }
297
298
    /**
299
     * Create a user in editor user group.
300
     */
301
    protected function createUserVersion1(string $login = 'user', ?string $email = null): User
302
    {
303
        $repository = $this->getRepository();
304
305
        /* BEGIN: Inline */
306
        // ID of the "Editors" user group in an eZ Publish demo installation
307
        $editorsGroupId = 13;
308
309
        $userService = $repository->getUserService();
310
311
        // Instantiate a create struct with mandatory properties
312
        $email = $email ?? "{$login}@example.com";
313
        $userCreate = $userService->newUserCreateStruct(
314
            $login,
315
            $email,
316
            'secret',
317
            'eng-US'
318
        );
319
        $userCreate->enabled = true;
320
321
        // Set some fields required by the user ContentType
322
        $userCreate->setField('first_name', 'Example');
323
        $userCreate->setField('last_name', 'User');
324
325
        // Load parent group for the user
326
        $group = $userService->loadUserGroup($editorsGroupId);
327
328
        // Create a new user instance.
329
        $user = $userService->createUser($userCreate, [$group]);
330
        /* END: Inline */
331
332
        return $user;
333
    }
334
335
    /**
336
     * Create a user in new user group with editor rights limited to Media Library (/1/48/).
337
     *
338
     * @uses ::createCustomUserVersion1()
339
     *
340
     * @return \eZ\Publish\API\Repository\Values\User\User
341
     */
342
    protected function createMediaUserVersion1()
343
    {
344
        return $this->createCustomUserVersion1(
345
            'Media Editor',
346
            'Editor',
347
            new SubtreeLimitation(['limitationValues' => ['/1/43/']])
348
        );
349
    }
350
351
    /**
352
     * Create a user with new user group and assign a existing role (optionally with RoleLimitation).
353
     *
354
     * @param string $userGroupName Name of the new user group to create
355
     * @param string $roleIdentifier Role identifier to assign to the new group
356
     * @param RoleLimitation|null $roleLimitation
357
     *
358
     * @return \eZ\Publish\API\Repository\Values\User\User
359
     */
360
    protected function createCustomUserVersion1($userGroupName, $roleIdentifier, RoleLimitation $roleLimitation = null)
361
    {
362
        return $this->createCustomUserWithLogin(
363
            'user',
364
            '[email protected]',
365
            $userGroupName,
366
            $roleIdentifier,
367
            $roleLimitation
368
        );
369
    }
370
371
    /**
372
     * Create a user with new user group and assign a existing role (optionally with RoleLimitation).
373
     *
374
     * @param string $login User login
375
     * @param string $email User e-mail
376
     * @param string $userGroupName Name of the new user group to create
377
     * @param string $roleIdentifier Role identifier to assign to the new group
378
     * @param RoleLimitation|null $roleLimitation
379
     * @return \eZ\Publish\API\Repository\Values\User\User
380
     */
381
    protected function createCustomUserWithLogin(
382
        $login,
383
        $email,
384
        $userGroupName,
385
        $roleIdentifier,
386
        RoleLimitation $roleLimitation = null
387
    ) {
388
        $repository = $this->getRepository();
389
390
        /* BEGIN: Inline */
391
        // ID of the "Users" user group in an eZ Publish demo installation
392
        $rootUsersGroupId = $this->generateId('location', 4);
393
394
        $roleService = $repository->getRoleService();
395
        $userService = $repository->getUserService();
396
397
        // Get a group create struct
398
        $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
399
        $userGroupCreate->setField('name', $userGroupName);
400
401
        // Create new group with media editor rights
402
        $userGroup = $userService->createUserGroup(
403
            $userGroupCreate,
404
            $userService->loadUserGroup($rootUsersGroupId)
405
        );
406
        $roleService->assignRoleToUserGroup(
407
            $roleService->loadRoleByIdentifier($roleIdentifier),
408
            $userGroup,
409
            $roleLimitation
410
        );
411
412
        // Instantiate a create struct with mandatory properties
413
        $userCreate = $userService->newUserCreateStruct(
414
            $login,
415
            $email,
416
            'secret',
417
            'eng-US'
418
        );
419
        $userCreate->enabled = true;
420
421
        // Set some fields required by the user ContentType
422
        $userCreate->setField('first_name', 'Example');
423
        $userCreate->setField('last_name', ucfirst($login));
424
425
        // Create a new user instance.
426
        $user = $userService->createUser($userCreate, [$userGroup]);
427
        /* END: Inline */
428
429
        return $user;
430
    }
431
432
    /**
433
     * Create a user using given data.
434
     *
435
     * @param string $login
436
     * @param string $firstName
437
     * @param string $lastName
438
     * @param \eZ\Publish\API\Repository\Values\User\UserGroup|null $userGroup optional user group, Editor by default
439
     *
440
     * @return \eZ\Publish\API\Repository\Values\User\User
441
     */
442
    protected function createUser($login, $firstName, $lastName, UserGroup $userGroup = null)
443
    {
444
        $repository = $this->getRepository();
445
446
        $userService = $repository->getUserService();
447
        if (null === $userGroup) {
448
            $userGroup = $userService->loadUserGroup(13);
449
        }
450
451
        // Instantiate a create struct with mandatory properties
452
        $userCreate = $userService->newUserCreateStruct(
453
            $login,
454
            "{$login}@example.com",
455
            'secret',
456
            'eng-US'
457
        );
458
        $userCreate->enabled = true;
459
460
        // Set some fields required by the user ContentType
461
        $userCreate->setField('first_name', $firstName);
462
        $userCreate->setField('last_name', $lastName);
463
464
        // Create a new user instance.
465
        $user = $userService->createUser($userCreate, [$userGroup]);
466
467
        return $user;
468
    }
469
470
    /**
471
     * Only for internal use.
472
     *
473
     * Creates a \DateTime object for $timestamp in the current time zone
474
     *
475
     * @param int $timestamp
476
     *
477
     * @return \DateTime
478
     */
479
    public function createDateTime($timestamp = null)
480
    {
481
        $dateTime = new \DateTime();
482
        if ($timestamp !== null) {
483
            $dateTime->setTimestamp($timestamp);
484
        }
485
486
        return $dateTime;
487
    }
488
489
    /**
490
     * Calls given Repository's aggregated SearchHandler::refresh().
491
     *
492
     * Currently implemented only in Solr search engine.
493
     *
494
     * @param \eZ\Publish\API\Repository\Repository $repository
495
     */
496
    protected function refreshSearch(Repository $repository)
497
    {
498
        $setupFactory = $this->getSetupFactory();
499
500
        if (!$setupFactory instanceof LegacySolrSetupFactory) {
0 ignored issues
show
Bug introduced by
The class EzSystems\EzPlatformSolr...tory\LegacySetupFactory does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
501
            return;
502
        }
503
504
        while (true) {
505
            $repositoryReflection = new \ReflectionObject($repository);
506
            // If the repository is decorated, we need to recurse in the "repository" property
507
            if (!$repositoryReflection->hasProperty('repository')) {
508
                break;
509
            }
510
511
            $repositoryProperty = $repositoryReflection->getProperty('repository');
512
            $repositoryProperty->setAccessible(true);
513
            $repository = $repositoryProperty->getValue($repository);
514
        }
515
516
        $searchHandlerProperty = new \ReflectionProperty($repository, 'searchHandler');
517
        $searchHandlerProperty->setAccessible(true);
518
519
        /** @var \EzSystems\EzPlatformSolrSearchEngine\Handler $searchHandler */
520
        $searchHandler = $searchHandlerProperty->getValue($repository);
521
522
        $searchHandler->commit();
523
    }
524
525
    /**
526
     * Create role of a given name with the given policies described by an array.
527
     *
528
     * @param $roleName
529
     * @param array $policiesData [['module' => 'content', 'function' => 'read', 'limitations' => []]
530
     *
531
     * @return \eZ\Publish\API\Repository\Values\User\Role
532
     *
533
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
534
     * @throws \eZ\Publish\API\Repository\Exceptions\LimitationValidationException
535
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
536
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
537
     */
538
    public function createRoleWithPolicies($roleName, array $policiesData)
539
    {
540
        $repository = $this->getRepository(false);
541
        $roleService = $repository->getRoleService();
542
543
        $roleCreateStruct = $roleService->newRoleCreateStruct($roleName);
544
        foreach ($policiesData as $policyData) {
545
            $policyCreateStruct = $roleService->newPolicyCreateStruct(
546
                $policyData['module'],
547
                $policyData['function']
548
            );
549
550
            if (isset($policyData['limitations'])) {
551
                foreach ($policyData['limitations'] as $limitation) {
552
                    $policyCreateStruct->addLimitation($limitation);
553
                }
554
            }
555
556
            $roleCreateStruct->addPolicy($policyCreateStruct);
557
        }
558
559
        $roleDraft = $roleService->createRole($roleCreateStruct);
560
561
        $roleService->publishRoleDraft($roleDraft);
562
563
        return $roleService->loadRole($roleDraft->id);
564
    }
565
566
    /**
567
     * Create user and assign new role with the given policies.
568
     *
569
     * @param string $login
570
     * @param array $policiesData list of policies in the form of <code>[ [ 'module' => 'name', 'function' => 'name'] ]</code>
571
     * @param \eZ\Publish\API\Repository\Values\User\Limitation\RoleLimitation|null $roleLimitation
572
     *
573
     * @return \eZ\Publish\API\Repository\Values\User\User
574
     *
575
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
576
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
577
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
578
     */
579
    public function createUserWithPolicies($login, array $policiesData, RoleLimitation $roleLimitation = null)
580
    {
581
        $repository = $this->getRepository(false);
582
        $roleService = $repository->getRoleService();
583
        $userService = $repository->getUserService();
584
585
        $repository->beginTransaction();
586
        try {
587
            $userCreateStruct = $userService->newUserCreateStruct(
588
                $login,
589
                "{$login}@test.local",
590
                $login,
591
                'eng-GB'
592
            );
593
            $userCreateStruct->setField('first_name', $login);
594
            $userCreateStruct->setField('last_name', $login);
595
            $user = $userService->createUser($userCreateStruct, [$userService->loadUserGroup(4)]);
596
597
            $role = $this->createRoleWithPolicies(uniqid('role_for_' . $login . '_', true), $policiesData);
598
            $roleService->assignRoleToUser($role, $user, $roleLimitation);
599
600
            $repository->commit();
601
602
            return $user;
603
        } catch (ForbiddenException | NotFoundException | UnauthorizedException $ex) {
604
            $repository->rollback();
605
            throw $ex;
606
        }
607
    }
608
609
    /**
610
     * @return \Doctrine\DBAL\Connection
611
     *
612
     * @throws \ErrorException
613
     */
614
    protected function getRawDatabaseConnection()
615
    {
616
        $connection = $this
617
            ->getSetupFactory()
618
            ->getServiceContainer()->get('ezpublish.api.storage_engine.legacy.connection');
619
620
        if (!$connection instanceof Connection) {
621
            throw new \RuntimeException(
622
                sprintf('Expected %s got %s', Connection::class, get_class($connection))
623
            );
624
        }
625
626
        return $connection;
627
    }
628
629
    /**
630
     * Executes the given callback passing raw Database Connection (\Doctrine\DBAL\Connection).
631
     * Returns the result returned by the given callback.
632
     *
633
     * **Note**: The method clears the entire persistence cache pool.
634
     *
635
     * @throws \Exception
636
     *
637
     * @param callable $callback
638
     *
639
     * @return mixed the return result of the given callback
640
     */
641
    public function performRawDatabaseOperation(callable $callback)
642
    {
643
        $repository = $this->getRepository(false);
644
        $repository->beginTransaction();
645
        try {
646
            $callback(
647
                $this->getRawDatabaseConnection()
648
            );
649
            $repository->commit();
650
        } catch (Exception $e) {
651
            $repository->rollback();
652
            throw $e;
653
        }
654
655
        /** @var \Symfony\Component\Cache\Adapter\TagAwareAdapterInterface $cachePool */
656
        $cachePool = $this
657
            ->getSetupFactory()
658
            ->getServiceContainer()->get('ezpublish.cache_pool');
659
660
        $cachePool->clear();
661
    }
662
663
    /**
664
     * Traverse all errors for all fields in all Translations to find expected one.
665
     *
666
     * @param \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException $exception
667
     * @param string $expectedValidationErrorMessage
668
     */
669
    protected function assertValidationErrorOccurs(
670
        ContentFieldValidationException $exception,
671
        string $expectedValidationErrorMessage
672
    ): void {
673
        $constraint = new PHPUnitConstraintValidationErrorOccurs($expectedValidationErrorMessage);
674
675
        self::assertThat($exception, $constraint);
676
    }
677
678
    /**
679
     * Traverse all errors for all fields in all Translations to find if all expected ones occurred.
680
     *
681
     * @param \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException $exception
682
     * @param string[] $expectedValidationErrorMessages
683
     */
684
    protected function assertAllValidationErrorsOccur(
685
        ContentFieldValidationException $exception,
686
        array $expectedValidationErrorMessages
687
    ): void {
688
        $constraint = new PHPUnitConstraintAllValidationErrorsOccur(
689
            $expectedValidationErrorMessages
690
        );
691
692
        self::assertThat($exception, $constraint);
693
    }
694
695
    /**
696
     * Create 'folder' Content.
697
     *
698
     * @param array $names Folder names in the form of <code>['&lt;language_code&gt;' => '&lt;name&gt;']</code>
699
     * @param int $parentLocationId
700
     *
701
     * @return \eZ\Publish\API\Repository\Values\Content\Content published Content
702
     *
703
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
704
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
705
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
706
     */
707
    protected function createFolder(array $names, $parentLocationId)
708
    {
709
        $repository = $this->getRepository(false);
710
        $contentService = $repository->getContentService();
711
        $contentTypeService = $repository->getContentTypeService();
712
        $locationService = $repository->getLocationService();
713
714
        if (empty($names)) {
715
            throw new \RuntimeException(sprintf('%s expects non-empty names list', __METHOD__));
716
        }
717
        $mainLanguageCode = array_keys($names)[0];
718
719
        $struct = $contentService->newContentCreateStruct(
720
            $contentTypeService->loadContentTypeByIdentifier('folder'),
721
            $mainLanguageCode
722
        );
723
        foreach ($names as $languageCode => $translatedName) {
724
            $struct->setField('name', $translatedName, $languageCode);
725
        }
726
        $contentDraft = $contentService->createContent(
727
            $struct,
728
            [$locationService->newLocationCreateStruct($parentLocationId)]
729
        );
730
731
        return $contentService->publishVersion($contentDraft->versionInfo);
732
    }
733
734
    /**
735
     * Update 'folder' Content.
736
     *
737
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
738
     * @param array $names Folder names in the form of <code>['&lt;language_code&gt;' => '&lt;name&gt;']</code>
739
     *
740
     * @return \eZ\Publish\API\Repository\Values\Content\Content
741
     *
742
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
743
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
744
     * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException
745
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
746
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
747
     */
748
    protected function updateFolder(Content $content, array $names)
749
    {
750
        $repository = $this->getRepository(false);
751
        $contentService = $repository->getContentService();
752
753
        $draft = $contentService->createContentDraft($content->contentInfo);
754
        $struct = $contentService->newContentUpdateStruct();
755
        $struct->initialLanguageCode = array_keys($names)[0];
0 ignored issues
show
Documentation Bug introduced by
It seems like array_keys($names)[0] can also be of type integer. However, the property $initialLanguageCode is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
756
757
        foreach ($names as $languageCode => $translatedName) {
758
            $struct->setField('name', $translatedName, $languageCode);
759
        }
760
761
        return $contentService->updateContent($draft->versionInfo, $struct);
762
    }
763
764
    /**
765
     * Add new Language to the Repository.
766
     *
767
     * @param string $languageCode
768
     * @param string $name
769
     * @param bool $enabled
770
     *
771
     * @return \eZ\Publish\API\Repository\Values\Content\Language
772
     */
773
    protected function createLanguage(string $languageCode, string $name, bool $enabled = true): Language
774
    {
775
        $repository = $this->getRepository(false);
776
777
        $languageService = $repository->getContentLanguageService();
778
        $languageStruct = $languageService->newLanguageCreateStruct();
779
        $languageStruct->name = $name;
780
        $languageStruct->languageCode = $languageCode;
781
        $languageStruct->enabled = $enabled;
782
783
        return $languageService->createLanguage($languageStruct);
784
    }
785
}
786