diff --git a/config/form.yml b/config/form.yml index e9e8dfa..d083c1c 100644 --- a/config/form.yml +++ b/config/form.yml @@ -1,34 +1,70 @@ services: - websmid.customhtml.form.type.customhtml: + websmid.customhtml.form.type.customhtml_group: public: true - class: 'Websmid\CustomHtml\Form\Type\CustomHtmlType' + class: 'Websmid\CustomHtml\Form\Type\CustomHtmlGroupType' parent: 'form.type.translatable.aware' tags: - { name: form.type } - websmid.customhtml.form.customhtml_data_provider: + websmid.customhtml.form.customhtmlgroup_data_provider: public: true - class: 'Websmid\CustomHtml\Form\DataProvider\CustomHtmlDataProvider' + class: 'Websmid\CustomHtml\Form\DataProvider\CustomHtmlGroupDataProvider' - websmid.customhtml.form.customhtml_data_form_builder: + websmid.customhtml.form.customhtmlgroup_data_form_builder: public: true class: 'PrestaShop\PrestaShop\Core\Form\IdentifiableObject\Builder\FormBuilder' factory: - '@prestashop.core.form.builder.form_builder_factory' - 'create' arguments: - - 'Websmid\CustomHtml\Form\Type\CustomHtmlType' - - '@websmid.customhtml.form.customhtml_data_provider' + - 'Websmid\CustomHtml\Form\Type\CustomHtmlGroupType' + - '@websmid.customhtml.form.customhtmlgroup_data_provider' - websmid.customhtml.form.customhtml_data_handler: + websmid.customhtml.form.customhtmlgroup_data_handler: public: true - class: 'Websmid\CustomHtml\Form\DataHandler\CustomHtmlDataHandler' + class: 'Websmid\CustomHtml\Form\DataHandler\CustomHtmlGroupDataHandler' - websmid.customhtml.form.customhtml_form_handler: + websmid.customhtml.form.customhtmlgroup_form_handler: public: true class: 'PrestaShop\PrestaShop\Core\Form\IdentifiableObject\Handler\FormHandler' factory: - '@prestashop.core.form.identifiable_object.handler.form_handler_factory' - 'create' arguments: - - '@websmid.customhtml.form.customhtml_data_handler' + - '@websmid.customhtml.form.customhtmlgroup_data_handler' + + websmid.customhtml.form.type.customhtml_block: + public: true + class: 'Websmid\CustomHtml\Form\Type\CustomHtmlBlockType' + parent: 'form.type.translatable.aware' + arguments: + - '@websmid.customhtml.form.choice_provider.customhtml_group_choice_provider' + tags: + - { name: form.type } + + websmid.customhtml.form.customhtmlblock_data_provider: + public: true + class: 'Websmid\CustomHtml\Form\DataProvider\CustomHtmlBlockDataProvider' + + websmid.customhtml.form.customhtmlblock_data_form_builder: + public: true + class: 'PrestaShop\PrestaShop\Core\Form\IdentifiableObject\Builder\FormBuilder' + factory: + - '@prestashop.core.form.builder.form_builder_factory' + - 'create' + arguments: + - 'Websmid\CustomHtml\Form\Type\CustomHtmlBlockType' + - '@websmid.customhtml.form.customhtmlblock_data_provider' + + websmid.customhtml.form.customhtmlblock_data_handler: + public: true + class: 'Websmid\CustomHtml\Form\DataHandler\CustomHtmlBlockDataHandler' + + websmid.customhtml.form.customhtmlblock_form_handler: + public: true + class: 'PrestaShop\PrestaShop\Core\Form\IdentifiableObject\Handler\FormHandler' + factory: + - '@prestashop.core.form.identifiable_object.handler.form_handler_factory' + - 'create' + arguments: + - '@websmid.customhtml.form.customhtmlblock_data_handler' diff --git a/config/grid.yml b/config/grid.yml index 573817d..25d2845 100644 --- a/config/grid.yml +++ b/config/grid.yml @@ -1,12 +1,12 @@ services: - websmid.customhtml.grid.definition.factory.customhtml_definition_factory: + websmid.customhtml.grid.definition.factory.customhtmlgroup_definition_factory: public: true - class: 'Websmid\CustomHtml\Grid\Definition\Factory\CustomHtmlGridDefinitionFactory' + class: 'Websmid\CustomHtml\Grid\Definition\Factory\CustomHtmlGroupGridDefinitionFactory' parent: 'prestashop.core.grid.definition.factory.abstract_grid_definition' - websmid.customhtml.grid.query.customhtml_query_builder: + websmid.customhtml.grid.query.customhtmlgroup_query_builder: public: true - class: 'Websmid\CustomHtml\Grid\Query\CustomHtmlQueryBuilder' + class: 'Websmid\CustomHtml\Grid\Query\CustomHtmlGroupQueryBuilder' parent: 'prestashop.core.grid.abstract_query_builder' arguments: - '@prestashop.core.query.doctrine_search_criteria_applicator' @@ -16,20 +16,55 @@ services: - '@prestashop.core.grid.query.filter.doctrine_filter_applicator' - '@prestashop.adapter.legacy.configuration' - websmid.customhtml.grid.data.factory.customhtml_data_factory: + websmid.customhtml.grid.data.factory.customhtmlgroup_data_factory: public: true class: '%prestashop.core.grid.data.factory.doctrine_grid_data_factory%' arguments: - - '@websmid.customhtml.grid.query.customhtml_query_builder' + - '@websmid.customhtml.grid.query.customhtmlgroup_query_builder' - '@prestashop.core.hook.dispatcher' - '@prestashop.core.grid.query.doctrine_query_parser' - - 'customhtml' + - 'customhtmlgroup' - websmid.customhtml.grid.customhtml_grid_factory: + websmid.customhtml.grid.customhtmlgroup_grid_factory: public: true class: 'PrestaShop\PrestaShop\Core\Grid\GridFactory' arguments: - - '@websmid.customhtml.grid.definition.factory.customhtml_definition_factory' - - '@websmid.customhtml.grid.data.factory.customhtml_data_factory' + - '@websmid.customhtml.grid.definition.factory.customhtmlgroup_definition_factory' + - '@websmid.customhtml.grid.data.factory.customhtmlgroup_data_factory' + - '@prestashop.core.grid.filter.form_factory' + - '@prestashop.core.hook.dispatcher' + + websmid.customhtml.grid.definition.factory.customhtmlblock_definition_factory: + public: true + class: 'Websmid\CustomHtml\Grid\Definition\Factory\CustomHtmlBlockGridDefinitionFactory' + parent: 'prestashop.core.grid.definition.factory.abstract_grid_definition' + + websmid.customhtml.grid.query.customhtmlblock_query_builder: + public: true + class: 'Websmid\CustomHtml\Grid\Query\CustomHtmlBlockQueryBuilder' + parent: 'prestashop.core.grid.abstract_query_builder' + arguments: + - '@prestashop.core.query.doctrine_search_criteria_applicator' + - "@=service('prestashop.adapter.legacy.context').getContext().language.id" + - "@=service('prestashop.adapter.legacy.context').getContext().shop.id" + - "@=service('prestashop.adapter.legacy.context').getContext().shop.id_shop_group" + - '@prestashop.core.grid.query.filter.doctrine_filter_applicator' + - '@prestashop.adapter.legacy.configuration' + + websmid.customhtml.grid.data.factory.customhtmlblock_data_factory: + public: true + class: '%prestashop.core.grid.data.factory.doctrine_grid_data_factory%' + arguments: + - '@websmid.customhtml.grid.query.customhtmlblock_query_builder' + - '@prestashop.core.hook.dispatcher' + - '@prestashop.core.grid.query.doctrine_query_parser' + - 'customhtmlblock' + + websmid.customhtml.grid.customhtmlblock_grid_factory: + public: true + class: 'PrestaShop\PrestaShop\Core\Grid\GridFactory' + arguments: + - '@websmid.customhtml.grid.definition.factory.customhtmlblock_definition_factory' + - '@websmid.customhtml.grid.data.factory.customhtmlblock_data_factory' - '@prestashop.core.grid.filter.form_factory' - '@prestashop.core.hook.dispatcher' diff --git a/config/provider.yml b/config/provider.yml new file mode 100644 index 0000000..92bd0bb --- /dev/null +++ b/config/provider.yml @@ -0,0 +1,4 @@ +services: + websmid.customhtml.form.choice_provider.customhtml_group_choice_provider: + public: true + class: 'Websmid\CustomHtml\Form\ChoiceProvider\CustomHtmlGroupChoiceProvider' diff --git a/config/routes.yml b/config/routes.yml index 6f5af42..5276c66 100644 --- a/config/routes.yml +++ b/config/routes.yml @@ -2,31 +2,72 @@ customhtml_index: path: ws_customhtml methods: [GET] defaults: - _controller: 'Websmid\CustomHtml\Controller\CustomHtmlController::indexAction' + _controller: 'Websmid\CustomHtml\Controller\CustomHtmlGroupController::indexAction' + _legacy_controller: AdminCustomHtmlParent + _legacy_link: AdminCustomHtmlParent:index + +customhtmlgroup_index: + path: ws_customhtml/group + methods: [GET] + defaults: + _controller: 'Websmid\CustomHtml\Controller\CustomHtmlGroupController::indexAction' _legacy_controller: AdminCustomHtmlOverview _legacy_link: AdminCustomHtmlOverview:index -customhtml_search: - path: ws_customhtml +customhtmlgroup_search: + path: ws_customhtml/group methods: [POST] defaults: - _controller: 'Websmid\CustomHtml\Controller\CustomHtmlController::searchAction' + _controller: 'Websmid\CustomHtml\Controller\CustomHtmlGroupController::searchAction' _legacy_controller: AdminCustomHtmlOverview -customhtml_create: - path: ws_customhtml/create +customhtmlgroup_create: + path: ws_customhtml/group/create methods: [POST, GET] defaults: - _controller: 'Websmid\CustomHtml\Controller\CustomHtmlController::createAction' + _controller: 'Websmid\CustomHtml\Controller\CustomHtmlGroupController::createAction' -customhtml_edit: - path: ws_customhtml/edit/{idCustomHtml} +customhtmlgroup_edit: + path: ws_customhtml/group/edit/{idCustomHtmlGroup} methods: [POST, GET] defaults: - _controller: 'Websmid\CustomHtml\Controller\CustomHtmlController::editAction' + _controller: 'Websmid\CustomHtml\Controller\CustomHtmlGroupController::editAction' -customhtml_delete: - path: ws_customhtml/delete/{idCustomHtml} +customhtmlgroup_delete: + path: ws_customhtml/group/delete/{idCustomHtmlGroup} methods: [DELETE, GET, POST] defaults: - _controller: 'Websmid\CustomHtml\Controller\CustomHtmlController::deleteAction' + _controller: 'Websmid\CustomHtml\Controller\CustomHtmlGroupController::deleteAction' + +customhtmlblock_index: + path: ws_customhtml/block + methods: [GET] + defaults: + _controller: 'Websmid\CustomHtml\Controller\CustomHtmlBlockController::indexAction' + _legacy_controller: AdminCustomHtmlBlockOverview + _legacy_link: AdminCustomHtmlBlockOverview:index + +customhtmlblock_search: + path: ws_customhtml/block + methods: [POST] + defaults: + _controller: 'Websmid\CustomHtml\Controller\CustomHtmlBlockController::searchAction' + _legacy_controller: AdminCustomHtmlBlockOverview + +customhtmlblock_create: + path: ws_customhtml/block/create + methods: [POST, GET] + defaults: + _controller: 'Websmid\CustomHtml\Controller\CustomHtmlBlockController::createAction' + +customhtmlblock_edit: + path: ws_customhtml/block/edit/{idCustomHtmlBlock} + methods: [POST, GET] + defaults: + _controller: 'Websmid\CustomHtml\Controller\CustomHtmlBlockController::editAction' + +customhtmlblock_delete: + path: ws_customhtml/block/delete/{idCustomHtmlBlock} + methods: [DELETE, GET, POST] + defaults: + _controller: 'Websmid\CustomHtml\Controller\CustomHtmlBlockController::deleteAction' diff --git a/config/services.yml b/config/services.yml index 7aec7d4..ee39e29 100644 --- a/config/services.yml +++ b/config/services.yml @@ -1,3 +1,4 @@ imports: - { resource: form.yml } - { resource: grid.yml } + - { resource: provider.yml } diff --git a/src/Config/Config.php b/src/Config/Config.php index 53e3b92..736c713 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -4,11 +4,21 @@ namespace Websmid\CustomHtml\Config; class Config { - const HOOKS = []; + const HOOKS = [ + 'actionAdminControllerSetMedia', + ]; + const ADMIN_CONTROLLERS = [ + 'AdminCustomHtmlParent', + 'AdminCustomHtmlOverview', + 'AdminCustomHtmlBlockOverview', + ]; + + // Order matters: the parent tab must be registered before its children so + // Tab::getIdFromClassName('AdminCustomHtmlParent') resolves during install. const TABS = [ [ - 'class_name' => 'AdminCustomHtmlOverview', + 'class_name' => 'AdminCustomHtmlParent', 'parent_class_name' => 'AdminParentThemes', 'name' => [ 'en' => 'Custom HTML', @@ -19,5 +29,29 @@ class Config 'route_name' => 'customhtml_index', 'active' => 1, ], + [ + 'class_name' => 'AdminCustomHtmlOverview', + 'parent_class_name' => 'AdminCustomHtmlParent', + 'name' => [ + 'en' => 'Groups', + 'nl' => 'Groepen', + ], + 'module' => 'ws_customhtml', + 'icon' => 'code', + 'route_name' => 'customhtmlgroup_index', + 'active' => 1, + ], + [ + 'class_name' => 'AdminCustomHtmlBlockOverview', + 'parent_class_name' => 'AdminCustomHtmlParent', + 'name' => [ + 'en' => 'Blocks', + 'nl' => 'Blokken', + ], + 'module' => 'ws_customhtml', + 'icon' => 'view_module', + 'route_name' => 'customhtmlblock_index', + 'active' => 1, + ], ]; } diff --git a/src/Controller/CustomHtmlBlockController.php b/src/Controller/CustomHtmlBlockController.php new file mode 100644 index 0000000..7dd0dbe --- /dev/null +++ b/src/Controller/CustomHtmlBlockController.php @@ -0,0 +1,134 @@ +query->has('idGroup')) { + $filters->addFilter(['id_ws_customhtml_group' => (int) $request->query->get('idGroup')]); + $filters->setNeedsToBePersisted(false); + } + + $gridFactory = $this->get('websmid.customhtml.grid.customhtmlblock_grid_factory'); + $grid = $gridFactory->getGrid($filters); + + return $this->render('@Modules/ws_customhtml/views/templates/admin/grid/customhtmlblock.html.twig', [ + 'customHtmlBlockGrid' => $this->presentGrid($grid), + 'layoutHeaderToolbarBtn' => $this->getToolbarButtons($request->get('_legacy_controller')), + ]); + } + + public function searchAction(Request $request): RedirectResponse + { + return $this->get('prestashop.bundle.grid.response_builder')->buildSearchResponse( + $this->get('websmid.customhtml.grid.definition.factory.customhtmlblock_definition_factory'), + $request, + CustomHtmlBlockGridDefinitionFactory::GRID_ID, + 'customhtmlblock_index' + ); + } + + public function createAction(Request $request): Response + { + $formBuilder = $this->get('websmid.customhtml.form.customhtmlblock_data_form_builder'); + $formHandler = $this->get('websmid.customhtml.form.customhtmlblock_form_handler'); + + $form = $formBuilder->getForm(); + + if ($request->isMethod('GET') && $request->query->has('idGroup')) { + $form->get('id_ws_customhtml_group')->setData((int) $request->query->get('idGroup')); + } + + $form->handleRequest($request); + + try { + $handlerResult = $formHandler->handle($form); + + if (null !== $handlerResult->getIdentifiableObjectId()) { + $this->addFlash('success', $this->trans('Successful creation.', 'Admin.Notifications.Success')); + + return $this->redirectToRoute('customhtmlblock_index'); + } + } catch (Exception $e) { + $this->addFlash('error', $this->getErrorMessageForException($e, [])); + } + + return $this->render('@Modules/ws_customhtml/views/templates/admin/form/customhtmlblock_create.html.twig', [ + 'customHtmlBlockForm' => $form->createView(), + ]); + } + + public function editAction(Request $request, int $idCustomHtmlBlock): Response + { + $formBuilder = $this->get('websmid.customhtml.form.customhtmlblock_data_form_builder'); + $formHandler = $this->get('websmid.customhtml.form.customhtmlblock_form_handler'); + + $form = $formBuilder->getFormFor($idCustomHtmlBlock); + + try { + $form->handleRequest($request); + $handlerResult = $formHandler->handleFor($idCustomHtmlBlock, $form); + + if ($handlerResult->isSubmitted() && $handlerResult->isValid()) { + $this->addFlash('success', $this->trans('Successful update.', 'Admin.Notifications.Success')); + + return $this->redirectToRoute('customhtmlblock_index'); + } + } catch (Exception $e) { + $this->addFlash('error', $this->getErrorMessageForException($e, [])); + } + + return $this->render('@Modules/ws_customhtml/views/templates/admin/form/customhtmlblock_edit.html.twig', [ + 'customHtmlBlockForm' => $form->createView(), + 'idCustomHtmlBlock' => $idCustomHtmlBlock, + ]); + } + + public function deleteAction(Request $request, int $idCustomHtmlBlock): RedirectResponse + { + $block = new CustomHtmlBlock($idCustomHtmlBlock); + + if (!Validate::isLoadedObject($block)) { + $this->addFlash('error', $this->trans('Unable to find the block.', 'Modules.Wscustomhtml.Admin')); + + return $this->redirectToRoute('customhtmlblock_index'); + } + + $block->delete(); + $this->addFlash('success', $this->trans('Successful deletion.', 'Admin.Notifications.Success')); + + return $this->redirectToRoute('customhtmlblock_index'); + } + + private function getToolbarButtons(?string $securitySubject): array + { + $toolbarButtons = []; + + if (!$securitySubject || !$this->isGranted(PageVoter::CREATE, $securitySubject)) { + return $toolbarButtons; + } + + $toolbarButtons['customhtmlblock_create'] = [ + 'href' => $this->generateUrl('customhtmlblock_create'), + 'desc' => $this->trans('New block', 'Admin.Actions'), + 'icon' => 'add_circle_outline', + 'class' => 'btn-primary', + 'floating_class' => '', + ]; + + return $toolbarButtons; + } +} diff --git a/src/Controller/CustomHtmlController.php b/src/Controller/CustomHtmlGroupController.php similarity index 63% rename from src/Controller/CustomHtmlController.php rename to src/Controller/CustomHtmlGroupController.php index a482c5e..1dabed9 100644 --- a/src/Controller/CustomHtmlController.php +++ b/src/Controller/CustomHtmlGroupController.php @@ -8,20 +8,20 @@ use PrestaShopBundle\Security\Voter\PageVoter; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Websmid\CustomHtml\Grid\Definition\Factory\CustomHtmlGridDefinitionFactory; -use Websmid\CustomHtml\Grid\Filters\CustomHtmlFilters; -use Websmid\CustomHtml\Model\CustomHtml; +use Websmid\CustomHtml\Grid\Definition\Factory\CustomHtmlGroupGridDefinitionFactory; +use Websmid\CustomHtml\Grid\Filters\CustomHtmlGroupFilters; +use Websmid\CustomHtml\Model\CustomHtmlGroup; use Validate; -class CustomHtmlController extends FrameworkBundleAdminController +class CustomHtmlGroupController extends FrameworkBundleAdminController { - public function indexAction(Request $request, CustomHtmlFilters $filters): Response + public function indexAction(Request $request, CustomHtmlGroupFilters $filters): Response { - $gridFactory = $this->get('websmid.customhtml.grid.customhtml_grid_factory'); + $gridFactory = $this->get('websmid.customhtml.grid.customhtmlgroup_grid_factory'); $grid = $gridFactory->getGrid($filters); - return $this->render('@Modules/ws_customhtml/views/templates/admin/grid/customhtml.html.twig', [ - 'customHtmlGrid' => $this->presentGrid($grid), + return $this->render('@Modules/ws_customhtml/views/templates/admin/grid/customhtmlgroup.html.twig', [ + 'customHtmlGroupGrid' => $this->presentGrid($grid), 'layoutHeaderToolbarBtn' => $this->getToolbarButtons($request->get('_legacy_controller')), ]); } @@ -29,17 +29,17 @@ class CustomHtmlController extends FrameworkBundleAdminController public function searchAction(Request $request): RedirectResponse { return $this->get('prestashop.bundle.grid.response_builder')->buildSearchResponse( - $this->get('websmid.customhtml.grid.definition.factory.customhtml_definition_factory'), + $this->get('websmid.customhtml.grid.definition.factory.customhtmlgroup_definition_factory'), $request, - CustomHtmlGridDefinitionFactory::GRID_ID, - 'customhtml_index' + CustomHtmlGroupGridDefinitionFactory::GRID_ID, + 'customhtmlgroup_index' ); } public function createAction(Request $request): Response { - $formBuilder = $this->get('websmid.customhtml.form.customhtml_data_form_builder'); - $formHandler = $this->get('websmid.customhtml.form.customhtml_form_handler'); + $formBuilder = $this->get('websmid.customhtml.form.customhtmlgroup_data_form_builder'); + $formHandler = $this->get('websmid.customhtml.form.customhtmlgroup_form_handler'); $form = $formBuilder->getForm(); $form->handleRequest($request); @@ -50,57 +50,57 @@ class CustomHtmlController extends FrameworkBundleAdminController if (null !== $handlerResult->getIdentifiableObjectId()) { $this->addFlash('success', $this->trans('Successful creation.', 'Admin.Notifications.Success')); - return $this->redirectToRoute('customhtml_index'); + return $this->redirectToRoute('customhtmlgroup_index'); } } catch (Exception $e) { $this->addFlash('error', $this->getErrorMessageForException($e, [])); } - return $this->render('@Modules/ws_customhtml/views/templates/admin/form/customhtml_create.html.twig', [ - 'customHtmlForm' => $form->createView(), + return $this->render('@Modules/ws_customhtml/views/templates/admin/form/customhtmlgroup_create.html.twig', [ + 'customHtmlGroupForm' => $form->createView(), ]); } - public function editAction(Request $request, int $idCustomHtml): Response + public function editAction(Request $request, int $idCustomHtmlGroup): Response { - $formBuilder = $this->get('websmid.customhtml.form.customhtml_data_form_builder'); - $formHandler = $this->get('websmid.customhtml.form.customhtml_form_handler'); + $formBuilder = $this->get('websmid.customhtml.form.customhtmlgroup_data_form_builder'); + $formHandler = $this->get('websmid.customhtml.form.customhtmlgroup_form_handler'); - $form = $formBuilder->getFormFor($idCustomHtml); + $form = $formBuilder->getFormFor($idCustomHtmlGroup); try { $form->handleRequest($request); - $handlerResult = $formHandler->handleFor($idCustomHtml, $form); + $handlerResult = $formHandler->handleFor($idCustomHtmlGroup, $form); if ($handlerResult->isSubmitted() && $handlerResult->isValid()) { $this->addFlash('success', $this->trans('Successful update.', 'Admin.Notifications.Success')); - return $this->redirectToRoute('customhtml_index'); + return $this->redirectToRoute('customhtmlgroup_index'); } } catch (Exception $e) { $this->addFlash('error', $this->getErrorMessageForException($e, [])); } - return $this->render('@Modules/ws_customhtml/views/templates/admin/form/customhtml_edit.html.twig', [ - 'customHtmlForm' => $form->createView(), - 'idCustomHtml' => $idCustomHtml, + return $this->render('@Modules/ws_customhtml/views/templates/admin/form/customhtmlgroup_edit.html.twig', [ + 'customHtmlGroupForm' => $form->createView(), + 'idCustomHtmlGroup' => $idCustomHtmlGroup, ]); } - public function deleteAction(Request $request, int $idCustomHtml): RedirectResponse + public function deleteAction(Request $request, int $idCustomHtmlGroup): RedirectResponse { - $block = new CustomHtml($idCustomHtml); + $group = new CustomHtmlGroup($idCustomHtmlGroup); - if (!Validate::isLoadedObject($block)) { - $this->addFlash('error', $this->trans('Unable to find the block.', 'Modules.Wscustomhtml.Admin')); + if (!Validate::isLoadedObject($group)) { + $this->addFlash('error', $this->trans('Unable to find the group.', 'Modules.Wscustomhtml.Admin')); - return $this->redirectToRoute('customhtml_index'); + return $this->redirectToRoute('customhtmlgroup_index'); } - $block->delete(); + $group->delete(); $this->addFlash('success', $this->trans('Successful deletion.', 'Admin.Notifications.Success')); - return $this->redirectToRoute('customhtml_index'); + return $this->redirectToRoute('customhtmlgroup_index'); } private function getToolbarButtons(?string $securitySubject): array @@ -111,9 +111,9 @@ class CustomHtmlController extends FrameworkBundleAdminController return $toolbarButtons; } - $toolbarButtons['customhtml_create'] = [ - 'href' => $this->generateUrl('customhtml_create'), - 'desc' => $this->trans('New block', 'Admin.Actions'), + $toolbarButtons['customhtmlgroup_create'] = [ + 'href' => $this->generateUrl('customhtmlgroup_create'), + 'desc' => $this->trans('New group', 'Admin.Actions'), 'icon' => 'add_circle_outline', 'class' => 'btn-primary', 'floating_class' => '', diff --git a/src/Form/ChoiceProvider/CustomHtmlGroupChoiceProvider.php b/src/Form/ChoiceProvider/CustomHtmlGroupChoiceProvider.php new file mode 100644 index 0000000..f54854e --- /dev/null +++ b/src/Form/ChoiceProvider/CustomHtmlGroupChoiceProvider.php @@ -0,0 +1,36 @@ +executeS( + 'SELECT `id_ws_customhtml_group`, `title` + FROM `' . _DB_PREFIX_ . 'ws_customhtml_group` + ORDER BY `title` ASC' + ); + + $choices = []; + + foreach ($groups as $group) { + $choices[$group['title']] = (int) $group['id_ws_customhtml_group']; + } + + return $choices; + } + + public function getChoicesAttributes(): array + { + return []; + } +} diff --git a/src/Form/DataHandler/CustomHtmlBlockDataHandler.php b/src/Form/DataHandler/CustomHtmlBlockDataHandler.php new file mode 100644 index 0000000..f0f0517 --- /dev/null +++ b/src/Form/DataHandler/CustomHtmlBlockDataHandler.php @@ -0,0 +1,44 @@ +id_ws_customhtml_group = (int) $formData['id_ws_customhtml_group']; + $block->title = (string) $formData['title']; + $block->show_title = (int) $formData['show_title']; + $block->content = (string) $formData['content']; + $block->active = (int) $formData['active']; + $block->ordering = 0; + + if (!$block->add()) { + return false; + } + + return $block->id; + } + + public function update($id, array $formData) + { + $block = new CustomHtmlBlock((int) $id); + + if (!Validate::isLoadedObject($block)) { + return false; + } + + $block->id_ws_customhtml_group = (int) $formData['id_ws_customhtml_group']; + $block->title = (string) $formData['title']; + $block->show_title = (int) $formData['show_title']; + $block->content = (string) $formData['content']; + $block->active = (int) $formData['active']; + + return (bool) $block->update(); + } +} diff --git a/src/Form/DataHandler/CustomHtmlDataHandler.php b/src/Form/DataHandler/CustomHtmlGroupDataHandler.php similarity index 50% rename from src/Form/DataHandler/CustomHtmlDataHandler.php rename to src/Form/DataHandler/CustomHtmlGroupDataHandler.php index 03f4bbf..a7ebba3 100644 --- a/src/Form/DataHandler/CustomHtmlDataHandler.php +++ b/src/Form/DataHandler/CustomHtmlGroupDataHandler.php @@ -3,48 +3,44 @@ namespace Websmid\CustomHtml\Form\DataHandler; use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataHandler\FormDataHandlerInterface; -use Websmid\CustomHtml\Model\CustomHtml; +use Websmid\CustomHtml\Model\CustomHtmlGroup; use Context; use Hook; use Module; use Validate; -final class CustomHtmlDataHandler implements FormDataHandlerInterface +final class CustomHtmlGroupDataHandler implements FormDataHandlerInterface { public function create(array $formData) { - $block = new CustomHtml(); - $block->hook_name = (string) $formData['hook_name']; - $block->title = (string) $formData['title']; - $block->show_title = (int) $formData['show_title']; - $block->content = (string) $formData['content']; - $block->active = (int) $formData['active']; - $block->ordering = 0; + $group = new CustomHtmlGroup(); + $group->title = (string) $formData['title']; + $group->hook_name = (string) $formData['hook_name']; + $group->active = (int) $formData['active']; + $group->ordering = 0; - if (!$block->add()) { + if (!$group->add()) { return false; } $this->checkAndRegisterHookForModule((string) $formData['hook_name']); - return $block->id; + return $group->id; } public function update($id, array $formData) { - $block = new CustomHtml((int) $id); + $group = new CustomHtmlGroup((int) $id); - if (!Validate::isLoadedObject($block)) { + if (!Validate::isLoadedObject($group)) { return false; } - $block->hook_name = (string) $formData['hook_name']; - $block->title = (string) $formData['title']; - $block->show_title = (int) $formData['show_title']; - $block->content = (string) $formData['content']; - $block->active = (int) $formData['active']; + $group->title = (string) $formData['title']; + $group->hook_name = (string) $formData['hook_name']; + $group->active = (int) $formData['active']; - if (!$block->update()) { + if (!$group->update()) { return false; } diff --git a/src/Form/DataProvider/CustomHtmlBlockDataProvider.php b/src/Form/DataProvider/CustomHtmlBlockDataProvider.php new file mode 100644 index 0000000..493e288 --- /dev/null +++ b/src/Form/DataProvider/CustomHtmlBlockDataProvider.php @@ -0,0 +1,38 @@ +getDefaultData(); + } + + return [ + 'id_ws_customhtml_group' => (int) $block->id_ws_customhtml_group, + 'title' => $block->title, + 'show_title' => (bool) $block->show_title, + 'content' => $block->content, + 'active' => (bool) $block->active, + ]; + } + + public function getDefaultData() + { + return [ + 'id_ws_customhtml_group' => 0, + 'title' => '', + 'show_title' => false, + 'content' => '', + 'active' => true, + ]; + } +} diff --git a/src/Form/DataProvider/CustomHtmlDataProvider.php b/src/Form/DataProvider/CustomHtmlDataProvider.php deleted file mode 100644 index d448b2f..0000000 --- a/src/Form/DataProvider/CustomHtmlDataProvider.php +++ /dev/null @@ -1,38 +0,0 @@ -getDefaultData(); - } - - return [ - 'hook_name' => $block->hook_name, - 'title' => $block->title, - 'show_title' => (bool) $block->show_title, - 'content' => $block->content, - 'active' => (bool) $block->active, - ]; - } - - public function getDefaultData() - { - return [ - 'hook_name' => '', - 'title' => '', - 'show_title' => false, - 'content' => '', - 'active' => true, - ]; - } -} diff --git a/src/Form/DataProvider/CustomHtmlGroupDataProvider.php b/src/Form/DataProvider/CustomHtmlGroupDataProvider.php new file mode 100644 index 0000000..cb450b6 --- /dev/null +++ b/src/Form/DataProvider/CustomHtmlGroupDataProvider.php @@ -0,0 +1,34 @@ +getDefaultData(); + } + + return [ + 'title' => $group->title, + 'hook_name' => $group->hook_name, + 'active' => (bool) $group->active, + ]; + } + + public function getDefaultData() + { + return [ + 'title' => '', + 'hook_name' => '', + 'active' => true, + ]; + } +} diff --git a/src/Form/Type/CustomHtmlType.php b/src/Form/Type/CustomHtmlBlockType.php similarity index 68% rename from src/Form/Type/CustomHtmlType.php rename to src/Form/Type/CustomHtmlBlockType.php index 1bde9da..cf9c45e 100644 --- a/src/Form/Type/CustomHtmlType.php +++ b/src/Form/Type/CustomHtmlBlockType.php @@ -4,25 +4,33 @@ namespace Websmid\CustomHtml\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; +use PrestaShop\PrestaShop\Core\Form\ConfigurableFormChoiceProviderInterface; use PrestaShopBundle\Form\Admin\Type\SwitchType; use Symfony\Contracts\Translation\TranslatorInterface; -class CustomHtmlType extends AbstractType +class CustomHtmlBlockType extends AbstractType { private $translator; + private $groupChoiceProvider; - public function __construct(TranslatorInterface $translator, array $locales) - { + public function __construct( + TranslatorInterface $translator, + array $locales, + ConfigurableFormChoiceProviderInterface $groupChoiceProvider + ) { $this->translator = $translator; + $this->groupChoiceProvider = $groupChoiceProvider; } public function buildForm(FormBuilderInterface $formBuilder, array $options): void { $formBuilder - ->add('hook_name', TextType::class, [ - 'label' => $this->translator->trans('Hook name', [], 'Modules.Wscustomhtml.Admin'), + ->add('id_ws_customhtml_group', ChoiceType::class, [ + 'label' => $this->translator->trans('Group', [], 'Modules.Wscustomhtml.Admin'), + 'choices' => $this->groupChoiceProvider->getChoices(), 'required' => true, ]) ->add('title', TextType::class, [ diff --git a/src/Form/Type/CustomHtmlGroupType.php b/src/Form/Type/CustomHtmlGroupType.php new file mode 100644 index 0000000..2dd5dc7 --- /dev/null +++ b/src/Form/Type/CustomHtmlGroupType.php @@ -0,0 +1,36 @@ +translator = $translator; + } + + public function buildForm(FormBuilderInterface $formBuilder, array $options): void + { + $formBuilder + ->add('title', TextType::class, [ + 'label' => $this->translator->trans('Title', [], 'Modules.Wscustomhtml.Admin'), + 'required' => true, + ]) + ->add('hook_name', TextType::class, [ + 'label' => $this->translator->trans('Hook name', [], 'Modules.Wscustomhtml.Admin'), + 'required' => true, + ]) + ->add('active', SwitchType::class, [ + 'label' => $this->translator->trans('Active', [], 'Modules.Wscustomhtml.Admin'), + 'required' => false, + ]); + } +} diff --git a/src/Grid/Definition/Factory/CustomHtmlGridDefinitionFactory.php b/src/Grid/Definition/Factory/CustomHtmlBlockGridDefinitionFactory.php similarity index 79% rename from src/Grid/Definition/Factory/CustomHtmlGridDefinitionFactory.php rename to src/Grid/Definition/Factory/CustomHtmlBlockGridDefinitionFactory.php index 8d132ff..8c168dd 100644 --- a/src/Grid/Definition/Factory/CustomHtmlGridDefinitionFactory.php +++ b/src/Grid/Definition/Factory/CustomHtmlBlockGridDefinitionFactory.php @@ -10,15 +10,18 @@ use PrestaShop\PrestaShop\Core\Grid\Column\ColumnCollection; use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\ActionColumn; use PrestaShop\PrestaShop\Core\Grid\Column\Type\DataColumn; use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\AbstractGridDefinitionFactory; +use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\DeleteActionTrait; use PrestaShop\PrestaShop\Core\Grid\Filter\Filter; use PrestaShop\PrestaShop\Core\Grid\Filter\FilterCollection; use PrestaShop\PrestaShop\Core\Hook\HookDispatcherInterface; use PrestaShopBundle\Form\Admin\Type\SearchAndResetType; use Symfony\Component\Form\Extension\Core\Type\TextType; -final class CustomHtmlGridDefinitionFactory extends AbstractGridDefinitionFactory +final class CustomHtmlBlockGridDefinitionFactory extends AbstractGridDefinitionFactory { - const GRID_ID = 'customhtml'; + use DeleteActionTrait; + + const GRID_ID = 'customhtmlblock'; public function __construct(HookDispatcherInterface $dispatcher) { @@ -64,15 +67,20 @@ final class CustomHtmlGridDefinitionFactory extends AbstractGridDefinitionFactor ->setOptions(['field' => 'title']) ) ->add( - (new DataColumn('hook_name')) - ->setName($this->trans('Hook', [], 'Modules.Wscustomhtml.Admin')) - ->setOptions(['field' => 'hook_name']) + (new DataColumn('group_title')) + ->setName($this->trans('Group', [], 'Modules.Wscustomhtml.Admin')) + ->setOptions(['field' => 'group_title']) ) ->add( (new DataColumn('active')) ->setName($this->trans('Active', [], 'Admin.Global')) ->setOptions(['field' => 'active']) ) + ->add( + (new DataColumn('ordering')) + ->setName($this->trans('Position', [], 'Modules.Wscustomhtml.Admin')) + ->setOptions(['field' => 'ordering']) + ) ->add( (new DataColumn('date_add')) ->setName($this->trans('Date added', [], 'Admin.Global')) @@ -105,11 +113,11 @@ final class CustomHtmlGridDefinitionFactory extends AbstractGridDefinitionFactor ]) ) ->add( - (new Filter('hook_name', TextType::class)) - ->setAssociatedColumn('hook_name') + (new Filter('group_title', TextType::class)) + ->setAssociatedColumn('group_title') ->setTypeOptions([ 'required' => false, - 'attr' => ['placeholder' => $this->trans('Hook', [], 'Modules.Wscustomhtml.Admin')], + 'attr' => ['placeholder' => $this->trans('Group', [], 'Modules.Wscustomhtml.Admin')], ]) ) ->add( @@ -118,7 +126,7 @@ final class CustomHtmlGridDefinitionFactory extends AbstractGridDefinitionFactor ->setTypeOptions([ 'reset_route' => 'admin_common_reset_search_by_filter_id', 'reset_route_params' => ['filterId' => self::GRID_ID], - 'redirect_route' => 'customhtml_index', + 'redirect_route' => 'customhtmlblock_index', ]) ); } @@ -131,23 +139,15 @@ final class CustomHtmlGridDefinitionFactory extends AbstractGridDefinitionFactor ->setName($this->trans('Edit', [], 'Admin.Actions')) ->setIcon('edit') ->setOptions([ - 'route' => 'customhtml_edit', - 'route_param_name' => 'idCustomHtml', - 'route_param_field' => 'id_ws_customhtml', + 'route' => 'customhtmlblock_edit', + 'route_param_name' => 'idCustomHtmlBlock', + 'route_param_field' => 'id_ws_customhtml', 'use_inline_display' => true, - 'clickable_row' => true, + 'clickable_row' => true, ]) ) ->add( - (new LinkRowAction('delete')) - ->setName($this->trans('Delete', [], 'Admin.Actions')) - ->setIcon('delete') - ->setOptions([ - 'route' => 'customhtml_delete', - 'route_param_name' => 'idCustomHtml', - 'route_param_field' => 'id_ws_customhtml', - 'use_inline_display' => true, - ]) + $this->buildDeleteAction('customhtmlblock_delete', 'idCustomHtmlBlock', 'id_ws_customhtml') ); } } diff --git a/src/Grid/Definition/Factory/CustomHtmlGroupGridDefinitionFactory.php b/src/Grid/Definition/Factory/CustomHtmlGroupGridDefinitionFactory.php new file mode 100644 index 0000000..eda0f4d --- /dev/null +++ b/src/Grid/Definition/Factory/CustomHtmlGroupGridDefinitionFactory.php @@ -0,0 +1,173 @@ +trans('Custom HTML Groups', [], 'Modules.Wscustomhtml.Admin'); + } + + protected function getGridActions() + { + return (new GridActionCollection()) + ->add( + (new SimpleGridAction('common_refresh_list')) + ->setName($this->trans('Refresh list', [], 'Admin.Catalog.Feature')) + ->setIcon('refresh') + ) + ->add( + (new SimpleGridAction('common_show_query')) + ->setName($this->trans('Show SQL query', [], 'Admin.Catalog.Feature')) + ->setIcon('code') + ); + } + + protected function getColumns() + { + return (new ColumnCollection()) + ->add( + (new DataColumn('id_ws_customhtml_group')) + ->setName($this->trans('ID', [], 'Admin.Global')) + ->setOptions(['field' => 'id_ws_customhtml_group']) + ) + ->add( + (new DataColumn('title')) + ->setName($this->trans('Title', [], 'Modules.Wscustomhtml.Admin')) + ->setOptions(['field' => 'title']) + ) + ->add( + (new DataColumn('hook_name')) + ->setName($this->trans('Hook', [], 'Modules.Wscustomhtml.Admin')) + ->setOptions(['field' => 'hook_name']) + ) + ->add( + (new DataColumn('blocks_count')) + ->setName($this->trans('Blocks', [], 'Modules.Wscustomhtml.Admin')) + ->setOptions(['field' => 'blocks_count', 'sortable' => false]) + ) + ->add( + (new DataColumn('active')) + ->setName($this->trans('Active', [], 'Admin.Global')) + ->setOptions(['field' => 'active']) + ) + ->add( + (new DataColumn('date_add')) + ->setName($this->trans('Date added', [], 'Admin.Global')) + ->setOptions(['field' => 'date_add']) + ) + ->add( + (new ActionColumn('actions')) + ->setName($this->trans('Actions', [], 'Admin.Global')) + ->setOptions(['actions' => $this->buildRowActions()]) + ); + } + + protected function getFilters() + { + return (new FilterCollection()) + ->add( + (new Filter('id_ws_customhtml_group', TextType::class)) + ->setAssociatedColumn('id_ws_customhtml_group') + ->setTypeOptions([ + 'required' => false, + 'attr' => ['placeholder' => $this->trans('ID', [], 'Admin.Global')], + ]) + ) + ->add( + (new Filter('title', TextType::class)) + ->setAssociatedColumn('title') + ->setTypeOptions([ + 'required' => false, + 'attr' => ['placeholder' => $this->trans('Title', [], 'Modules.Wscustomhtml.Admin')], + ]) + ) + ->add( + (new Filter('hook_name', TextType::class)) + ->setAssociatedColumn('hook_name') + ->setTypeOptions([ + 'required' => false, + 'attr' => ['placeholder' => $this->trans('Hook', [], 'Modules.Wscustomhtml.Admin')], + ]) + ) + ->add( + (new Filter('actions', SearchAndResetType::class)) + ->setAssociatedColumn('actions') + ->setTypeOptions([ + 'reset_route' => 'admin_common_reset_search_by_filter_id', + 'reset_route_params' => ['filterId' => self::GRID_ID], + 'redirect_route' => 'customhtmlgroup_index', + ]) + ); + } + + private function buildRowActions(): RowActionCollection + { + return (new RowActionCollection()) + ->add( + (new LinkRowAction('view_blocks')) + ->setName($this->trans('View blocks', [], 'Modules.Wscustomhtml.Admin')) + ->setIcon('visibility') + ->setOptions([ + 'route' => 'customhtmlblock_index', + 'route_param_name' => 'idGroup', + 'route_param_field' => 'id_ws_customhtml_group', + ]) + ) + ->add( + (new LinkRowAction('add_block')) + ->setName($this->trans('Add block', [], 'Modules.Wscustomhtml.Admin')) + ->setIcon('note_add') + ->setOptions([ + 'route' => 'customhtmlblock_create', + 'route_param_name' => 'idGroup', + 'route_param_field' => 'id_ws_customhtml_group', + ]) + ) + ->add( + (new LinkRowAction('edit')) + ->setName($this->trans('Edit', [], 'Admin.Actions')) + ->setIcon('edit') + ->setOptions([ + 'route' => 'customhtmlgroup_edit', + 'route_param_name' => 'idCustomHtmlGroup', + 'route_param_field' => 'id_ws_customhtml_group', + 'use_inline_display' => true, + 'clickable_row' => true, + ]) + ) + ->add( + $this->buildDeleteAction('customhtmlgroup_delete', 'idCustomHtmlGroup', 'id_ws_customhtml_group') + ); + } +} diff --git a/src/Grid/Filters/CustomHtmlFilters.php b/src/Grid/Filters/CustomHtmlBlockFilters.php similarity index 54% rename from src/Grid/Filters/CustomHtmlFilters.php rename to src/Grid/Filters/CustomHtmlBlockFilters.php index 10a6f1d..b51fddb 100644 --- a/src/Grid/Filters/CustomHtmlFilters.php +++ b/src/Grid/Filters/CustomHtmlBlockFilters.php @@ -3,18 +3,18 @@ namespace Websmid\CustomHtml\Grid\Filters; use PrestaShop\PrestaShop\Core\Search\Filters; -use Websmid\CustomHtml\Grid\Definition\Factory\CustomHtmlGridDefinitionFactory; +use Websmid\CustomHtml\Grid\Definition\Factory\CustomHtmlBlockGridDefinitionFactory; -final class CustomHtmlFilters extends Filters +final class CustomHtmlBlockFilters extends Filters { - protected $filterId = CustomHtmlGridDefinitionFactory::GRID_ID; + protected $filterId = CustomHtmlBlockGridDefinitionFactory::GRID_ID; public static function getDefaults(): array { return [ 'limit' => 10, 'offset' => 0, - 'orderBy' => 'wch.id_ws_customhtml', + 'orderBy' => 'wchb.id_ws_customhtml', 'sortOrder' => 'asc', 'filters' => [], ]; diff --git a/src/Grid/Filters/CustomHtmlGroupFilters.php b/src/Grid/Filters/CustomHtmlGroupFilters.php new file mode 100644 index 0000000..6d4a48b --- /dev/null +++ b/src/Grid/Filters/CustomHtmlGroupFilters.php @@ -0,0 +1,22 @@ + 10, + 'offset' => 0, + 'orderBy' => 'wchg.id_ws_customhtml_group', + 'sortOrder' => 'asc', + 'filters' => [], + ]; + } +} diff --git a/src/Grid/Query/CustomHtmlBlockQueryBuilder.php b/src/Grid/Query/CustomHtmlBlockQueryBuilder.php new file mode 100644 index 0000000..0c7fad2 --- /dev/null +++ b/src/Grid/Query/CustomHtmlBlockQueryBuilder.php @@ -0,0 +1,115 @@ +searchCriteriaApplicator = $searchCriteriaApplicator; + $this->contextLanguageId = $contextLanguageId; + $this->contextShopId = $contextShopId; + $this->contextShopGroupId = $contextShopGroupId; + $this->filterApplicator = $filterApplicator; + $this->configuration = $configuration; + } + + public function getSearchQueryBuilder(SearchCriteriaInterface $searchCriteria) + { + $qb = $this->getBaseQuery(); + + $qb->select( + 'wchb.`id_ws_customhtml`', + 'wchb.`title`', + 'wchg.`title` AS group_title', + 'wchb.`active`', + 'wchb.`ordering`', + 'wchb.`date_add`' + ); + + $this->applyFilters($qb, $searchCriteria); + + $qb + ->orderBy($searchCriteria->getOrderBy(), $searchCriteria->getOrderWay()) + ->setFirstResult($searchCriteria->getOffset() ?? 0) + ->setMaxResults($searchCriteria->getLimit()); + + return $qb; + } + + public function getCountQueryBuilder(SearchCriteriaInterface $searchCriteria) + { + $qb = $this->getBaseQuery(); + $qb->select('COUNT(wchb.`id_ws_customhtml`)'); + + $this->applyFilters($qb, $searchCriteria); + + return $qb; + } + + private function getBaseQuery() + { + return $this->connection + ->createQueryBuilder() + ->from($this->dbPrefix . 'ws_customhtml', 'wchb') + ->leftJoin( + 'wchb', + $this->dbPrefix . 'ws_customhtml_group', + 'wchg', + 'wchg.`id_ws_customhtml_group` = wchb.`id_ws_customhtml_group`' + ); + } + + private function applyFilters($qb, SearchCriteriaInterface $searchCriteria): void + { + foreach ($searchCriteria->getFilters() as $filterName => $filterValue) { + if ($filterName === 'actions') { + continue; + } + + if ($filterName === 'id_ws_customhtml') { + $qb->andWhere('wchb.`id_ws_customhtml` = :id_ws_customhtml') + ->setParameter('id_ws_customhtml', (int) $filterValue); + continue; + } + + if ($filterName === 'id_ws_customhtml_group') { + $qb->andWhere('wchb.`id_ws_customhtml_group` = :id_ws_customhtml_group') + ->setParameter('id_ws_customhtml_group', (int) $filterValue); + continue; + } + + if ($filterName === 'group_title') { + $qb->andWhere('wchg.`title` LIKE :group_title') + ->setParameter('group_title', '%' . pSQL($filterValue) . '%'); + continue; + } + + $qb->andWhere('wchb.`' . $filterName . '` LIKE :' . $filterName) + ->setParameter($filterName, '%' . pSQL($filterValue) . '%'); + } + } +} diff --git a/src/Grid/Query/CustomHtmlQueryBuilder.php b/src/Grid/Query/CustomHtmlGroupQueryBuilder.php similarity index 74% rename from src/Grid/Query/CustomHtmlQueryBuilder.php rename to src/Grid/Query/CustomHtmlGroupQueryBuilder.php index 22ddd7f..8ddbaf9 100644 --- a/src/Grid/Query/CustomHtmlQueryBuilder.php +++ b/src/Grid/Query/CustomHtmlGroupQueryBuilder.php @@ -9,7 +9,7 @@ use PrestaShop\PrestaShop\Core\Grid\Query\DoctrineSearchCriteriaApplicatorInterf use PrestaShop\PrestaShop\Core\Grid\Query\Filter\DoctrineFilterApplicatorInterface; use PrestaShop\PrestaShop\Core\Grid\Search\SearchCriteriaInterface; -final class CustomHtmlQueryBuilder extends AbstractDoctrineQueryBuilder +final class CustomHtmlGroupQueryBuilder extends AbstractDoctrineQueryBuilder { private $searchCriteriaApplicator; private $contextLanguageId; @@ -42,11 +42,13 @@ final class CustomHtmlQueryBuilder extends AbstractDoctrineQueryBuilder $qb = $this->getBaseQuery(); $qb->select( - 'wch.`id_ws_customhtml`', - 'wch.`title`', - 'wch.`hook_name`', - 'wch.`active`', - 'wch.`date_add`' + 'wchg.`id_ws_customhtml_group`', + 'wchg.`title`', + 'wchg.`hook_name`', + 'wchg.`active`', + 'wchg.`date_add`', + '(SELECT COUNT(*) FROM `' . $this->dbPrefix . 'ws_customhtml` wch + WHERE wch.`id_ws_customhtml_group` = wchg.`id_ws_customhtml_group`) AS blocks_count' ); $this->applyFilters($qb, $searchCriteria); @@ -62,7 +64,7 @@ final class CustomHtmlQueryBuilder extends AbstractDoctrineQueryBuilder public function getCountQueryBuilder(SearchCriteriaInterface $searchCriteria) { $qb = $this->getBaseQuery(); - $qb->select('COUNT(wch.`id_ws_customhtml`)'); + $qb->select('COUNT(wchg.`id_ws_customhtml_group`)'); $this->applyFilters($qb, $searchCriteria); @@ -73,7 +75,7 @@ final class CustomHtmlQueryBuilder extends AbstractDoctrineQueryBuilder { return $this->connection ->createQueryBuilder() - ->from($this->dbPrefix . 'ws_customhtml', 'wch'); + ->from($this->dbPrefix . 'ws_customhtml_group', 'wchg'); } private function applyFilters($qb, SearchCriteriaInterface $searchCriteria): void @@ -83,13 +85,13 @@ final class CustomHtmlQueryBuilder extends AbstractDoctrineQueryBuilder continue; } - if ($filterName === 'id_ws_customhtml') { - $qb->andWhere('wch.`id_ws_customhtml` = :id_ws_customhtml') - ->setParameter('id_ws_customhtml', (int) $filterValue); + if ($filterName === 'id_ws_customhtml_group') { + $qb->andWhere('wchg.`id_ws_customhtml_group` = :id_ws_customhtml_group') + ->setParameter('id_ws_customhtml_group', (int) $filterValue); continue; } - $qb->andWhere('wch.`' . $filterName . '` LIKE :' . $filterName) + $qb->andWhere('wchg.`' . $filterName . '` LIKE :' . $filterName) ->setParameter($filterName, '%' . pSQL($filterValue) . '%'); } } diff --git a/src/Model/CustomHtmlBlock.php b/src/Model/CustomHtmlBlock.php new file mode 100644 index 0000000..e485c60 --- /dev/null +++ b/src/Model/CustomHtmlBlock.php @@ -0,0 +1,76 @@ + 'ws_customhtml', + 'primary' => 'id_ws_customhtml', + 'fields' => [ + 'id_ws_customhtml_group' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true], + 'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 256], + 'content' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'], + 'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'], + 'show_title' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'], + 'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'], + 'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'], + 'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'], + ], + ]; + + public static function getActiveByGroupIds(array $groupIds): array + { + $groupIds = array_map('intval', $groupIds); + + if (empty($groupIds)) { + return []; + } + + $result = Db::getInstance()->executeS( + 'SELECT `id_ws_customhtml`, `id_ws_customhtml_group`, `title`, `content`, `active`, `show_title`, `ordering` + FROM `' . _DB_PREFIX_ . 'ws_customhtml` + WHERE `id_ws_customhtml_group` IN (' . implode(',', $groupIds) . ') + AND `active` = 1 + ORDER BY `ordering` ASC' + ); + + $blocksByGroup = []; + + foreach ($result as $row) { + $blocksByGroup[(int) $row['id_ws_customhtml_group']][] = $row; + } + + return $blocksByGroup; + } +} diff --git a/src/Model/CustomHtml.php b/src/Model/CustomHtmlGroup.php similarity index 54% rename from src/Model/CustomHtml.php rename to src/Model/CustomHtmlGroup.php index edc0137..b219950 100644 --- a/src/Model/CustomHtml.php +++ b/src/Model/CustomHtmlGroup.php @@ -5,7 +5,7 @@ namespace Websmid\CustomHtml\Model; use ObjectModel; use Db; -class CustomHtml extends ObjectModel +class CustomHtmlGroup extends ObjectModel { /** @var int */ public $id; @@ -16,15 +16,9 @@ class CustomHtml extends ObjectModel /** @var string */ public $title = ''; - /** @var string */ - public $content = ''; - /** @var int */ public $active = 1; - /** @var int */ - public $show_title = 0; - /** @var int */ public $ordering = 0; @@ -35,25 +29,23 @@ class CustomHtml extends ObjectModel public $date_upd; public static $definition = [ - 'table' => 'ws_customhtml', - 'primary' => 'id_ws_customhtml', + 'table' => 'ws_customhtml_group', + 'primary' => 'id_ws_customhtml_group', 'fields' => [ 'hook_name' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64], 'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 256], - 'content' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'], - 'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'], - 'show_title' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'], - 'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'], - 'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'], - 'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'], + 'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'], + 'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'], + 'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'], + 'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'], ], ]; public static function getActiveByHookName(string $hookName): array { $result = Db::getInstance()->executeS( - 'SELECT `id_ws_customhtml`, `title`, `content`, `active`, `show_title`, `ordering` - FROM `' . _DB_PREFIX_ . 'ws_customhtml` + 'SELECT `id_ws_customhtml_group`, `title`, `active`, `ordering` + FROM `' . _DB_PREFIX_ . 'ws_customhtml_group` WHERE `hook_name` = \'' . pSQL($hookName) . '\' AND `active` = 1 ORDER BY `ordering` ASC' diff --git a/src/Module/AdminHooks.php b/src/Module/AdminHooks.php index 94afaa6..0d05f41 100644 --- a/src/Module/AdminHooks.php +++ b/src/Module/AdminHooks.php @@ -2,6 +2,7 @@ namespace Websmid\CustomHtml\Module; +use Websmid\CustomHtml\Config\Config; use Tools; trait AdminHooks @@ -13,6 +14,17 @@ trait AdminHooks public function getContent() { - Tools::redirectAdmin($this->get('router')->generate('customhtml_index')); + Tools::redirectAdmin($this->get('router')->generate('customhtmlgroup_index')); + } + + public function hookActionAdminControllerSetMedia(): void + { + $controllerName = $this->context->controller->controller_name ?? ''; + + if (!in_array($controllerName, Config::ADMIN_CONTROLLERS, true)) { + return; + } + + $this->context->controller->addCSS($this->getPathUri() . 'views/css/admin/grid.css'); } } diff --git a/src/Module/DisplayHooks.php b/src/Module/DisplayHooks.php index 6f17817..7dc4865 100644 --- a/src/Module/DisplayHooks.php +++ b/src/Module/DisplayHooks.php @@ -2,7 +2,8 @@ namespace Websmid\CustomHtml\Module; -use Websmid\CustomHtml\Model\CustomHtml; +use Websmid\CustomHtml\Model\CustomHtmlBlock; +use Websmid\CustomHtml\Model\CustomHtmlGroup; use Context; trait DisplayHooks @@ -32,15 +33,36 @@ trait DisplayHooks public function getWidgetVariables($hookName = null, array $configuration = []) { - $blockList = CustomHtml::getActiveByHookName((string) $hookName); + $groupList = $this->loadActiveGroupsWithBlocks((string) $hookName); - if (empty($blockList)) { + if (empty($groupList)) { return []; } return [ 'hookName' => $hookName, - 'blockList' => $blockList, + 'groupList' => $groupList, ]; } + + private function loadActiveGroupsWithBlocks(string $hookName): array + { + $groups = CustomHtmlGroup::getActiveByHookName($hookName); + + if (empty($groups)) { + return []; + } + + $blocksByGroup = CustomHtmlBlock::getActiveByGroupIds(array_column($groups, 'id_ws_customhtml_group')); + + $groups = array_map(static function (array $group) use ($blocksByGroup) { + $group['blocks'] = $blocksByGroup[(int) $group['id_ws_customhtml_group']] ?? []; + + return $group; + }, $groups); + + return array_values(array_filter($groups, static function (array $group) { + return !empty($group['blocks']); + })); + } } diff --git a/src/Module/Install.php b/src/Module/Install.php index 58fb8dc..5ad1cda 100644 --- a/src/Module/Install.php +++ b/src/Module/Install.php @@ -38,17 +38,30 @@ trait Install { $sqlToExec = []; + $sqlToExec[] = ' + CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml_group ( + `id_ws_customhtml_group` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `hook_name` VARCHAR(64) NOT NULL, + `title` VARCHAR(256) NOT NULL DEFAULT \'\', + `active` TINYINT(1) NOT NULL DEFAULT 1, + `ordering` INT(11) NOT NULL DEFAULT 0, + `date_add` DATETIME NOT NULL, + `date_upd` DATETIME NOT NULL + ); + '; + $sqlToExec[] = ' CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml ( `id_ws_customhtml` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, - `hook_name` VARCHAR(64) NOT NULL, + `id_ws_customhtml_group` INT(11) NOT NULL, `title` VARCHAR(256) NOT NULL DEFAULT \'\', `content` LONGTEXT, `active` TINYINT(1) NOT NULL DEFAULT 1, `show_title` TINYINT(1) NOT NULL DEFAULT 0, `ordering` INT(11) NOT NULL DEFAULT 0, `date_add` DATETIME NOT NULL, - `date_upd` DATETIME NOT NULL + `date_upd` DATETIME NOT NULL, + KEY `id_ws_customhtml_group` (`id_ws_customhtml_group`) ); '; diff --git a/views/css/admin/grid.css b/views/css/admin/grid.css new file mode 100644 index 0000000..fbca35b --- /dev/null +++ b/views/css/admin/grid.css @@ -0,0 +1,11 @@ +td.action-type { + display: flex; + align-items: center; + justify-content: center; +} + +td.action-type .btn-group-action { + display: flex; + align-items: center; + justify-content: center; +} diff --git a/views/templates/admin/form/blocks/form.html.twig b/views/templates/admin/form/blocks/block_form.html.twig similarity index 63% rename from views/templates/admin/form/blocks/form.html.twig rename to views/templates/admin/form/blocks/block_form.html.twig index a563c4f..01e4c2d 100644 --- a/views/templates/admin/form/blocks/form.html.twig +++ b/views/templates/admin/form/blocks/block_form.html.twig @@ -1,25 +1,25 @@ {% import '@PrestaShop/Admin/macros.html.twig' as ps %} -{% form_theme customHtmlForm '@PrestaShop/Admin/TwigTemplateForm/prestashop_ui_kit.html.twig' %} +{% form_theme customHtmlBlockForm '@PrestaShop/Admin/TwigTemplateForm/prestashop_ui_kit.html.twig' %} -{% block customhtml_form_block %} +{% block customhtmlblock_form_block %}