From 7ba5238831911088cd66c63facdf93ab4f553182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Ste=CC=A8pien=CC=81?= Date: Sat, 16 Dec 2023 01:51:09 +0100 Subject: [PATCH] customer page, favorite products list --- config/front/services.yml | 1 + src/Hook/AbstractDisplayAdminHook.php | 52 +++++++++++++++ src/Hook/AbstractDisplayHook.php | 2 +- src/Hook/ActionFrontControllerSetMedia.php | 6 +- src/Hook/DisplayAdminCustomers.php | 65 +++++++++++++++++++ src/Installer/ModuleInstaller.php | 1 + .../AdminFavoriteProductPresenter.php | 60 +++++++++++++++++ ...AdminFavoriteProductPresenterInterface.php | 12 ++++ ...r.php => FavoriteProductJsonPresenter.php} | 2 +- src/Presenter/JsonPresenterInterface.php | 2 +- .../CustomerFavoriteProductsProvider.php | 46 +++++++++++++ ...tomerFavoriteProductsProviderInterface.php | 11 ++++ src/Repository/ProductLegacyRepository.php | 25 +++++++ .../admin/displayAdminCustomers.html.twig | 37 +++++++++++ .../hook/{ => front}/button-product.tpl | 0 views/templates/hook/{ => front}/button.tpl | 0 .../displayCrossSellingShoppingCart.tpl | 0 views/templates/hook/{ => front}/index.php | 0 views/templates/hook/{ => front}/top.tpl | 0 19 files changed, 316 insertions(+), 6 deletions(-) create mode 100644 src/Hook/AbstractDisplayAdminHook.php create mode 100644 src/Hook/DisplayAdminCustomers.php create mode 100644 src/Presenter/AdminFavoriteProductPresenter.php create mode 100644 src/Presenter/AdminFavoriteProductPresenterInterface.php rename src/Presenter/{FavoriteProductJsonJsonPresenter.php => FavoriteProductJsonPresenter.php} (81%) create mode 100644 src/Provider/CustomerFavoriteProductsProvider.php create mode 100644 src/Provider/CustomerFavoriteProductsProviderInterface.php create mode 100644 views/templates/hook/admin/displayAdminCustomers.html.twig rename views/templates/hook/{ => front}/button-product.tpl (100%) rename views/templates/hook/{ => front}/button.tpl (100%) rename views/templates/hook/{ => front}/displayCrossSellingShoppingCart.tpl (100%) rename views/templates/hook/{ => front}/index.php (100%) rename views/templates/hook/{ => front}/top.tpl (100%) diff --git a/config/front/services.yml b/config/front/services.yml index 07db710..5e85f58 100644 --- a/config/front/services.yml +++ b/config/front/services.yml @@ -27,6 +27,7 @@ services: public: true resource: '../../src/Hook/*' exclude: + - '../../src/Hook/{DisplayAdminCustomers.php,AbstractDisplayAdminHook.php}' - '../../src/Hook/index.php' Oksydan\IsFavoriteProducts\Services\FavoriteProductService: diff --git a/src/Hook/AbstractDisplayAdminHook.php b/src/Hook/AbstractDisplayAdminHook.php new file mode 100644 index 0000000..7cdc760 --- /dev/null +++ b/src/Hook/AbstractDisplayAdminHook.php @@ -0,0 +1,52 @@ +twig = $twig; + } + + public function execute(array $params): string + { + if (!$this->shouldBlockBeDisplayed($params)) { + return ''; + } + + return $this->twig->render($this->getTemplateFullPath(), $this->getTemplateVariables($params)); + } + + protected function getTemplateVariables(array $params): array + { + return []; + } + + protected function shouldBlockBeDisplayed(array $params) + { + return true; + } + + public function getTemplateFullPath(): string + { + return "@Modules/{$this->module->name}/views/templates/hook/admin/{$this->getTemplate()}"; + } + + abstract protected function getTemplate(): string; +} diff --git a/src/Hook/AbstractDisplayHook.php b/src/Hook/AbstractDisplayHook.php index 1e2e393..eccd8a2 100644 --- a/src/Hook/AbstractDisplayHook.php +++ b/src/Hook/AbstractDisplayHook.php @@ -28,7 +28,7 @@ protected function shouldBlockBeDisplayed(array $params) public function getTemplateFullPath(): string { - return "module:{$this->module->name}/views/templates/hook/{$this->getTemplate()}"; + return "module:{$this->module->name}/views/templates/hook/front/{$this->getTemplate()}"; } abstract protected function getTemplate(): string; diff --git a/src/Hook/ActionFrontControllerSetMedia.php b/src/Hook/ActionFrontControllerSetMedia.php index b00bd79..8046176 100644 --- a/src/Hook/ActionFrontControllerSetMedia.php +++ b/src/Hook/ActionFrontControllerSetMedia.php @@ -5,18 +5,18 @@ namespace Oksydan\IsFavoriteProducts\Hook; use Oksydan\IsFavoriteProducts\DTO\FavoriteProduct; -use Oksydan\IsFavoriteProducts\Presenter\FavoriteProductJsonJsonPresenter; +use Oksydan\IsFavoriteProducts\Presenter\FavoriteProductJsonPresenter; use Oksydan\IsFavoriteProducts\Services\FavoriteProductService; class ActionFrontControllerSetMedia extends AbstractHook { - private FavoriteProductJsonJsonPresenter $productPresenter; + private FavoriteProductJsonPresenter $productPresenter; public function __construct( \Is_favoriteproducts $module, \Context $context, FavoriteProductService $favoriteProductService, - FavoriteProductJsonJsonPresenter $productPresenter + FavoriteProductJsonPresenter $productPresenter ) { parent::__construct($module, $context, $favoriteProductService); $this->productPresenter = $productPresenter; diff --git a/src/Hook/DisplayAdminCustomers.php b/src/Hook/DisplayAdminCustomers.php new file mode 100644 index 0000000..6f9a7fc --- /dev/null +++ b/src/Hook/DisplayAdminCustomers.php @@ -0,0 +1,65 @@ +customerFavoriteProductsProvider = $customerFavoriteProductsProvider; + $this->adminFavoriteProductPresenter = $adminFavoriteProductPresenter; + } + + private const TEMPLATE_FILE = 'displayAdminCustomers.html.twig'; + + protected function getTemplate(): string + { + return self::TEMPLATE_FILE; + } + + protected function getTemplateVariables(array $params): array + { + $idCustomer = (int) $params['id_customer']; + $customer = new \Customer($idCustomer); + + if (!Validate::isLoadedObject($customer)) { + return []; + } + + $shop = new \Shop($customer->id_shop); + + if (!Validate::isLoadedObject($shop)) { + return []; + } + + $productsRaw = $this->customerFavoriteProductsProvider->getFavoriteProductsByCustomer($customer, $shop); + $products = []; + + foreach ($productsRaw as $productRaw) { + $products[] = $this->adminFavoriteProductPresenter->present($productRaw, $this->context->language); + } + + return [ + 'products' => $products, + ]; + } +} diff --git a/src/Installer/ModuleInstaller.php b/src/Installer/ModuleInstaller.php index 2cab966..e7921e9 100644 --- a/src/Installer/ModuleInstaller.php +++ b/src/Installer/ModuleInstaller.php @@ -14,6 +14,7 @@ class ModuleInstaller 'displayProductActions', 'displayCrossSellingShoppingCart', 'actionCartSave', + 'displayAdminCustomers', ]; private \Is_favoriteproducts $module; diff --git a/src/Presenter/AdminFavoriteProductPresenter.php b/src/Presenter/AdminFavoriteProductPresenter.php new file mode 100644 index 0000000..1ead6b0 --- /dev/null +++ b/src/Presenter/AdminFavoriteProductPresenter.php @@ -0,0 +1,60 @@ +router = $router; + $this->productLegacyRepository = $productLegacyRepository; + } + + public function present(FavoriteProduct $favoriteProduct, \Language $language): array + { + $productObject = new \Product($favoriteProduct->getIdProduct(), false, $language->id); + $idAttribute = $favoriteProduct->getIdProductAttribute(); + $productName = $productObject->name; + + if ($idAttribute > 0) { + $combination = $this->productLegacyRepository->getProductCombinationForIdProductAttribute($favoriteProduct->getIdProduct(), $idAttribute, $language->id); + + $combinationName = array_reduce($combination, function ($combinationReduced, $combination) { + $combinationReduced[] = $combination['group_name'] . ': ' . $combination['attribute_name']; + + return $combinationReduced; + }, []); + + $productName = $productName . ' - ' . implode(', ', $combinationName); + } + + $admin_url = $this->router->generate('admin_product_form', [ + 'id' => $favoriteProduct->getIdProduct(), + ]); + + return [ + 'id' => $favoriteProduct->getIdProduct(), + 'name' => $productName, + 'admin_url' => $admin_url, + 'date_add' => $favoriteProduct->getDateAdd()->format(self::DATE_FORMAT), + ]; + } +} diff --git a/src/Presenter/AdminFavoriteProductPresenterInterface.php b/src/Presenter/AdminFavoriteProductPresenterInterface.php new file mode 100644 index 0000000..2c86fc3 --- /dev/null +++ b/src/Presenter/AdminFavoriteProductPresenterInterface.php @@ -0,0 +1,12 @@ +favoriteProductsRepository = $favoriteProductsRepository; + $this->favoriteProductMapper = $favoriteProductMapper; + } + + public function getFavoriteProductsByCustomer(\Customer $customer, \Shop $shop): array + { + $favoriteProducts = $this->favoriteProductsRepository->getFavoriteProductsByCustomer( + (int) $customer->id, + (int) $shop->id + ); + + $products = array_map(function (FavoriteProduct $favoriteProduct) { + return $this->favoriteProductMapper->mapFavoriteProductEntityToFavoriteProductDTO($favoriteProduct); + }, $favoriteProducts); + + return $products; + } +} diff --git a/src/Provider/CustomerFavoriteProductsProviderInterface.php b/src/Provider/CustomerFavoriteProductsProviderInterface.php new file mode 100644 index 0000000..66c4176 --- /dev/null +++ b/src/Provider/CustomerFavoriteProductsProviderInterface.php @@ -0,0 +1,11 @@ +execute()->fetchOne(); } + + public function getProductCombinationForIdProductAttribute( + int $idProduct, + int $idProductAttribute, + int $idLang + ): array { + $qb = $this->connection->createQueryBuilder() + ->select('alg.name AS group_name, al.`name` AS attribute_name') + ->from($this->dbPrefix . 'product_attribute', 'pa') + ->leftJoin('pa', $this->dbPrefix . 'product_attribute_combination', 'pac', 'pac.id_product_attribute = pa.id_product_attribute') + ->leftJoin('pac', $this->dbPrefix . 'attribute', 'a', 'a.id_attribute = pac.id_attribute') + ->leftJoin('a', $this->dbPrefix . 'attribute_lang', 'al', 'a.id_attribute = al.id_attribute') + ->leftJoin('a', $this->dbPrefix . 'attribute_group', 'ag', 'ag.id_attribute_group = a.id_attribute_group') + ->leftJoin('ag', $this->dbPrefix . 'attribute_group_lang', 'alg', 'ag.id_attribute_group = alg.id_attribute_group') + ->where('pa.id_product = :id_product') + ->andWhere('pa.id_product_attribute = :id_product_attribute') + ->andWhere('al.id_lang = :id_lang') + ->setParameter('id_product', $idProduct) + ->setParameter('id_product_attribute', $idProductAttribute) + ->setParameter('id_lang', $idLang) + ->groupBy('pa.id_product_attribute, ag.id_attribute_group') + ->orderBy('pa.id_product_attribute'); + + return $qb->execute()->fetchAllAssociative(); + } } diff --git a/views/templates/hook/admin/displayAdminCustomers.html.twig b/views/templates/hook/admin/displayAdminCustomers.html.twig new file mode 100644 index 0000000..a4e592e --- /dev/null +++ b/views/templates/hook/admin/displayAdminCustomers.html.twig @@ -0,0 +1,37 @@ +{% if products is not empty %} +
+ +
+

