diff --git a/CHANGELOG.md b/CHANGELOG.md index 59680d2c..9c5cfdec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ All notable changes to this project will be documented in this file. This project adheres to Semantic Versioning (http://semver.org/). +## 4.0.6 +* Support faceting and pagination in Category Merchandising query + ## 4.0.5 * Introduce new exception types for product building failures diff --git a/src/Operation/Recommendation/AbstractFilters.php b/src/Operation/Recommendation/AbstractFilters.php new file mode 100644 index 00000000..7fd2cba9 --- /dev/null +++ b/src/Operation/Recommendation/AbstractFilters.php @@ -0,0 +1,164 @@ + + * @copyright 2019 Nosto Solutions Ltd + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause + * + */ + +namespace Nosto\Operation\Recommendation; + +abstract class AbstractFilters +{ + /** @var string[] */ + public $brands = []; + + /** @var string[] */ + public $categories = []; + + /** @var array */ + public $customFields = []; + + /** @var boolean */ + public $discounted; + + /** @var string[] */ + public $productIds; + + /** @var string */ + public $search; + + /** @var string[] */ + public $tag1; + + /** @var string[] */ + public $tag2; + + /** @var string[] */ + public $tag3; + + /** + * @param string[] $brands + */ + public function setBrands(array $brands) + { + $this->brands = array_merge($this->brands, $brands); + } + + /** + * @param string[] $categories + */ + public function setCategories(array $categories) + { + $this->categories = array_merge($this->categories, $categories); + } + + /** + * @param string $attribute + * @param array $values + */ + public function setCustomFields($attribute, array $values) + { + foreach ($this->customFields as $customField) { + if ($customField['attribute'] === $attribute) { + $customField['values'] = array_merge($customField['values'], $values); + } + } + + $this->customFields[] = [ + 'attribute' => $attribute, + 'values' => $values + ]; + } + + /** + * @param boolean $discounted + */ + public function setDiscounted($discounted) + { + $this->discounted = $discounted; + } + + /** + * @param string[] $productIds + */ + public function setProductIds(array $productIds) + { + $this->productIds = array_merge($this->productIds, $productIds); + } + + /** + * @param string $search + */ + public function setSearch($search) + { + $this->search = $search; + } + + /** + * @param string[] $tag1 + */ + public function setTag1(array $tag1) + { + $this->tag1 = $tag1; + } + + /** + * @param string[] $tag2 + */ + public function setTag2(array $tag2) + { + $this->tag2 = $tag2; + } + + /** + * @param string[] $tag3 + */ + public function setTag3(array $tag3) + { + $this->tag3 = $tag3; + } + + /** + * @return array + * @suppress PhanTypeSuspiciousNonTraversableForeach + */ + public function toArray() + { + $array = []; + foreach ($this as $key => $value) { + if ($value !== null) { + $array = array_merge($array, [$key => $value]); + } + } + return $array; + } +} diff --git a/src/Operation/Recommendation/CategoryMerchandising.php b/src/Operation/Recommendation/CategoryMerchandising.php index 89b351f2..846af370 100644 --- a/src/Operation/Recommendation/CategoryMerchandising.php +++ b/src/Operation/Recommendation/CategoryMerchandising.php @@ -43,11 +43,23 @@ class CategoryMerchandising extends AbstractRecommendation /** @var string $category */ private $category; + /** @var IncludeFilters */ + private $includeFilters; + + /** @var ExcludeFilters */ + private $excludeFilters; + + /** @var int */ + private $skipPages; + /** * CategoryMerchandising constructor. * @param AccountInterface $account * @param $customerId * @param $category + * @param $skipPages + * @param IncludeFilters $includeFilters + * @param ExcludeFilters $excludeFilters * @param string $activeDomain * @param string $customerBy * @param bool $previewMode @@ -57,12 +69,18 @@ public function __construct( AccountInterface $account, $customerId, $category, + $skipPages, + IncludeFilters $includeFilters, + ExcludeFilters $excludeFilters, $activeDomain = '', $customerBy = self::IDENTIFIER_BY_CID, $previewMode = false, $limit = self::LIMIT ) { $this->category = $category; + $this->skipPages = $skipPages; + $this->includeFilters = $includeFilters; + $this->excludeFilters = $excludeFilters; parent::__construct($account, $customerId, $activeDomain, $customerBy, $previewMode, $limit); } @@ -73,28 +91,29 @@ public function getQuery() { $query = << $this->category, 'limit' => $this->limit, 'preview' => $this->previewMode, - 'by' => $this->customerBy + 'by' => $this->customerBy, + 'skipPages' => $this->skipPages, + 'includeFilters' => $this->includeFilters->toArray(), + 'excludeFilters' => $this->excludeFilters->toArray() ]; return $variables; diff --git a/src/Operation/Recommendation/ExcludeFilters.php b/src/Operation/Recommendation/ExcludeFilters.php new file mode 100644 index 00000000..371bf1b3 --- /dev/null +++ b/src/Operation/Recommendation/ExcludeFilters.php @@ -0,0 +1,42 @@ + + * @copyright 2019 Nosto Solutions Ltd + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause + * + */ + +namespace Nosto\Operation\Recommendation; + +class ExcludeFilters extends AbstractFilters +{ + +} diff --git a/src/Operation/Recommendation/IncludeFilters.php b/src/Operation/Recommendation/IncludeFilters.php new file mode 100644 index 00000000..0e48624d --- /dev/null +++ b/src/Operation/Recommendation/IncludeFilters.php @@ -0,0 +1,97 @@ + + * @copyright 2019 Nosto Solutions Ltd + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause + * + */ + +namespace Nosto\Operation\Recommendation; + +class IncludeFilters extends AbstractFilters +{ + /** @var boolean */ + public $fresh; + + /** @var array */ + public $price; + + /** @var float */ + public $rating; + + /** @var int */ + public $reviews; + + /** @var array */ + public $stock; + + /** + * @param boolean $fresh + */ + public function setFresh($fresh) + { + $this->fresh = $fresh; + } + + /** + * @param int $min + * @param int $max + */ + public function setPrice($min, $max) + { + $this->price = ['min' => $min, 'max' => $max]; + } + + /** + * @param float $rating + */ + public function setRating($rating) + { + $this->rating = $rating; + } + + /** + * @param int $reviews + */ + public function setReviews($reviews) + { + $this->reviews = $reviews; + } + + /** + * @param int $min + * @param int $max + */ + public function setStock($min, $max) + { + $this->stock = ['min' => $min, 'max' => $max]; + } +} diff --git a/src/Result/Graphql/Recommendation/CategoryMerchandisingResult.php b/src/Result/Graphql/Recommendation/CategoryMerchandisingResult.php index 98565e7d..8b944549 100644 --- a/src/Result/Graphql/Recommendation/CategoryMerchandisingResult.php +++ b/src/Result/Graphql/Recommendation/CategoryMerchandisingResult.php @@ -44,17 +44,25 @@ class CategoryMerchandisingResult /** @var string $trackingCode */ private $trackingCode; + /** @var int $totalPrimaryCount */ + private $totalPrimaryCount; + /** * CategoryMerchandisingResult constructor. * @param ResultSet $resultSet * @param string $trackingCode + * @param int $totalPrimaryCount */ - public function __construct(ResultSet $resultSet, $trackingCode) - { + public function __construct( + ResultSet $resultSet, + $trackingCode, + $totalPrimaryCount + ) { $this->resultSet = $resultSet; $this->trackingCode = $trackingCode; + $this->totalPrimaryCount = $totalPrimaryCount; } - + /** * @return ResultSet */ @@ -70,4 +78,12 @@ public function getTrackingCode() { return $this->trackingCode; } + + /** + * @return int + */ + public function getTotalPrimaryCount() + { + return $this->totalPrimaryCount; + } } diff --git a/src/Result/Graphql/Recommendation/RecommendationResultHandler.php b/src/Result/Graphql/Recommendation/RecommendationResultHandler.php index bcb7c3ac..11bfc781 100644 --- a/src/Result/Graphql/Recommendation/RecommendationResultHandler.php +++ b/src/Result/Graphql/Recommendation/RecommendationResultHandler.php @@ -45,6 +45,7 @@ class RecommendationResultHandler extends GraphQLResultHandler const GRAPHQL_DATA_PRIMARY = 'primary'; const GRAPHQL_DATA_CATEGORY = 'category'; const GRAPHQL_DATA_RESULT_ID = 'resultId'; + const GRAPHQL_DATA_PRIMARY_COUNT = 'totalPrimaryCount'; /** * @inheritdoc @@ -53,11 +54,17 @@ protected function parseQueryResult(\stdClass $stdClass) { /** @var \stdClass $categoryData */ $categoryData = self::parseData($stdClass, self::GRAPHQL_DATA_CATEGORY); - /** @var string $trackingCode */ $trackingCode = self::parseData($categoryData, self::GRAPHQL_DATA_RESULT_ID); + /** @var int $totalPrimaryCount */ + $totalPrimaryCount = self::parseData($categoryData, self::GRAPHQL_DATA_PRIMARY_COUNT); + /** @var ResultSet $resultSet */ $resultSet = self::buildResultSet($categoryData); - return new CategoryMerchandisingResult($resultSet, $trackingCode); + return new CategoryMerchandisingResult( + $resultSet, + $trackingCode, + $totalPrimaryCount + ); } /** @@ -83,7 +90,7 @@ private static function buildResultSet(\stdClass $stdClass) /** * @param \stdClass $stdClass * @param string $dataType - * @return string|\stdClass|array + * @return string|int|\stdClass|array * @throws NostoException */ private static function parseData(\stdClass $stdClass, $dataType)