From 8df0fa601cd574c4f5988afa5d6a429a2cd0c05a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Ste=CC=A8pien=CC=81?= Date: Mon, 19 Feb 2024 08:47:08 +0100 Subject: [PATCH 1/9] REFACTO WIP --- config/admin/command.yml | 22 ++ config/admin/form.yml | 51 ++-- config/admin/grid.yml | 2 - config/admin/services.yml | 21 +- config/configuration.yml | 1 + config/database.yml | 47 ---- config/database/image_slider.yml | 5 +- config/database/image_slider_image.yml | 32 +++ config/database/image_slider_lang.yml | 24 +- config/routes.yml | 46 +--- is_imageslider.php | 2 +- src/Adapter/CommandBus.php | 23 ++ src/Adapter/CommandBusInterface.php | 15 ++ .../{ => Admin}/ImagesliderController.php | 155 ++++++++----- src/Controller/Admin/index.php | 11 + .../Command/CreateImageSliderCommand.php | 33 +++ .../Command/EditImageSliderCommand.php | 33 +++ .../CreateImageSliderHandler.php | 28 +++ .../CreateImageSliderHandlerInterface.php | 12 + .../CommandHandler/EditImageSliderHandler.php | 26 +++ .../EditImageSliderHandlerInterface.php | 12 + src/Entity/ImageSlider.php | 141 ++++------- src/Entity/ImageSliderImage.php | 56 +++++ src/Entity/ImageSliderLang.php | 111 ++------- .../ImageSliderFormDataHandler.php | 218 ------------------ .../Lang/LangModeDataTransformer.php | 37 +++ .../Shop/ShopChoiceModelDataTransformer.php | 55 +++++ .../ImagesliderFormSubscriber.php | 68 ++++++ src/Form/ImageSliderType.php | 167 -------------- .../Provider/ImageSliderFormDataProvider.php | 130 ----------- .../ImageSliderConfigurationType.php | 4 +- src/Form/Type/ImageSliderType.php | 108 +++++++++ src/Form/Type/Lang/LangFieldsType.php | 144 ++++++++++++ src/Form/Type/Lang/LangType.php | 30 +++ .../Shop/ShopAssociationChoiceTreeType.php | 75 ++++++ src/Form/Type/Slider/ImageSliderLangType.php | 73 ++++++ src/Form/Type/Slider/ImageType.php | 58 +++++ .../Factory/ImageSliderGridDataFactory.php | 6 +- .../ImageSliderGridDefinitionFactory.php | 8 +- src/Repository/ImageSliderRepository.php | 7 + src/Type/TranslatableFile.php | 47 ---- views/css/form.css | 12 +- views/js/createForm.js | 35 --- views/js/form.js | 67 +++++- views/js/list.js | 15 ++ views/templates/admin/form.html.twig | 12 +- .../templates/admin/form/form_theme.html.twig | 68 ++++++ .../admin/form/prestashop_ui_kit.html.twig | 77 ------- views/templates/admin/index.html.twig | 54 ++--- 49 files changed, 1362 insertions(+), 1122 deletions(-) create mode 100644 config/admin/command.yml delete mode 100644 config/database.yml create mode 100644 config/database/image_slider_image.yml create mode 100644 src/Adapter/CommandBus.php create mode 100644 src/Adapter/CommandBusInterface.php rename src/Controller/{ => Admin}/ImagesliderController.php (66%) create mode 100644 src/Controller/Admin/index.php create mode 100644 src/Domain/ImageSlider/Command/CreateImageSliderCommand.php create mode 100644 src/Domain/ImageSlider/Command/EditImageSliderCommand.php create mode 100644 src/Domain/ImageSlider/CommandHandler/CreateImageSliderHandler.php create mode 100644 src/Domain/ImageSlider/CommandHandler/CreateImageSliderHandlerInterface.php create mode 100644 src/Domain/ImageSlider/CommandHandler/EditImageSliderHandler.php create mode 100644 src/Domain/ImageSlider/CommandHandler/EditImageSliderHandlerInterface.php create mode 100644 src/Entity/ImageSliderImage.php delete mode 100644 src/Form/DataHandler/ImageSliderFormDataHandler.php create mode 100644 src/Form/DataTransformer/Lang/LangModeDataTransformer.php create mode 100644 src/Form/DataTransformer/Shop/ShopChoiceModelDataTransformer.php create mode 100644 src/Form/EventListener/ImagesliderFormSubscriber.php delete mode 100644 src/Form/ImageSliderType.php delete mode 100644 src/Form/Provider/ImageSliderFormDataProvider.php rename src/Form/{ => Type}/ImageSliderConfigurationType.php (96%) create mode 100644 src/Form/Type/ImageSliderType.php create mode 100644 src/Form/Type/Lang/LangFieldsType.php create mode 100644 src/Form/Type/Lang/LangType.php create mode 100644 src/Form/Type/Shop/ShopAssociationChoiceTreeType.php create mode 100644 src/Form/Type/Slider/ImageSliderLangType.php create mode 100644 src/Form/Type/Slider/ImageType.php delete mode 100644 src/Type/TranslatableFile.php delete mode 100644 views/js/createForm.js create mode 100644 views/js/list.js create mode 100644 views/templates/admin/form/form_theme.html.twig delete mode 100644 views/templates/admin/form/prestashop_ui_kit.html.twig diff --git a/config/admin/command.yml b/config/admin/command.yml new file mode 100644 index 0000000..8ec7643 --- /dev/null +++ b/config/admin/command.yml @@ -0,0 +1,22 @@ + +services: + _defaults: + autowire: true + public: false + + Oksydan\IsImageslider\Domain\ImageSlider\CommandHandler\CreateImageSliderHandlerInterface: + alias: Oksydan\IsImageslider\Domain\ImageSlider\CommandHandler\CreateImageSliderHandler + + Oksydan\IsImageslider\Domain\ImageSlider\CommandHandler\CreateImageSliderHandler: + tags: + - name: tactician.handler + command: Oksydan\IsImageslider\Domain\ImageSlider\Command\CreateImageSliderCommand + + + Oksydan\IsImageslider\Domain\ImageSlider\CommandHandler\EditImageSliderHandlerInterface: + alias: Oksydan\IsImageslider\Domain\ImageSlider\CommandHandler\EditImageSliderHandler + + Oksydan\IsImageslider\Domain\ImageSlider\CommandHandler\EditImageSliderHandler: + tags: + - name: tactician.handler + command: Oksydan\IsImageslider\Domain\ImageSlider\Command\EditImageSliderCommand diff --git a/config/admin/form.yml b/config/admin/form.yml index 667105d..1c2db63 100644 --- a/config/admin/form.yml +++ b/config/admin/form.yml @@ -1,43 +1,34 @@ services: - oksydan.is_imageslider.image_slider.configuration: - class: 'Oksydan\IsImageslider\Form\DataConfiguration\ImageSliderDataConfiguration' + Oksydan\IsImageslider\Form\DataTransformer\Shop\ShopChoiceModelDataTransformer: + class: 'Oksydan\IsImageslider\Form\DataTransformer\Shop\ShopChoiceModelDataTransformer' + autowire: false arguments: - - '@prestashop.adapter.legacy.configuration' - - '@prestashop.adapter.shop.context' - - '@prestashop.adapter.multistore_feature' + - '@prestashop.core.admin.shop.repository' - oksydan.is_imageslider.image_slider_configuration.form_handler: - class: 'PrestaShop\PrestaShop\Core\Form\Handler' + Oksydan\IsImageslider\Form\DataTransformer\Lang\LangModeDataTransformer: + class: 'Oksydan\IsImageslider\Form\DataTransformer\Lang\LangModeDataTransformer' + autowire: false arguments: - - '@form.factory' - - '@prestashop.core.hook.dispatcher' - - '@Oksydan\IsImageslider\Form\Provider\ImageSliderConfigurationFormDataProvider' - - 'Oksydan\IsImageslider\Form\ImageSliderConfigurationType' - - 'ConfigurationForm' + - '@prestashop.core.admin.lang.repository' - - Oksydan\IsImageslider\Type\TranslatableFile: - class: 'Oksydan\IsImageslider\Type\TranslatableFile' - parent: 'form.type.common.translatable' - public: true + Oksydan\IsImageslider\Form\Type\Shop\ShopAssociationChoiceTreeType: + class: 'Oksydan\IsImageslider\Form\Type\Shop\ShopAssociationChoiceTreeType' + autowire: false + arguments: + $shopTreeChoicesProvider: '@prestashop.adapter.form.choice_provider.shop_tree_choice_provider' + $shopChoiceModelDataTransformer: '@Oksydan\IsImageslider\Form\DataTransformer\Shop\ShopChoiceModelDataTransformer' tags: - { name: form.type } + oksydan.is_imageslider.image_slider.configuration: + class: 'Oksydan\IsImageslider\Form\DataConfiguration\ImageSliderDataConfiguration' + arguments: + - '@prestashop.adapter.legacy.configuration' + - '@prestashop.adapter.shop.context' + - '@prestashop.adapter.multistore_feature' + oksydan.is_imageslider.provider.image_provider: class: 'Oksydan\IsImageslider\Provider\ImageProvider' public: true arguments: - '%is_imageslider_images_uri%' - - oksydan.is_imageslider.form.identifiable_object.builder.image_slider_form_builder: - class: 'PrestaShop\PrestaShop\Core\Form\IdentifiableObject\Builder\FormBuilder' - factory: 'prestashop.core.form.builder.form_builder_factory:create' - arguments: - - 'Oksydan\IsImageslider\Form\ImageSliderType' - - '@Oksydan\IsImageslider\Form\Provider\ImageSliderFormDataProvider' - - oksydan.is_imageslider.form.identifiable_object.handler.image_slider_form_handler: - class: 'PrestaShop\PrestaShop\Core\Form\IdentifiableObject\Handler\FormHandler' - factory: 'prestashop.core.form.identifiable_object.handler.form_handler_factory:create' - arguments: - - '@Oksydan\IsImageslider\Form\DataHandler\ImageSliderFormDataHandler' diff --git a/config/admin/grid.yml b/config/admin/grid.yml index 789c622..deb8475 100644 --- a/config/admin/grid.yml +++ b/config/admin/grid.yml @@ -1,5 +1,4 @@ services: - oksydan.is_imageslider.grid.image_slider_grid_factory: class: 'PrestaShop\PrestaShop\Core\Grid\GridFactory' arguments: @@ -8,7 +7,6 @@ services: - '@prestashop.core.grid.filter.form_factory' - '@prestashop.core.hook.dispatcher' - oksydan.is_imageslider.grid.data.factory.image_slider_data_factory: class: '%prestashop.core.grid.data.factory.doctrine_grid_data_factory%' arguments: diff --git a/config/admin/services.yml b/config/admin/services.yml index e847d86..e745fcd 100644 --- a/config/admin/services.yml +++ b/config/admin/services.yml @@ -2,7 +2,7 @@ imports: - { resource: ../common.yml } - { resource: ./grid.yml } - { resource: ./form.yml } - + - { resource: ./command.yml } services: _defaults: @@ -29,17 +29,24 @@ services: Oksydan\IsImageslider\: resource: '../../src/*' exclude: - - '../../src/{Controller,Falconize}' + - '../../src/{Controller,Falconize,Domain}' + - '../../src/Form/DataTransformer' + - '../../src/Form/Type/Shop' - '../../src/index.php' - '../../src/*/index.php' - '../../src/**/index.php' - Oksydan\IsImageslider\Controller\ImagesliderController: - class: Oksydan\IsImageslider\Controller\ImagesliderController + Oksydan\IsImageslider\Controller\Admin\ImagesliderController: + class: Oksydan\IsImageslider\Controller\Admin\ImagesliderController arguments: $imagsliderGridFactory: '@oksydan.is_imageslider.grid.image_slider_grid_factory' - $imagesliderConfigurationFormHandler: '@oksydan.is_imageslider.image_slider_configuration.form_handler' - $imagesliderFormBuilder: '@oksydan.is_imageslider.form.identifiable_object.builder.image_slider_form_builder' - $imagesliderFormHandler: '@oksydan.is_imageslider.form.identifiable_object.handler.image_slider_form_handler' $gridPresenter: '@prestashop.core.grid.presenter.grid_presenter' + Oksydan\IsImageslider\Adapter\CommandBusInterface: '@Oksydan\IsImageslider\Adapter\CommandBus' + Oksydan\IsImageslider\Adapter\CommandBus: + class: Oksydan\IsImageslider\Adapter\CommandBus + autowire: false + public: false + arguments: + - '@prestashop.core.command_bus' + diff --git a/config/configuration.yml b/config/configuration.yml index 9219dc6..acd75ed 100644 --- a/config/configuration.yml +++ b/config/configuration.yml @@ -1,5 +1,6 @@ imports: - { resource: './database/image_slider.yml' } - { resource: './database/image_slider_lang.yml' } + - { resource: './database/image_slider_image.yml' } - { resource: './database/image_slider_shop.yml' } - { resource: './hooks/register.yml' } diff --git a/config/database.yml b/config/database.yml deleted file mode 100644 index 15bfef5..0000000 --- a/config/database.yml +++ /dev/null @@ -1,47 +0,0 @@ -database: - image_slider: - columns: - id_slide: INT AUTO_INCREMENT NOT NULL - active: TINYINT(1) NOT NULL - position: INT NOT NULL - display_from: datetime DEFAULT NULL - display_to: datetime DEFAULT NULL - primary: - - id_slide - engine: InnoDb - - image_slider_lang: - columns: - id_slide: INT NOT NULL - id_lang: INT NOT NULL - title: VARCHAR(255) NOT NULL - legend: VARCHAR(255) NOT NULL - image: VARCHAR(255) NOT NULL - image_mobile: VARCHAR(255) NOT NULL - url: VARCHAR(255) NOT NULL - description: LONGTEXT NOT NULL - primary: - - id_slide - - id_lang - engine: InnoDb - - image_slider_shop: - columns: - id_slide: INT NOT NULL - id_shop: INT NOT NULL - primary: - - id_slide - - id_shop - engine: InnoDb - -database_add: - image_slider: - columns: - display_from: datetime DEFAULT NULL - display_to: datetime DEFAULT NULL - -database_modify: - image_slider: - columns: - display_from: datetime DEFAULT NULL - display_to: datetime DEFAULT NULL diff --git a/config/database/image_slider.yml b/config/database/image_slider.yml index f4c26d0..237fbaf 100644 --- a/config/database/image_slider.yml +++ b/config/database/image_slider.yml @@ -21,6 +21,9 @@ database_tables: type: datetime notnull: false default: null + - name: image_to_all_langs + type: boolean + default: false + notnull: true primary: - id_slide - diff --git a/config/database/image_slider_image.yml b/config/database/image_slider_image.yml new file mode 100644 index 0000000..ffcd879 --- /dev/null +++ b/config/database/image_slider_image.yml @@ -0,0 +1,32 @@ +database_tables: + image_slider_image: + columns: + - name: id_image + type: integer + length: 11 + notnull: true + autoincrement: true + - name: name + type: string + length: 255 + primary: + - id_image + + constraint_keys: + - name: is_imageslider_constraint_image_slider_image_lang + foreign_table: image_slider_lang + update: NO ACTION + delete: CASCADE + local_columns: + - id_image + foreign_columns: + - image + + - name: is_imageslider_constraint_image_slider_image_mobile_lang + foreign_table: image_slider_lang + update: NO ACTION + delete: CASCADE + local_columns: + - id_image + foreign_columns: + - image_mobile diff --git a/config/database/image_slider_lang.yml b/config/database/image_slider_lang.yml index fe3037c..da1df03 100644 --- a/config/database/image_slider_lang.yml +++ b/config/database/image_slider_lang.yml @@ -16,26 +16,34 @@ database_tables: - name: legend type: string length: 255 - notnull: true + notnull: false - name: image - type: string - length: 255 - notnull: true + type: integer + length: 11 + notnull: false - name: image_mobile - type: string - length: 255 - notnull: true + type: integer + length: 11 + notnull: false - name: url type: string length: 255 notnull: true - name: description type: text - notnull: true + notnull: false primary: - id_slide - id_lang + indexes: + - name: image_slider_lang_image + columns: + - image + - name: image_slider_lang_image_mobile + columns: + - image_mobile + constraint_keys: - name: is_imageslider_constraint_lang foreign_table: lang diff --git a/config/routes.yml b/config/routes.yml index a83152f..fc5f8f1 100644 --- a/config/routes.yml +++ b/config/routes.yml @@ -1,42 +1,4 @@ -is_imageslider_controller: - path: /is_imageslider/configuration - methods: [GET] - defaults: - _controller: 'Oksydan\IsImageslider\Controller\ImagesliderController::index' - -is_imageslider_controller_configuration_save: - path: /is_imageslider/configuration - methods: [POST, PATCH] - defaults: - _controller: 'Oksydan\IsImageslider\Controller\ImagesliderController::saveConfiguration' - -is_imageslider_controller_create: - path: /is_imageslider/imageslide/create - methods: [GET, POST] - defaults: - _controller: 'Oksydan\IsImageslider\Controller\ImagesliderController::create' - -is_imageslider_controller_edit: - path: /is_imageslider/imageslide/{slideId}/edit - methods: [GET, POST] - defaults: - _controller: 'Oksydan\IsImageslider\Controller\ImagesliderController::edit' - -is_imageslider_controller_delete: - path: /is_imageslider/imageslide/{slideId}/delete - methods: [GET, POST] - defaults: - _controller: 'Oksydan\IsImageslider\Controller\ImagesliderController::delete' - -is_imageslider_controller_toggle_status: - path: /is_imageslider/imageslide/{slideId}/toggle - methods: [POST] - defaults: - _controller: 'Oksydan\IsImageslider\Controller\ImagesliderController::toggleStatus' - -is_imageslider_controller_update_positions: - path: /is_imageslider/imageslide/update_positions - methods: [POST] - defaults: - _controller: 'Oksydan\IsImageslider\Controller\ImagesliderController::updatePositionAction' - +is_imageslider: + resource: ../src/Controller/Admin/ + type: annotation + prefix: /is_imageslider diff --git a/is_imageslider.php b/is_imageslider.php index ccae754..8d6f627 100644 --- a/is_imageslider.php +++ b/is_imageslider.php @@ -87,7 +87,7 @@ public function uninstall(): bool public function getContent(): void { - Tools::redirectAdmin(SymfonyContainer::getInstance()->get('router')->generate('is_imageslider_controller')); + Tools::redirectAdmin(SymfonyContainer::getInstance()->get('router')->generate('admin_imageslider_controller_index')); } /** diff --git a/src/Adapter/CommandBus.php b/src/Adapter/CommandBus.php new file mode 100644 index 0000000..ca7d88b --- /dev/null +++ b/src/Adapter/CommandBus.php @@ -0,0 +1,23 @@ +commandBus = $commandBus; + } + + public function handle($command) + { + $this->commandBus->handle($command); + } +} + diff --git a/src/Adapter/CommandBusInterface.php b/src/Adapter/CommandBusInterface.php new file mode 100644 index 0000000..576e814 --- /dev/null +++ b/src/Adapter/CommandBusInterface.php @@ -0,0 +1,15 @@ +templateCache = $templateCache; $this->deleteSlideHandler = $deleteSlideHandler; $this->imagsliderGridFactory = $imagsliderGridFactory; - $this->imagesliderConfigurationFormHandler = $imagesliderConfigurationFormHandler; $this->gridPresenter = $gridPresenter; - $this->imagesliderFormBuilder = $imagesliderFormBuilder; - $this->imagesliderFormHandler = $imagesliderFormHandler; $this->translator = $translator; $this->imageSliderRepository = $imageSliderRepository; $this->toggleSlideActivityHandler = $toggleSlideActivityHandler; $this->updateSliderPositionHandler = $updateSliderPositionHandler; } + /** + * @Route(path="/index", name="index", methods={"GET", "POST"}) + */ public function index(ImageSliderFileters $filters): Response { $imageSliderGrid = $this->imagsliderGridFactory->getGrid($filters); - $configurationForm = $this->imagesliderConfigurationFormHandler->getForm(); - return $this->render('@Modules/is_imageslider/views/templates/admin/index.html.twig', [ 'translationDomain' => TranslationDomains::TRANSLATION_DOMAIN_ADMIN, 'imageSliderkGrid' => $this->presentGrid($imageSliderGrid), - 'configurationForm' => $configurationForm->createView(), 'help_link' => false, ]); } - public function create(Request $request): Response + private function flattenUploadedImagesArray(array $files): array + { + if (!empty($files['image_slider']['slider_langs'])) { + return $files['image_slider']['slider_langs']; + } + + return []; + } + + /** + * @Route(path="/create", name="create", methods={"GET", "POST"}) + */ + public function create(Request $request, CommandBusInterface $commandBus): Response { - $form = $this->imagesliderFormBuilder->getForm(); + $form = $this->createForm(ImageSliderType::class); + $form->handleRequest($request); - try { - $result = $this->imagesliderFormHandler->handle($form); + if ($form->isSubmitted() && $form->isValid()) { + try { + $commandBus->handle(new CreateImageSliderCommand( + $form->getData(), + $this->flattenUploadedImagesArray($request->files->all()) + )); - if (null !== $result->getIdentifiableObjectId()) { $this->addFlash( 'success', $this->trans('Successful creation.', 'Admin.Notifications.Success') @@ -106,10 +118,11 @@ public function create(Request $request): Response $this->clearTemplateCache(); - return $this->redirectToRoute('is_imageslider_controller'); + return $this->redirectToRoute('admin_imageslider_controller_index'); + } catch (\Exception $e) { + throw $e; + $this->addFlash('error', $this->getErrorMessagesForExceptions($e, $this->getErrorMessages())); } - } catch (\Exception $e) { - $this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessages())); } return $this->render('@Modules/is_imageslider/views/templates/admin/form.html.twig', [ @@ -119,15 +132,22 @@ public function create(Request $request): Response ]); } - public function edit(Request $request, int $slideId): Response + /** + * @Route(path="/edit/{slideId}", name="edit", methods={"GET", "POST"}) + * @ParamConverter("imageSlider", class="Oksydan\IsImageslider\Entity\ImageSlider", options={"id" = "slideId"}) + */ + public function edit(Request $request, ImageSlider $imageSlider, CommandBusInterface $commandBus): Response { - $form = $this->imagesliderFormBuilder->getFormFor($slideId); + $form = $this->createForm(ImageSliderType::class, $imageSlider); $form->handleRequest($request); - try { - $result = $this->imagesliderFormHandler->handleFor($slideId, $form); + if ($form->isSubmitted() && $form->isValid()) { + try { + $commandBus->handle(new EditImageSliderCommand( + $form->getData(), + $this->flattenUploadedImagesArray($request->files->all()) + )); - if (null !== $result->getIdentifiableObjectId()) { $this->addFlash( 'success', $this->trans('Successful edition.', 'Admin.Notifications.Success') @@ -135,10 +155,10 @@ public function edit(Request $request, int $slideId): Response $this->clearTemplateCache(); - return $this->redirectToRoute('is_imageslider_controller'); + return $this->redirectToRoute('admin_imageslider_controller_index'); + } catch (\Exception $e) { + $this->addFlash('error', $this->getErrorMessagesForExceptions($e, $this->getErrorMessages())); } - } catch (\Exception $e) { - $this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessages())); } return $this->render('@Modules/is_imageslider/views/templates/admin/form.html.twig', [ @@ -148,10 +168,12 @@ public function edit(Request $request, int $slideId): Response ]); } - public function delete(Request $request, int $slideId): Response + /** + * @Route(path="/delete/{$slideId}", name="delete", methods={"GET", "POST"}) + * @Entity("imageSlider", expr="repository.find(slideId)") + */ + public function delete(Request $request, ImageSlider $imageSlider): Response { - $imageSlide = $this->imageSliderRepository->find($slideId); - if (!empty($imageSlide)) { $this->deleteSlideHandler->handle($imageSlide); @@ -211,24 +233,13 @@ public function saveConfiguration(Request $request): Response } /** - * @param Request $request - * @param int $slideId - * - * @return Response + * @Route(path="/toggleStatus/{$slideId}", name="toggle_status", methods={"GET", "POST"}) + * @Entity("imageSlider", expr="repository.find(slideId)") */ - public function toggleStatus(Request $request, int $slideId): Response + public function toggleStatus(Request $request, ImageSlider $imageSlider): Response { - $imageSlide = $this->imageSliderRepository->find($slideId); - - if (empty($imageSlide)) { - return $this->json([ - 'status' => false, - 'message' => sprintf('Image slide %d doesn\'t exist', $slideId), - ]); - } - try { - $this->toggleSlideActivityHandler->handle($imageSlide); + $this->toggleSlideActivityHandler->handle($imageSlider); $response = [ 'status' => true, @@ -239,7 +250,7 @@ public function toggleStatus(Request $request, int $slideId): Response 'status' => false, 'message' => sprintf( 'There was an error while updating the status of slide %d: %s', - $slideId, + $imageSlider->getId(), $e->getMessage() ), ]; @@ -248,6 +259,9 @@ public function toggleStatus(Request $request, int $slideId): Response return $this->json($response); } + /** + * @Route(path="/updatePosition/", name="update_position", methods={"POST"}) + */ public function updatePositionAction(Request $request): Response { try { @@ -267,17 +281,11 @@ private function clearTemplateCache() $this->templateCache->clearTemplateCache(); } - /** - * @inerhitDoc - */ protected function presentGrid(GridInterface $grid) { return $this->gridPresenter->present($grid); } - /** - * @inerhitDoc - */ protected function trans($key, $domain, array $parameters = []) { return $this->translator->trans($key, $parameters, $domain); @@ -299,4 +307,31 @@ private function getErrorMessages(): array ], ]; } + + protected function getErrorMessagesForExceptions(\Exception $e, array $messages) + { + $exceptionType = get_class($e); + $exceptionCode = $e->getCode(); + + if (isset($messages[$exceptionType])) { + $message = $messages[$exceptionType]; + + if (is_string($message)) { + return $message; + } + + if (is_array($message) && isset($message[$exceptionCode])) { + return $message[$exceptionCode]; + } + } + + return $this->trans( + 'An unexpected error occurred. [%type% code %code%]', + 'Admin.Notifications.Error', + [ + '%type%' => $exceptionType, + '%code%' => $exceptionCode, + ] + ); + } } diff --git a/src/Controller/Admin/index.php b/src/Controller/Admin/index.php new file mode 100644 index 0000000..88355f6 --- /dev/null +++ b/src/Controller/Admin/index.php @@ -0,0 +1,11 @@ +imageSlider = $imageSlider; + $this->files = $files; + } + + public function getImageSlider(): ImageSlider + { + return $this->imageSlider; + } + + public function getFiles(): array + { + return $this->files; + } +} diff --git a/src/Domain/ImageSlider/Command/EditImageSliderCommand.php b/src/Domain/ImageSlider/Command/EditImageSliderCommand.php new file mode 100644 index 0000000..f85f92d --- /dev/null +++ b/src/Domain/ImageSlider/Command/EditImageSliderCommand.php @@ -0,0 +1,33 @@ +imageSlider = $imageSlider; + $this->files = $files; + } + + public function getImageSlider(): ImageSlider + { + return $this->imageSlider; + } + + public function getFiles(): array + { + return $this->files; + } +} diff --git a/src/Domain/ImageSlider/CommandHandler/CreateImageSliderHandler.php b/src/Domain/ImageSlider/CommandHandler/CreateImageSliderHandler.php new file mode 100644 index 0000000..8275520 --- /dev/null +++ b/src/Domain/ImageSlider/CommandHandler/CreateImageSliderHandler.php @@ -0,0 +1,28 @@ +imageSliderRepository = $imageSliderRepository; + } + + public function handle(CreateImageSliderCommand $command): void + { + $imageSlider = $command->getImageSlider(); + $files = $command->getFiles(); + + $imageSlider->setPosition($this->imageSliderRepository->getHighestPosition() + 1); + + $this->imageSliderRepository->save($imageSlider); + } +} diff --git a/src/Domain/ImageSlider/CommandHandler/CreateImageSliderHandlerInterface.php b/src/Domain/ImageSlider/CommandHandler/CreateImageSliderHandlerInterface.php new file mode 100644 index 0000000..e07b3ff --- /dev/null +++ b/src/Domain/ImageSlider/CommandHandler/CreateImageSliderHandlerInterface.php @@ -0,0 +1,12 @@ +imageSliderRepository = $imageSliderRepository; + } + + public function handle(EditImageSliderCommand $command): void + { + $imageSlider = $command->getImageSlider(); + $files = $command->getFiles(); + + $this->imageSliderRepository->save($imageSlider); + } +} diff --git a/src/Domain/ImageSlider/CommandHandler/EditImageSliderHandlerInterface.php b/src/Domain/ImageSlider/CommandHandler/EditImageSliderHandlerInterface.php new file mode 100644 index 0000000..1918050 --- /dev/null +++ b/src/Domain/ImageSlider/CommandHandler/EditImageSliderHandlerInterface.php @@ -0,0 +1,12 @@ +shops = new ArrayCollection(); - $this->sliderLangs = new ArrayCollection(); + $this->sliderLang = new ArrayCollection(); + $this->active = false; + $this->image_to_all_langs = false; } - /** - * @return int - */ public function getId(): int { return $this->id; } + public function setId(int $id): void + { + $this->id = $id; + } + /** * @return bool */ @@ -92,154 +103,82 @@ public function getActive(): bool return $this->active; } - /** - * @param bool $active - * - * @return ImageSlider $this - */ - public function setActive(bool $active): ImageSlider + public function setActive(bool $active): void { $this->active = $active; - - return $this; } - /** - * @return int - */ public function getPosition(): int { return $this->position; } - /** - * @param int $position - * - * @return ImageSlider $this - */ - public function setPosition(int $position): ImageSlider + public function setPosition(int $position): void { $this->position = $position; - - return $this; } - /** - * @return \DateTime - */ public function getDisplayFrom(): \DateTime { return $this->display_from; } - /** - * @param \DateTime $display_from - * - * @return ImageSlider $this - */ - public function setDisplayFrom(\DateTime $display_from): ImageSlider + public function setDisplayFrom(\DateTime $display_from): void { $this->display_from = $display_from; - - return $this; } - /** - * @return \DateTime - */ public function getDisplayTo(): \DateTime { return $this->display_to; } - /** - * @param \DateTime $display_to - * - * @return ImageSlider $this - */ - public function setDisplayTo(\DateTime $display_to): ImageSlider + public function setDisplayTo(\DateTime $display_to): void { $this->display_to = $display_to; - - return $this; } - /** - * @param Shop $shop - * - * @return ImageSlider $this - */ - public function addShop(Shop $shop): ImageSlider + public function getImagesForAllLangs(): bool { - $this->shops[] = $shop; - - return $this; + return $this->image_to_all_langs; } - /** - * @param Shop $shop - * - * @return ImageSlider $this - */ - public function removeShop(Shop $shop): ImageSlider + public function setImagesForAllLangs(bool $image_to_all_langs): void { - $this->shops->removeElement($shop); - - return $this; + $this->image_to_all_langs = $image_to_all_langs; } - /** - * @return Collection - */ - public function getShops(): Collection + public function addShopAssociation(Shop $shop): void { - return $this->shops; + $this->shops[] = $shop; } - /** - * @return ImageSlider $this - */ - public function clearShops(): ImageSlider + public function removeShopAssociation(Shop $shop): void { - $this->shops->clear(); - - return $this; + $this->shops->removeElement($shop); } /** - * @return ArrayCollection + * @return Collection */ - public function getSliderLangs() + public function getShopAssociation(): Collection { - return $this->sliderLangs; + return $this->shops; } - /** - * @param int $langId - * - * @return ImageSliderLang|null - */ - public function getImageSliderLangByLangId(int $langId) + public function getSliderLangs(): Collection { - foreach ($this->sliderLangs as $sliderLang) { - if ($langId === $sliderLang->getLang()->getId()) { - return $sliderLang; - } - } - - return null; + return $this->sliderLang; } - /** - * @param ImageSliderLang $sliderLang - * - * @return ImageSlider $this - */ - public function addImageSliderLang(ImageSliderLang $sliderLang): ImageSlider + public function addSliderLang(ImageSliderLang $sliderLang): void { $sliderLang->setImageSlider($this); - $this->sliderLangs->add($sliderLang); + $this->sliderLang->add($sliderLang); + } - return $this; + public function removeSliderLang(ImageSliderLang $sliderLang): void + { + $this->sliderLang->removeElement($sliderLang); } } diff --git a/src/Entity/ImageSliderImage.php b/src/Entity/ImageSliderImage.php new file mode 100644 index 0000000..743e541 --- /dev/null +++ b/src/Entity/ImageSliderImage.php @@ -0,0 +1,56 @@ +id; + } + + public function setId(int $id): void + { + $this->id = $id; + } + + public function getName(): string + { + return $this->name; + } + + public function setName(?string $name): void + { + $this->name = $name ?? ''; + } +} diff --git a/src/Entity/ImageSliderLang.php b/src/Entity/ImageSliderLang.php index f0e58e9..e1995c5 100644 --- a/src/Entity/ImageSliderLang.php +++ b/src/Entity/ImageSliderLang.php @@ -65,97 +65,55 @@ class ImageSliderLang private string $description; /** - * @var string - * - * @ORM\Column(name="image", type="text") + * @ORM\OneToOne(targetEntity="Oksydan\IsImageslider\Entity\ImageSliderImage", cascade={"persist", "remove"}, mappedBy="imageSlideLang") + * @ORM\JoinColumn(name="image", referencedColumnName="id_image", nullable=true) */ - private string $image; + private ImageSliderImage $image; /** - * @var string - * - * @ORM\Column(name="image_mobile", type="text") + * @ORM\OneToOne(targetEntity="Oksydan\IsImageslider\Entity\ImageSliderImage", cascade={"persist", "remove"}, mappedBy="imageSlideLang") + * @ORM\JoinColumn(name="image_mobile", referencedColumnName="id_image", nullable=true) */ - private string $imageMobile; + private ImageSliderImage $imageMobile; - /** - * @return ImageSlider - */ public function getImageSlider(): ImageSlider { return $this->imageSlide; } - /** - * @param ImageSlider $imageSlide - * - * @return ImageSliderLang $this - */ - public function setImageSlider(ImageSlider $imageSlide): ImageSliderLang + public function setImageSlider(ImageSlider $imageSlide): void { $this->imageSlide = $imageSlide; - - return $this; } - /** - * @return string - */ public function getTitle(): string { return $this->title; } - /** - * @param string $title - * - * @return ImageSliderLang $this - */ - public function setTitle(string $title): ImageSliderLang + public function setTitle(?string $title): void { $this->title = $title; - - return $this; } - /** - * @return string - */ public function getLegend(): string { return $this->legend; } - /** - * @param string $legend - * - * @return ImageSliderLang $this - */ - public function setLegend(string $legend): ImageSliderLang + public function setLegend(?string $legend): void { $this->legend = $legend; - - return $this; } - /** - * @return string - */ public function getUrl(): string { return $this->url; } - /** - * @param string $url - * - * @return ImageSliderLang $this - */ - public function setUrl(string $url): ImageSliderLang + public function setUrl(string $url): void { $this->url = $url; - - return $this; } /** @@ -166,75 +124,38 @@ public function getDescription(): string return $this->description; } - /** - * @param string $description - * - * @return ImageSliderLang $this - */ - public function setDescription(string $description): ImageSliderLang + public function setDescription(?string $description): void { $this->description = $description; - - return $this; } - /** - * @return string|null - */ - public function getImage(): ?string + public function getImage(): ImageSliderImage { return $this->image; } - /** - * @param string $image - * - * @return ImageSliderLang $this - */ - public function setImage(string $image): ImageSliderLang + public function setImage(ImageSliderImage $image): void { $this->image = $image; - - return $this; } - /** - * @return string|null - */ - public function getImageMobile(): ?string + public function getImageMobile(): ImageSliderImage { return $this->imageMobile; } - /** - * @param string $imageMobile - * - * @return ImageSliderLang $this - */ - public function setImageMobile(string $imageMobile): ImageSliderLang + public function setImageMobile(ImageSliderImage $imageMobile): void { $this->imageMobile = $imageMobile; - - return $this; } - /** - * @return Lang - */ public function getLang(): Lang { return $this->lang; } - /** - * @param Lang $lang - * - * @return ImageSliderLang $this - */ - public function setLang(Lang $lang): ImageSliderLang + public function setLang(Lang $lang): void { $this->lang = $lang; - - return $this; } } diff --git a/src/Form/DataHandler/ImageSliderFormDataHandler.php b/src/Form/DataHandler/ImageSliderFormDataHandler.php deleted file mode 100644 index a66c7ab..0000000 --- a/src/Form/DataHandler/ImageSliderFormDataHandler.php +++ /dev/null @@ -1,218 +0,0 @@ -imageSliderRepository = $imageSliderRepository; - $this->langRepository = $langRepository; - $this->entityManager = $entityManager; - $this->fileUploader = $fileUploader; - $this->fileEraser = $fileEraser; - $this->locales = $locales; - } - - /** - * {@inheritdoc} - */ - public function create(array $data): int - { - $this->assertSliderDataRangeActivity($data); - - $imageSlide = new ImageSlider(); - - $imageSlide->setActive($data['active']); - $imageSlide->setDisplayFrom($data['display_from'] ?? new \DateTime()); - $imageSlide->setDisplayTo($data['display_to'] ?? new \DateTime()); - $imageSlide->setPosition($this->imageSliderRepository->getHighestPosition() + 1); - $this->addAssociatedShops($imageSlide, $data['shop_association'] ?? null); - - foreach ($this->locales as $language) { - $langId = (int) $language['id_lang']; - $lang = $this->langRepository->findOneById($langId); - $imageSliderLang = new ImageSliderLang(); - - $imageSliderLang - ->setLang($lang) - ->setTitle($data['title'][$langId] ?? '') - ->setUrl($data['url'][$langId] ?? '') - ->setLegend($data['legend'][$langId] ?? '') - ->setDescription($data['description'][$langId] ?? ''); - - if (!empty($data['image'][$langId])) { - $imageSliderLang->setImage($this->uploadFile($data['image'][$langId])); - } - - if (!empty($data['image_mobile'][$langId])) { - $imageSliderLang->setImageMobile($this->uploadFile($data['image_mobile'][$langId])); - } - - $imageSlide->addImageSliderLang($imageSliderLang); - } - - $this->entityManager->persist($imageSlide); - $this->entityManager->flush(); - - return $imageSlide->getId(); - } - - /** - * {@inheritdoc} - */ - public function update($id, array $data): int - { - $this->assertSliderDataRangeActivity($data); - - $imageSlide = $this->entityManager->getRepository(ImageSlider::class)->find($id); - - $imageSlide->setActive($data['active']); - $imageSlide->setDisplayFrom($data['display_from'] ?? new \DateTime()); - $imageSlide->setDisplayTo($data['display_to'] ?? new \DateTime()); - $this->addAssociatedShops($imageSlide, $data['shop_association'] ?? null); - - foreach ($this->locales as $language) { - $langId = (int) $language['id_lang']; - $imageSliderLang = $imageSlide->getImageSliderLangByLangId($langId); - - $newImageSliderLang = false; - if (null === $imageSliderLang) { - $imageSliderLang = new ImageSliderLang(); - $lang = $this->langRepository->findOneById($langId); - $imageSliderLang->setLang($lang); - $newImageSliderLang = true; - } - - $imageSliderLang - ->setTitle($data['title'][$langId] ?? '') - ->setUrl($data['url'][$langId] ?? '') - ->setLegend($data['legend'][$langId] ?? '') - ->setDescription($data['description'][$langId] ?? ''); - - if (!empty($data['image'][$langId])) { - if ($imageSliderLang->getImage() !== null) { - $this->eraseFile($imageSliderLang->getImage()); - } - $imageSliderLang->setImage($this->uploadFile($data['image'][$langId])); - } - - if (!empty($data['image_mobile'][$langId])) { - if ($imageSliderLang->getImage() !== null) { - $this->eraseFile($imageSliderLang->getImageMobile()); - } - $imageSliderLang->setImageMobile($this->uploadFile($data['image_mobile'][$langId])); - } - - if ($newImageSliderLang) { - $imageSlide->addImageSliderLang($imageSliderLang); - } - } - - $this->entityManager->flush(); - - return $imageSlide->getId(); - } - - /** - * @params array $data - * - * @return void - * - * @throws DateRangeNotValidException - */ - private function assertSliderDataRangeActivity($data): void - { - if (!empty($data['display_from']) && !empty($data['display_to'])) { - if ($data['display_from'] > $data['display_to']) { - throw new DateRangeNotValidException(); - } - } - } - - /** - * @param ImageSlider $imageSlide - * @param array|null $shopIdList - */ - private function addAssociatedShops(ImageSlider &$imageSlide, array $shopIdList = null): void - { - $imageSlide->clearShops(); - - if (empty($shopIdList)) { - return; - } - - foreach ($shopIdList as $shopId) { - $shop = $this->entityManager->getRepository(Shop::class)->find($shopId); - $imageSlide->addShop($shop); - } - } - - private function uploadFile(UploadedFile $file): string - { - return $this->fileUploader->upload($file); - } - - private function eraseFile(string $fileName): bool - { - return $this->fileEraser->remove($fileName); - } -} diff --git a/src/Form/DataTransformer/Lang/LangModeDataTransformer.php b/src/Form/DataTransformer/Lang/LangModeDataTransformer.php new file mode 100644 index 0000000..1e1dae2 --- /dev/null +++ b/src/Form/DataTransformer/Lang/LangModeDataTransformer.php @@ -0,0 +1,37 @@ +langRepository = $langRepository; + } + + public function transform($value) + { + if ($value instanceof Lang) { + return $value->getId(); + } + + return $value; + } + + public function reverseTransform($value) + { + if (is_int((int) $value)) { + return $this->langRepository->find($value); + } + + return $value; + } +} diff --git a/src/Form/DataTransformer/Shop/ShopChoiceModelDataTransformer.php b/src/Form/DataTransformer/Shop/ShopChoiceModelDataTransformer.php new file mode 100644 index 0000000..561af52 --- /dev/null +++ b/src/Form/DataTransformer/Shop/ShopChoiceModelDataTransformer.php @@ -0,0 +1,55 @@ +shopRepository = $shopRepository; + } + + public function transform($value) + { + $shopList = []; + + if (null === $value) { + return $shopList; + } + + foreach ($value as $shop) { + if ($shop instanceof Shop) { + $shopList[] = $shop->getId(); + } + } + + return $shopList; + } + + public function reverseTransform($value): array + { + $shopList = []; + + if (!$value || !is_array($value)) { + return $shopList; + } + + foreach ($value as $shopId) { + $shop = $this->shopRepository->findOneById((int) $shopId); + + if ($shop) { + $shopList[] = $shop; + } + } + + return $shopList; + } +} diff --git a/src/Form/EventListener/ImagesliderFormSubscriber.php b/src/Form/EventListener/ImagesliderFormSubscriber.php new file mode 100644 index 0000000..c417185 --- /dev/null +++ b/src/Form/EventListener/ImagesliderFormSubscriber.php @@ -0,0 +1,68 @@ + 'preSubmit', + FormEvents::PRE_SET_DATA => 'preSetData', + ]; + } + + private function modifyFormBasedOnSelectedType($form, $data) + { + $isEdit = $data['edit'] ?? false; + $imagesForAllLangs = $data['images_for_all_langs'] ?? false; + + $imageConstrains = [ + new File([ + 'mimeTypes' => [ + 'image/gif', + 'image/jpeg', + 'image/png', + ], + ]), + ]; + + if (!$isEdit) { + $imageConstrains[] = new NotBlank(); + } + +// if ($imagesForAllLangs) { +// $form->add('images', ImagesType::class, [ +// 'imagesConstraints' => $imageConstrains, +// ]); +// } else { +// $form->add('images', ImagesMultilangType::class, [ +// 'imagesConstraints' => $imageConstrains, +// ]); +// } + } + + public function preSetData(FormEvent $event) + { + $data = $event->getData(); + $form = $event->getForm(); + + $this->modifyFormBasedOnSelectedType($form, $data); + } + + public function preSubmit(FormEvent $event): void + { + $data = $event->getData(); + $form = $event->getForm(); + + $this->modifyFormBasedOnSelectedType($form, $data); + } +} diff --git a/src/Form/ImageSliderType.php b/src/Form/ImageSliderType.php deleted file mode 100644 index 76278c5..0000000 --- a/src/Form/ImageSliderType.php +++ /dev/null @@ -1,167 +0,0 @@ -multistoreFeature = $multistoreFeature; - } - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options): void - { - $isEdit = !empty($options['data']['image']); - - $imageConstrains = [ - new File([ - 'mimeTypes' => [ - 'image/jpeg', - 'image/png', - ], - ]), - ]; - - if (!$isEdit) { - $imageConstrains[] = new NotBlank(); - } - - $builder - ->add('image_preview', TranslatableType::class, [ - 'type' => ImagePreviewType::class, - 'label' => $this->trans('Image preview', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'locales' => $this->locales, - 'required' => false, - ]) - ->add('image', TranslatableFile::class, [ - 'type' => FileType::class, - 'label' => $this->trans('Image', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'locales' => $this->locales, - 'options' => [ - 'data_class' => null, - 'constraints' => $imageConstrains, - ], - 'required' => true, - ]) - ->add('image_mobile_preview', TranslatableType::class, [ - 'type' => ImagePreviewType::class, - 'label' => $this->trans('Image mobile preview', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'locales' => $this->locales, - 'required' => false, - ]) - ->add('image_mobile', TranslatableFile::class, [ - 'type' => FileType::class, - 'label' => $this->trans('Image mobile', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'locales' => $this->locales, - 'options' => [ - 'data_class' => null, - 'constraints' => $imageConstrains, - ], - 'required' => true, - ]) - ->add('title', TranslatableType::class, [ - 'type' => TextType::class, - 'label' => $this->trans('Title', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'locales' => $this->locales, - 'required' => false, - ]) - ->add('legend', TranslatableType::class, [ - 'type' => TextType::class, - 'label' => $this->trans('Legend', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'locales' => $this->locales, - 'required' => false, - ]) - ->add('url', TranslatableType::class, [ - 'type' => TextType::class, - 'label' => $this->trans('Link', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'locales' => $this->locales, - 'required' => true, - 'options' => [ - 'constraints' => [ - new NotBlank(), - ], - ], - ]) - ->add('description', TranslatableType::class, [ - 'type' => FormattedTextareaType::class, - 'locales' => $this->locales, - 'label' => $this->trans('Description', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'required' => false, - ]) - ->add('active', SwitchType::class, [ - 'label' => $this->trans('Active', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'required' => true, - ]) - ->add('display_from', DateTimeType::class, [ - 'label' => $this->trans('Display from', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'required' => true, - 'widget' => 'single_text', - 'html5' => true, - 'input' => 'datetime', - 'with_seconds' => true, - ]) - ->add('display_to', DateTimeType::class, [ - 'label' => $this->trans('Display to', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'required' => true, - 'widget' => 'single_text', - 'html5' => true, - 'input' => 'datetime', - 'with_seconds' => true, - ]); - - if ($this->multistoreFeature->isUsed()) { - $builder->add( - 'shop_association', - ShopChoiceTreeType::class, - [ - 'label' => $this->trans('Shop associations', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), - 'constraints' => [ - new NotBlank([ - 'message' => $this->trans( - 'You have to select at least one shop to associate this item with', - 'Admin.Notifications.Error' - ), - ]), - ], - ] - ); - } - } -} diff --git a/src/Form/Provider/ImageSliderFormDataProvider.php b/src/Form/Provider/ImageSliderFormDataProvider.php deleted file mode 100644 index 18f5c85..0000000 --- a/src/Form/Provider/ImageSliderFormDataProvider.php +++ /dev/null @@ -1,130 +0,0 @@ -repository = $repository; - $this->shopContext = $shopContext; - $this->imagesliderImageThumbProvider = $imagesliderImageThumbProvider; - $this->placeholderImage = $placeholderImage; - $this->langRepository = $langRepository; - } - - /** - * @param mixed $id - * - * @return array - */ - public function getData($id): array - { - $imageSlide = $this->repository->findOneById((int) $id); - - $shopIds = []; - $slideData = []; - - foreach ($imageSlide->getShops() as $shop) { - $shopIds[] = $shop->getId(); - } - - $slideData['shop_association'] = $shopIds; - $slideData['active'] = $imageSlide->getActive(); - $slideData['display_from'] = $imageSlide->getDisplayFrom(); - $slideData['display_to'] = $imageSlide->getDisplayTo(); - - foreach ($imageSlide->getSliderLangs() as $imageSlideLang) { - $slideData['title'][$imageSlideLang->getLang()->getId()] = $imageSlideLang->getTitle(); - $slideData['legend'][$imageSlideLang->getLang()->getId()] = $imageSlideLang->getLegend(); - $slideData['url'][$imageSlideLang->getLang()->getId()] = $imageSlideLang->getUrl(); - $slideData['description'][$imageSlideLang->getLang()->getId()] = $imageSlideLang->getDescription(); - $slideData['image'][$imageSlideLang->getLang()->getId()] = $imageSlideLang->getImage(); - $slideData['image_mobile'][$imageSlideLang->getLang()->getId()] = $imageSlideLang->getImageMobile(); - - $slideData['image_preview'][$imageSlideLang->getLang()->getId()] = $this->imagesliderImageThumbProvider->getPath($imageSlideLang->getImage()) ?? $this->placeholderImage; - $slideData['image_mobile_preview'][$imageSlideLang->getLang()->getId()] = $this->imagesliderImageThumbProvider->getPath($imageSlideLang->getImageMobile()) ?? $this->placeholderImage; - } - - return $slideData; - } - - /** - * @return array - */ - private function getImagePreviewPlaceholder(): array - { - $imagePreview = []; - $languages = $this->langRepository->findBy(['active' => true]); - - foreach ($languages as $lang) { - $imagePreview[$lang->getId()] = $this->placeholderImage; - } - - return $imagePreview; - } - - /** - * @return array - */ - public function getDefaultData(): array - { - return [ - 'image_preview' => $this->getImagePreviewPlaceholder(), - 'image_mobile_preview' => $this->getImagePreviewPlaceholder(), - 'title' => [], - 'legend' => [], - 'url' => [], - 'description' => [], - 'active' => false, - 'display_from' => new \DateTime(), - 'display_to' => new \DateTime(), - 'shop_association' => $this->shopContext->getContextListShopID(), - ]; - } -} diff --git a/src/Form/ImageSliderConfigurationType.php b/src/Form/Type/ImageSliderConfigurationType.php similarity index 96% rename from src/Form/ImageSliderConfigurationType.php rename to src/Form/Type/ImageSliderConfigurationType.php index 1616416..97fc540 100644 --- a/src/Form/ImageSliderConfigurationType.php +++ b/src/Form/Type/ImageSliderConfigurationType.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Oksydan\IsImageslider\Form; +namespace Oksydan\IsImageslider\Form\Type; use Oksydan\IsImageslider\Configuration\SliderConfiguration; use Oksydan\IsImageslider\Translations\TranslationDomains; @@ -13,7 +13,7 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Validator\Constraints\Range; -class ImageSliderConfigurationType extends TranslatorAwareType +final class ImageSliderConfigurationType extends TranslatorAwareType { /** * {@inheritdoc} diff --git a/src/Form/Type/ImageSliderType.php b/src/Form/Type/ImageSliderType.php new file mode 100644 index 0000000..38d94af --- /dev/null +++ b/src/Form/Type/ImageSliderType.php @@ -0,0 +1,108 @@ +multistoreFeature = $multistoreFeature; + $this->imagesliderFormSubscriber = $imagesliderFormSubscriber; + } + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('images_for_all_langs', SwitchType::class, [ + 'label' => $this->trans('Set one image for all languages', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), + 'attr' => [ + 'class' => 'js-toggle-images-types', + ], + ]) + ->add('slider_langs', LangFieldsType::class, [ + 'entry_type' => ImageSliderLangType::class, + 'entity_class' => ImageSliderLang::class, + 'entity_lang_field' => 'lang', + ]) + ->add('active', SwitchType::class, [ + 'label' => $this->trans('Active', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), + 'required' => true, + ]) + ->add('display_from', DateTimeType::class, [ + 'label' => $this->trans('Display from', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), + 'required' => true, + 'widget' => 'single_text', + 'html5' => true, + 'input' => 'datetime', + 'with_seconds' => true, + ]) + ->add('display_to', DateTimeType::class, [ + 'label' => $this->trans('Display to', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), + 'required' => true, + 'widget' => 'single_text', + 'html5' => true, + 'input' => 'datetime', + 'with_seconds' => true, + ]); + + if ($this->multistoreFeature->isUsed()) { + $builder->add('shop_association', ShopAssociationChoiceTreeType::class, [ + 'label' => $this->trans('Shop associations', TranslationDomains::TRANSLATION_DOMAIN_ADMIN), + 'constraints' => [ + new NotBlank([ + 'message' => $this->trans( + 'You have to select at least one shop to associate this item with', + 'Admin.Notifications.Error' + ), + ]), + ], + ]); + } + +// $builder->addEventSubscriber($this->imagesliderFormSubscriber); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => ImageSlider::class, + ]); + } +} diff --git a/src/Form/Type/Lang/LangFieldsType.php b/src/Form/Type/Lang/LangFieldsType.php new file mode 100644 index 0000000..a2b562c --- /dev/null +++ b/src/Form/Type/Lang/LangFieldsType.php @@ -0,0 +1,144 @@ +langRepository = $langRepository; + $this->configuration = $configuration; + $this->legacyContext = $legacyContext; + } + + public function getParent(): string + { + return CollectionType::class; + } + + public function buildView(FormView $view, FormInterface $form, array $options) + { + $locales = $this->langRepository->findAll(); + + $view->vars['locales'] = $locales; + $view->vars['default_locale'] = $this->getDefaultLocale($locales); + + } + + public function finishView(FormView $view, FormInterface $form, array $options) + { + foreach ($view->children as $child) { + $langGetter = 'get' . ucfirst($options['entity_lang_field']); + $langAwareEntity = $child->vars['value']; + + if (!method_exists($langAwareEntity, $langGetter)) { + throw new \InvalidArgumentException(sprintf('Method %s does not exist in class %s', $langGetter, $options['entity_class'])); + } + + $child->vars['form_locale'] = $child->vars['value']->{$langGetter}(); + } + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'allow_delete' => false, + 'allow_add' => false, + 'entity_lang_field' => 'lang', + ]); + + $resolver->setRequired([ + 'entity_class', + ]); + + $resolver->setAllowedTypes('entity_class', 'string'); + $resolver->setAllowedTypes('entity_lang_field', 'string'); + } + + private function fillDefaultData(array $options): array + { + $emptyData = []; + + foreach ($this->langRepository->findAll() as $lang) { + $langSetter = 'set' . ucfirst($options['entity_lang_field']); + + $langAwareEntity = new $options['entity_class'](); + $langAwareEntity->setLang($lang); + + if (!method_exists($langAwareEntity, $langSetter)) { + throw new \InvalidArgumentException(sprintf('Method %s does not exist in class %s', $langSetter, $options['entity_class'])); + } + + $langAwareEntity->{$langSetter}($lang); + + $emptyData[] = $langAwareEntity; + } + + return $emptyData; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->setData($this->fillDefaultData($options)); + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix() + { + return 'langfields'; + } + + + /** + * Get default locale. + * + * @param array $locales + * + * @return array + */ + private function getDefaultLocale(array $locales) + { + $defaultShopLocaleId = $this->configuration->getInt('PS_LANG_DEFAULT', null); + $defaultFormLocaledId = $this->legacyContext->getContext()->employee->id_lang ?? null; + + if ($defaultFormLocaledId) { + foreach ($locales as $locale) { + if ($locale->getId() == $defaultFormLocaledId) { + return $locale; + } + } + } + + foreach ($locales as $locale) { + if ($locale->getId() === $defaultShopLocaleId) { + return $locale; + } + } + + return reset($locales); + } + +} diff --git a/src/Form/Type/Lang/LangType.php b/src/Form/Type/Lang/LangType.php new file mode 100644 index 0000000..b3ae9a0 --- /dev/null +++ b/src/Form/Type/Lang/LangType.php @@ -0,0 +1,30 @@ +langModeDataTransformer = $langModeDataTransformer; + } + + public function getParent(): string + { + return HiddenType::class; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->addModelTransformer($this->langModeDataTransformer); + } +} diff --git a/src/Form/Type/Shop/ShopAssociationChoiceTreeType.php b/src/Form/Type/Shop/ShopAssociationChoiceTreeType.php new file mode 100644 index 0000000..0896f3f --- /dev/null +++ b/src/Form/Type/Shop/ShopAssociationChoiceTreeType.php @@ -0,0 +1,75 @@ +shopTreeChoicesProvider = $shopTreeChoicesProvider; + $this->shopChoiceModelDataTransformer = $shopChoiceModelDataTransformer; + } + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->addModelTransformer($this->shopChoiceModelDataTransformer); + $builder->addEventListener( + FormEvents::PRE_SET_DATA, + [$this, 'onPreSetData'] + ); + + parent::buildForm($builder, $options); + } + + public function onPreSetData($event) + { + $data = $this->shopChoiceModelDataTransformer->transform($event->getData()); + + $event->setData($data); + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'choices_tree' => $this->shopTreeChoicesProvider->getChoices(), + 'multiple' => true, + 'choice_label' => 'name', + 'choice_value' => 'id_shop', + ]); + } + + /** + * {@inheritdoc} + */ + public function getParent() + { + return ShopChoiceTreeType::class; + } +} diff --git a/src/Form/Type/Slider/ImageSliderLangType.php b/src/Form/Type/Slider/ImageSliderLangType.php new file mode 100644 index 0000000..41d3aef --- /dev/null +++ b/src/Form/Type/Slider/ImageSliderLangType.php @@ -0,0 +1,73 @@ +translator = $translator; + } + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('lang', LangType::class) + ->add('title', TextType::class, [ + 'label' => $this->translator->trans('Title', [], TranslationDomains::TRANSLATION_DOMAIN_ADMIN), + 'required' => true, + ]) + ->add('legend', TextType::class, [ + 'label' => $this->translator->trans('Legend', [], TranslationDomains::TRANSLATION_DOMAIN_ADMIN), + 'required' => false, + ]) + ->add('url', TextType::class, [ + 'label' => $this->translator->trans('Link', [], TranslationDomains::TRANSLATION_DOMAIN_ADMIN), + 'required' => true, + 'constraints' => [ + new NotBlank(), + ], + ]) + ->add('description', FormattedTextareaType::class, [ + 'label' => $this->translator->trans('Description', [], TranslationDomains::TRANSLATION_DOMAIN_ADMIN), + 'required' => false, + ]) + ->add('image_file', ImageType::class, [ + 'label' => $this->translator->trans('Image', [], TranslationDomains::TRANSLATION_DOMAIN_ADMIN), + 'mapped' => false, + ]) + ->add('image_mobile_file', ImageType::class, [ + 'label' => $this->translator->trans('Image mobile', [], TranslationDomains::TRANSLATION_DOMAIN_ADMIN), + 'mapped' => false, + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => ImageSliderLang::class, + ]); + } +} diff --git a/src/Form/Type/Slider/ImageType.php b/src/Form/Type/Slider/ImageType.php new file mode 100644 index 0000000..32d322f --- /dev/null +++ b/src/Form/Type/Slider/ImageType.php @@ -0,0 +1,58 @@ +translator = $translator; + } + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('image_preview', ImagePreviewType::class, [ + 'required' => false, + 'mapped' => false, + 'label' => false, + ]) + ->add('image', FileType::class, [ + 'data_class' => null, + 'mapped' => false, + 'required' => false, + 'label' => false, + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => ImageSliderImage::class, + ]); + } + + public function getBlockPrefix() + { + return 'image'; + } +} diff --git a/src/Grid/Data/Factory/ImageSliderGridDataFactory.php b/src/Grid/Data/Factory/ImageSliderGridDataFactory.php index 492634e..00fae86 100644 --- a/src/Grid/Data/Factory/ImageSliderGridDataFactory.php +++ b/src/Grid/Data/Factory/ImageSliderGridDataFactory.php @@ -59,9 +59,9 @@ public function getData(SearchCriteriaInterface $searchCriteria) */ private function applyModification(array $sliders) { - foreach ($sliders as $i => $slider) { - $sliders[$i]['image'] = $this->imagesliderImageThumbProvider->getPath($slider['image']); - } +// foreach ($sliders as $i => $slider) { +// $sliders[$i]['image'] = $this->imagesliderImageThumbProvider->getPath($slider['image']); +// } return $sliders; } diff --git a/src/Grid/Definition/Factory/ImageSliderGridDefinitionFactory.php b/src/Grid/Definition/Factory/ImageSliderGridDefinitionFactory.php index edbb384..0ce5041 100644 --- a/src/Grid/Definition/Factory/ImageSliderGridDefinitionFactory.php +++ b/src/Grid/Definition/Factory/ImageSliderGridDefinitionFactory.php @@ -66,7 +66,7 @@ protected function getColumns() ->setOptions([ 'id_field' => 'id_slide', 'position_field' => 'position', - 'update_route' => 'is_imageslider_controller_update_positions', + 'update_route' => 'admin_imageslider_controller_update_position', 'update_method' => 'POST', ]) ) @@ -104,7 +104,7 @@ protected function getColumns() ->setOptions([ 'field' => 'active', 'primary_field' => 'id_slide', - 'route' => 'is_imageslider_controller_toggle_status', + 'route' => 'admin_imageslider_controller_toggle_status', 'route_param_name' => 'slideId', ]) ) @@ -116,7 +116,7 @@ protected function getColumns() (new LinkRowAction('edit')) ->setIcon('edit') ->setOptions([ - 'route' => 'is_imageslider_controller_edit', + 'route' => 'admin_imageslider_controller_edit', 'route_param_name' => 'slideId', 'route_param_field' => 'id_slide', ]) @@ -126,7 +126,7 @@ protected function getColumns() ->setName($this->trans->trans('Delete', [], 'Admin.Actions')) ->setIcon('delete') ->setOptions([ - 'route' => 'is_imageslider_controller_delete', + 'route' => 'admin_imageslider_controller_delete', 'route_param_name' => 'slideId', 'route_param_field' => 'id_slide', 'confirm_message' => $this->trans->trans( diff --git a/src/Repository/ImageSliderRepository.php b/src/Repository/ImageSliderRepository.php index 166aeff..07fb20c 100644 --- a/src/Repository/ImageSliderRepository.php +++ b/src/Repository/ImageSliderRepository.php @@ -19,6 +19,13 @@ public function __construct(ManagerRegistry $registry) parent::__construct($registry, ImageSlider::class); } + + public function save(ImageSlider $imageSlider): void + { + $this->getEntityManager()->persist($imageSlider); + $this->getEntityManager()->flush(); + } + public function getAllIds(): array { /** @var QueryBuilder $qb */ diff --git a/src/Type/TranslatableFile.php b/src/Type/TranslatableFile.php deleted file mode 100644 index cd73058..0000000 --- a/src/Type/TranslatableFile.php +++ /dev/null @@ -1,47 +0,0 @@ -vars = array_replace($view->vars, [ - 'locales' => $options['locales'], - 'default_locale' => reset($options['locales']), - ]); - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - parent::configureOptions($resolver); - - $resolver->setDefaults([ - 'choice_translation_domain' => false, - 'allow_extra_fields' => true, - ]); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'translatable_file'; - } -} diff --git a/views/css/form.css b/views/css/form.css index 1c42710..0c849e6 100644 --- a/views/css/form.css +++ b/views/css/form.css @@ -1,20 +1,20 @@ -#image_slider .input-group { +.image_slider .input-group { flex-wrap: nowrap; } -#image_slider .dropdown { +.image_slider .dropdown { flex: 0 0 auto; align-self: end; } -#image_slider .custom-file-label, -#image_slider .custom-file-input, -#image_slider .custom-file { +.image_slider .custom-file-label, +.image_slider .custom-file-input, +.image_slider .custom-file { min-height: 39px; margin: 0; } -#image_slider .custom-file .custom-file-label::after { +.image_slider .custom-file .custom-file-label::after { line-height: 1.8; } diff --git a/views/js/createForm.js b/views/js/createForm.js deleted file mode 100644 index a6bd1b8..0000000 --- a/views/js/createForm.js +++ /dev/null @@ -1,35 +0,0 @@ -$(document).ready(function () { - handleFileInputChange(); - - window.prestashop.component.initComponents( - [ - 'TranslatableField', - 'TinyMCEEditor', - 'TranslatableInput', - ], - ); - - const choiceTree = new window.prestashop.component.ChoiceTree('#image_slider_shop_association'); - choiceTree.enableAutoCheckChildren(); -}); - - -function handleFileInputChange() { - const $fileInput = $('#image_slider [type="file"]'); - - $fileInput.on('change', (e) => { - const $input = $(e.currentTarget); - const $relatedImage = $(`[data-related-field="${$input.attr('id')}"]`); - const files = $input[0].files; - - if (FileReader && files && files.length) { - const reader = new FileReader(); - - reader.onload = function () { - $relatedImage.attr('src', reader.result) - } - - reader.readAsDataURL(files[0]); - } - }) -} diff --git a/views/js/form.js b/views/js/form.js index 2d8129e..e5760f6 100644 --- a/views/js/form.js +++ b/views/js/form.js @@ -1,15 +1,64 @@ -$(document).ready(function () { + +const handleFileInputChange = () => { + const $fileInput = $('#image_slider [type="file"]'); + + $fileInput.on('change', (e) => { + const $input = $(e.currentTarget); + const $relatedImage = $(`[data-related-field="${$input.attr('id')}"]`); + const files = $input[0].files; + + if (FileReader && files && files.length) { + const reader = new FileReader(); + + reader.onload = function () { + $relatedImage.attr('data-placeholder', $relatedImage.attr('src')); + $relatedImage.attr('src', reader.result) + } + + reader.readAsDataURL(files[0]); + } + }) +} + +const handleImageTypeSwitch = () => { + const $imageSwitch = $('.js-toggle-images-types'); + + $imageSwitch.on('change', (e) => { + const $radio = $(e.currentTarget); + const $form = $radio.closest('form'); + const data = {}; + const $token = $('#image_slider__token'); + const $edit = $('#image_slider_edit'); + + data[$radio.attr('name')] = $radio.val(); + data[$token.attr('name')] = $token.val(); + data[$edit.attr('name')] = 1; // We don't want to trigger NotEmpty constraint on the image fields + + $.ajax({ + method: $form.attr('method'), + data, + success: (response) => { + const $newImagesFields = $(response).find('.js-image-fields'); + + $form.find('.js-image-fields').replaceWith($newImagesFields); + } + }) + }) +} + +$(() => { + handleFileInputChange(); + handleImageTypeSwitch(); + window.prestashop.component.initComponents( [ - 'MultistoreConfigField', - 'Grid', + 'TranslatableField', + 'TinyMCEEditor', + 'TranslatableInput', ], ); - const imageSliderkGrid = new window.prestashop.component.Grid('is_imageslider'); - - imageSliderkGrid.addExtension(new prestashop.component.GridExtensions.AsyncToggleColumnExtension()); - imageSliderkGrid.addExtension(new window.prestashop.component.GridExtensions.SortingExtension()); - imageSliderkGrid.addExtension(new window.prestashop.component.GridExtensions.PositionExtension()); - imageSliderkGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension()); + const choiceTree = new window.prestashop.component.ChoiceTree('#image_slider_shop_association'); + choiceTree.enableAutoCheckChildren(); }); + diff --git a/views/js/list.js b/views/js/list.js new file mode 100644 index 0000000..2d8129e --- /dev/null +++ b/views/js/list.js @@ -0,0 +1,15 @@ +$(document).ready(function () { + window.prestashop.component.initComponents( + [ + 'MultistoreConfigField', + 'Grid', + ], + ); + + const imageSliderkGrid = new window.prestashop.component.Grid('is_imageslider'); + + imageSliderkGrid.addExtension(new prestashop.component.GridExtensions.AsyncToggleColumnExtension()); + imageSliderkGrid.addExtension(new window.prestashop.component.GridExtensions.SortingExtension()); + imageSliderkGrid.addExtension(new window.prestashop.component.GridExtensions.PositionExtension()); + imageSliderkGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension()); +}); diff --git a/views/templates/admin/form.html.twig b/views/templates/admin/form.html.twig index 12fcc95..acc1873 100644 --- a/views/templates/admin/form.html.twig +++ b/views/templates/admin/form.html.twig @@ -18,7 +18,7 @@ #} {% extends '@PrestaShop/Admin/layout.html.twig' %} -{% form_theme imageSliderForm '@Modules/is_imageslider/views/templates/admin/form/prestashop_ui_kit.html.twig' %} +{% form_theme imageSliderForm '@Modules/is_imageslider/views/templates/admin/form/form_theme.html.twig' %} {% block content %} {{ form_start(imageSliderForm) }} @@ -30,7 +30,11 @@
-
+
+ {{ form_row(imageSliderForm.images_for_all_langs) }} + + {{ form_widget(imageSliderForm.slider_langs) }} + {{ form_widget(imageSliderForm) }} {{ form_rest(imageSliderForm) }}
@@ -39,7 +43,7 @@