+ favorite + {{ 'Favorite products'|trans({}, 'Modules.Isfavoriteproducts.Admin') }} + {{ products|length }} +

+
+ + + + + + + + + + {% for product in products %} + + + + + + {% endfor %} + +
{{ 'ID'|trans({}, 'Admin.Global') }}{{ 'Name'|trans({}, 'Admin.Global') }}{{ 'Data add'|trans({}, 'Admin.Global') }}
{{ product.id }} + + {{ product.name }} + + {{ product.date_add }}
+
+
+ +
+{% endif %} diff --git a/views/templates/hook/button-product.tpl b/views/templates/hook/front/button-product.tpl similarity index 100% rename from views/templates/hook/button-product.tpl rename to views/templates/hook/front/button-product.tpl diff --git a/views/templates/hook/button.tpl b/views/templates/hook/front/button.tpl similarity index 100% rename from views/templates/hook/button.tpl rename to views/templates/hook/front/button.tpl diff --git a/views/templates/hook/displayCrossSellingShoppingCart.tpl b/views/templates/hook/front/displayCrossSellingShoppingCart.tpl similarity index 100% rename from views/templates/hook/displayCrossSellingShoppingCart.tpl rename to views/templates/hook/front/displayCrossSellingShoppingCart.tpl diff --git a/views/templates/hook/index.php b/views/templates/hook/front/index.php similarity index 100% rename from views/templates/hook/index.php rename to views/templates/hook/front/index.php diff --git a/views/templates/hook/top.tpl b/views/templates/hook/front/top.tpl similarity index 100% rename from views/templates/hook/top.tpl rename to views/templates/hook/front/top.tpl