diff --git a/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/AccountSelectionPropertyResolver.php b/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/AccountSelectionPropertyResolver.php index d5a5d1e5b37..78867b9a126 100644 --- a/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/AccountSelectionPropertyResolver.php +++ b/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/AccountSelectionPropertyResolver.php @@ -23,6 +23,7 @@ public function resolve(mixed $data, string $locale, array $params = []): Conten { if (!\is_array($data) || 0 === \count($data) + || !\array_is_list($data) ) { return ContentView::create([], ['ids' => [], ...$params]); } diff --git a/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/ContactAccountSelectionPropertyResolver.php b/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/ContactAccountSelectionPropertyResolver.php index 637a0dc7f53..baceee0a8da 100644 --- a/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/ContactAccountSelectionPropertyResolver.php +++ b/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/ContactAccountSelectionPropertyResolver.php @@ -29,6 +29,7 @@ public function resolve(mixed $data, string $locale, array $params = []): Conten { if (!\is_array($data) || 0 === \count($data) + || !\array_is_list($data) ) { return ContentView::create([], ['ids' => [], ...$params]); } @@ -40,6 +41,10 @@ public function resolve(mixed $data, string $locale, array $params = []): Conten $resolvableResources = []; foreach ($data as $id) { + if (!\is_string($id)) { + continue; + } + $key = \substr($id, 0, 1); $id = \substr($id, 1); $id = \is_numeric($id) ? \intval($id) : null; @@ -61,7 +66,7 @@ public function resolve(mixed $data, string $locale, array $params = []): Conten return ContentView::create( $resolvableResources, [ - 'ids' => $data, + 'ids' => 0 === \count($resolvableResources) ? [] : $data, ...$params, ], ); diff --git a/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/ContactSelectionPropertyResolver.php b/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/ContactSelectionPropertyResolver.php index e5777a58aca..059f5160e21 100644 --- a/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/ContactSelectionPropertyResolver.php +++ b/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/ContactSelectionPropertyResolver.php @@ -23,6 +23,7 @@ public function resolve(mixed $data, string $locale, array $params = []): Conten { if (!\is_array($data) || 0 === \count($data) + || !\array_is_list($data) ) { return ContentView::create([], ['ids' => [], ...$params]); } diff --git a/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/SingleAccountSelectionPropertyResolver.php b/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/SingleAccountSelectionPropertyResolver.php index 1aacae9d90e..689e67f4750 100644 --- a/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/SingleAccountSelectionPropertyResolver.php +++ b/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/SingleAccountSelectionPropertyResolver.php @@ -21,18 +21,18 @@ class SingleAccountSelectionPropertyResolver implements PropertyResolverInterfac { public function resolve(mixed $data, string $locale, array $params = []): ContentView { - if (!\is_int($data)) { - return ContentView::create([], ['id' => null, ...$params]); + if (!\is_numeric($data)) { + return ContentView::create(null, ['id' => null, ...$params]); } /** @var string $resourceLoaderKey */ $resourceLoaderKey = $params['resourceLoader'] ?? AccountResourceLoader::getKey(); return ContentView::createResolvable( - $data, + (int) $data, $resourceLoaderKey, [ - 'ids' => $data, + 'id' => $data, ...$params, ], ); diff --git a/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/SingleContactSelectionPropertyResolver.php b/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/SingleContactSelectionPropertyResolver.php index e607dd7f914..a22af942a1e 100644 --- a/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/SingleContactSelectionPropertyResolver.php +++ b/src/Sulu/Bundle/ContactBundle/Infrastructure/Sulu/Content/PropertyResolver/SingleContactSelectionPropertyResolver.php @@ -21,15 +21,15 @@ class SingleContactSelectionPropertyResolver implements PropertyResolverInterfac { public function resolve(mixed $data, string $locale, array $params = []): ContentView { - if (!\is_int($data)) { - return ContentView::create([], ['id' => null, ...$params]); + if (!\is_numeric($data)) { + return ContentView::create(null, ['id' => null, ...$params]); } /** @var string $resourceLoaderKey */ $resourceLoaderKey = $params['resourceLoader'] ?? ContactResourceLoader::getKey(); return ContentView::createResolvable( - $data, + (int) $data, $resourceLoaderKey, [ 'id' => $data, diff --git a/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/AccountSelectionPropertyResolverTest.php b/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/AccountSelectionPropertyResolverTest.php new file mode 100644 index 00000000000..e0abc06d643 --- /dev/null +++ b/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/AccountSelectionPropertyResolverTest.php @@ -0,0 +1,114 @@ +resolver = new AccountSelectionPropertyResolver(); + } + + public function testResolveEmpty(): void + { + $contentView = $this->resolver->resolve([], 'en'); + + $this->assertSame([], $contentView->getContent()); + $this->assertSame(['ids' => []], $contentView->getView()); + } + + public function testResolveParams(): void + { + $contentView = $this->resolver->resolve([], 'en', ['custom' => 'params']); + + $this->assertSame([], $contentView->getContent()); + $this->assertSame([ + 'ids' => [], + 'custom' => 'params', + ], $contentView->getView()); + } + + #[DataProvider('provideUnresolvableData')] + public function testResolveUnresolvableData(mixed $data): void + { + $contentView = $this->resolver->resolve($data, 'en'); + + $this->assertSame([], $contentView->getContent()); + $this->assertSame(['ids' => []], $contentView->getView()); + } + + /** + * @return iterable + */ + public static function provideUnresolvableData(): iterable + { + yield 'null' => [null]; + yield 'smart_content' => [['source' => '123']]; + yield 'single_value' => [1]; + yield 'object' => [(object) [1, 2]]; + } + + /** + * @param array $data + */ + #[DataProvider('provideResolvableData')] + public function testResolveResolvableData(array $data): void + { + $contentView = $this->resolver->resolve($data, 'en'); + + $content = $contentView->getContent(); + $this->assertIsArray($content); + foreach ($data as $key => $value) { + $resolvable = $content[$key] ?? null; + $this->assertInstanceOf(ResolvableResource::class, $resolvable); + $this->assertSame($value, $resolvable->getId()); + $this->assertSame('account', $resolvable->getResourceLoaderKey()); + } + + $this->assertSame(['ids' => $data], $contentView->getView()); + } + + /** + * @return iterable, + * }> + */ + public static function provideResolvableData(): iterable + { + yield 'empty' => [[]]; + yield 'int_list' => [[1, 2]]; + yield 'string_list' => [['1', '2']]; + } + + public function testCustomResourceLoader(): void + { + $contentView = $this->resolver->resolve([1], 'en', ['resourceLoader' => 'custom_account']); + + $content = $contentView->getContent(); + $this->assertIsArray($content); + $resolvable = $content[0] ?? null; + $this->assertInstanceOf(ResolvableResource::class, $resolvable); + $this->assertSame(1, $resolvable->getId()); + $this->assertSame('custom_account', $resolvable->getResourceLoaderKey()); + } +} diff --git a/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/ContactAccountSelectionPropertyResolverTest.php b/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/ContactAccountSelectionPropertyResolverTest.php new file mode 100644 index 00000000000..c1fe60470c3 --- /dev/null +++ b/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/ContactAccountSelectionPropertyResolverTest.php @@ -0,0 +1,126 @@ +resolver = new ContactAccountSelectionPropertyResolver(); + } + + public function testResolveEmpty(): void + { + $contentView = $this->resolver->resolve([], 'en'); + + $this->assertSame([], $contentView->getContent()); + $this->assertSame(['ids' => []], $contentView->getView()); + } + + public function testResolveParams(): void + { + $contentView = $this->resolver->resolve([], 'en', ['custom' => 'params']); + + $this->assertSame([], $contentView->getContent()); + $this->assertSame([ + 'ids' => [], + 'custom' => 'params', + ], $contentView->getView()); + } + + #[DataProvider('provideUnresolvableData')] + public function testResolveUnresolvableData(mixed $data): void + { + $contentView = $this->resolver->resolve($data, 'en'); + + $this->assertSame([], $contentView->getContent()); + $this->assertSame(['ids' => []], $contentView->getView()); + } + + /** + * @return iterable + */ + public static function provideUnresolvableData(): iterable + { + yield 'null' => [null]; + yield 'smart_content' => [['source' => '123']]; + yield 'single_value' => [1]; + yield 'object' => [(object) [1, 2]]; + yield 'unknown_prefix' => [['e1', 'b2']]; + } + + /** + * @param string[] $data + * @param string[] $expectedResourceLoaderKeys + */ + #[DataProvider('provideResolvableData')] + public function testResolveResolvableData(array $data, array $expectedResourceLoaderKeys): void + { + $contentView = $this->resolver->resolve($data, 'en'); + + $content = $contentView->getContent(); + $this->assertIsArray($content); + foreach ($data as $key => $value) { + $resolvable = $content[$key] ?? null; + $this->assertInstanceOf(ResolvableResource::class, $resolvable); + $this->assertSame((int) \substr($value, 1), $resolvable->getId()); + $expectedResourceLoaderKey = $expectedResourceLoaderKeys[$key] ?? null; + $this->assertSame($expectedResourceLoaderKey, $resolvable->getResourceLoaderKey()); + } + + $this->assertSame(['ids' => $data], $contentView->getView()); + } + + /** + * @return iterable + */ + public static function provideResolvableData(): iterable + { + yield 'empty' => [[], []]; + yield 'contact_list' => [['c1', 'a2'], ['contact', 'account']]; + } + + public function testCustomResourceLoader(): void + { + $contentView = $this->resolver->resolve(['c1', 'a2'], 'en', [ + 'contactResourceLoader' => 'custom_contact', + 'accountResourceLoader' => 'custom_account', + ]); + + $content = $contentView->getContent(); + $this->assertIsArray($content); + + $resolvable = $content[0] ?? null; + $this->assertInstanceOf(ResolvableResource::class, $resolvable); + $this->assertSame(1, $resolvable->getId()); + $this->assertSame('custom_contact', $resolvable->getResourceLoaderKey()); + + $resolvable = $content[1] ?? null; + $this->assertInstanceOf(ResolvableResource::class, $resolvable); + $this->assertSame(2, $resolvable->getId()); + $this->assertSame('custom_account', $resolvable->getResourceLoaderKey()); + } +} diff --git a/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/ContactSelectionPropertyResolverTest.php b/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/ContactSelectionPropertyResolverTest.php new file mode 100644 index 00000000000..0da9f6c394f --- /dev/null +++ b/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/ContactSelectionPropertyResolverTest.php @@ -0,0 +1,114 @@ +resolver = new ContactSelectionPropertyResolver(); + } + + public function testResolveEmpty(): void + { + $contentView = $this->resolver->resolve([], 'en'); + + $this->assertSame([], $contentView->getContent()); + $this->assertSame(['ids' => []], $contentView->getView()); + } + + public function testResolveParams(): void + { + $contentView = $this->resolver->resolve([], 'en', ['custom' => 'params']); + + $this->assertSame([], $contentView->getContent()); + $this->assertSame([ + 'ids' => [], + 'custom' => 'params', + ], $contentView->getView()); + } + + #[DataProvider('provideUnresolvableData')] + public function testResolveUnresolvableData(mixed $data): void + { + $contentView = $this->resolver->resolve($data, 'en'); + + $this->assertSame([], $contentView->getContent()); + $this->assertSame(['ids' => []], $contentView->getView()); + } + + /** + * @return iterable + */ + public static function provideUnresolvableData(): iterable + { + yield 'null' => [null]; + yield 'smart_content' => [['source' => '123']]; + yield 'single_value' => [1]; + yield 'object' => [(object) [1, 2]]; + } + + /** + * @param array $data + */ + #[DataProvider('provideResolvableData')] + public function testResolveResolvableData(array $data): void + { + $contentView = $this->resolver->resolve($data, 'en'); + + $content = $contentView->getContent(); + $this->assertIsArray($content); + foreach ($data as $key => $value) { + $resolvable = $content[$key] ?? null; + $this->assertInstanceOf(ResolvableResource::class, $resolvable); + $this->assertSame($value, $resolvable->getId()); + $this->assertSame('contact', $resolvable->getResourceLoaderKey()); + } + + $this->assertSame(['ids' => $data], $contentView->getView()); + } + + /** + * @return iterable, + * }> + */ + public static function provideResolvableData(): iterable + { + yield 'empty' => [[]]; + yield 'int_list' => [[1, 2]]; + yield 'string_list' => [['1', '2']]; + } + + public function testCustomResourceLoader(): void + { + $contentView = $this->resolver->resolve([1], 'en', ['resourceLoader' => 'custom_contact']); + + $content = $contentView->getContent(); + $this->assertIsArray($content); + $resolvable = $content[0] ?? null; + $this->assertInstanceOf(ResolvableResource::class, $resolvable); + $this->assertSame(1, $resolvable->getId()); + $this->assertSame('custom_contact', $resolvable->getResourceLoaderKey()); + } +} diff --git a/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/SingleAccountSelectionPropertyResolverTest.php b/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/SingleAccountSelectionPropertyResolverTest.php new file mode 100644 index 00000000000..9b8af355c0c --- /dev/null +++ b/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/SingleAccountSelectionPropertyResolverTest.php @@ -0,0 +1,105 @@ +resolver = new SingleAccountSelectionPropertyResolver(); + } + + public function testResolveEmpty(): void + { + $contentView = $this->resolver->resolve(null, 'en'); + + $this->assertNull($contentView->getContent()); + $this->assertSame(['id' => null], $contentView->getView()); + } + + public function testResolveParams(): void + { + $contentView = $this->resolver->resolve(null, 'en', ['custom' => 'params']); + + $this->assertNull($contentView->getContent()); + $this->assertSame([ + 'id' => null, + 'custom' => 'params', + ], $contentView->getView()); + } + + #[DataProvider('provideUnresolvableData')] + public function testResolveUnresolvableData(mixed $data): void + { + $contentView = $this->resolver->resolve($data, 'en'); + + $this->assertNull($contentView->getContent()); + $this->assertSame(['id' => null], $contentView->getView()); + } + + /** + * @return iterable + */ + public static function provideUnresolvableData(): iterable + { + yield 'null' => [null]; + yield 'smart_content' => [['source' => '123']]; + yield 'multi_value' => [[1]]; + yield 'object' => [(object) [1]]; + } + + #[DataProvider('provideResolvableData')] + public function testResolveResolvableData(int|string $data): void + { + $contentView = $this->resolver->resolve($data, 'en'); + + $content = $contentView->getContent(); + $this->assertInstanceOf(ResolvableResource::class, $content); + $this->assertSame((int) $data, $content->getId()); + $this->assertSame('account', $content->getResourceLoaderKey()); + + $this->assertSame(['id' => $data], $contentView->getView()); + } + + /** + * @return iterable + */ + public static function provideResolvableData(): iterable + { + yield 'int' => [1]; + yield 'string' => ['2']; + } + + public function testCustomResourceLoader(): void + { + $contentView = $this->resolver->resolve(1, 'en', ['resourceLoader' => 'custom_account']); + + $content = $contentView->getContent(); + + $this->assertInstanceOf(ResolvableResource::class, $content); + $this->assertSame(1, $content->getId()); + $this->assertSame('custom_account', $content->getResourceLoaderKey()); + } +} diff --git a/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/SingleContactSelectionPropertyResolverTest.php b/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/SingleContactSelectionPropertyResolverTest.php new file mode 100644 index 00000000000..688801d60b4 --- /dev/null +++ b/src/Sulu/Bundle/ContactBundle/Tests/Unit/Infrastructure/Sulu/Content/PropertyResolver/SingleContactSelectionPropertyResolverTest.php @@ -0,0 +1,105 @@ +resolver = new SingleContactSelectionPropertyResolver(); + } + + public function testResolveEmpty(): void + { + $contentView = $this->resolver->resolve(null, 'en'); + + $this->assertNull($contentView->getContent()); + $this->assertSame(['id' => null], $contentView->getView()); + } + + public function testResolveParams(): void + { + $contentView = $this->resolver->resolve(null, 'en', ['custom' => 'params']); + + $this->assertNull($contentView->getContent()); + $this->assertSame([ + 'id' => null, + 'custom' => 'params', + ], $contentView->getView()); + } + + #[DataProvider('provideUnresolvableData')] + public function testResolveUnresolvableData(mixed $data): void + { + $contentView = $this->resolver->resolve($data, 'en'); + + $this->assertNull($contentView->getContent()); + $this->assertSame(['id' => null], $contentView->getView()); + } + + /** + * @return iterable + */ + public static function provideUnresolvableData(): iterable + { + yield 'null' => [null]; + yield 'smart_content' => [['source' => '123']]; + yield 'multi_value' => [[1]]; + yield 'object' => [(object) [1]]; + } + + #[DataProvider('provideResolvableData')] + public function testResolveResolvableData(int|string $data): void + { + $contentView = $this->resolver->resolve($data, 'en'); + + $content = $contentView->getContent(); + $this->assertInstanceOf(ResolvableResource::class, $content); + $this->assertSame((int) $data, $content->getId()); + $this->assertSame('contact', $content->getResourceLoaderKey()); + + $this->assertSame(['id' => $data], $contentView->getView()); + } + + /** + * @return iterable + */ + public static function provideResolvableData(): iterable + { + yield 'int' => [1]; + yield 'string' => ['2']; + } + + public function testCustomResourceLoader(): void + { + $contentView = $this->resolver->resolve(1, 'en', ['resourceLoader' => 'custom_contact']); + + $content = $contentView->getContent(); + + $this->assertInstanceOf(ResolvableResource::class, $content); + $this->assertSame(1, $content->getId()); + $this->assertSame('custom_contact', $content->getResourceLoaderKey()); + } +}