vendor/crehler/mojebambino-catalog/src/Service/CatalogReader/Loader/CatalogPageLoader.php line 192

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4.  * @copyright 2020 Crehler Sp. z o. o.
  5.  * @link https://crehler.com/
  6.  * @support support@crehler.com
  7.  *
  8.  * @author Mateusz FlasiƄski
  9.  *
  10.  * For the full copyright and license information, please view the LICENSE
  11.  * file that was distributed with this source code.
  12.  */
  13. namespace Crehler\Catalog\Service\CatalogReader\Loader;
  14. use Crehler\Catalog\Entity\Catalog\Aggregate\CatalogBookmarks\CatalogBookmarksEntity;
  15. use Crehler\Catalog\Entity\Catalog\Aggregate\CatalogPage\CatalogPageEntity;
  16. use Crehler\Catalog\Entity\Catalog\CatalogDefinition;
  17. use Crehler\Catalog\Entity\Catalog\CatalogEntity;
  18. use Crehler\Catalog\Service\CatalogReader\UrlGenerator;
  19. use Crehler\Catalog\Service\Media\MediaLoaderInterface;
  20. use Crehler\Catalog\Struct\CatalogDetail\CatalogDetailDotStruct;
  21. use Crehler\Catalog\Struct\CatalogDetail\CatalogDetailPageStruct;
  22. use Crehler\Catalog\Struct\CatalogDetail\CatalogDetailSeoStruct;
  23. use Crehler\Catalog\Struct\CatalogDetail\CatalogDetailStruct;
  24. use Crehler\Catalog\Struct\CatalogDetail\CatalogPageNavigationStruct;
  25. use Crehler\Catalog\Struct\CatalogPageStruct;
  26. use Doctrine\DBAL\Connection;
  27. use Shopware\Core\Framework\Context;
  28. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  29. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  30. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  31. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  32. use Shopware\Core\Framework\Uuid\Uuid;
  33. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  34. use Symfony\Component\HttpFoundation\Request;
  35. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  36. class CatalogPageLoader
  37. {
  38.     private EntityRepositoryInterface $catalogRepository;
  39.     private EntityRepositoryInterface $catalogPageRepository;
  40.     private EntityRepositoryInterface $catalogBookmarkRepository;
  41.     private EntityRepositoryInterface $catalogProductDotRepository;
  42.     private Connection $connection;
  43.     private UrlGenerator $urlGenerator;
  44.     private MediaLoaderInterface $mediaLoaderService;
  45.     public function __construct(EntityRepositoryInterface $catalogRepository,
  46.                                 EntityRepositoryInterface $catalogPageRepository,
  47.                                 EntityRepositoryInterface $catalogBookmarkRepository,
  48.                                 Connection $connection,
  49.                                 EntityRepositoryInterface $catalogProductDotRepository,
  50.                                 UrlGenerator $urlGenerator,
  51.                                 MediaLoaderInterface $mediaLoaderService)
  52.     {
  53.         $this->catalogRepository $catalogRepository;
  54.         $this->catalogPageRepository $catalogPageRepository;
  55.         $this->catalogBookmarkRepository $catalogBookmarkRepository;
  56.         $this->connection $connection;
  57.         $this->catalogProductDotRepository $catalogProductDotRepository;
  58.         $this->urlGenerator $urlGenerator;
  59.         $this->mediaLoaderService $mediaLoaderService;
  60.     }
  61.     public function load(Request $requestSalesChannelContext $context): CatalogPageStruct
  62.     {
  63.         $catalogId $request->get('catalogId'null);
  64.         $pageId $request->get('pageId'null);
  65.         $bookmarkId $request->get('bookmarkId'null);
  66.         if ($catalogId === null && $pageId !== null) {
  67.             $catalogId $this->getCatalogIdByPage($pageId$context->getContext());
  68.         } elseif ($catalogId === null && $bookmarkId !== null) {
  69.             $bookmark $this->getCatalogBookmark($bookmarkId$context->getContext());
  70.             if ($bookmark !== null) {
  71.                 $catalogId $bookmark->getCatalogId();
  72.                 $pageId $bookmark->getCatalogPageId();
  73.             }
  74.         }
  75.         if ($catalogId === null) {
  76.             throw new NotFoundHttpException();
  77.         }
  78.         $criteria = new Criteria([$catalogId]);
  79.         $criteria->addAssociations(['pages''productBoxImageMedia']);
  80.         $criteria->addFilter(new EqualsFilter('status'CatalogDefinition::STATUS_PUBLISHED));
  81.         /** @var CatalogEntity $catalogEntity */
  82.         $catalogEntity $this->catalogRepository->search($criteria$context->getContext())->first();
  83.         if ($catalogEntity === null) {
  84.             throw new NotFoundHttpException();
  85.         }
  86.         $struct = new CatalogPageStruct();
  87.         $struct->setCatalog($catalogEntity);
  88.         if ($pageId !== null) {
  89.             $currentPage $catalogEntity->getPages()->get($pageId);
  90.         } else {
  91.             $currentPage $catalogEntity->getPages()->getByPageNumber(1);
  92.         }
  93.         $struct->setCatalogPageEntity($currentPage)
  94.             ->setCatalogPages($catalogEntity->getPages());
  95.         $products $this->getProducts($currentPage->getId());
  96.         $struct->setCatalogProductsIds($products);
  97.         return $struct;
  98.     }
  99.     public function getProducts(string $catalogPageId): array
  100.     {
  101.         $qb $this->connection->createQueryBuilder();
  102.         $data $qb->select('id as mappingId, product_id as productId')
  103.             ->from('catalog_page_product')
  104.             ->where('catalog_page_id = :page')
  105.             ->setParameter('page'Uuid::fromHexToBytes($catalogPageId))
  106.             ->orderBy('auto_increment''ASC')
  107.             ->execute()
  108.             ->fetchAll();
  109.         return array_map(function ($item) {
  110.             return [
  111.                 'mappingId' => Uuid::fromBytesToHex($item['mappingId']),
  112.                 'productId' => Uuid::fromBytesToHex($item['productId']),
  113.             ];
  114.         }, $data);
  115.     }
  116.     public function getPageDetail(string $pageIdSalesChannelContext $salesChannelContextint $displayType 1): CatalogDetailStruct
  117.     {
  118.         $struct = new CatalogDetailStruct();
  119.         $struct->setRequestedId($pageId);
  120.         $firstPage $this->loadDetailStruct($pageId$salesChannelContext);
  121.         if ($displayType === 1) {
  122.             $struct->setLeft($firstPage);
  123.             $this->loadAdditionalDetailData($struct$salesChannelContext);
  124.             return $struct;
  125.         } elseif ($firstPage->getPage()->getPageNumber() % !== 0) { // Nieparzysta
  126.             $struct->setRight($firstPage);
  127.             $secondPageNumber $firstPage->getPage()->getPageNumber() - 1;
  128.             $secondIsRight false;
  129.         } else {
  130.             $struct->setLeft($firstPage);
  131.             $secondPageNumber $firstPage->getPage()->getPageNumber() + 1;
  132.             $secondIsRight true;
  133.         }
  134.         $criteria = new Criteria();
  135.         $criteria->addFilter(
  136.             new MultiFilter(
  137.                 MultiFilter::CONNECTION_AND,
  138.                 [
  139.                     new EqualsFilter('pageNumber'$secondPageNumber),
  140.                     new EqualsFilter('catalogId'$firstPage->getPage()->getCatalogId()),
  141.                 ]
  142.             )
  143.         );
  144.         $id $this->catalogPageRepository->searchIds($criteria$salesChannelContext->getContext())->firstId();
  145.         if ($id === null) {
  146.             $this->loadAdditionalDetailData($struct$salesChannelContext);
  147.             return $struct;
  148.         }
  149.         $secondPage $this->loadDetailStruct($id$salesChannelContext);
  150.         if ($secondIsRight) {
  151.             $struct->setRight($secondPage);
  152.         } else {
  153.             $struct->setLeft($secondPage);
  154.         }
  155.         $this->loadAdditionalDetailData($struct$salesChannelContext);
  156.         return $struct;
  157.     }
  158.     private function getCatalogIdByPage(string $pageIdContext $context): ?string
  159.     {
  160.         $criteria = new Criteria([$pageId]);
  161.         /** @var CatalogPageEntity $page */
  162.         $page $this->catalogPageRepository->search($criteria$context)->first();
  163.         return $page->getCatalogId();
  164.     }
  165.     private function getCatalogBookmark(string $bookmarkIdContext $context): ?CatalogBookmarksEntity
  166.     {
  167.         $criteria = new Criteria([$bookmarkId]);
  168.         return $this->catalogBookmarkRepository->search($criteria$context)->first();
  169.     }
  170.     private function loadAdditionalDetailData(CatalogDetailStruct $catalogDetailStructSalesChannelContext $salesChannelContext)
  171.     {
  172.         $this->loadNextAndPrevPages($catalogDetailStruct$salesChannelContext);
  173.         $this->loadSeoMeta($catalogDetailStruct$salesChannelContext);
  174.     }
  175.     private function loadSeoMeta(CatalogDetailStruct $catalogDetailStructSalesChannelContext $salesChannelContext)
  176.     {
  177.         $page null;
  178.         if ($catalogDetailStruct->getLeft() !== null && $catalogDetailStruct->getLeft()->getPage()->getId() === $catalogDetailStruct->getRequestedId()) {
  179.             $page $catalogDetailStruct->getLeft();
  180.         } elseif ($catalogDetailStruct->getRight() !== null && $catalogDetailStruct->getRight()->getPage()->getId() === $catalogDetailStruct->getRequestedId()) {
  181.             $page $catalogDetailStruct->getRight();
  182.         }
  183.         if ($page === null) {
  184.             return;
  185.         }
  186.         $struct = new CatalogDetailSeoStruct();
  187.         $url $this->urlGenerator->generateDetailUrl($page->getPage(), $salesChannelContext);
  188.         $struct->setSeoDescription($page->getSeoDescription())
  189.             ->setSeoTitle($page->getSeoTitle())
  190.             ->setSeoThumbnail($page->getMediaEntity()->getUrl())
  191.             ->setSeoUrl($url);
  192.         $catalogDetailStruct->setSeo($struct);
  193.     }
  194.     private function loadNextAndPrevPages(CatalogDetailStruct $catalogDetailStructSalesChannelContext $salesChannelContext)
  195.     {
  196.         if ($catalogDetailStruct->getLeft() !== null) {
  197.             $prevPageNumber $catalogDetailStruct->getLeft()->getPage()->getPageNumber() - 1;
  198.             $catalogId $catalogDetailStruct->getLeft()->getPage()->getCatalogId();
  199.         } else {
  200.             $prevPageNumber $catalogDetailStruct->getRight()->getPage()->getPageNumber() - 1;
  201.             $catalogId $catalogDetailStruct->getRight()->getPage()->getCatalogId();
  202.         }
  203.         if ($catalogDetailStruct->getRight() !== null) {
  204.             $nextPageNumber $catalogDetailStruct->getRight()->getPage()->getPageNumber() + 1;
  205.         } else {
  206.             $nextPageNumber $catalogDetailStruct->getLeft()->getPage()->getPageNumber() + 1;
  207.         }
  208.         $catalogDetailStruct->setPrev($this->findPage($prevPageNumber$catalogId$salesChannelContext));
  209.         $catalogDetailStruct->setNext($this->findPage($nextPageNumber$catalogId$salesChannelContext));
  210.     }
  211.     private function findPage(int $pageNumberstring $catalogIdSalesChannelContext $salesChannelContext): CatalogPageNavigationStruct
  212.     {
  213.         $struct = new CatalogPageNavigationStruct();
  214.         $criteria = new Criteria();
  215.         $criteria->addFilter(new EqualsFilter('catalogId'$catalogId));
  216.         $criteria->addFilter(new EqualsFilter('pageNumber'$pageNumber));
  217.         $page $this->catalogPageRepository->search($criteria$salesChannelContext->getContext())->first();
  218.         if ($page === null) {
  219.             return $struct;
  220.         }
  221.         $url $this->urlGenerator->generateDetailUrl($page$salesChannelContext);
  222.         $struct->setUrl($url)
  223.             ->setId($page->getId())
  224.             ->setAvailable(true);
  225.         return $struct;
  226.     }
  227.     private function loadDetailStruct(string $pageIdSalesChannelContext $salesChannelContext): CatalogDetailPageStruct
  228.     {
  229. //        $timer = Timer::start('loadDetailStruct');
  230. //        $partTimer = Timer::start('loadDetailStructPart');
  231.         $times = [];
  232.         $struct = new CatalogDetailPageStruct();
  233. //        $times['structCreate'] = $partTimer->stop()['duration'];
  234. //        $partTimer = Timer::start('loadDetailStructPart');
  235.         $criteria = new Criteria([$pageId]);
  236.         $criteria->addAssociations(['media''pdf''catalog''bookmarks']);
  237. //        $times['criteriaCreate'] = $partTimer->stop()['duration'];
  238. //        $partTimer = Timer::start('loadDetailStructPart');
  239.         /** @var CatalogPageEntity $page */
  240.         $page $this->catalogPageRepository->search($criteria$salesChannelContext->getContext())->first();
  241. //        $times['pageSearch'] = $partTimer->stop()['duration'];
  242. //        $partTimer = Timer::start('loadDetailStructPart');
  243.         $catalog $page->getCatalog();
  244.         $bookmark $page->getBookmarks()->first();
  245.         if ($page->getSeoTitle() !== null) {
  246.             $struct->setSeoTitle($page->getSeoTitle());
  247.         } elseif ($bookmark !== null && $bookmark['seoTitle'] !== null) {
  248.             $struct->setSeoTitle($bookmark['seoTitle']);
  249.         } elseif ($catalog->getSeoTitle() !== null) {
  250.             $struct->setSeoTitle($catalog->getSeoTitle());
  251.         }
  252.         if ($page->getSeoDescription() !== null) {
  253.             $struct->setSeoDescription($page->getSeoDescription());
  254.         } elseif ($bookmark !== null && $bookmark['seoDescription'] !== null) {
  255.             $struct->setSeoDescription($bookmark['seoDescription']);
  256.         } elseif ($catalog->getSeoDescription() !== null) {
  257.             $struct->setSeoDescription($catalog->getSeoDescription());
  258.         }
  259. //        $times['seo'] = $partTimer->stop()['duration'];
  260. //        $partTimer = Timer::start('loadDetailStructPart');
  261.         $dotsCriteria = new Criteria();
  262.         $dotsCriteria->addFilter(
  263.             new MultiFilter(
  264.                 MultiFilter::CONNECTION_AND,
  265.                 [
  266.                     new EqualsFilter('catalogPageId'$pageId),
  267.                     new EqualsFilter('enabled'true),
  268.                 ]
  269.             )
  270.         );
  271. //        $times['dotsCriteria'] = $partTimer->stop()['duration'];
  272. //        $partTimer = Timer::start('loadDetailStructPart');
  273.         $dots $this->catalogProductDotRepository->search($dotsCriteria$salesChannelContext->getContext());
  274. //        $times['dotsSearch'] = $partTimer->stop()['duration'];
  275. //        $partTimer = Timer::start('loadDetailStructPart');
  276.         foreach ($dots->getElements() as $dot) {
  277.             $dotStruct = new CatalogDetailDotStruct();
  278.             $dotStruct->setX($dot['xPosition'])
  279.                 ->setY($dot['yPosition'])
  280.                 ->setProductId($dot['catalogProductId'])
  281.                 ->setRadius($dot['radius'])
  282.                 ->setHideOnMobile($dot['hideOnMobile']);
  283.             $struct->getDot()->append($dotStruct);
  284.         }
  285. //        $times['dotsStruct'] = $partTimer->stop()['duration'];
  286. //        $partTimer = Timer::start('loadDetailStructPart');
  287.         $struct->setMediaEntity($page->getMedia())
  288.             ->setPdf($page->getPdf()->getUrl())
  289.             ->setPage($page);
  290. //        $times['mediaPdfAndPage'] = $partTimer->stop()['duration'];
  291. //        $partTimer = Timer::start('loadDetailStructPart');
  292.         $mediaCollection $this->mediaLoaderService->loadMediaStruct($page->getMedia());
  293. //        $times['mediaCollection'] = $partTimer->stop()['duration'];
  294. //        $partTimer = Timer::start('loadDetailStructPart');
  295.         $struct->setMedia($mediaCollection);
  296. //        $times['all'] = $timer->stop()['duration'];
  297. //
  298. //        $struct->setTimer($times);
  299.         return $struct;
  300.     }
  301. }