vendor/shopware/core/Content/Product/Cms/ProductDescriptionReviewsCmsElementResolver.php line 48

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Product\Cms;
  3. use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
  4. use Shopware\Core\Content\Cms\DataResolver\Element\ElementDataCollection;
  5. use Shopware\Core\Content\Cms\DataResolver\ResolverContext\EntityResolverContext;
  6. use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
  7. use Shopware\Core\Content\Cms\SalesChannel\Struct\ProductDescriptionReviewsStruct;
  8. use Shopware\Core\Content\Product\Aggregate\ProductReview\ProductReviewEntity;
  9. use Shopware\Core\Content\Product\SalesChannel\Review\AbstractProductReviewRoute;
  10. use Shopware\Core\Content\Product\SalesChannel\Review\ProductReviewResult;
  11. use Shopware\Core\Content\Product\SalesChannel\Review\RatingMatrix;
  12. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Bucket\FilterAggregation;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Bucket\TermsAggregation;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Bucket\TermsResult;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  19. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  20. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
  21. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  22. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  23. use Symfony\Component\HttpFoundation\Request;
  24. class ProductDescriptionReviewsCmsElementResolver extends AbstractProductDetailCmsElementResolver
  25. {
  26.     private const LIMIT 10;
  27.     private const DEFAULT_PAGE 1;
  28.     private const FILTER_LANGUAGE 'filter-language';
  29.     private AbstractProductReviewRoute $productReviewRoute;
  30.     /**
  31.      * @internal
  32.      */
  33.     public function __construct(AbstractProductReviewRoute $productReviewRoute)
  34.     {
  35.         $this->productReviewRoute $productReviewRoute;
  36.     }
  37.     public function getType(): string
  38.     {
  39.         return 'product-description-reviews';
  40.     }
  41.     public function enrich(CmsSlotEntity $slotResolverContext $resolverContextElementDataCollection $result): void
  42.     {
  43.         $data = new ProductDescriptionReviewsStruct();
  44.         $slot->setData($data);
  45.         $productConfig $slot->getFieldConfig()->get('product');
  46.         if ($productConfig === null) {
  47.             return;
  48.         }
  49.         $request $resolverContext->getRequest();
  50.         $ratingSuccess = (bool) $request->get('success'false);
  51.         $data->setRatingSuccess($ratingSuccess);
  52.         $product null;
  53.         if ($productConfig->isMapped() && $resolverContext instanceof EntityResolverContext) {
  54.             $product $this->resolveEntityValue($resolverContext->getEntity(), $productConfig->getStringValue());
  55.         }
  56.         if ($productConfig->isStatic()) {
  57.             $product $this->getSlotProduct($slot$result$productConfig->getStringValue());
  58.         }
  59.         /** @var SalesChannelProductEntity|null $product */
  60.         if ($product !== null) {
  61.             $data->setProduct($product);
  62.             $data->setReviews($this->loadProductReviews($product$request$resolverContext->getSalesChannelContext()));
  63.         }
  64.     }
  65.     private function loadProductReviews(SalesChannelProductEntity $productRequest $requestSalesChannelContext $context): ProductReviewResult
  66.     {
  67.         $reviewCriteria $this->createReviewCriteria($request$context);
  68.         $reviews $this->productReviewRoute
  69.             ->load($product->getParentId() ?? $product->getId(), $request$context$reviewCriteria)
  70.             ->getResult();
  71.         $matrix $this->getReviewRatingMatrix($reviews);
  72.         $reviewResult ProductReviewResult::createFrom($reviews);
  73.         $reviewResult->setMatrix($matrix);
  74.         $reviewResult->setProductId($product->getId());
  75.         $reviewResult->setCustomerReview($this->getCustomerReview($product->getId(), $context));
  76.         $reviewResult->setTotalReviews($matrix->getTotalReviewCount());
  77.         $reviewResult->setProductId($product->getId());
  78.         $reviewResult->setParentId($product->getParentId() ?? $product->getId());
  79.         return $reviewResult;
  80.     }
  81.     private function createReviewCriteria(Request $requestSalesChannelContext $context): Criteria
  82.     {
  83.         $limit = (int) $request->get('limit'self::LIMIT);
  84.         $page = (int) $request->get('p'self::DEFAULT_PAGE);
  85.         $offset $limit * ($page 1);
  86.         $criteria = new Criteria();
  87.         $criteria->setLimit($limit);
  88.         $criteria->setOffset($offset);
  89.         $sorting = new FieldSorting('createdAt''DESC');
  90.         if ($request->get('sort''points') === 'points') {
  91.             $sorting = new FieldSorting('points''DESC');
  92.         }
  93.         $criteria->addSorting($sorting);
  94.         if ($request->get('language') === self::FILTER_LANGUAGE) {
  95.             $criteria->addPostFilter(
  96.                 new EqualsFilter('languageId'$context->getContext()->getLanguageId())
  97.             );
  98.         }
  99.         $this->handlePointsAggregation($request$criteria);
  100.         return $criteria;
  101.     }
  102.     private function handlePointsAggregation(Request $requestCriteria $criteria): void
  103.     {
  104.         $points $request->get('points', []);
  105.         if (\is_array($points) && \count($points) > 0) {
  106.             $pointFilter = [];
  107.             foreach ($points as $point) {
  108.                 $pointFilter[] = new RangeFilter('points', [
  109.                     'gte' => $point 0.5,
  110.                     'lt' => $point 0.5,
  111.                 ]);
  112.             }
  113.             $criteria->addPostFilter(new MultiFilter(MultiFilter::CONNECTION_OR$pointFilter));
  114.         }
  115.         $criteria->addAggregation(
  116.             new FilterAggregation(
  117.                 'status-filter',
  118.                 new TermsAggregation('ratingMatrix''points'),
  119.                 [new EqualsFilter('status'1)]
  120.             )
  121.         );
  122.     }
  123.     private function getCustomerReview(string $productIdSalesChannelContext $context): ?ProductReviewEntity
  124.     {
  125.         $customer $context->getCustomer();
  126.         if (!$customer) {
  127.             return null;
  128.         }
  129.         $criteria = new Criteria();
  130.         $criteria->setLimit(1);
  131.         $criteria->setOffset(0);
  132.         $criteria->addFilter(new EqualsFilter('customerId'$customer->getId()));
  133.         $customerReviews $this->productReviewRoute
  134.             ->load($productId, new Request(), $context$criteria)
  135.             ->getResult();
  136.         return $customerReviews->first();
  137.     }
  138.     private function getReviewRatingMatrix(EntitySearchResult $reviews): RatingMatrix
  139.     {
  140.         $aggregation $reviews->getAggregations()->get('ratingMatrix');
  141.         if ($aggregation instanceof TermsResult) {
  142.             return new RatingMatrix($aggregation->getBuckets());
  143.         }
  144.         return new RatingMatrix([]);
  145.     }
  146. }