Completed
Push — 7.2 ( ba794f...0c78be )
by Łukasz
41:49
created

BaseTest::createLanguage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
227
            if ($propertyValue instanceof ValueObject) {
228
                $this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName);
229
            } else {
230
                $this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName, true);
231
            }
232
        }
233
    }
234
235
    /**
236
     * Asserts all properties from $expectedValues are correctly set in
237
     * $actualObject. Additional (virtual) properties can be asserted using
238
     * $additionalProperties.
239
     *
240
     * @param \eZ\Publish\API\Repository\Values\ValueObject $expectedValues
241
     * @param \eZ\Publish\API\Repository\Values\ValueObject $actualObject
242
     * @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...
243
     */
244
    protected function assertStructPropertiesCorrect(ValueObject $expectedValues, ValueObject $actualObject, array $additionalProperties = array())
245
    {
246 View Code Duplication
        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...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
247
            if ($propertyValue instanceof ValueObject) {
248
                $this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName);
249
            } else {
250
                $this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName);
251
            }
252
        }
253
254
        foreach ($additionalProperties as $propertyName) {
255
            $this->assertPropertiesEqual($propertyName, $expectedValues->$propertyName, $actualObject->$propertyName);
256
        }
257
    }
258
259
    /**
260
     * @see \eZ\Publish\API\Repository\Tests\BaseTest::assertPropertiesCorrectUnsorted()
261
     *
262
     * @param array $items An array of scalar values
263
     */
264
    private function sortItems(array &$items)
265
    {
266
        $sorter = function ($a, $b) {
267
            if (!is_scalar($a) || !is_scalar($b)) {
268
                $this->fail('Wrong usage: method ' . __METHOD__ . ' accepts only an array of scalar values');
269
            }
270
271
            return strcmp($a, $b);
272
        };
273
        usort($items, $sorter);
274
    }
275
276
    private function assertPropertiesEqual($propertyName, $expectedValue, $actualValue, $sortArray = false)
277
    {
278
        if ($expectedValue instanceof ArrayObject) {
279
            $expectedValue = $expectedValue->getArrayCopy();
280
        } elseif ($expectedValue instanceof DateTime) {
281
            $expectedValue = $expectedValue->format(DateTime::RFC850);
282
        }
283
        if ($actualValue instanceof ArrayObject) {
284
            $actualValue = $actualValue->getArrayCopy();
285
        } elseif ($actualValue instanceof DateTime) {
286
            $actualValue = $actualValue->format(DateTime::RFC850);
287
        }
288
289
        if ($sortArray && is_array($actualValue) && is_array($expectedValue)) {
290
            $this->sortItems($actualValue);
291
            $this->sortItems($expectedValue);
292
        }
293
294
        $this->assertEquals(
295
            $expectedValue,
296
            $actualValue,
297
            sprintf('Object property "%s" incorrect.', $propertyName)
298
        );
299
    }
300
301
    /**
302
     * Create a user in editor user group.
303
     *
304
     * @param string $login
305
     *
306
     * @return \eZ\Publish\API\Repository\Values\User\User
307
     */
308
    protected function createUserVersion1($login = 'user')
309
    {
310
        $repository = $this->getRepository();
311
312
        /* BEGIN: Inline */
313
        // ID of the "Editors" user group in an eZ Publish demo installation
314
        $editorsGroupId = 13;
315
316
        $userService = $repository->getUserService();
317
318
        // Instantiate a create struct with mandatory properties
319
        $userCreate = $userService->newUserCreateStruct(
320
            $login,
321
            "{$login}@example.com",
322
            'secret',
323
            'eng-US'
324
        );
325
        $userCreate->enabled = true;
326
327
        // Set some fields required by the user ContentType
328
        $userCreate->setField('first_name', 'Example');
329
        $userCreate->setField('last_name', 'User');
330
331
        // Load parent group for the user
332
        $group = $userService->loadUserGroup($editorsGroupId);
333
334
        // Create a new user instance.
335
        $user = $userService->createUser($userCreate, array($group));
336
        /* END: Inline */
337
338
        return $user;
339
    }
340
341
    /**
342
     * Create a user in new user group with editor rights limited to Media Library (/1/48/).
343
     *
344
     * @uses ::createCustomUserVersion1()
345
     *
346
     * @return \eZ\Publish\API\Repository\Values\User\User
347
     */
348
    protected function createMediaUserVersion1()
