diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index db3eb2b85b..119d1bfb4b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -48798,102 +48798,6 @@ parameters: count: 1 path: tests/lib/MVC/Symfony/Templating/RenderLocationStrategyTest.php - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\ContentExtensionTest\:\:getConfigResolverMock\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/ContentExtensionTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\ContentExtensionTest\:\:getContent\(\) has parameter \$fieldsData with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/ContentExtensionTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\ContentExtensionTest\:\:getContent\(\) has parameter \$namesData with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/ContentExtensionTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\ContentExtensionTest\:\:getField\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/ContentExtensionTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\ContentExtensionTest\:\:getField\(\) has parameter \$isEmpty with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/ContentExtensionTest.php - - - - message: '#^Parameter \#1 \$repository of class Ibexa\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\ContentExtension constructor expects Ibexa\\Contracts\\Core\\Repository\\Repository, PHPUnit\\Framework\\MockObject\\MockObject given\.$#' - identifier: argument.type - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/ContentExtensionTest.php - - - - message: '#^Property Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\ContentExtensionTest\:\:\$fieldHelperMock \(Ibexa\\Contracts\\Core\\Repository\\ContentTypeService&PHPUnit\\Framework\\MockObject\\MockObject\) does not accept Ibexa\\Core\\Helper\\FieldHelper&PHPUnit\\Framework\\MockObject\\MockObject\.$#' - identifier: assign.propertyType - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/ContentExtensionTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\FieldRenderingExtensionIntegrationTest\:\:getConfigResolverMock\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\FieldRenderingExtensionIntegrationTest\:\:getContent\(\) has parameter \$fieldsData with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\FieldRenderingExtensionIntegrationTest\:\:getContent\(\) has parameter \$namesData with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\FieldRenderingExtensionIntegrationTest\:\:getFieldDefinition\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\FieldRenderingExtensionIntegrationTest\:\:getFieldDefinition\(\) has parameter \$id with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\FieldRenderingExtensionIntegrationTest\:\:getFieldDefinition\(\) has parameter \$settings with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\FieldRenderingExtensionIntegrationTest\:\:getFieldDefinition\(\) has parameter \$typeIdentifier with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php - - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\FieldRenderingExtensionIntegrationTest\:\:getTemplatePath\(\) has parameter \$tpl with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php - - - - message: '#^Property Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\FieldRenderingExtensionIntegrationTest\:\:\$fieldDefinitions has no type specified\.$#' - identifier: missingType.property - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php - - message: '#^Argument of an invalid type string supplied for foreach, only iterables are supported\.$#' identifier: foreach.nonIterable diff --git a/tests/lib/MVC/Symfony/Templating/Twig/Extension/ContentExtensionTest.php b/tests/lib/MVC/Symfony/Templating/Twig/Extension/ContentExtensionTest.php index 7c8a1de4f7..34f47505af 100644 --- a/tests/lib/MVC/Symfony/Templating/Twig/Extension/ContentExtensionTest.php +++ b/tests/lib/MVC/Symfony/Templating/Twig/Extension/ContentExtensionTest.php @@ -4,6 +4,7 @@ * @copyright Copyright (C) Ibexa AS. All rights reserved. * @license For full copyright and license information view LICENSE file distributed with this source code. */ +declare(strict_types=1); namespace Ibexa\Tests\Core\MVC\Symfony\Templating\Twig\Extension; @@ -13,7 +14,6 @@ use Ibexa\Contracts\Core\Repository\Values\Content\ContentAwareInterface; use Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo; use Ibexa\Contracts\Core\Repository\Values\Content\Field; -use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface; use Ibexa\Core\Helper\FieldHelper; use Ibexa\Core\Helper\FieldsGroups\FieldsGroupsList; use Ibexa\Core\Helper\TranslationHelper; @@ -21,27 +21,21 @@ use Ibexa\Core\Repository\Values\Content\Content; use Ibexa\Core\Repository\Values\Content\VersionInfo; use Ibexa\Core\Repository\Values\ContentType\ContentType; -use Ibexa\Core\Repository\Values\ContentType\FieldDefinition; use Ibexa\Core\Repository\Values\ContentType\FieldDefinitionCollection; +use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; /** - * Integration tests for ContentExtension templates. + * Tests ContentExtension in the context of site with "fre-FR, eng-US" configured as languages. + * - * Tests ContentExtension in context of site with "fre-FR, eng-US" configured as languages. + * @phpstan-import-type TFieldsData from \Ibexa\Tests\Core\MVC\Symfony\Templating\Twig\Extension\FileSystemTwigIntegrationTestCase */ class ContentExtensionTest extends FileSystemTwigIntegrationTestCase { - /** @var \Ibexa\Contracts\Core\Repository\ContentTypeService|\PHPUnit\Framework\MockObject\MockObject */ - private $fieldHelperMock; - - /** @var array */ - private $fieldDefinitions = []; + private FieldHelper & MockObject $fieldHelperMock; - /** @var int[] */ - private $identityMap = []; - - public function getExtensions() + public function getExtensions(): array { $this->fieldHelperMock = $this->createMock(FieldHelper::class); $configResolver = $this->getConfigResolverMock(); @@ -69,39 +63,16 @@ protected static function getFixturesDirectory(): string /** * Creates content with initial/main language being fre-FR. * - * @param string $contentTypeIdentifier - * @param array $fieldsData - * @param array $namesData - * - * @return \Ibexa\Core\Repository\Values\Content\Content + * @param TFieldsData $fieldsData + * @param array $namesData */ - protected function getContent(string $contentTypeIdentifier, array $fieldsData, array $namesData = []) + protected function getContent(string $contentTypeIdentifier, array $fieldsData, array $namesData = []): Content { - if (!array_key_exists($contentTypeIdentifier, $this->identityMap)) { - $this->identityMap[$contentTypeIdentifier] = count($this->identityMap) + 1; - } - - $contentTypeId = $this->identityMap[$contentTypeIdentifier]; - - $fields = []; - foreach ($fieldsData as $fieldTypeIdentifier => $fieldsArray) { - $fieldsArray = isset($fieldsArray['id']) ? [$fieldsArray] : $fieldsArray; - foreach ($fieldsArray as $fieldInfo) { - // Save field definitions in property for mocking purposes - $this->fieldDefinitions[$contentTypeId][$fieldInfo['fieldDefIdentifier']] = new FieldDefinition( - [ - 'identifier' => $fieldInfo['fieldDefIdentifier'], - 'id' => $fieldInfo['id'], - 'fieldTypeIdentifier' => $fieldTypeIdentifier, - 'names' => isset($fieldInfo['fieldDefNames']) ? $fieldInfo['fieldDefNames'] : [], - 'descriptions' => isset($fieldInfo['fieldDefDescriptions']) ? $fieldInfo['fieldDefDescriptions'] : [], - ] - ); - unset($fieldInfo['fieldDefNames'], $fieldInfo['fieldDefDescriptions']); - $fields[] = new Field($fieldInfo); - } - } - $content = new Content( + $contentTypeId = $this->getContentTypeId($contentTypeIdentifier); + + $fields = $this->buildFieldsFromData($fieldsData, $contentTypeIdentifier); + + return new Content( [ 'internalFields' => $fields, 'versionInfo' => new VersionInfo( @@ -120,12 +91,10 @@ protected function getContent(string $contentTypeIdentifier, array $fieldsData, ] ), 'contentType' => new ContentType([ - 'fieldDefinitions' => new FieldDefinitionCollection($this->fieldDefinitions[$contentTypeId] ?? []), + 'fieldDefinitions' => new FieldDefinitionCollection($this->fieldDefinitions[$contentTypeIdentifier] ?? []), ]), ] ); - - return $content; } /** @@ -142,28 +111,6 @@ protected function getContentAwareObject(string $contentTypeIdentifier, array $f return $mock; } - private function getConfigResolverMock() - { - $mock = $this->createMock(ConfigResolverInterface::class); - // Signature: ConfigResolverInterface->getParameter( $paramName, $namespace = null, $scope = null ) - $mock->expects(self::any()) - ->method('getParameter') - ->will( - self::returnValueMap( - [ - [ - 'languages', - null, - null, - ['fre-FR', 'eng-US'], - ], - ] - ) - ); - - return $mock; - } - private function getFieldsGroupsListMock(): FieldsGroupsList { $fieldsGroupsList = $this->createMock(FieldsGroupsList::class); @@ -174,55 +121,49 @@ private function getFieldsGroupsListMock(): FieldsGroupsList return $fieldsGroupsList; } - protected function getField($isEmpty) + protected function getField(bool $isEmpty): Field { $field = new Field(['fieldDefIdentifier' => 'testfield', 'value' => null]); $this->fieldHelperMock ->expects(self::once()) ->method('isFieldEmpty') - ->will(self::returnValue($isEmpty)); + ->willReturn($isEmpty); return $field; } - /** - * @return \PHPUnit\Framework\MockObject\MockObject - */ - protected function getRepositoryMock() + protected function getRepositoryMock(): Repository & MockObject { $mock = $this->createMock(Repository::class); - $mock->expects(self::any()) + $mock ->method('getContentTypeService') - ->will(self::returnValue($this->getContentTypeServiceMock())); + ->willReturn($this->getContentTypeServiceMock()); return $mock; } - /** - * @return \PHPUnit\Framework\MockObject\MockObject - */ - protected function getContentTypeServiceMock() + protected function getContentTypeServiceMock(): ContentTypeService & MockObject { $mock = $this->createMock(ContentTypeService::class); - $mock->expects(self::any()) + $mock ->method('loadContentType') - ->will( - self::returnCallback( - function ($contentTypeId) { - return new ContentType( - [ - 'identifier' => $contentTypeId, - 'mainLanguageCode' => 'fre-FR', - 'fieldDefinitions' => new FieldDefinitionCollection( - $this->fieldDefinitions[$contentTypeId] - ), - ] - ); - } - ) + ->willReturnCallback( + function ($contentTypeId): ContentType { + $contentTypeIdentifier = $this->getContentTypeIdentifier($contentTypeId); + + return new ContentType( + [ + 'identifier' => $contentTypeId, + 'mainLanguageCode' => 'fre-FR', + 'fieldDefinitions' => new FieldDefinitionCollection( + $this->fieldDefinitions[$contentTypeIdentifier] + ), + ] + ); + } ); return $mock; diff --git a/tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php b/tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php index 981806df4a..bad04e4e80 100644 --- a/tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php +++ b/tests/lib/MVC/Symfony/Templating/Twig/Extension/FieldRenderingExtensionIntegrationTest.php @@ -4,14 +4,13 @@ * @copyright Copyright (C) Ibexa AS. All rights reserved. * @license For full copyright and license information view LICENSE file distributed with this source code. */ +declare(strict_types=1); namespace Ibexa\Tests\Core\MVC\Symfony\Templating\Twig\Extension; use Ibexa\Contracts\Core\Repository\ContentService; use Ibexa\Contracts\Core\Repository\Values\Content\ContentAwareInterface; use Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo; -use Ibexa\Contracts\Core\Repository\Values\Content\Field; -use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface; use Ibexa\Core\Helper\TranslationHelper; use Ibexa\Core\MVC\Symfony\FieldType\View\ParameterProviderRegistryInterface; use Ibexa\Core\MVC\Symfony\Templating\Twig\Extension\FieldRenderingExtension; @@ -22,23 +21,18 @@ use Ibexa\Core\Repository\Values\ContentType\ContentType; use Ibexa\Core\Repository\Values\ContentType\FieldDefinition; use Ibexa\Core\Repository\Values\ContentType\FieldDefinitionCollection; +use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; use Twig\Environment; +/** + * @phpstan-import-type TFieldsData from \Ibexa\Tests\Core\MVC\Symfony\Templating\Twig\Extension\FileSystemTwigIntegrationTestCase + */ class FieldRenderingExtensionIntegrationTest extends FileSystemTwigIntegrationTestCase { private const int EXAMPLE_FIELD_DEFINITION_ID = 2; - private $fieldDefinitions = []; - - /** - * Content type identifier to id map (in-memory cache). - * - * @var array - */ - private array $contentTypeIdCache = []; - - public function getExtensions() + public function getExtensions(): array { $configResolver = $this->getConfigResolverMock(); $twig = $this->createMock(Environment::class); @@ -69,7 +63,10 @@ protected static function getFixturesDirectory(): string return __DIR__ . '/_fixtures/field_rendering_functions/'; } - public function getFieldDefinition($typeIdentifier, $id = null, $settings = []) + /** + * @param array $settings + */ + public function getFieldDefinition(string $typeIdentifier, ?int $id = null, array $settings = []): FieldDefinition { return new FieldDefinition( [ @@ -83,33 +80,15 @@ public function getFieldDefinition($typeIdentifier, $id = null, $settings = []) /** * Creates content with initial/main language being fre-FR. * - * @param string $contentTypeIdentifier - * @param array $fieldsData - * @param array $namesData + * @phpstan-param TFieldsData $fieldsData * - * @return \Ibexa\Core\Repository\Values\Content\Content + * @param array $namesData */ - protected function getContent($contentTypeIdentifier, array $fieldsData, array $namesData = []) + protected function getContent(string $contentTypeIdentifier, array $fieldsData, array $namesData = []): Content { - $fields = []; - foreach ($fieldsData as $fieldTypeIdentifier => $fieldsArray) { - $fieldsArray = isset($fieldsArray['id']) ? [$fieldsArray] : $fieldsArray; - foreach ($fieldsArray as $fieldInfo) { - // Save field definitions in property for mocking purposes - $this->fieldDefinitions[$contentTypeIdentifier][$fieldInfo['fieldDefIdentifier']] = new FieldDefinition( - [ - 'identifier' => $fieldInfo['fieldDefIdentifier'], - 'id' => $fieldInfo['id'], - 'fieldTypeIdentifier' => $fieldTypeIdentifier, - 'names' => isset($fieldInfo['fieldDefNames']) ? $fieldInfo['fieldDefNames'] : [], - 'descriptions' => isset($fieldInfo['fieldDefDescriptions']) ? $fieldInfo['fieldDefDescriptions'] : [], - ] - ); - unset($fieldInfo['fieldDefNames'], $fieldInfo['fieldDefDescriptions']); - $fields[] = new Field($fieldInfo); - } - } - $content = new Content( + $fields = $this->buildFieldsFromData($fieldsData, $contentTypeIdentifier); + + return new Content( [ 'internalFields' => $fields, 'contentType' => new ContentType([ @@ -138,16 +117,17 @@ protected function getContent($contentTypeIdentifier, array $fieldsData, array $ ), ] ); - - return $content; } /** - * @param array $fieldsData - * @param array $namesData + * @param array $fieldsData + * @param array $namesData */ - protected function getContentAwareObject(string $contentTypeIdentifier, array $fieldsData, array $namesData = []): ContentAwareInterface - { + protected function getContentAwareObject( + string $contentTypeIdentifier, + array $fieldsData, + array $namesData = [] + ): ContentAwareInterface { $content = $this->getContent($contentTypeIdentifier, $fieldsData, $namesData); $mock = $this->createMock(ContentAwareInterface::class); @@ -156,37 +136,12 @@ protected function getContentAwareObject(string $contentTypeIdentifier, array $f return $mock; } - private function getTemplatePath($tpl): string + private function getTemplatePath(string $tpl): string { return 'templates/' . $tpl; } - private function getConfigResolverMock() - { - $mock = $this->createMock(ConfigResolverInterface::class); - // Signature: ConfigResolverInterface->getParameter( $paramName, $namespace = null, $scope = null ) - $mock->expects(self::any()) - ->method('getParameter') - ->will( - self::returnValueMap( - [ - [ - 'languages', - null, - null, - ['fre-FR', 'eng-US'], - ], - ] - ) - ); - - return $mock; - } - - /** - * @return \Ibexa\Core\MVC\Symfony\Templating\Twig\ResourceProviderInterface|\PHPUnit\Framework\MockObject\MockObject - */ - private function getResourceProviderMock(): ResourceProviderInterface + private function getResourceProviderMock(): ResourceProviderInterface & MockObject { $mock = $this->createMock(ResourceProviderInterface::class); @@ -228,15 +183,4 @@ private function getResourceProviderMock(): ResourceProviderInterface return $mock; } - - private function getContentTypeId(string $contentTypeIdentifier): int - { - if (!isset($this->contentTypeIdCache[$contentTypeIdentifier])) { - $lastId = end($this->contentTypeIdCache); - $nextId = $lastId !== false ? $lastId + 1 : 1; - $this->contentTypeIdCache[$contentTypeIdentifier] = $nextId; - } - - return $this->contentTypeIdCache[$contentTypeIdentifier]; - } } diff --git a/tests/lib/MVC/Symfony/Templating/Twig/Extension/FileSystemTwigIntegrationTestCase.php b/tests/lib/MVC/Symfony/Templating/Twig/Extension/FileSystemTwigIntegrationTestCase.php index 2813fe091c..392d04d71c 100644 --- a/tests/lib/MVC/Symfony/Templating/Twig/Extension/FileSystemTwigIntegrationTestCase.php +++ b/tests/lib/MVC/Symfony/Templating/Twig/Extension/FileSystemTwigIntegrationTestCase.php @@ -4,11 +4,16 @@ * @copyright Copyright (C) Ibexa AS. All rights reserved. * @license For full copyright and license information view LICENSE file distributed with this source code. */ +declare(strict_types=1); namespace Ibexa\Tests\Core\MVC\Symfony\Templating\Twig\Extension; use Exception; +use Ibexa\Contracts\Core\Repository\Values\Content\Field; +use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface; +use Ibexa\Core\Repository\Values\ContentType\FieldDefinition; use PHPUnit\Framework\Constraint\Exception as PHPUnitException; +use PHPUnit\Framework\MockObject\MockObject; use Twig\Environment; use Twig\Error\Error; use Twig\Loader\ArrayLoader; @@ -21,9 +26,22 @@ * Class FileSystemTwigIntegrationTestCase * This class adds a custom version of the doIntegrationTest from \Twig\Test\IntegrationTestCase to * allow loading (custom) templates located in the FixturesDir. + * + * @phpstan-type TFieldData array{id: int, fieldDefIdentifier: string, value: mixed, languageCode: string} + * @phpstan-type TFieldsData array> */ abstract class FileSystemTwigIntegrationTestCase extends IntegrationTestCase { + /** @var array> */ + protected array $fieldDefinitions = []; + + /** + * Content type identifier to id map (in-memory cache). + * + * @var array + */ + private array $contentTypeIdCache = []; + /** * Overrides the default implementation to use the chain loader so that * templates used internally are correctly loaded. @@ -143,4 +161,76 @@ protected function buildTwigErrorFromException(Exception $e, string $file): Erro return new Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $source, $e); } + + /** + * @phpstan-param TFieldsData $fieldsData + * + * @return \Ibexa\Contracts\Core\Repository\Values\Content\Field[] + */ + protected function buildFieldsFromData(array $fieldsData, string $contentTypeIdentifier): array + { + $fields = []; + foreach ($fieldsData as $fieldTypeIdentifier => $fieldsArray) { + $fieldsArray = isset($fieldsArray['id']) ? [$fieldsArray] : $fieldsArray; + foreach ($fieldsArray as $fieldInfo) { + // Save field definitions in property for mocking purposes + $this->fieldDefinitions[$contentTypeIdentifier][$fieldInfo['fieldDefIdentifier']] = new FieldDefinition( + [ + 'identifier' => $fieldInfo['fieldDefIdentifier'], + 'id' => $fieldInfo['id'], + 'fieldTypeIdentifier' => $fieldTypeIdentifier, + 'names' => $fieldInfo['fieldDefNames'] ?? [], + 'descriptions' => $fieldInfo['fieldDefDescriptions'] ?? [], + ] + ); + unset($fieldInfo['fieldDefNames'], $fieldInfo['fieldDefDescriptions']); + $fields[] = new Field($fieldInfo); + } + } + + return $fields; + } + + protected function getConfigResolverMock(): ConfigResolverInterface & MockObject + { + $mock = $this->createMock(ConfigResolverInterface::class); + // Signature: ConfigResolverInterface->getParameter( $paramName, $namespace = null, $scope = null ) + $mock + ->method('getParameter') + ->willReturnMap( + [ + [ + 'languages', + null, + null, + ['fre-FR', 'eng-US'], + ], + ] + ); + + return $mock; + } + + protected function getContentTypeId(string $contentTypeIdentifier): int + { + if (!isset($this->contentTypeIdCache[$contentTypeIdentifier])) { + $lastId = end($this->contentTypeIdCache); + $nextId = $lastId !== false ? $lastId + 1 : 1; + $this->contentTypeIdCache[$contentTypeIdentifier] = $nextId; + } + + return $this->contentTypeIdCache[$contentTypeIdentifier]; + } + + protected function getContentTypeIdentifier(int $contentTypeId): string + { + $identifier = array_flip($this->contentTypeIdCache)[$contentTypeId] ?? null; + + self::assertNotNull( + $identifier, + "Content type identifier not found for ID: $contentTypeId" + ); + + return $identifier; + } }