From 825e7db6352f104e1a8ef2d01b7dc42ec623b49f Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Fri, 29 Dec 2023 14:39:07 +0100 Subject: [PATCH 01/15] NGSTACK-822 sorting for standard netgen site search implemented --- bundle/QueryType/SearchQueryType.php | 70 ++++++++++++++++++++----- bundle/Resources/config/parameters.yaml | 5 ++ 2 files changed, 63 insertions(+), 12 deletions(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index 08e82590..3e137398 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -18,47 +18,93 @@ final class SearchQueryType extends OptionsResolverBasedQueryType { - public function __construct(private Site $site, private ConfigResolverInterface $configResolver) {} - + /* + * It is a mapper that contains a set of key-value pairs, where key is + * allowed sort parameter value and value is name of class + * that provides implementation of that key + */ + private array $sortKeysAllowed; + public function __construct( + private readonly Site $site, + private readonly ConfigResolverInterface $configResolver, + ) { + $this->sortKeysAllowed = $this->configResolver->getParameter('search.sort_allowed_keys', 'ngsite'); + } public static function getName(): string { return 'NetgenSite:Search'; } - protected function configureOptions(OptionsResolver $optionsResolver): void { - $optionsResolver->setRequired(['search_text', 'content_types', 'subtree']); - + $optionsResolver->setRequired(['search_text', 'content_types', 'subtree', 'sort', 'order']); $optionsResolver->setAllowedTypes('search_text', 'string'); $optionsResolver->setAllowedTypes('content_types', 'string[]'); + $optionsResolver->setAllowedTypes('sort', 'string[]'); $optionsResolver->setAllowedTypes('subtree', ['int', 'string']); - $optionsResolver->setAllowedValues( 'search_text', static fn (string $searchText): bool => trim($searchText) !== '', ); - + $optionsResolver->setAllowedValues( + 'sort', + /** @var String[] $keys */ + static function(array $keys): bool { + return $this->sortKeysAllowed($keys); + }, + ); + $optionsResolver->setAllowedValues( + 'order', + static fn (string $searchText): bool => trim($searchText) === 'asc' || trim($searchText) === 'desc', + ); $optionsResolver->setDefault('content_types', $this->configResolver->getParameter('search.content_types', 'ngsite')); $optionsResolver->setDefault('subtree', $this->site->getSettings()->rootLocationId); - } + $optionsResolver->setDefault('sort', ['published_date']); + $optionsResolver->setDefault('order', 'desc'); - protected function doGetQuery(array $parameters): Query + } + public function doGetQuery(array $parameters): Query { $subtreeLocation = $this->site->getLoadService()->loadLocation($parameters['subtree']); - + $sortingKeys = $parameters['sort']; + $order = $parameters['order']; + $descendingOrder = $order === 'desc'; $criteria = [ new Criterion\Subtree($subtreeLocation->pathString), new Criterion\Visibility(Criterion\Visibility::VISIBLE), ]; - if (count($parameters['content_types']) > 0) { $criteria[] = new Criterion\ContentTypeIdentifier($parameters['content_types']); } - $query = new LocationQuery(); $query->query = new FullText(trim($parameters['search_text'])); $query->filter = new Criterion\LogicalAnd($criteria); + $sortClauses = []; + foreach ($sortingKeys as $sortingKey){ + $sortClauses[] = $this->createSortClause($sortingKey, $descendingOrder); + } + $query->sortClauses = $sortClauses; return $query; } + + private function sortKeyAllowed(string $key): bool { + return array_key_exists(trim($key), $this->sortKeysAllowed); + } + private function sortKeysAllowed(array $keys): bool { + foreach ($keys as $key){ + if(!$this->sortKeyAllowed($key)){ + return false; + } + } + return true; + } + + public function createSortClause(string $name, bool $desc = true): mixed { + $className = $this->sortKeysAllowed[$name]; + if($desc){ + return new $className(Query::SORT_DESC); + } else { + return new $className(Query::SORT_ASC); + } + } } diff --git a/bundle/Resources/config/parameters.yaml b/bundle/Resources/config/parameters.yaml index f09b27b7..01b6070d 100644 --- a/bundle/Resources/config/parameters.yaml +++ b/bundle/Resources/config/parameters.yaml @@ -54,6 +54,11 @@ parameters: ngsite.default.search.default_limit: 10 ngsite.default.search.content_types: [] + ngsite.default.search.sort_allowed_keys: + published_date: 'Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause\DatePublished' + content_name: 'Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause\ContentName' + score: 'Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause\Score' + modification_date: 'Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause\DateModified' ngsite.default.template.errors.default: '@@NetgenSite/errors/default.html.twig' ngsite.default.template.pagerfanta.ngsite: '@@NetgenSite/pagerfanta/ngsite.html.twig' From 7f1374267630c4983d3887effc448e8463645ffb Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Fri, 29 Dec 2023 14:52:33 +0100 Subject: [PATCH 02/15] NGSTACK-822 SearchQueryType fixed with php-cs-fixer --- bundle/QueryType/SearchQueryType.php | 82 +++++++++++++++------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index 3e137398..7bd4365e 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -13,6 +13,7 @@ use Netgen\IbexaSiteApi\API\Site; use Symfony\Component\OptionsResolver\OptionsResolver; +use function array_key_exists; use function count; use function trim; @@ -23,17 +24,46 @@ final class SearchQueryType extends OptionsResolverBasedQueryType * allowed sort parameter value and value is name of class * that provides implementation of that key */ + /** @var array */ private array $sortKeysAllowed; + public function __construct( private readonly Site $site, private readonly ConfigResolverInterface $configResolver, ) { $this->sortKeysAllowed = $this->configResolver->getParameter('search.sort_allowed_keys', 'ngsite'); } + public static function getName(): string { return 'NetgenSite:Search'; } + + protected function doGetQuery(array $parameters): Query + { + $subtreeLocation = $this->site->getLoadService()->loadLocation($parameters['subtree']); + $sortingKeys = $parameters['sort']; + $order = $parameters['order']; + $descendingOrder = $order === 'desc'; + $criteria = [ + new Criterion\Subtree($subtreeLocation->pathString), + new Criterion\Visibility(Criterion\Visibility::VISIBLE), + ]; + if (count($parameters['content_types']) > 0) { + $criteria[] = new Criterion\ContentTypeIdentifier($parameters['content_types']); + } + $query = new LocationQuery(); + $query->query = new FullText(trim($parameters['search_text'])); + $query->filter = new Criterion\LogicalAnd($criteria); + $sortClauses = []; + foreach ($sortingKeys as $sortingKey) { + $sortClauses[] = $this->createSortClause($sortingKey, $descendingOrder); + } + $query->sortClauses = $sortClauses; + + return $query; + } + protected function configureOptions(OptionsResolver $optionsResolver): void { $optionsResolver->setRequired(['search_text', 'content_types', 'subtree', 'sort', 'order']); @@ -47,10 +77,8 @@ protected function configureOptions(OptionsResolver $optionsResolver): void ); $optionsResolver->setAllowedValues( 'sort', - /** @var String[] $keys */ - static function(array $keys): bool { - return $this->sortKeysAllowed($keys); - }, + /** @var string[] $keys */ + static fn (array $keys): bool => $this->sortKeysAllowed($keys), ); $optionsResolver->setAllowedValues( 'order', @@ -60,51 +88,31 @@ static function(array $keys): bool { $optionsResolver->setDefault('subtree', $this->site->getSettings()->rootLocationId); $optionsResolver->setDefault('sort', ['published_date']); $optionsResolver->setDefault('order', 'desc'); - - } - public function doGetQuery(array $parameters): Query - { - $subtreeLocation = $this->site->getLoadService()->loadLocation($parameters['subtree']); - $sortingKeys = $parameters['sort']; - $order = $parameters['order']; - $descendingOrder = $order === 'desc'; - $criteria = [ - new Criterion\Subtree($subtreeLocation->pathString), - new Criterion\Visibility(Criterion\Visibility::VISIBLE), - ]; - if (count($parameters['content_types']) > 0) { - $criteria[] = new Criterion\ContentTypeIdentifier($parameters['content_types']); - } - $query = new LocationQuery(); - $query->query = new FullText(trim($parameters['search_text'])); - $query->filter = new Criterion\LogicalAnd($criteria); - $sortClauses = []; - foreach ($sortingKeys as $sortingKey){ - $sortClauses[] = $this->createSortClause($sortingKey, $descendingOrder); - } - $query->sortClauses = $sortClauses; - - return $query; } - private function sortKeyAllowed(string $key): bool { + private function sortKeyAllowed(string $key): bool + { return array_key_exists(trim($key), $this->sortKeysAllowed); } - private function sortKeysAllowed(array $keys): bool { - foreach ($keys as $key){ - if(!$this->sortKeyAllowed($key)){ + + private function sortKeysAllowed(array $keys): bool + { + foreach ($keys as $key) { + if (!$this->sortKeyAllowed($key)) { return false; } } + return true; } - public function createSortClause(string $name, bool $desc = true): mixed { + private function createSortClause(string $name, bool $desc = true): mixed + { $className = $this->sortKeysAllowed[$name]; - if($desc){ + if ($desc) { return new $className(Query::SORT_DESC); - } else { - return new $className(Query::SORT_ASC); } + + return new $className(Query::SORT_ASC); } } From cf8fd66ede3becc37a6660b26d1fac21c5d71c84 Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Wed, 7 Feb 2024 16:01:04 +0100 Subject: [PATCH 03/15] NGSTACK-822 type hint to array parameter of function added --- bundle/QueryType/SearchQueryType.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index 7bd4365e..1a547163 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -95,6 +95,10 @@ private function sortKeyAllowed(string $key): bool return array_key_exists(trim($key), $this->sortKeysAllowed); } + /** + * @param string[] $keys + * @return bool + */ private function sortKeysAllowed(array $keys): bool { foreach ($keys as $key) { From 4b4245bf9ec2085189e526d7fa5a2cda2ae7daf1 Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Wed, 7 Feb 2024 16:35:47 +0100 Subject: [PATCH 04/15] NGSTACK-822 static function made non static where this is needed --- bundle/QueryType/SearchQueryType.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index 1a547163..7fff1e6c 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -78,7 +78,7 @@ protected function configureOptions(OptionsResolver $optionsResolver): void $optionsResolver->setAllowedValues( 'sort', /** @var string[] $keys */ - static fn (array $keys): bool => $this->sortKeysAllowed($keys), + fn (array $keys): bool => $this->sortKeysAllowed($keys), ); $optionsResolver->setAllowedValues( 'order', @@ -97,6 +97,7 @@ private function sortKeyAllowed(string $key): bool /** * @param string[] $keys + * * @return bool */ private function sortKeysAllowed(array $keys): bool From dfdd3af3b766ae1519cfabd28db359b04d4e4d20 Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Wed, 7 Feb 2024 17:35:06 +0100 Subject: [PATCH 05/15] NGSTACK-822 switched functons order to avoid big git diff --- bundle/QueryType/SearchQueryType.php | 50 ++++++++++++++-------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index 7fff1e6c..7df77e6b 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -39,31 +39,6 @@ public static function getName(): string return 'NetgenSite:Search'; } - protected function doGetQuery(array $parameters): Query - { - $subtreeLocation = $this->site->getLoadService()->loadLocation($parameters['subtree']); - $sortingKeys = $parameters['sort']; - $order = $parameters['order']; - $descendingOrder = $order === 'desc'; - $criteria = [ - new Criterion\Subtree($subtreeLocation->pathString), - new Criterion\Visibility(Criterion\Visibility::VISIBLE), - ]; - if (count($parameters['content_types']) > 0) { - $criteria[] = new Criterion\ContentTypeIdentifier($parameters['content_types']); - } - $query = new LocationQuery(); - $query->query = new FullText(trim($parameters['search_text'])); - $query->filter = new Criterion\LogicalAnd($criteria); - $sortClauses = []; - foreach ($sortingKeys as $sortingKey) { - $sortClauses[] = $this->createSortClause($sortingKey, $descendingOrder); - } - $query->sortClauses = $sortClauses; - - return $query; - } - protected function configureOptions(OptionsResolver $optionsResolver): void { $optionsResolver->setRequired(['search_text', 'content_types', 'subtree', 'sort', 'order']); @@ -90,6 +65,31 @@ protected function configureOptions(OptionsResolver $optionsResolver): void $optionsResolver->setDefault('order', 'desc'); } + protected function doGetQuery(array $parameters): Query + { + $subtreeLocation = $this->site->getLoadService()->loadLocation($parameters['subtree']); + $sortingKeys = $parameters['sort']; + $order = $parameters['order']; + $descendingOrder = $order === 'desc'; + $criteria = [ + new Criterion\Subtree($subtreeLocation->pathString), + new Criterion\Visibility(Criterion\Visibility::VISIBLE), + ]; + if (count($parameters['content_types']) > 0) { + $criteria[] = new Criterion\ContentTypeIdentifier($parameters['content_types']); + } + $query = new LocationQuery(); + $query->query = new FullText(trim($parameters['search_text'])); + $query->filter = new Criterion\LogicalAnd($criteria); + $sortClauses = []; + foreach ($sortingKeys as $sortingKey) { + $sortClauses[] = $this->createSortClause($sortingKey, $descendingOrder); + } + $query->sortClauses = $sortClauses; + + return $query; + } + private function sortKeyAllowed(string $key): bool { return array_key_exists(trim($key), $this->sortKeysAllowed); From a70fcb9e93e51bee19f4868918de7e0a42514f9a Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Thu, 8 Feb 2024 15:26:59 +0100 Subject: [PATCH 06/15] NGSTACK-822 switch from string mapped to sort clause to FQN --- bundle/QueryType/SearchQueryType.php | 24 ++++-------------------- bundle/Resources/config/parameters.yaml | 5 ----- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index 7df77e6b..5e62427c 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -13,25 +13,15 @@ use Netgen\IbexaSiteApi\API\Site; use Symfony\Component\OptionsResolver\OptionsResolver; -use function array_key_exists; use function count; use function trim; final class SearchQueryType extends OptionsResolverBasedQueryType { - /* - * It is a mapper that contains a set of key-value pairs, where key is - * allowed sort parameter value and value is name of class - * that provides implementation of that key - */ - /** @var array */ - private array $sortKeysAllowed; - public function __construct( private readonly Site $site, private readonly ConfigResolverInterface $configResolver, ) { - $this->sortKeysAllowed = $this->configResolver->getParameter('search.sort_allowed_keys', 'ngsite'); } public static function getName(): string @@ -61,7 +51,7 @@ protected function configureOptions(OptionsResolver $optionsResolver): void ); $optionsResolver->setDefault('content_types', $this->configResolver->getParameter('search.content_types', 'ngsite')); $optionsResolver->setDefault('subtree', $this->site->getSettings()->rootLocationId); - $optionsResolver->setDefault('sort', ['published_date']); + $optionsResolver->setDefault('sort', [Query\SortClause\DatePublished::class]); $optionsResolver->setDefault('order', 'desc'); } @@ -90,11 +80,6 @@ protected function doGetQuery(array $parameters): Query return $query; } - private function sortKeyAllowed(string $key): bool - { - return array_key_exists(trim($key), $this->sortKeysAllowed); - } - /** * @param string[] $keys * @@ -103,7 +88,7 @@ private function sortKeyAllowed(string $key): bool private function sortKeysAllowed(array $keys): bool { foreach ($keys as $key) { - if (!$this->sortKeyAllowed($key)) { + if (!class_exists($key)) { return false; } } @@ -113,11 +98,10 @@ private function sortKeysAllowed(array $keys): bool private function createSortClause(string $name, bool $desc = true): mixed { - $className = $this->sortKeysAllowed[$name]; if ($desc) { - return new $className(Query::SORT_DESC); + return new $name(Query::SORT_DESC); } - return new $className(Query::SORT_ASC); + return new $name(Query::SORT_ASC); } } diff --git a/bundle/Resources/config/parameters.yaml b/bundle/Resources/config/parameters.yaml index 01b6070d..f09b27b7 100644 --- a/bundle/Resources/config/parameters.yaml +++ b/bundle/Resources/config/parameters.yaml @@ -54,11 +54,6 @@ parameters: ngsite.default.search.default_limit: 10 ngsite.default.search.content_types: [] - ngsite.default.search.sort_allowed_keys: - published_date: 'Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause\DatePublished' - content_name: 'Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause\ContentName' - score: 'Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause\Score' - modification_date: 'Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause\DateModified' ngsite.default.template.errors.default: '@@NetgenSite/errors/default.html.twig' ngsite.default.template.pagerfanta.ngsite: '@@NetgenSite/pagerfanta/ngsite.html.twig' From 98e8d7d04f933e78da8eb6a17dd2536886fdd604 Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Wed, 28 Aug 2024 12:23:33 +0200 Subject: [PATCH 07/15] NGSTACK-822 logic of ordering changes, string parameter replaced by QN --- bundle/QueryType/SearchQueryType.php | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index 5e62427c..f651d5d0 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -52,15 +52,13 @@ protected function configureOptions(OptionsResolver $optionsResolver): void $optionsResolver->setDefault('content_types', $this->configResolver->getParameter('search.content_types', 'ngsite')); $optionsResolver->setDefault('subtree', $this->site->getSettings()->rootLocationId); $optionsResolver->setDefault('sort', [Query\SortClause\DatePublished::class]); - $optionsResolver->setDefault('order', 'desc'); + $optionsResolver->setDefault('order', Query::SORT_DESC); } protected function doGetQuery(array $parameters): Query { $subtreeLocation = $this->site->getLoadService()->loadLocation($parameters['subtree']); $sortingKeys = $parameters['sort']; - $order = $parameters['order']; - $descendingOrder = $order === 'desc'; $criteria = [ new Criterion\Subtree($subtreeLocation->pathString), new Criterion\Visibility(Criterion\Visibility::VISIBLE), @@ -73,7 +71,7 @@ protected function doGetQuery(array $parameters): Query $query->filter = new Criterion\LogicalAnd($criteria); $sortClauses = []; foreach ($sortingKeys as $sortingKey) { - $sortClauses[] = $this->createSortClause($sortingKey, $descendingOrder); + $sortClauses[] = new $sortingKey($parameters['order']); } $query->sortClauses = $sortClauses; @@ -96,12 +94,4 @@ private function sortKeysAllowed(array $keys): bool return true; } - private function createSortClause(string $name, bool $desc = true): mixed - { - if ($desc) { - return new $name(Query::SORT_DESC); - } - - return new $name(Query::SORT_ASC); - } } From a777492bcaf23370a03422b798103e7cd9b1dde1 Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Wed, 28 Aug 2024 12:26:37 +0200 Subject: [PATCH 08/15] NGSTACK-822 logic of ordering changes, string parameter replaced by QN --- bundle/QueryType/SearchQueryType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index f651d5d0..3ee002b4 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -47,7 +47,7 @@ protected function configureOptions(OptionsResolver $optionsResolver): void ); $optionsResolver->setAllowedValues( 'order', - static fn (string $searchText): bool => trim($searchText) === 'asc' || trim($searchText) === 'desc', + static fn (string $order): bool => in_array($order, [Query::SORT_ASC, Query::SORT_DESC], true), ); $optionsResolver->setDefault('content_types', $this->configResolver->getParameter('search.content_types', 'ngsite')); $optionsResolver->setDefault('subtree', $this->site->getSettings()->rootLocationId); From b5debe8075c0690a0d99fb44eb519e41188719f3 Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Wed, 28 Aug 2024 12:31:41 +0200 Subject: [PATCH 09/15] NGSTACK-822 added check if sort key class exists --- bundle/QueryType/SearchQueryType.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index 3ee002b4..b2672f20 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -86,7 +86,8 @@ protected function doGetQuery(array $parameters): Query private function sortKeysAllowed(array $keys): bool { foreach ($keys as $key) { - if (!class_exists($key)) { + if (!class_exists($key) || !is_a($key, SortClause::class, true)) { + return false; } } From 90ae053e553e7957a227171e49c96009a265d54b Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Wed, 28 Aug 2024 12:34:52 +0200 Subject: [PATCH 10/15] NGSTACK-822 php-cs-fixed --- bundle/QueryType/SearchQueryType.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index b2672f20..4ce12a13 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -13,7 +13,10 @@ use Netgen\IbexaSiteApi\API\Site; use Symfony\Component\OptionsResolver\OptionsResolver; +use function class_exists; use function count; +use function in_array; +use function is_a; use function trim; final class SearchQueryType extends OptionsResolverBasedQueryType @@ -21,8 +24,7 @@ final class SearchQueryType extends OptionsResolverBasedQueryType public function __construct( private readonly Site $site, private readonly ConfigResolverInterface $configResolver, - ) { - } + ) {} public static function getName(): string { @@ -87,12 +89,10 @@ private function sortKeysAllowed(array $keys): bool { foreach ($keys as $key) { if (!class_exists($key) || !is_a($key, SortClause::class, true)) { - return false; } } return true; } - } From f1827212bfd3530719a1c51e3c3d17db66c3ea4c Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Tue, 3 Sep 2024 17:19:15 +0200 Subject: [PATCH 11/15] NGSTACK-822 removed variable that is only used once --- bundle/QueryType/SearchQueryType.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index 4ce12a13..87aca80c 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -60,7 +60,7 @@ protected function configureOptions(OptionsResolver $optionsResolver): void protected function doGetQuery(array $parameters): Query { $subtreeLocation = $this->site->getLoadService()->loadLocation($parameters['subtree']); - $sortingKeys = $parameters['sort']; + $criteria = [ new Criterion\Subtree($subtreeLocation->pathString), new Criterion\Visibility(Criterion\Visibility::VISIBLE), @@ -72,7 +72,7 @@ protected function doGetQuery(array $parameters): Query $query->query = new FullText(trim($parameters['search_text'])); $query->filter = new Criterion\LogicalAnd($criteria); $sortClauses = []; - foreach ($sortingKeys as $sortingKey) { + foreach ($parameters['sort'] as $sortingKey) { $sortClauses[] = new $sortingKey($parameters['order']); } $query->sortClauses = $sortClauses; From 90259bf7a8d66a5320de6528c57c1c9da3158c6c Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Tue, 3 Sep 2024 17:20:44 +0200 Subject: [PATCH 12/15] NGSTACK-822 accidantely deleted newline returned --- bundle/QueryType/SearchQueryType.php | 1 + 1 file changed, 1 insertion(+) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index 87aca80c..b491770e 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -65,6 +65,7 @@ protected function doGetQuery(array $parameters): Query new Criterion\Subtree($subtreeLocation->pathString), new Criterion\Visibility(Criterion\Visibility::VISIBLE), ]; + if (count($parameters['content_types']) > 0) { $criteria[] = new Criterion\ContentTypeIdentifier($parameters['content_types']); } From 5bf05f1178035f0d47beb2523fa90c9603f13856 Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Tue, 3 Sep 2024 17:23:09 +0200 Subject: [PATCH 13/15] NGSTACK-822 unnecessary returns in PHPDoc removed --- bundle/QueryType/SearchQueryType.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index b491770e..f620d28a 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -65,7 +65,7 @@ protected function doGetQuery(array $parameters): Query new Criterion\Subtree($subtreeLocation->pathString), new Criterion\Visibility(Criterion\Visibility::VISIBLE), ]; - + if (count($parameters['content_types']) > 0) { $criteria[] = new Criterion\ContentTypeIdentifier($parameters['content_types']); } @@ -83,8 +83,6 @@ protected function doGetQuery(array $parameters): Query /** * @param string[] $keys - * - * @return bool */ private function sortKeysAllowed(array $keys): bool { From d0a1408f678375ce08c40a770c5d3f323b49761d Mon Sep 17 00:00:00 2001 From: Miljenko Muha Date: Tue, 3 Sep 2024 17:38:54 +0200 Subject: [PATCH 14/15] NGSTACK-822 sort keys nomenclature changed --- bundle/QueryType/SearchQueryType.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index f620d28a..ed1af522 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -44,8 +44,8 @@ protected function configureOptions(OptionsResolver $optionsResolver): void ); $optionsResolver->setAllowedValues( 'sort', - /** @var string[] $keys */ - fn (array $keys): bool => $this->sortKeysAllowed($keys), + /** @var string[] $classNames */ + fn (array $classNames): bool => $this->validateSortConfig($classNames), ); $optionsResolver->setAllowedValues( 'order', @@ -73,8 +73,8 @@ protected function doGetQuery(array $parameters): Query $query->query = new FullText(trim($parameters['search_text'])); $query->filter = new Criterion\LogicalAnd($criteria); $sortClauses = []; - foreach ($parameters['sort'] as $sortingKey) { - $sortClauses[] = new $sortingKey($parameters['order']); + foreach ($parameters['sort'] as $className) { + $sortClauses[] = new $className($parameters['order']); } $query->sortClauses = $sortClauses; @@ -82,12 +82,12 @@ protected function doGetQuery(array $parameters): Query } /** - * @param string[] $keys + * @param string[] $classNames */ - private function sortKeysAllowed(array $keys): bool + private function validateSortConfig(array $classNames): bool { - foreach ($keys as $key) { - if (!class_exists($key) || !is_a($key, SortClause::class, true)) { + foreach ($classNames as $className) { + if (!class_exists($className) || !is_a($className, SortClause::class, true)) { return false; } } From ca7fe2f8bba9e5e21b5498e6e38909b22427fed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edi=20Modri=C4=87?= Date: Wed, 4 Sep 2024 09:41:43 +0200 Subject: [PATCH 15/15] NGSTACK-822: Fix PHPStan issues --- bundle/QueryType/SearchQueryType.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/bundle/QueryType/SearchQueryType.php b/bundle/QueryType/SearchQueryType.php index ed1af522..c7cc002f 100644 --- a/bundle/QueryType/SearchQueryType.php +++ b/bundle/QueryType/SearchQueryType.php @@ -7,6 +7,7 @@ use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; use Ibexa\Contracts\Core\Repository\Values\Content\Query; use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; +use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface; use Ibexa\Core\QueryType\OptionsResolverBasedQueryType; use Netgen\Bundle\SiteBundle\API\Search\Criterion\FullText; @@ -34,26 +35,30 @@ public static function getName(): string protected function configureOptions(OptionsResolver $optionsResolver): void { $optionsResolver->setRequired(['search_text', 'content_types', 'subtree', 'sort', 'order']); + $optionsResolver->setAllowedTypes('search_text', 'string'); $optionsResolver->setAllowedTypes('content_types', 'string[]'); $optionsResolver->setAllowedTypes('sort', 'string[]'); $optionsResolver->setAllowedTypes('subtree', ['int', 'string']); + $optionsResolver->setAllowedValues( 'search_text', static fn (string $searchText): bool => trim($searchText) !== '', ); + $optionsResolver->setAllowedValues( 'sort', - /** @var string[] $classNames */ fn (array $classNames): bool => $this->validateSortConfig($classNames), ); + $optionsResolver->setAllowedValues( 'order', static fn (string $order): bool => in_array($order, [Query::SORT_ASC, Query::SORT_DESC], true), ); + $optionsResolver->setDefault('content_types', $this->configResolver->getParameter('search.content_types', 'ngsite')); $optionsResolver->setDefault('subtree', $this->site->getSettings()->rootLocationId); - $optionsResolver->setDefault('sort', [Query\SortClause\DatePublished::class]); + $optionsResolver->setDefault('sort', [SortClause\DatePublished::class]); $optionsResolver->setDefault('order', Query::SORT_DESC); } @@ -69,13 +74,18 @@ protected function doGetQuery(array $parameters): Query if (count($parameters['content_types']) > 0) { $criteria[] = new Criterion\ContentTypeIdentifier($parameters['content_types']); } + $query = new LocationQuery(); $query->query = new FullText(trim($parameters['search_text'])); $query->filter = new Criterion\LogicalAnd($criteria); + $sortClauses = []; + + /** @var class-string<\Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause> $className */ foreach ($parameters['sort'] as $className) { $sortClauses[] = new $className($parameters['order']); } + $query->sortClauses = $sortClauses; return $query;