349
    {
350
        return $this->createCustomUserVersion1(
351
            'Media Editor',
352
            'Editor',
353
            new SubtreeLimitation(array('limitationValues' => array('/1/43/')))
354
        );
355
    }
356
357
    /**
358
     * Create a user with new user group and assign a existing role (optionally with RoleLimitation).
359
     *
360
     * @param string $userGroupName Name of the new user group to create
361
     * @param string $roleIdentifier Role identifier to assign to the new group
362
     * @param RoleLimitation|null $roleLimitation
363
     *
364
     * @return \eZ\Publish\API\Repository\Values\User\User
365
     */
366
    protected function createCustomUserVersion1($userGroupName, $roleIdentifier, RoleLimitation $roleLimitation = null)
367
    {
368
        return $this->createCustomUserWithLogin(
369
            'user',
370
            '[email protected]',
371
            $userGroupName,
372
            $roleIdentifier,
373
            $roleLimitation
374
        );
375
    }
376
377
    /**
378
     * Create a user with new user group and assign a existing role (optionally with RoleLimitation).
379
     *
380
     * @param string $login User login
381
     * @param string $email User e-mail
382
     * @param string $userGroupName Name of the new user group to create
383
     * @param string $roleIdentifier Role identifier to assign to the new group
384
     * @param RoleLimitation|null $roleLimitation
385
     * @return \eZ\Publish\API\Repository\Values\User\User
386
     */
387
    protected function createCustomUserWithLogin(
388
        $login,
389
        $email,
390
        $userGroupName,
391
        $roleIdentifier,
392
        RoleLimitation $roleLimitation = null
393
    ) {
394
        $repository = $this->getRepository();
395
396
        /* BEGIN: Inline */
397
        // ID of the "Users" user group in an eZ Publish demo installation
398
        $rootUsersGroupId = $this->generateId('location', 4);
399
400
        $roleService = $repository->getRoleService();
401
        $userService = $repository->getUserService();
402
403
        // Get a group create struct
404
        $userGroupCreate = $userService->newUserGroupCreateStruct('eng-US');
405
        $userGroupCreate->setField('name', $userGroupName);
406
407
        // Create new group with media editor rights
408
        $userGroup = $userService->createUserGroup(
409
            $userGroupCreate,
410
            $userService->loadUserGroup($rootUsersGroupId)
411
        );
412
        $roleService->assignRoleToUserGroup(
413
            $roleService->loadRoleByIdentifier($roleIdentifier),
414
            $userGroup,
415
            $roleLimitation
416
        );
417
418
        // Instantiate a create struct with mandatory properties
419
        $userCreate = $userService->newUserCreateStruct(
420
            $login,
421
            $email,
422
            'secret',
423
            'eng-US'
424
        );
425
        $userCreate->enabled = true;
426
427
        // Set some fields required by the user ContentType
428
        $userCreate->setField('first_name', 'Example');
429
        $userCreate->setField('last_name', ucfirst($login));
430
431
        // Create a new user instance.
432
        $user = $userService->createUser($userCreate, array($userGroup));
433
        /* END: Inline */
434
435
        return $user;
436
    }
437
438
    /**
439
     * Create a user using given data.
440
     *
441
     * @param string $login
442
     * @param string $firstName
443
     * @param string $lastName
444
     * @param \eZ\Publish\API\Repository\Values\User\UserGroup|null $userGroup optional user group, Editor by default
445
     *
446
     * @return \eZ\Publish\API\Repository\Values\User\User
447
     */
448
    protected function createUser($login, $firstName, $lastName, UserGroup $userGroup = null)
449
    {
450
        $repository = $this->getRepository();
451
452
        $userService = $repository->getUserService();
453
        if (null === $userGroup) {
454
            $userGroup = $userService->loadUserGroup(13);
455
        }
456
457
        // Instantiate a create struct with mandatory properties
458
        $userCreate = $userService->newUserCreateStruct(
459
            $login,
460
            "{$login}@example.com",
461
            'secret',
462
            'eng-US'
463
        );
464
        $userCreate->enabled = true;
465
466
        // Set some fields required by the user ContentType
467
        $userCreate->setField('first_name', $firstName);
468
        $userCreate->setField('last_name', $lastName);
469
470
        // Create a new user instance.
471
        $user = $userService->createUser($userCreate, array($userGroup));
472
473
        return $user;
474
    }
