vendor/store.shopware.com/coewishlistsw6/src/Storefront/Controller/WishlistController.php line 102

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace CoeWishlistSw6\Storefront\Controller;
  3. use App\Product;
  4. use CoeWishlistSw6\Core\Content\Wishlist\Service\WishlistPriceQuantityService;
  5. use CoeWishlistSw6\Core\Content\Wishlist\Service\WishlistPriceQuantityServiceInterface;
  6. use CoeWishlistSw6\Core\Content\Wishlist\Service\WishlistService;
  7. use CoeWishlistSw6\Core\Content\Wishlist\Service\WishlistServiceInterface;
  8. use CoeWishlistSw6\Core\Content\Wishlist\WishlistCollection;
  9. use CoeWishlistSw6\Core\Content\Wishlist\WishlistEntity;
  10. use CoeWishlistSw6\Core\Content\Wishlist\Aggregate\WishlistNoteEntity;
  11. use CoeWishlistSw6\Storefront\Page\Wishlist\WishlistPage;
  12. use CoeWishlistSw6\Storefront\Page\Wishlist\WishlistPageLoader;
  13. use http\Exception\InvalidArgumentException;
  14. use Shopware\Core\Content\Product\Exception\ProductNotFoundException;
  15. use Shopware\Core\Content\Product\ProductCollection;
  16. use Shopware\Core\Content\Product\ProductEntity;
  17. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  19. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  20. use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
  21. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  22. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  23. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  24. use Shopware\Storefront\Controller\StorefrontController;
  25. use Symfony\Component\HttpFoundation\JsonResponse;
  26. use Symfony\Component\HttpFoundation\RedirectResponse;
  27. use Symfony\Component\HttpFoundation\Response;
  28. use Symfony\Component\HttpFoundation\Request;
  29. use Symfony\Component\Routing\Annotation\Route;
  30. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  31. /**
  32.  * Class WishlistController
  33.  * @package CoeWishlistSw6\Storefront\Controller
  34.  * @author Jeffry Block <jeffry.block@codeenterprise.de>
  35.  */
  36. class WishlistController extends StorefrontController
  37. {
  38.     /**
  39.      * @var WishlistPageLoader
  40.      */
  41.     private $wishlistPageLoader;
  42.     /**
  43.      * @var WishlistServiceInterface
  44.      */
  45.     private $wishlistService;
  46.     /**
  47.      * @var EntityRepositoryInterface
  48.      */
  49.     private $wishlistRepository;
  50.     /**
  51.      * @var WishlistPriceQuantityServiceInterface
  52.      */
  53.     private $wishlistPriceQuantityService;
  54.     /**
  55.      * @var SalesChannelRepositoryInterface
  56.      */
  57.     private SalesChannelRepositoryInterface $productRepository;
  58.     /**
  59.      * WishlistController constructor.
  60.      * @param WishlistPageLoader $wishlistPageLoader
  61.      * @param WishlistServiceInterface $wishlistService
  62.      * @param EntityRepositoryInterface $wishlistRepository
  63.      * @param WishlistPriceQuantityServiceInterface $wishlistPriceQuantityService
  64.      * @param SalesChannelRepositoryInterface $productRepository
  65.      */
  66.     public function __construct(
  67.         WishlistPageLoader $wishlistPageLoader,
  68.         WishlistServiceInterface $wishlistService,
  69.         EntityRepositoryInterface $wishlistRepository,
  70.         WishlistPriceQuantityServiceInterface $wishlistPriceQuantityService,
  71.         SalesChannelRepositoryInterface $productRepository
  72.     ) {
  73.         $this->wishlistPageLoader $wishlistPageLoader;
  74.         $this->wishlistService $wishlistService;
  75.         $this->wishlistRepository $wishlistRepository;
  76.         $this->wishlistPriceQuantityService $wishlistPriceQuantityService;
  77.         $this->productRepository $productRepository;
  78.     }
  79.     /**
  80.      * @RouteScope(scopes={"storefront"})
  81.      * @Route("/note", name="frontend.wishlist.page", methods={"GET"}, options={"seo"="false"})
  82.      * @Route("/note/{listId}", name="frontend.wishlist.page", methods={"GET"}, options={"seo"="false"}, requirements={"listId"=".{32}"}, defaults={"listId"=null})
  83.      * @param string|null $listId
  84.      * @param Request $request
  85.      * @param SalesChannelContext $context
  86.      * @return \Symfony\Component\HttpFoundation\Response
  87.      * @throws MissingRequestParameterException
  88.      * @throws \Shopware\Core\Content\Category\Exception\CategoryNotFoundException
  89.      * @throws \Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException
  90.      * @author Jeffry Block <jeffry.block@codeenterprise.de>
  91.      * @throws \Exception
  92.      */
  93.     public function index(?string $listId nullRequest $requestSalesChannelContext $context): Response
  94.     {
  95.         if ($listId) {
  96.             if (!$this->wishlistService->loadList($listId$context->getContext())) {
  97.                 throw new \Exception(sprintf("Wishlist with ID %s does not exist"$listId));
  98.             }
  99.         }
  100.         try {
  101.             /** @var WishlistPage $page */
  102.             $page $this->wishlistPageLoader->load($request$context);
  103.         } catch (\Exception $e) {
  104.             $this->container->get("session")->getFlashBag()->add('warning'$e->getMessage());
  105.             $url $this->container->get("router")->generate('frontend.wishlist.page');
  106.             return new RedirectResponse($url);
  107.         }
  108.         /** @var Response $response */
  109.         $response $this->renderStorefront('@CoeWishlistSw6/storefront/page/wishlist/overview/index.html.twig', [
  110.             'page' => $page,
  111.         ]);
  112.         $response->headers->set("X-Robots""noindex,nofollow");
  113.         return $response;
  114.     }
  115.     /**
  116.      * @RouteScope(scopes={"storefront"})
  117.      * @Route("/note/save/note", name="frontend.wishlist.save.note", methods={"POST"}, defaults={"XmlHttpRequest": true})
  118.      * @param RequestDataBag $dataBag
  119.      * @param Request $request
  120.      * @param SalesChannelContext $context
  121.      */
  122.     public function saveNote(RequestDataBag $dataBagRequest $requestSalesChannelContext $context): Response
  123.     {
  124.         /** @var string|null $sku */
  125.         $sku $dataBag->get("sku");
  126.         // If parameter "useSKU" is set, get the product ID based on the SKU.
  127.         // Using SKU means, that the request came from the "add product manually"-form where users can enter the quantity
  128.         // manually as well. In this case we also need to make sure that the entered quantity is actually valid.
  129.         if ($sku) {
  130.             $criteria = new Criteria();
  131.             $criteria->addFilter(new EqualsFilter("productNumber"trim($sku)));
  132.             /** @var ProductCollection $products */
  133.             $products $this->productRepository->search($criteria$context);
  134.             if ($products->count() === 0) {
  135.                 throw new ProductNotFoundException($sku);
  136.             }
  137.             /** @var ProductEntity $product */
  138.             $product $products->first();
  139.             /** @var int $quantity */
  140.             $quantity $dataBag->getInt("quantity"1);
  141.             if (!$this->wishlistService->isQuantityValidForProduct($product$quantity)) {
  142.                 throw new \Exception(sprintf("Quantity %s not allowed for product %s"$quantity$product->getProductNumber()));
  143.             }
  144.             $dataBag->set("productId"$product->getId());
  145.         }
  146.         /** @var string $productId */
  147.         $productId $dataBag->get("productId");
  148.         if (!$productId) {
  149.             throw new MissingRequestParameterException('productId');
  150.         }
  151.         /** @var string $listId */
  152.         $listId $dataBag->get("listId");
  153.         if ($dataBag->getBoolean("addNewList")) {
  154.             $listId = ($this -> wishlistService -> createList($dataBag$context, ["notes","notes.product"]))->getId();
  155.         }
  156.         /** @var WishlistEntity $list */
  157.         $list $this -> wishlistService -> loadList($listId$context->getContext(), ["notes","notes.product"]);
  158.         if (!$list) {
  159.             throw new \Exception(sprintf("Wishlist with ID %s does not exist"$list));
  160.         }
  161.         /** @var WishlistNoteEntity $addedNote */
  162.         $addedNote $this -> wishlistService -> addNote($dataBag$list$context);
  163.         return new JsonResponse([
  164.             "success" => true,
  165.             "data" => [
  166.                 "noteId" => $addedNote->getId(),
  167.                 "listId" => $list->getId(),
  168.             ],
  169.         ], 200);
  170.     }
  171.     /**
  172.      * @RouteScope(scopes={"storefront"})
  173.      * @Route("/note/save/list", name="frontend.wishlist.save.list", methods={"POST"}, defaults={"XmlHttpRequest": true})
  174.      * @param RequestDataBag $dataBag
  175.      * @param Request $request
  176.      * @param SalesChannelContext $context
  177.      */
  178.     public function saveList(RequestDataBag $dataBagRequest $requestSalesChannelContext $context): Response
  179.     {
  180.         $listId = ($this -> wishlistService -> createList($dataBag$context, ["notes","notes.product"]))->getId();
  181.         return new JsonResponse([
  182.             "success" => true,
  183.             "data" => [
  184.                 "listId" => $listId,
  185.             ],
  186.         ], 200);
  187.     }
  188.     /**
  189.      * @RouteScope(scopes={"storefront"})
  190.      * @Route("/note/save/list/visibility", name="frontend.wishlist.save.list.visiblity", methods={"POST"}, defaults={"XmlHttpRequest": true})
  191.      * @param RequestDataBag $dataBag
  192.      * @param Request $request
  193.      * @param SalesChannelContext $context
  194.      */
  195.     public function saveListVisibility(RequestDataBag $dataBagRequest $requestSalesChannelContext $context): Response
  196.     {
  197.         $listId $dataBag->get("listId");
  198.         $visibility $dataBag->getBoolean("public"false);
  199.         if (!$listId) {
  200.             throw new MissingRequestParameterException('listId');
  201.         }
  202.         if (!$this->wishlistService->listBelongsToCurrentUser($listId$context)) {
  203.             throw new \Exception(sprintf("Access to resource with ID %s denied"$listId));
  204.         }
  205.         $this->wishlistRepository->update([[
  206.             "id" => $listId,
  207.             "public" => $visibility,
  208.         ]], $context->getContext());
  209.         return new JsonResponse([
  210.             "success" => true,
  211.             "data" => [
  212.                 "listId" => $listId,
  213.             ],
  214.         ], 200);
  215.     }
  216.     /**
  217.      * @RouteScope(scopes={"storefront"})
  218.      * @Route("/note/save/list/name", name="frontend.wishlist.save.list.name", methods={"POST"}, defaults={"XmlHttpRequest": true})
  219.      * @param RequestDataBag $dataBag
  220.      * @param Request $request
  221.      * @param SalesChannelContext $context
  222.      */
  223.     public function saveListName(RequestDataBag $dataBagRequest $requestSalesChannelContext $context): Response
  224.     {
  225.         $listId $dataBag->get("listId");
  226.         $name $dataBag->get("listName""No Name");
  227.         if (!$listId) {
  228.             throw new MissingRequestParameterException('listId');
  229.         }
  230.         if (!$this->wishlistService->listBelongsToCurrentUser($listId$context)) {
  231.             throw new \Exception(sprintf("Access to resource with ID %s denied"$listId));
  232.         }
  233.         $this->wishlistRepository->update([[
  234.             "id" => $listId,
  235.             "name" => $name,
  236.         ]], $context->getContext());
  237.         return new JsonResponse([
  238.             "success" => true,
  239.         ], 200);
  240.     }
  241.     /**
  242.      * @RouteScope(scopes={"storefront"})
  243.      * @Route("/note/save/note/quantity", name="frontend.wishlist.save.note.quantity", methods={"POST"}, defaults={"XmlHttpRequest": true})
  244.      * @param RequestDataBag $dataBag
  245.      * @param Request $request
  246.      * @param SalesChannelContext $context
  247.      */
  248.     public function saveNoteQuantity(RequestDataBag $dataBagRequest $requestSalesChannelContext $context): Response
  249.     {
  250.         $quantity $dataBag->getInt("quantity");
  251.         if (!$quantity || $quantity === 0) {
  252.             throw new MissingRequestParameterException('quantity');
  253.         }
  254.         $noteId $dataBag->get("noteId");
  255.         if (!$noteId) {
  256.             throw new MissingRequestParameterException('noteId');
  257.         }
  258.         $productId $dataBag->get("productId");
  259.         if (!$productId) {
  260.             throw new MissingRequestParameterException('productId');
  261.         }
  262.         // Update the Quantity
  263.         // @todo check if the list of the note belongs to the user. Currently the note qty can be changed by everyone
  264.         $this->wishlistService->updateNoteQuantity($noteId$quantity$context->getContext());
  265.         try {
  266.             // When updating the quantity, the price per piece may have changed. Recalculate the price to show in storefront.
  267.             $quantityPrice $this->wishlistPriceQuantityService->buildPrices($productId$quantity$context);
  268.             return new JsonResponse([
  269.                 "success" => true,
  270.                 "data" => [
  271.                     "noteId" => $noteId,
  272.                     "priceQty" => $this->wishlistPriceQuantityService->format($quantityPrice$context),
  273.                     "priceSum" => $this->wishlistPriceQuantityService->format($quantity $quantityPrice$context),
  274.                     "qty" => $quantity,
  275.                 ],
  276.             ], 200);
  277.         } catch (\Exception $e) {
  278.             // If an exception occured during price calculation, just return null as data and reload the storefront
  279.             // instead of replacing the elemens dynamically.
  280.             return new JsonResponse([
  281.                 "success" => true,
  282.                 "data" => [
  283.                     "qty" => $quantity,
  284.                     "noteId" => $noteId,
  285.                 ],
  286.             ]);
  287.         }
  288.     }
  289.     /**
  290.      * @RouteScope(scopes={"storefront"})
  291.      * @Route("/note/count", name="frontend.wishlist.count.snippet", methods={"GET"}, defaults={"XmlHttpRequest": true})
  292.      * @param RequestDataBag $dataBag
  293.      * @param Request $request
  294.      * @param SalesChannelContext $context
  295.      */
  296.     public function getNoteCount(RequestDataBag $dataBagRequest $requestSalesChannelContext $context): Response
  297.     {
  298.         /** @var WishlistCollection $lists */
  299.         $lists $this->wishlistService->loadLists($context, ["notes"]);
  300.         $counter $lists->getAccumulatedNoteCount();
  301.         return new Response((string)$counter);
  302.     }
  303.     /**
  304.      * @RouteScope(scopes={"storefront"})
  305.      * @Route("/note/productids", name="frontend.wishlist.productids.snippet", methods={"GET"}, defaults={"XmlHttpRequest": true})
  306.      * @param RequestDataBag $dataBag
  307.      * @param Request $request
  308.      * @param SalesChannelContext $context
  309.      */
  310.     public function getNoteProductIds(RequestDataBag $dataBagRequest $requestSalesChannelContext $context): Response
  311.     {
  312.         /** @var WishlistCollection $lists */
  313.         $lists $this->wishlistService->loadLists($context, ["notes","notes.product"]);
  314.         $numbers $lists->getAllProductsIds();
  315.         return new JsonResponse($numbers);
  316.     }
  317.     /**
  318.      * @RouteScope(scopes={"storefront"})
  319.      * @Route("/note/delete/list", name="frontend.wishlist.delete.list", methods={"POST"}, defaults={"XmlHttpRequest": true})
  320.      * @param RequestDataBag $dataBag
  321.      * @param Request $request
  322.      * @param SalesChannelContext $context
  323.      */
  324.     public function deleteList(RequestDataBag $dataBagRequest $requestSalesChannelContext $context): Response
  325.     {
  326.         $listId $dataBag->get("listId");
  327.         if (!$listId) {
  328.             throw new MissingRequestParameterException('listId');
  329.         }
  330.         if (!$this->wishlistService->listBelongsToCurrentUser($listId$context)) {
  331.             throw new \Exception(sprintf("Access to resource with ID %s denied"$listId));
  332.         }
  333.         $this->wishlistService->deleteList($listId$context->getContext());
  334.         if ($context->getCustomer()) {
  335.             $this->wishlistService->resetDefault($context->getCustomer()->getId(), $context->getContext());
  336.         }
  337.         return new JsonResponse([
  338.             "success" => true,
  339.             "data" => [
  340.                 "listId" => $listId,
  341.             ],
  342.         ], 200);
  343.     }
  344.     /**
  345.      * @RouteScope(scopes={"storefront"})
  346.      * @Route("/note/delete/note", name="frontend.wishlist.delete.note", methods={"POST"}, defaults={"XmlHttpRequest": true})
  347.      * @param RequestDataBag $dataBag
  348.      * @param Request $request
  349.      * @param SalesChannelContext $context
  350.      */
  351.     public function deleteNote(RequestDataBag $dataBagRequest $requestSalesChannelContext $context): Response
  352.     {
  353.         $noteId $dataBag->get("noteId");
  354.         if (!$noteId) {
  355.             throw new MissingRequestParameterException('noteId');
  356.         }
  357.         // @todo check if the list of the note belongs to the user. Currently notes can be deleted by everyone
  358.         $this->wishlistService->deleteNote($noteId$context->getContext());
  359.         return new JsonResponse([
  360.             "success" => true,
  361.             "data" => [
  362.                 "noteId" => $noteId,
  363.             ],
  364.         ], 200);
  365.     }
  366.     /**
  367.      * @RouteScope(scopes={"storefront"})
  368.      * @Route("/note/debug", name="frontend.wishlist.debug.page", methods={"GET"})
  369.      * @param Request $request
  370.      * @param SalesChannelContext $context
  371.      * @return \Symfony\Component\HttpFoundation\Response
  372.      */
  373.     public function debug(Request $requestSalesChannelContext $context)
  374.     {
  375.         return new JsonResponse("[]");
  376.     }
  377. }