vendor/shopware/storefront/Controller/WishlistController.php line 68

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Storefront\Controller;
  3. use Shopware\Core\Checkout\Customer\CustomerEntity;
  4. use Shopware\Core\Checkout\Customer\Exception\CustomerWishlistNotFoundException;
  5. use Shopware\Core\Checkout\Customer\Exception\DuplicateWishlistProductException;
  6. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractAddWishlistProductRoute;
  7. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractLoadWishlistRoute;
  8. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractMergeWishlistProductRoute;
  9. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractRemoveWishlistProductRoute;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\Log\Package;
  12. use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
  13. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  14. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  15. use Shopware\Storefront\Page\Wishlist\GuestWishlistPageLoadedHook;
  16. use Shopware\Storefront\Page\Wishlist\GuestWishlistPageLoader;
  17. use Shopware\Storefront\Page\Wishlist\WishlistPageLoadedHook;
  18. use Shopware\Storefront\Page\Wishlist\WishlistPageLoader;
  19. use Shopware\Storefront\Page\Wishlist\WishListPageProductCriteriaEvent;
  20. use Shopware\Storefront\Page\Wishlist\WishlistWidgetLoadedHook;
  21. use Shopware\Storefront\Pagelet\Wishlist\GuestWishlistPageletLoadedHook;
  22. use Shopware\Storefront\Pagelet\Wishlist\GuestWishlistPageletLoader;
  23. use Symfony\Component\HttpFoundation\JsonResponse;
  24. use Symfony\Component\HttpFoundation\Request;
  25. use Symfony\Component\HttpFoundation\Response;
  26. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  27. use Symfony\Component\Routing\Annotation\Route;
  28. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  29. /**
  30.  * @internal
  31.  * Do not use direct or indirect repository calls in a controller. Always use a store-api route to get or put data
  32.  */
  33. #[Route(defaults: ['_routeScope' => ['storefront']])]
  34. #[Package('storefront')]
  35. class WishlistController extends StorefrontController
  36. {
  37.     /**
  38.      * @internal
  39.      */
  40.     public function __construct(
  41.         private readonly WishlistPageLoader $wishlistPageLoader,
  42.         private readonly AbstractLoadWishlistRoute $wishlistLoadRoute,
  43.         private readonly AbstractAddWishlistProductRoute $addWishlistRoute,
  44.         private readonly AbstractRemoveWishlistProductRoute $removeWishlistProductRoute,
  45.         private readonly AbstractMergeWishlistProductRoute $mergeWishlistProductRoute,
  46.         private readonly GuestWishlistPageLoader $guestPageLoader,
  47.         private readonly GuestWishlistPageletLoader $guestPageletLoader,
  48.         private readonly EventDispatcherInterface $eventDispatcher
  49.     ) {
  50.     }
  51.     #[Route(path'/wishlist'name'frontend.wishlist.page'options: ['seo' => false], defaults: ['_noStore' => true], methods: ['GET'])]
  52.     public function index(Request $requestSalesChannelContext $context): Response
  53.     {
  54.         $customer $context->getCustomer();
  55.         if ($customer !== null && $customer->getGuest() === false) {
  56.             $page $this->wishlistPageLoader->load($request$context$customer);
  57.             $this->hook(new WishlistPageLoadedHook($page$context));
  58.         } else {
  59.             $page $this->guestPageLoader->load($request$context);
  60.             $this->hook(new GuestWishlistPageLoadedHook($page$context));
  61.         }
  62.         return $this->renderStorefront('@Storefront/storefront/page/wishlist/index.html.twig', ['page' => $page]);
  63.     }
  64.     #[Route(path'/wishlist/guest-pagelet'name'frontend.wishlist.guestPage.pagelet'options: ['seo' => false], defaults: ['XmlHttpRequest' => true], methods: ['POST'])]
  65.     public function guestPagelet(Request $requestSalesChannelContext $context): Response
  66.     {
  67.         $customer $context->getCustomer();
  68.         if ($customer !== null && $customer->getGuest() === false) {
  69.             throw new NotFoundHttpException();
  70.         }
  71.         $pagelet $this->guestPageletLoader->load($request$context);
  72.         $this->hook(new GuestWishlistPageletLoadedHook($pagelet$context));
  73.         return $this->renderStorefront(
  74.             '@Storefront/storefront/page/wishlist/wishlist-pagelet.html.twig',
  75.             ['page' => $pagelet'searchResult' => $pagelet->getSearchResult()->getObject()]
  76.         );
  77.     }
  78.     #[Route(path'/widgets/wishlist'name'widgets.wishlist.pagelet'options: ['seo' => false], defaults: ['XmlHttpRequest' => true'_loginRequired' => true], methods: ['GET''POST'])]
  79.     public function ajaxPagination(Request $requestSalesChannelContext $contextCustomerEntity $customer): Response
  80.     {
  81.         $request->request->set('no-aggregations'true);
  82.         $page $this->wishlistPageLoader->load($request$context$customer);
  83.         $this->hook(new WishlistPageLoadedHook($page$context));
  84.         $response $this->renderStorefront('@Storefront/storefront/page/wishlist/index.html.twig', ['page' => $page]);
  85.         $response->headers->set('x-robots-tag''noindex');
  86.         return $response;
  87.     }
  88.     #[Route(path'/wishlist/list'name'frontend.wishlist.product.list'options: ['seo' => false], defaults: ['XmlHttpRequest' => true'_loginRequired' => true], methods: ['GET'])]
  89.     public function ajaxList(Request $requestSalesChannelContext $contextCustomerEntity $customer): Response
  90.     {
  91.         $criteria = new Criteria();
  92.         $this->eventDispatcher->dispatch(new WishListPageProductCriteriaEvent($criteria$context$request));
  93.         try {
  94.             $res $this->wishlistLoadRoute->load($request$context$criteria$customer);
  95.         } catch (CustomerWishlistNotFoundException) {
  96.             return new JsonResponse([]);
  97.         }
  98.         return new JsonResponse($res->getProductListing()->getIds());
  99.     }
  100.     #[Route(path'/wishlist/product/delete/{id}'name'frontend.wishlist.product.delete'defaults: ['XmlHttpRequest' => true'_loginRequired' => true], methods: ['POST''DELETE'])]
  101.     public function remove(string $idRequest $requestSalesChannelContext $contextCustomerEntity $customer): Response
  102.     {
  103.         if (!$id) {
  104.             throw new MissingRequestParameterException('Parameter id missing');
  105.         }
  106.         try {
  107.             $this->removeWishlistProductRoute->delete($id$context$customer);
  108.             $this->addFlash(self::SUCCESS$this->trans('wishlist.itemDeleteSuccess'));
  109.         } catch (\Throwable) {
  110.             $this->addFlash(self::DANGER$this->trans('error.message-default'));
  111.         }
  112.         return $this->createActionResponse($request);
  113.     }
  114.     #[Route(path'/wishlist/add/{productId}'name'frontend.wishlist.product.add'options: ['seo' => false], defaults: ['XmlHttpRequest' => true'_loginRequired' => true], methods: ['POST'])]
  115.     public function ajaxAdd(string $productIdSalesChannelContext $contextCustomerEntity $customer): JsonResponse
  116.     {
  117.         try {
  118.             $this->addWishlistRoute->add($productId$context$customer);
  119.             $success true;
  120.         } catch (\Throwable) {
  121.             $success false;
  122.         }
  123.         return new JsonResponse([
  124.             'success' => $success,
  125.         ]);
  126.     }
  127.     #[Route(path'/wishlist/remove/{productId}'name'frontend.wishlist.product.remove'options: ['seo' => false], defaults: ['XmlHttpRequest' => true'_loginRequired' => true], methods: ['POST'])]
  128.     public function ajaxRemove(string $productIdSalesChannelContext $contextCustomerEntity $customer): JsonResponse
  129.     {
  130.         try {
  131.             $this->removeWishlistProductRoute->delete($productId$context$customer);
  132.             $success true;
  133.         } catch (\Throwable) {
  134.             $success false;
  135.         }
  136.         return new JsonResponse([
  137.             'success' => $success,
  138.         ]);
  139.     }
  140.     #[Route(path'/wishlist/add-after-login/{productId}'name'frontend.wishlist.add.after.login'options: ['seo' => false], defaults: ['_loginRequired' => true], methods: ['GET'])]
  141.     public function addAfterLogin(string $productIdSalesChannelContext $contextCustomerEntity $customer): Response
  142.     {
  143.         try {
  144.             $this->addWishlistRoute->add($productId$context$customer);
  145.             $this->addFlash(self::SUCCESS$this->trans('wishlist.itemAddedSuccess'));
  146.         } catch (DuplicateWishlistProductException) {
  147.             $this->addFlash(self::WARNING$this->trans('wishlist.duplicateItemError'));
  148.         } catch (\Throwable) {
  149.             $this->addFlash(self::DANGER$this->trans('error.message-default'));
  150.         }
  151.         return $this->redirectToRoute('frontend.home.page');
  152.     }
  153.     #[Route(path'/wishlist/merge'name'frontend.wishlist.product.merge'options: ['seo' => false], defaults: ['XmlHttpRequest' => true'_loginRequired' => true], methods: ['POST'])]
  154.     public function ajaxMerge(RequestDataBag $requestDataBagRequest $requestSalesChannelContext $contextCustomerEntity $customer): Response
  155.     {
  156.         try {
  157.             $this->mergeWishlistProductRoute->merge($requestDataBag$context$customer);
  158.             return $this->renderStorefront('@Storefront/storefront/utilities/alert.html.twig', [
  159.                 'type' => 'info''content' => $this->trans('wishlist.wishlistMergeHint'),
  160.             ]);
  161.         } catch (\Throwable) {
  162.             $this->addFlash(self::DANGER$this->trans('error.message-default'));
  163.         }
  164.         return $this->createActionResponse($request);
  165.     }
  166.     #[Route(path'/wishlist/merge/pagelet'name'frontend.wishlist.product.merge.pagelet'defaults: ['XmlHttpRequest' => true'_loginRequired' => true], methods: ['GET''POST'])]
  167.     public function ajaxPagelet(Request $requestSalesChannelContext $contextCustomerEntity $customer): Response
  168.     {
  169.         $request->request->set('no-aggregations'true);
  170.         $page $this->wishlistPageLoader->load($request$context$customer);
  171.         $this->hook(new WishlistWidgetLoadedHook($page$context));
  172.         return $this->renderStorefront('@Storefront/storefront/page/wishlist/wishlist-pagelet.html.twig', [
  173.             'page' => $page,
  174.             'searchResult' => $page->getWishlist()->getProductListing(),
  175.         ]);
  176.     }
  177. }