475
476
    /**
477
     * Only for internal use.
478
     *
479
     * Creates a \DateTime object for $timestamp in the current time zone
480
     *
481
     * @param int $timestamp
482
     *
483
     * @return \DateTime
484
     */
485
    public function createDateTime($timestamp = null)
486
    {
487
        $dateTime = new \DateTime();
488
        if ($timestamp !== null) {
489
            $dateTime->setTimestamp($timestamp);
490
        }
491
492
        return $dateTime;
493
    }
494
495
    /**
496
     * Calls given Repository's aggregated SearchHandler::refresh().
497
     *
498
     * Currently implemented only in Solr search engine.
499
     *
500
     * @param \eZ\Publish\API\Repository\Repository $repository
501
     */
502
    protected function refreshSearch(Repository $repository)
503
    {
504
        $setupFactory = $this->getSetupFactory();
505
506
        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...
507
            return;
508
        }
509
510
        while (true) {
511
            $repositoryReflection = new \ReflectionObject($repository);
512
            // If the repository is decorated, we need to recurse in the "repository" property
513
            if (!$repositoryReflection->hasProperty('repository')) {
514
                break;
515
            }
516
517
            $repositoryProperty = $repositoryReflection->getProperty('repository');
518
            $repositoryProperty->setAccessible(true);
519
            $repository = $repositoryProperty->getValue($repository);
520
        }
521
522
        $searchHandlerProperty = new \ReflectionProperty($repository, 'searchHandler');
523
        $searchHandlerProperty->setAccessible(true);
524
525
        /** @var \EzSystems\EzPlatformSolrSearchEngine\Handler $searchHandler */
526
        $searchHandler = $searchHandlerProperty->getValue($repository);
527
528
        $searchHandler->commit();
529
    }
530
531
    /**
532
     * Create role of a given name with the given policies described by an array.
533
     *
534
     * @param $roleName
535
     * @param array $policiesData [['module' => 'content', 'function' => 'read', 'limitations' => []]
536
     *
537
     * @return \eZ\Publish\API\Repository\Values\User\Role
538
     *
539
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
540
     * @throws \eZ\Publish\API\Repository\Exceptions\LimitationValidationException
541
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
542
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
543
     */
544
    public function createRoleWithPolicies($roleName, array $policiesData)
545
    {
546
        $repository = $this->getRepository(false);
547
        $roleService = $repository->getRoleService();
548
549
        $roleCreateStruct = $roleService->newRoleCreateStruct($roleName);
550
        foreach ($policiesData as $policyData) {
551
            $policyCreateStruct = $roleService->newPolicyCreateStruct(
552
                $policyData['module'],
553
                $policyData['function']
554
            );
555
556
            if (isset($policyData['limitations'])) {
557
                foreach ($policyData['limitations'] as $limitation) {
558
                    $policyCreateStruct->addLimitation($limitation);
559
                }
560
            }
561
562
            $roleCreateStruct->addPolicy($policyCreateStruct);
563
        }
564
565
        $roleDraft = $roleService->createRole($roleCreateStruct);
566
567
        $roleService->publishRoleDraft($roleDraft);
568
569
        return $roleService->loadRole($roleDraft->id);
570
    }
571
572
    /**
573
     * Create user and assign new role with the given policies.
574
     *
575
     * @param string $login
576
     * @param array $policiesData list of policies in the form of <code>[ [ 'module' => 'name', 'function' => 'name'] ]</code>
577
     *
578
     * @return \eZ\Publish\API\Repository\Values\User\User
579
     *
580
     * @throws \Exception
581
     */
582
    public function createUserWithPolicies($login, array $policiesData)
583
    {
584
        $repository = $this->getRepository(false);
585
        $roleService = $repository->getRoleService();
586
        $userService = $repository->getUserService();
587
588
        $repository->beginTransaction();
589
        try {
590
            $userCreateStruct = $userService->newUserCreateStruct(
591
                $login,
592
                "{$login}@test.local",
593
                $login,
594
                'eng-GB'
595
            );
596
            $userCreateStruct->setField('first_name', $login);
597
            $userCreateStruct->setField('last_name', $login);
598
            $user = $userService->createUser($userCreateStruct, [$userService->loadUserGroup(4)]);
599
600
            $role = $this->createRoleWithPolicies(uniqid('role_for_' . $login . '_'), $policiesData);
601
            $roleService->assignRoleToUser($role, $user);
602
603
            $repository->commit();
604
605
            return $user;
606
        } catch (\Exception $ex) {
607
            $repository->rollback();
608
            throw $ex;
609
        }
610
    }
