From cf964a607f887e2de28f38a2691fa0487f0e3c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ludvik?= Date: Mon, 2 Sep 2024 14:51:36 +0200 Subject: [PATCH] [shopsys] moved category parameters to framework package (#3387) --- src/Form/Admin/Category/CategoryFormType.php | 44 +++++++++++++++++++ src/Model/Category/CategoryData.php | 12 +++++ src/Model/Category/CategoryDataFactory.php | 22 ++++++++++ src/Model/Category/CategoryFacade.php | 6 +++ .../Product/Parameter/ParameterRepository.php | 39 ++++++++++++++++ src/Resources/translations/messages.cs.po | 9 ++++ src/Resources/translations/messages.en.po | 9 ++++ 7 files changed, 141 insertions(+) diff --git a/src/Form/Admin/Category/CategoryFormType.php b/src/Form/Admin/Category/CategoryFormType.php index 55e9e2fa87..87951afd9c 100644 --- a/src/Form/Admin/Category/CategoryFormType.php +++ b/src/Form/Admin/Category/CategoryFormType.php @@ -15,11 +15,13 @@ use Shopsys\FrameworkBundle\Form\GroupType; use Shopsys\FrameworkBundle\Form\ImageUploadType; use Shopsys\FrameworkBundle\Form\Locale\LocalizedType; +use Shopsys\FrameworkBundle\Form\SortableValuesType; use Shopsys\FrameworkBundle\Form\UrlListType; use Shopsys\FrameworkBundle\Model\Category\Category; use Shopsys\FrameworkBundle\Model\Category\CategoryData; use Shopsys\FrameworkBundle\Model\Category\CategoryFacade; use Shopsys\FrameworkBundle\Model\Localization\Localization; +use Shopsys\FrameworkBundle\Model\Product\Parameter\ParameterRepository; use Shopsys\FrameworkBundle\Model\Seo\SeoSettingFacade; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; @@ -41,6 +43,7 @@ class CategoryFormType extends AbstractType * @param \Shopsys\FrameworkBundle\Model\Seo\SeoSettingFacade $seoSettingFacade * @param \Shopsys\FrameworkBundle\Component\Plugin\PluginCrudExtensionFacade $pluginCrudExtensionFacade * @param \Shopsys\FrameworkBundle\Model\Localization\Localization $localization + * @param \Shopsys\FrameworkBundle\Model\Product\Parameter\ParameterRepository $parameterRepository */ public function __construct( private readonly CategoryFacade $categoryFacade, @@ -48,6 +51,7 @@ public function __construct( private readonly SeoSettingFacade $seoSettingFacade, private readonly PluginCrudExtensionFacade $pluginCrudExtensionFacade, private readonly Localization $localization, + private readonly ParameterRepository $parameterRepository, ) { } @@ -229,6 +233,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->add('save', SubmitType::class); $this->pluginCrudExtensionFacade->extendForm($builder, 'category', 'pluginData'); + + $this->buildFilterParameters($builder, $options['category']); } /** @@ -257,4 +263,42 @@ private function getCategoryNameForPlaceholder(DomainConfig $domainConfig, ?Cate return $category === null ? '' : $category->getName($domainLocale); } + + /** + * @param \Symfony\Component\Form\FormBuilderInterface $builder + * @param \Shopsys\FrameworkBundle\Model\Category\Category|null $category + */ + protected function buildFilterParameters( + FormBuilderInterface $builder, + ?Category $category, + ): void { + if ($category === null) { + return; + } + $parametersFilterBuilder = $builder->add('parametersGroup', GroupType::class, ['label' => t('Filter parameters')]); + + $parameterNamesById = []; + + $parametersUsedByProductsInCategory = $this->parameterRepository->getParametersUsedByProductsInCategory($category, $this->domain->getDomainConfigById(Domain::FIRST_DOMAIN_ID)); + + foreach ($parametersUsedByProductsInCategory as $parameter) { + $parameterNamesById[$parameter->getId()] = $parameter->getName(); + } + + $parametersFilterBuilder->add('parametersPosition', SortableValuesType::class, [ + 'labels_by_value' => $parameterNamesById, + 'label' => t('Parameters order in category'), + 'required' => false, + ]); + + $parametersFilterBuilder->add('parametersCollapsed', ChoiceType::class, [ + 'required' => false, + 'label' => t('Filter parameters closed by default'), + 'choices' => $parametersUsedByProductsInCategory, + 'expanded' => true, + 'choice_label' => 'name', + 'choice_value' => 'id', + 'multiple' => true, + ]); + } } diff --git a/src/Model/Category/CategoryData.php b/src/Model/Category/CategoryData.php index 5250047bd7..20ed525f13 100644 --- a/src/Model/Category/CategoryData.php +++ b/src/Model/Category/CategoryData.php @@ -63,6 +63,16 @@ class CategoryData */ public $uuid; + /** + * @var int[]|null[] + */ + public $parametersPosition; + + /** + * @var \Shopsys\FrameworkBundle\Model\Product\Parameter\Parameter[] + */ + public $parametersCollapsed; + public function __construct() { $this->name = []; @@ -73,5 +83,7 @@ public function __construct() $this->enabled = []; $this->urls = new UrlListData(); $this->pluginData = []; + $this->parametersPosition = []; + $this->parametersCollapsed = []; } } diff --git a/src/Model/Category/CategoryDataFactory.php b/src/Model/Category/CategoryDataFactory.php index b830f8268a..c1672c0250 100644 --- a/src/Model/Category/CategoryDataFactory.php +++ b/src/Model/Category/CategoryDataFactory.php @@ -16,12 +16,14 @@ class CategoryDataFactory implements CategoryDataFactoryInterface * @param \Shopsys\FrameworkBundle\Component\Plugin\PluginCrudExtensionFacade $pluginCrudExtensionFacade * @param \Shopsys\FrameworkBundle\Component\Domain\Domain $domain * @param \Shopsys\FrameworkBundle\Component\FileUpload\ImageUploadDataFactory $imageUploadDataFactory + * @param \Shopsys\FrameworkBundle\Model\Category\CategoryParameterRepository $categoryParameterRepository */ public function __construct( protected readonly FriendlyUrlFacade $friendlyUrlFacade, protected readonly PluginCrudExtensionFacade $pluginCrudExtensionFacade, protected readonly Domain $domain, protected readonly ImageUploadDataFactory $imageUploadDataFactory, + protected readonly CategoryParameterRepository $categoryParameterRepository, ) { } @@ -101,7 +103,27 @@ protected function fillFromCategory(CategoryData $categoryData, Category $catego $categoryData->urls->mainFriendlyUrlsByDomainId[$domainId] = $mainFriendlyUrl; } + $parameters = $this->categoryParameterRepository->getParametersCollapsedByCategory($category); + $categoryData->parametersCollapsed = $parameters; + $categoryData->parametersPosition = $this->getParametersSortedByPositionFilteredByCategory($category); + $categoryData->pluginData = $this->pluginCrudExtensionFacade->getAllData('category', $category->getId()); $categoryData->image = $this->imageUploadDataFactory->createFromEntityAndType($category); } + + /** + * @param \Shopsys\FrameworkBundle\Model\Category\Category $category + * @return int[] + */ + protected function getParametersSortedByPositionFilteredByCategory(Category $category): array + { + $parameterIdsSortedByPosition = []; + $categoryParameters = $this->categoryParameterRepository->getCategoryParametersByCategorySortedByPosition($category); + + foreach ($categoryParameters as $categoryParameter) { + $parameterIdsSortedByPosition[] = $categoryParameter->getParameter()->getId(); + } + + return $parameterIdsSortedByPosition; + } } diff --git a/src/Model/Category/CategoryFacade.php b/src/Model/Category/CategoryFacade.php index c4aaca1907..f1896454d7 100644 --- a/src/Model/Category/CategoryFacade.php +++ b/src/Model/Category/CategoryFacade.php @@ -35,6 +35,7 @@ class CategoryFacade * @param \Shopsys\FrameworkBundle\Model\Category\CategoryFactoryInterface $categoryFactory * @param \Shopsys\FrameworkBundle\Model\Product\Recalculation\ProductRecalculationDispatcher $productRecalculationDispatcher * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher + * @param \Shopsys\FrameworkBundle\Model\Category\CategoryParameterFacade $categoryParameterFacade */ public function __construct( protected readonly EntityManagerInterface $em, @@ -49,6 +50,7 @@ public function __construct( protected readonly CategoryFactoryInterface $categoryFactory, protected readonly ProductRecalculationDispatcher $productRecalculationDispatcher, protected readonly EventDispatcherInterface $eventDispatcher, + protected readonly CategoryParameterFacade $categoryParameterFacade, ) { } @@ -110,6 +112,8 @@ public function create(CategoryData $categoryData) $this->friendlyUrlFacade->createFriendlyUrls('front_product_list', $category->getId(), $category->getNames()); $this->imageFacade->manageImages($category, $categoryData->image); + $this->categoryParameterFacade->saveRelation($category, $categoryData->parametersPosition, $categoryData->parametersCollapsed); + $this->pluginCrudExtensionFacade->saveAllData('category', $category->getId(), $categoryData->pluginData); $this->categoryVisibilityRecalculationScheduler->scheduleRecalculation(); @@ -141,6 +145,8 @@ public function edit($categoryId, CategoryData $categoryData) $this->imageFacade->manageImages($category, $categoryData->image); + $this->categoryParameterFacade->saveRelation($category, $categoryData->parametersPosition, $categoryData->parametersCollapsed); + $this->pluginCrudExtensionFacade->saveAllData('category', $category->getId(), $categoryData->pluginData); $this->categoryVisibilityRecalculationScheduler->scheduleRecalculation(); diff --git a/src/Model/Product/Parameter/ParameterRepository.php b/src/Model/Product/Parameter/ParameterRepository.php index 7153a21e69..2775c1ccd8 100644 --- a/src/Model/Product/Parameter/ParameterRepository.php +++ b/src/Model/Product/Parameter/ParameterRepository.php @@ -10,9 +10,12 @@ use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Shopsys\FrameworkBundle\Component\Doctrine\OrderByCollationHelper; +use Shopsys\FrameworkBundle\Component\Domain\Config\DomainConfig; +use Shopsys\FrameworkBundle\Model\Category\Category; use Shopsys\FrameworkBundle\Model\Product\Parameter\Exception\ParameterNotFoundException; use Shopsys\FrameworkBundle\Model\Product\Parameter\Exception\ParameterValueNotFoundException; use Shopsys\FrameworkBundle\Model\Product\Product; +use Shopsys\FrameworkBundle\Model\Product\ProductCategoryDomain; class ParameterRepository { @@ -81,6 +84,42 @@ public function getById($parameterId) return $parameter; } + /** + * @param \Shopsys\FrameworkBundle\Model\Category\Category $category + * @param \Shopsys\FrameworkBundle\Component\Domain\Config\DomainConfig $domainConfig + * @return \Shopsys\FrameworkBundle\Model\Product\Parameter\Parameter[] + */ + public function getParametersUsedByProductsInCategory(Category $category, DomainConfig $domainConfig): array + { + $queryBuilder = $this->getParameterRepository()->createQueryBuilder('p') + ->select('p') + ->join(ProductParameterValue::class, 'ppv', Join::WITH, 'p = ppv.parameter') + ->join('p.translations', 'pt', Join::WITH, 'pt.locale = :locale') + ->setParameter('locale', $domainConfig->getLocale()) + ->orderBy(OrderByCollationHelper::createOrderByForLocale('pt.name', $domainConfig->getLocale())) + ->groupBy('p, pt'); + + $this->applyCategorySeoConditions($queryBuilder, $category, $domainConfig->getId()); + + return $queryBuilder->getQuery()->execute(); + } + + /** + * @param \Doctrine\ORM\QueryBuilder $queryBuilder + * @param \Shopsys\FrameworkBundle\Model\Category\Category $category + * @param int $domainId + */ + protected function applyCategorySeoConditions(QueryBuilder $queryBuilder, Category $category, int $domainId): void + { + $queryBuilder + ->join(Product::class, 'product', Join::WITH, 'ppv.product = product') + ->join(ProductCategoryDomain::class, 'pcd', Join::WITH, 'product = pcd.product') + ->andWhere('pcd.category = :category') + ->andWhere('pcd.domainId = :domainId') + ->setParameter('category', $category) + ->setParameter('domainId', $domainId); + } + /** * @param string $uuid * @return \Shopsys\FrameworkBundle\Model\Product\Parameter\Parameter diff --git a/src/Resources/translations/messages.cs.po b/src/Resources/translations/messages.cs.po index a8e180f821..40cd49fa56 100644 --- a/src/Resources/translations/messages.cs.po +++ b/src/Resources/translations/messages.cs.po @@ -1663,6 +1663,12 @@ msgstr "Pro vytvoření produktu doplňte chybějící nastavení. Více informa msgid "Filter by" msgstr "Filtrovat podle" +msgid "Filter parameters" +msgstr "Parametry filtru" + +msgid "Filter parameters closed by default" +msgstr "Defaultně zavřené parametry ve filtru" + msgid "Finish the assigning" msgstr "Dokončit přiřazování" @@ -2596,6 +2602,9 @@ msgstr "Parametry - vše" msgid "Parameters - view" msgstr "Parametry - zobrazení" +msgid "Parameters order in category" +msgstr "Pořadí parametrů v kategorii" + msgid "Parameters overview" msgstr "Přehled parametrů" diff --git a/src/Resources/translations/messages.en.po b/src/Resources/translations/messages.en.po index f5b2d99f74..03a9939ed3 100644 --- a/src/Resources/translations/messages.en.po +++ b/src/Resources/translations/messages.en.po @@ -1663,6 +1663,12 @@ msgstr "" msgid "Filter by" msgstr "" +msgid "Filter parameters" +msgstr "" + +msgid "Filter parameters closed by default" +msgstr "" + msgid "Finish the assigning" msgstr "" @@ -2596,6 +2602,9 @@ msgstr "" msgid "Parameters - view" msgstr "" +msgid "Parameters order in category" +msgstr "" + msgid "Parameters overview" msgstr ""