611
612
    /**
613
     * @return \Doctrine\DBAL\Connection
614
     *
615
     * @throws \ErrorException
616
     */
617
    protected function getRawDatabaseConnection()
618
    {
619
        $connection = $this
620
            ->getSetupFactory()
621
            ->getServiceContainer()->get('ezpublish.api.storage_engine.legacy.connection');
622
623
        if (!$connection instanceof Connection) {
624
            throw new \RuntimeException(
625
                sprintf('Expected %s got %s', Connection::class, get_class($connection))
626
            );
627
        }
628
629
        return $connection;
630
    }
631
632
    /**
633
     * Executes the given callback passing raw Database Connection (\Doctrine\DBAL\Connection).
634
     * Returns the result returned by the given callback.
635
     *
636
     * **Note**: The method clears the entire persistence cache pool.
637
     *
638
     * @throws \Exception
639
     *
640
     * @param callable $callback
641
     *
642
     * @return mixed the return result of the given callback
643
     */
644
    public function performRawDatabaseOperation(callable $callback)
645
    {
646
        $repository = $this->getRepository(false);
647
        $repository->beginTransaction();
648
        try {
649
            $callback(
650
                $this->getRawDatabaseConnection()
651
            );
652
            $repository->commit();
653
        } catch (Exception $e) {
654
            $repository->rollback();
655
            throw $e;
656
        }
657
658
        /** @var \Symfony\Component\Cache\Adapter\TagAwareAdapterInterface $cachePool */
659
        $cachePool = $this
660
            ->getSetupFactory()
661
            ->getServiceContainer()->get('ezpublish.cache_pool');
662
663
        $cachePool->clear();
664
    }
665
666
    /**
667
     * Traverse all errors for all fields in all Translations to find expected one.
668
     *
669
     * @param \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException $exception
670
     * @param string $expectedValidationErrorMessage
671
     */
672
    protected function assertValidationErrorOccurs(
673
        ContentFieldValidationException $exception,
674
        $expectedValidationErrorMessage
675
    ) {
676
        $constraint = new PHPUnitConstraintValidationErrorOccurs($expectedValidationErrorMessage);
677
678
        self::assertThat($exception, $constraint);
679
    }
680
681
    /**
682
     * Create 'folder' Content.
683
     *
684
     * @param array $names Folder names in the form of <code>['&lt;language_code&gt;' => '&lt;name&gt;']</code>
685
     * @param int $parentLocationId
686
     *
687
     * @return \eZ\Publish\API\Repository\Values\Content\Content published Content
688
     *
689
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
690
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
691
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
692
     */
693
    protected function createFolder(array $names, $parentLocationId)
694
    {
695
        $repository = $this->getRepository(false);
696
        $contentService = $repository->getContentService();
697
        $contentTypeService = $repository->getContentTypeService();
698
        $locationService = $repository->getLocationService();
699
700
        if (empty($names)) {
701
            throw new \RuntimeException(sprintf('%s expects non-empty names list', __METHOD__));
702
        }
703
        $mainLanguageCode = array_keys($names)[0];
704
705
        $struct = $contentService->newContentCreateStruct(
706
            $contentTypeService->loadContentTypeByIdentifier('folder'),
707
            $mainLanguageCode
708
        );
709
        foreach ($names as $languageCode => $translatedName) {
710
            $struct->setField('name', $translatedName, $languageCode);
711
        }
712
        $contentDraft = $contentService->createContent(
713
            $struct,
714
            [$locationService->newLocationCreateStruct($parentLocationId)]
715
        );
716
717
        return $contentService->publishVersion($contentDraft->versionInfo);
718
    }
719
720
    /**
721
     * Add new Language to the Repository.
722
     *
723
     * @param string $languageCode
724
     * @param string $name
725
     * @param bool $enabled
726
     *
727
     * @return \eZ\Publish\API\Repository\Values\Content\Language
728
     */
729
    protected function createLanguage(string $languageCode, string $name, bool $enabled = true): Language
730
    {
731
        $repository = $this->getRepository(false);
732
733
        $languageService = $repository->getContentLanguageService();
734
        $languageStruct = $languageService->newLanguageCreateStruct();
735
        $languageStruct->name = $name;
736
        $languageStruct->languageCode = $languageCode;
737
        $languageStruct->enabled = $enabled;
738
739
        return $languageService->createLanguage($languageStruct);
740
    }
741
}
742