Compare commits
17
Commits
635c13a0ed
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e97af7a1da | ||
|
|
150e068550 | ||
|
|
a71ab197ce | ||
|
|
ccd105907a | ||
|
|
4e7333493a | ||
|
|
7cafc376b7 | ||
|
|
85b56f1a13 | ||
|
|
620c34e353 | ||
|
|
be9a676d9d | ||
|
|
06e98a429b | ||
|
|
a4e479490b | ||
|
|
e804c37175 | ||
|
|
34fb95a699 | ||
|
|
ce480314f3 | ||
|
|
fb641fc236 | ||
|
|
d0da05845a | ||
|
|
1493081602 |
@@ -1 +1,3 @@
|
|||||||
/vendor/
|
/vendor/
|
||||||
|
/views/img/banners/*
|
||||||
|
!/views/img/banners/.gitkeep
|
||||||
|
|||||||
+16
-2
@@ -2,7 +2,7 @@ services:
|
|||||||
websmid.customhtml.form.type.customhtml_group:
|
websmid.customhtml.form.type.customhtml_group:
|
||||||
public: true
|
public: true
|
||||||
class: 'Websmid\CustomHtml\Form\Type\CustomHtmlGroupType'
|
class: 'Websmid\CustomHtml\Form\Type\CustomHtmlGroupType'
|
||||||
parent: 'form.type.translatable.aware'
|
parent: "form.type.translatable.aware"
|
||||||
tags:
|
tags:
|
||||||
- { name: form.type }
|
- { name: form.type }
|
||||||
|
|
||||||
@@ -33,10 +33,24 @@ services:
|
|||||||
arguments:
|
arguments:
|
||||||
- '@websmid.customhtml.form.customhtmlgroup_data_handler'
|
- '@websmid.customhtml.form.customhtmlgroup_data_handler'
|
||||||
|
|
||||||
|
websmid.customhtml.form.type.customhtml_faq:
|
||||||
|
public: true
|
||||||
|
class: 'Websmid\CustomHtml\Form\Type\CustomHtmlFaqType'
|
||||||
|
parent: "form.type.translatable.aware"
|
||||||
|
tags:
|
||||||
|
- { name: form.type }
|
||||||
|
|
||||||
|
websmid.customhtml.form.type.customhtml_slide:
|
||||||
|
public: true
|
||||||
|
class: 'Websmid\CustomHtml\Form\Type\CustomHtmlSlideType'
|
||||||
|
parent: "form.type.translatable.aware"
|
||||||
|
tags:
|
||||||
|
- { name: form.type }
|
||||||
|
|
||||||
websmid.customhtml.form.type.customhtml_block:
|
websmid.customhtml.form.type.customhtml_block:
|
||||||
public: true
|
public: true
|
||||||
class: 'Websmid\CustomHtml\Form\Type\CustomHtmlBlockType'
|
class: 'Websmid\CustomHtml\Form\Type\CustomHtmlBlockType'
|
||||||
parent: 'form.type.translatable.aware'
|
parent: "form.type.translatable.aware"
|
||||||
arguments:
|
arguments:
|
||||||
- '@websmid.customhtml.form.choice_provider.customhtml_group_choice_provider'
|
- '@websmid.customhtml.form.choice_provider.customhtml_group_choice_provider'
|
||||||
tags:
|
tags:
|
||||||
|
|||||||
@@ -34,6 +34,16 @@ services:
|
|||||||
- '@prestashop.core.grid.filter.form_factory'
|
- '@prestashop.core.grid.filter.form_factory'
|
||||||
- '@prestashop.core.hook.dispatcher'
|
- '@prestashop.core.hook.dispatcher'
|
||||||
|
|
||||||
|
websmid.customhtml.grid.position.customhtmlgroup_position_definition:
|
||||||
|
public: true
|
||||||
|
class: 'PrestaShop\PrestaShop\Core\Grid\Position\PositionDefinition'
|
||||||
|
arguments:
|
||||||
|
- 'ws_customhtml_group'
|
||||||
|
- 'id_ws_customhtml_group'
|
||||||
|
- 'ordering'
|
||||||
|
- ~
|
||||||
|
- 0
|
||||||
|
|
||||||
websmid.customhtml.grid.definition.factory.customhtmlblock_definition_factory:
|
websmid.customhtml.grid.definition.factory.customhtmlblock_definition_factory:
|
||||||
public: true
|
public: true
|
||||||
class: 'Websmid\CustomHtml\Grid\Definition\Factory\CustomHtmlBlockGridDefinitionFactory'
|
class: 'Websmid\CustomHtml\Grid\Definition\Factory\CustomHtmlBlockGridDefinitionFactory'
|
||||||
@@ -68,3 +78,13 @@ services:
|
|||||||
- '@websmid.customhtml.grid.data.factory.customhtmlblock_data_factory'
|
- '@websmid.customhtml.grid.data.factory.customhtmlblock_data_factory'
|
||||||
- '@prestashop.core.grid.filter.form_factory'
|
- '@prestashop.core.grid.filter.form_factory'
|
||||||
- '@prestashop.core.hook.dispatcher'
|
- '@prestashop.core.hook.dispatcher'
|
||||||
|
|
||||||
|
websmid.customhtml.grid.position.customhtmlblock_position_definition:
|
||||||
|
public: true
|
||||||
|
class: 'PrestaShop\PrestaShop\Core\Grid\Position\PositionDefinition'
|
||||||
|
arguments:
|
||||||
|
- 'ws_customhtml'
|
||||||
|
- 'id_ws_customhtml'
|
||||||
|
- 'ordering'
|
||||||
|
- 'id_ws_customhtml_group'
|
||||||
|
- 0
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -39,6 +39,18 @@ customhtmlgroup_delete:
|
|||||||
defaults:
|
defaults:
|
||||||
_controller: 'Websmid\CustomHtml\Controller\CustomHtmlGroupController::deleteAction'
|
_controller: 'Websmid\CustomHtml\Controller\CustomHtmlGroupController::deleteAction'
|
||||||
|
|
||||||
|
customhtmlgroup_toggle:
|
||||||
|
path: ws_customhtml/group/toggle/{idCustomHtmlGroup}
|
||||||
|
methods: [GET, POST]
|
||||||
|
defaults:
|
||||||
|
_controller: 'Websmid\CustomHtml\Controller\CustomHtmlGroupController::toggleAction'
|
||||||
|
|
||||||
|
customhtmlgroup_update_position:
|
||||||
|
path: ws_customhtml/group/update-position
|
||||||
|
methods: [POST]
|
||||||
|
defaults:
|
||||||
|
_controller: 'Websmid\CustomHtml\Controller\CustomHtmlGroupController::updatePositionAction'
|
||||||
|
|
||||||
customhtmlblock_index:
|
customhtmlblock_index:
|
||||||
path: ws_customhtml/block
|
path: ws_customhtml/block
|
||||||
methods: [GET]
|
methods: [GET]
|
||||||
@@ -71,3 +83,9 @@ customhtmlblock_delete:
|
|||||||
methods: [DELETE, GET, POST]
|
methods: [DELETE, GET, POST]
|
||||||
defaults:
|
defaults:
|
||||||
_controller: 'Websmid\CustomHtml\Controller\CustomHtmlBlockController::deleteAction'
|
_controller: 'Websmid\CustomHtml\Controller\CustomHtmlBlockController::deleteAction'
|
||||||
|
|
||||||
|
customhtmlblock_update_position:
|
||||||
|
path: ws_customhtml/block/{idGroup}/update-position
|
||||||
|
methods: [POST]
|
||||||
|
defaults:
|
||||||
|
_controller: 'Websmid\CustomHtml\Controller\CustomHtmlBlockController::updatePositionAction'
|
||||||
|
|||||||
+39
-4
@@ -6,14 +6,49 @@ class Config
|
|||||||
{
|
{
|
||||||
const HOOKS = [
|
const HOOKS = [
|
||||||
'actionAdminControllerSetMedia',
|
'actionAdminControllerSetMedia',
|
||||||
|
'actionCustomhtmlblockGridDataModifier',
|
||||||
|
'actionFrontControllerSetMedia',
|
||||||
];
|
];
|
||||||
|
|
||||||
const ADMIN_CONTROLLERS = [
|
const BLOCK_TYPES = [
|
||||||
'AdminCustomHtmlParent',
|
'html' => 'HTML',
|
||||||
'AdminCustomHtmlOverview',
|
'faq' => 'FAQ Accordion',
|
||||||
'AdminCustomHtmlBlockOverview',
|
'banner' => 'Banner',
|
||||||
|
'alert' => 'Alert',
|
||||||
|
'usp' => 'USP',
|
||||||
|
'slider' => 'Slider',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const SLIDER_DEFAULT_SLIDES_PER_VIEW_MOBILE = 1;
|
||||||
|
|
||||||
|
const SLIDER_DEFAULT_SLIDES_PER_VIEW_TABLET = 2;
|
||||||
|
|
||||||
|
const SLIDER_MODES = [
|
||||||
|
'always' => 'Always show as a slider',
|
||||||
|
'responsive' => 'Mobile only',
|
||||||
|
];
|
||||||
|
|
||||||
|
const SLIDER_DEFAULT_MODE = 'always';
|
||||||
|
|
||||||
|
const SLIDER_RESPONSIVE_BREAKPOINT = 480;
|
||||||
|
|
||||||
|
const ALERT_STYLES = [
|
||||||
|
'success' => 'Success',
|
||||||
|
'info' => 'Info',
|
||||||
|
'warning' => 'Warning',
|
||||||
|
'danger' => 'Danger',
|
||||||
|
];
|
||||||
|
|
||||||
|
const BANNER_IMAGE_ALLOWED_EXTENSIONS = [
|
||||||
|
'jpg' => 'image/jpeg',
|
||||||
|
'jpeg' => 'image/jpeg',
|
||||||
|
'png' => 'image/png',
|
||||||
|
'gif' => 'image/gif',
|
||||||
|
'webp' => 'image/webp',
|
||||||
|
];
|
||||||
|
|
||||||
|
const BANNER_IMAGE_MAX_SIZE = 5242880;
|
||||||
|
|
||||||
// Order matters: the parent tab must be registered before its children so
|
// Order matters: the parent tab must be registered before its children so
|
||||||
// Tab::getIdFromClassName('AdminCustomHtmlParent') resolves during install.
|
// Tab::getIdFromClassName('AdminCustomHtmlParent') resolves during install.
|
||||||
const TABS = [
|
const TABS = [
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -3,6 +3,9 @@
|
|||||||
namespace Websmid\CustomHtml\Controller;
|
namespace Websmid\CustomHtml\Controller;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Position\Exception\PositionUpdateException;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Position\GridPositionUpdaterInterface;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Position\PositionUpdateFactoryInterface;
|
||||||
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
|
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
|
||||||
use PrestaShopBundle\Security\Voter\PageVoter;
|
use PrestaShopBundle\Security\Voter\PageVoter;
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
@@ -11,14 +14,18 @@ use Symfony\Component\HttpFoundation\Response;
|
|||||||
use Websmid\CustomHtml\Grid\Definition\Factory\CustomHtmlBlockGridDefinitionFactory;
|
use Websmid\CustomHtml\Grid\Definition\Factory\CustomHtmlBlockGridDefinitionFactory;
|
||||||
use Websmid\CustomHtml\Grid\Filters\CustomHtmlBlockFilters;
|
use Websmid\CustomHtml\Grid\Filters\CustomHtmlBlockFilters;
|
||||||
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
||||||
|
use Websmid\CustomHtml\Model\CustomHtmlFaq;
|
||||||
use Validate;
|
use Validate;
|
||||||
|
|
||||||
class CustomHtmlBlockController extends FrameworkBundleAdminController
|
class CustomHtmlBlockController extends FrameworkBundleAdminController
|
||||||
{
|
{
|
||||||
public function indexAction(Request $request, CustomHtmlBlockFilters $filters): Response
|
public function indexAction(Request $request, CustomHtmlBlockFilters $filters): Response
|
||||||
{
|
{
|
||||||
|
$idGroup = null;
|
||||||
|
|
||||||
if ($request->query->has('idGroup')) {
|
if ($request->query->has('idGroup')) {
|
||||||
$filters->addFilter(['id_ws_customhtml_group' => (int) $request->query->get('idGroup')]);
|
$idGroup = (int) $request->query->get('idGroup');
|
||||||
|
$filters->addFilter(['id_ws_customhtml_group' => $idGroup]);
|
||||||
$filters->setNeedsToBePersisted(false);
|
$filters->setNeedsToBePersisted(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +34,7 @@ class CustomHtmlBlockController extends FrameworkBundleAdminController
|
|||||||
|
|
||||||
return $this->render('@Modules/ws_customhtml/views/templates/admin/grid/customhtmlblock.html.twig', [
|
return $this->render('@Modules/ws_customhtml/views/templates/admin/grid/customhtmlblock.html.twig', [
|
||||||
'customHtmlBlockGrid' => $this->presentGrid($grid),
|
'customHtmlBlockGrid' => $this->presentGrid($grid),
|
||||||
'layoutHeaderToolbarBtn' => $this->getToolbarButtons($request->get('_legacy_controller')),
|
'layoutHeaderToolbarBtn' => $this->getToolbarButtons($request->get('_legacy_controller'), $idGroup),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,9 +54,11 @@ class CustomHtmlBlockController extends FrameworkBundleAdminController
|
|||||||
$formHandler = $this->get('websmid.customhtml.form.customhtmlblock_form_handler');
|
$formHandler = $this->get('websmid.customhtml.form.customhtmlblock_form_handler');
|
||||||
|
|
||||||
$form = $formBuilder->getForm();
|
$form = $formBuilder->getForm();
|
||||||
|
$idGroup = $request->query->has('idGroup') ? (int) $request->query->get('idGroup') : null;
|
||||||
|
$redirectParams = null !== $idGroup ? ['idGroup' => $idGroup] : [];
|
||||||
|
|
||||||
if ($request->isMethod('GET') && $request->query->has('idGroup')) {
|
if ($request->isMethod('GET') && null !== $idGroup) {
|
||||||
$form->get('id_ws_customhtml_group')->setData((int) $request->query->get('idGroup'));
|
$form->get('id_ws_customhtml_group')->setData($idGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
@@ -60,7 +69,7 @@ class CustomHtmlBlockController extends FrameworkBundleAdminController
|
|||||||
if (null !== $handlerResult->getIdentifiableObjectId()) {
|
if (null !== $handlerResult->getIdentifiableObjectId()) {
|
||||||
$this->addFlash('success', $this->trans('Successful creation.', 'Admin.Notifications.Success'));
|
$this->addFlash('success', $this->trans('Successful creation.', 'Admin.Notifications.Success'));
|
||||||
|
|
||||||
return $this->redirectToRoute('customhtmlblock_index');
|
return $this->redirectToRoute('customhtmlblock_index', $redirectParams);
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->addFlash('error', $this->getErrorMessageForException($e, []));
|
$this->addFlash('error', $this->getErrorMessageForException($e, []));
|
||||||
@@ -68,6 +77,7 @@ class CustomHtmlBlockController extends FrameworkBundleAdminController
|
|||||||
|
|
||||||
return $this->render('@Modules/ws_customhtml/views/templates/admin/form/customhtmlblock_create.html.twig', [
|
return $this->render('@Modules/ws_customhtml/views/templates/admin/form/customhtmlblock_create.html.twig', [
|
||||||
'customHtmlBlockForm' => $form->createView(),
|
'customHtmlBlockForm' => $form->createView(),
|
||||||
|
'idGroup' => $idGroup,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +87,8 @@ class CustomHtmlBlockController extends FrameworkBundleAdminController
|
|||||||
$formHandler = $this->get('websmid.customhtml.form.customhtmlblock_form_handler');
|
$formHandler = $this->get('websmid.customhtml.form.customhtmlblock_form_handler');
|
||||||
|
|
||||||
$form = $formBuilder->getFormFor($idCustomHtmlBlock);
|
$form = $formBuilder->getFormFor($idCustomHtmlBlock);
|
||||||
|
$idGroup = $request->query->has('idGroup') ? (int) $request->query->get('idGroup') : null;
|
||||||
|
$redirectParams = null !== $idGroup ? ['idGroup' => $idGroup] : [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
@@ -85,35 +97,66 @@ class CustomHtmlBlockController extends FrameworkBundleAdminController
|
|||||||
if ($handlerResult->isSubmitted() && $handlerResult->isValid()) {
|
if ($handlerResult->isSubmitted() && $handlerResult->isValid()) {
|
||||||
$this->addFlash('success', $this->trans('Successful update.', 'Admin.Notifications.Success'));
|
$this->addFlash('success', $this->trans('Successful update.', 'Admin.Notifications.Success'));
|
||||||
|
|
||||||
return $this->redirectToRoute('customhtmlblock_index');
|
return $this->redirectToRoute('customhtmlblock_index', $redirectParams);
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->addFlash('error', $this->getErrorMessageForException($e, []));
|
$this->addFlash('error', $this->getErrorMessageForException($e, []));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$block = new CustomHtmlBlock($idCustomHtmlBlock);
|
||||||
|
$currentImageUrl = Validate::isLoadedObject($block) ? CustomHtmlBlock::getBannerImageUrl($block->image) : '';
|
||||||
|
|
||||||
return $this->render('@Modules/ws_customhtml/views/templates/admin/form/customhtmlblock_edit.html.twig', [
|
return $this->render('@Modules/ws_customhtml/views/templates/admin/form/customhtmlblock_edit.html.twig', [
|
||||||
'customHtmlBlockForm' => $form->createView(),
|
'customHtmlBlockForm' => $form->createView(),
|
||||||
'idCustomHtmlBlock' => $idCustomHtmlBlock,
|
'idCustomHtmlBlock' => $idCustomHtmlBlock,
|
||||||
|
'currentImageUrl' => $currentImageUrl,
|
||||||
|
'idGroup' => $idGroup,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteAction(Request $request, int $idCustomHtmlBlock): RedirectResponse
|
public function deleteAction(Request $request, int $idCustomHtmlBlock): RedirectResponse
|
||||||
{
|
{
|
||||||
|
$idGroup = $request->query->has('idGroup') ? (int) $request->query->get('idGroup') : null;
|
||||||
|
$redirectParams = null !== $idGroup ? ['idGroup' => $idGroup] : [];
|
||||||
|
|
||||||
$block = new CustomHtmlBlock($idCustomHtmlBlock);
|
$block = new CustomHtmlBlock($idCustomHtmlBlock);
|
||||||
|
|
||||||
if (!Validate::isLoadedObject($block)) {
|
if (!Validate::isLoadedObject($block)) {
|
||||||
$this->addFlash('error', $this->trans('Unable to find the block.', 'Modules.Wscustomhtml.Admin'));
|
$this->addFlash('error', $this->trans('Unable to find the block.', 'Modules.Wscustomhtml.Admin'));
|
||||||
|
|
||||||
return $this->redirectToRoute('customhtmlblock_index');
|
return $this->redirectToRoute('customhtmlblock_index', $redirectParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CustomHtmlFaq::deleteByBlockId($idCustomHtmlBlock);
|
||||||
$block->delete();
|
$block->delete();
|
||||||
$this->addFlash('success', $this->trans('Successful deletion.', 'Admin.Notifications.Success'));
|
$this->addFlash('success', $this->trans('Successful deletion.', 'Admin.Notifications.Success'));
|
||||||
|
|
||||||
return $this->redirectToRoute('customhtmlblock_index');
|
return $this->redirectToRoute('customhtmlblock_index', $redirectParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getToolbarButtons(?string $securitySubject): array
|
public function updatePositionAction(int $idGroup, Request $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$positionDefinition = $this->get('websmid.customhtml.grid.position.customhtmlblock_position_definition');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$positionUpdateFactory = $this->get(PositionUpdateFactoryInterface::class);
|
||||||
|
$positionUpdate = $positionUpdateFactory->buildPositionUpdate([
|
||||||
|
'positions' => $request->request->all('positions'),
|
||||||
|
'parentId' => $idGroup,
|
||||||
|
], $positionDefinition);
|
||||||
|
|
||||||
|
$updater = $this->get(GridPositionUpdaterInterface::class);
|
||||||
|
$updater->update($positionUpdate);
|
||||||
|
|
||||||
|
$this->addFlash('success', $this->trans('Successful update.', 'Admin.Notifications.Success'));
|
||||||
|
} catch (PositionUpdateException $e) {
|
||||||
|
$this->addFlash('error', $this->getErrorMessageForException($e, []));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->redirectToRoute('customhtmlblock_index', ['idGroup' => $idGroup]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getToolbarButtons(?string $securitySubject, ?int $idGroup = null): array
|
||||||
{
|
{
|
||||||
$toolbarButtons = [];
|
$toolbarButtons = [];
|
||||||
|
|
||||||
@@ -121,8 +164,10 @@ class CustomHtmlBlockController extends FrameworkBundleAdminController
|
|||||||
return $toolbarButtons;
|
return $toolbarButtons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$routeParams = null !== $idGroup ? ['idGroup' => $idGroup] : [];
|
||||||
|
|
||||||
$toolbarButtons['customhtmlblock_create'] = [
|
$toolbarButtons['customhtmlblock_create'] = [
|
||||||
'href' => $this->generateUrl('customhtmlblock_create'),
|
'href' => $this->generateUrl('customhtmlblock_create', $routeParams),
|
||||||
'desc' => $this->trans('New block', 'Admin.Actions'),
|
'desc' => $this->trans('New block', 'Admin.Actions'),
|
||||||
'icon' => 'add_circle_outline',
|
'icon' => 'add_circle_outline',
|
||||||
'class' => 'btn-primary',
|
'class' => 'btn-primary',
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
namespace Websmid\CustomHtml\Controller;
|
namespace Websmid\CustomHtml\Controller;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Position\Exception\PositionUpdateException;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Position\GridPositionUpdaterInterface;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Position\PositionUpdateFactoryInterface;
|
||||||
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
|
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
|
||||||
use PrestaShopBundle\Security\Voter\PageVoter;
|
use PrestaShopBundle\Security\Voter\PageVoter;
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
@@ -103,6 +106,48 @@ class CustomHtmlGroupController extends FrameworkBundleAdminController
|
|||||||
return $this->redirectToRoute('customhtmlgroup_index');
|
return $this->redirectToRoute('customhtmlgroup_index');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function toggleAction(int $idCustomHtmlGroup): RedirectResponse
|
||||||
|
{
|
||||||
|
$group = new CustomHtmlGroup($idCustomHtmlGroup);
|
||||||
|
|
||||||
|
if (!Validate::isLoadedObject($group)) {
|
||||||
|
$this->addFlash('error', $this->trans('Unable to find the group.', 'Modules.Wscustomhtml.Admin'));
|
||||||
|
|
||||||
|
return $this->redirectToRoute('customhtmlgroup_index');
|
||||||
|
}
|
||||||
|
|
||||||
|
$group->active = (int) !$group->active;
|
||||||
|
|
||||||
|
if (!$group->update()) {
|
||||||
|
$this->addFlash('error', $this->trans('An error occurred while updating the status.', 'Admin.Notifications.Error'));
|
||||||
|
} else {
|
||||||
|
$this->addFlash('success', $this->trans('Successful update.', 'Admin.Notifications.Success'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->redirectToRoute('customhtmlgroup_index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updatePositionAction(Request $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$positionDefinition = $this->get('websmid.customhtml.grid.position.customhtmlgroup_position_definition');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$positionUpdateFactory = $this->get(PositionUpdateFactoryInterface::class);
|
||||||
|
$positionUpdate = $positionUpdateFactory->buildPositionUpdate([
|
||||||
|
'positions' => $request->request->all('positions'),
|
||||||
|
], $positionDefinition);
|
||||||
|
|
||||||
|
$updater = $this->get(GridPositionUpdaterInterface::class);
|
||||||
|
$updater->update($positionUpdate);
|
||||||
|
|
||||||
|
$this->addFlash('success', $this->trans('Successful update.', 'Admin.Notifications.Success'));
|
||||||
|
} catch (PositionUpdateException $e) {
|
||||||
|
$this->addFlash('error', $this->getErrorMessageForException($e, []));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->redirectToRoute('customhtmlgroup_index');
|
||||||
|
}
|
||||||
|
|
||||||
private function getToolbarButtons(?string $securitySubject): array
|
private function getToolbarButtons(?string $securitySubject): array
|
||||||
{
|
{
|
||||||
$toolbarButtons = [];
|
$toolbarButtons = [];
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -5,6 +5,7 @@ namespace Websmid\CustomHtml\Form\ChoiceProvider;
|
|||||||
use PrestaShop\PrestaShop\Core\Form\ConfigurableFormChoiceProviderInterface;
|
use PrestaShop\PrestaShop\Core\Form\ConfigurableFormChoiceProviderInterface;
|
||||||
use PrestaShop\PrestaShop\Core\Form\FormChoiceAttributeProviderInterface;
|
use PrestaShop\PrestaShop\Core\Form\FormChoiceAttributeProviderInterface;
|
||||||
use PrestaShop\PrestaShop\Core\Form\FormChoiceProviderInterface;
|
use PrestaShop\PrestaShop\Core\Form\FormChoiceProviderInterface;
|
||||||
|
use Context;
|
||||||
use Db;
|
use Db;
|
||||||
|
|
||||||
final class CustomHtmlGroupChoiceProvider implements
|
final class CustomHtmlGroupChoiceProvider implements
|
||||||
@@ -14,16 +15,10 @@ final class CustomHtmlGroupChoiceProvider implements
|
|||||||
{
|
{
|
||||||
public function getChoices(array $options = []): array
|
public function getChoices(array $options = []): array
|
||||||
{
|
{
|
||||||
$groups = Db::getInstance()->executeS(
|
|
||||||
'SELECT `id_ws_customhtml_group`, `title`
|
|
||||||
FROM `' . _DB_PREFIX_ . 'ws_customhtml_group`
|
|
||||||
ORDER BY `title` ASC'
|
|
||||||
);
|
|
||||||
|
|
||||||
$choices = [];
|
$choices = [];
|
||||||
|
|
||||||
foreach ($groups as $group) {
|
foreach ($this->getGroupsWithLabels() as $label => $group) {
|
||||||
$choices[$group['title']] = (int) $group['id_ws_customhtml_group'];
|
$choices[$label] = (int) $group['id_ws_customhtml_group'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $choices;
|
return $choices;
|
||||||
@@ -31,6 +26,42 @@ final class CustomHtmlGroupChoiceProvider implements
|
|||||||
|
|
||||||
public function getChoicesAttributes(): array
|
public function getChoicesAttributes(): array
|
||||||
{
|
{
|
||||||
return [];
|
$choicesAttributes = [];
|
||||||
|
|
||||||
|
foreach ($this->getGroupsWithLabels() as $label => $group) {
|
||||||
|
if (!empty($group['default_block_class'])) {
|
||||||
|
$choicesAttributes[$label]['data-default-block-class'] = $group['default_block_class'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $choicesAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getGroupsWithLabels(): array
|
||||||
|
{
|
||||||
|
$idLang = (int) Context::getContext()->language->id;
|
||||||
|
|
||||||
|
$groups = Db::getInstance()->executeS(
|
||||||
|
'SELECT g.`id_ws_customhtml_group`, gl.`title`, g.`default_block_class`
|
||||||
|
FROM `' . _DB_PREFIX_ . 'ws_customhtml_group` g
|
||||||
|
LEFT JOIN `' . _DB_PREFIX_ . 'ws_customhtml_group_lang` gl
|
||||||
|
ON gl.`id_ws_customhtml_group` = g.`id_ws_customhtml_group` AND gl.`id_lang` = ' . (int) $idLang . '
|
||||||
|
ORDER BY gl.`title` ASC'
|
||||||
|
);
|
||||||
|
|
||||||
|
$titleCounts = array_count_values(array_column($groups, 'title'));
|
||||||
|
$groupsWithLabels = [];
|
||||||
|
|
||||||
|
foreach ($groups as $group) {
|
||||||
|
$label = $group['title'];
|
||||||
|
|
||||||
|
if ($titleCounts[$label] > 1) {
|
||||||
|
$label .= ' (#' . $group['id_ws_customhtml_group'] . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
$groupsWithLabels[$label] = $group;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $groupsWithLabels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -3,25 +3,50 @@
|
|||||||
namespace Websmid\CustomHtml\Form\DataHandler;
|
namespace Websmid\CustomHtml\Form\DataHandler;
|
||||||
|
|
||||||
use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataHandler\FormDataHandlerInterface;
|
use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataHandler\FormDataHandlerInterface;
|
||||||
|
use Websmid\CustomHtml\Config\Config;
|
||||||
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
||||||
|
use Websmid\CustomHtml\Model\CustomHtmlFaq;
|
||||||
|
use Websmid\CustomHtml\Model\CustomHtmlSlide;
|
||||||
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||||
|
use Db;
|
||||||
|
use Exception;
|
||||||
use Validate;
|
use Validate;
|
||||||
|
|
||||||
final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface
|
final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface
|
||||||
{
|
{
|
||||||
public function create(array $formData)
|
public function create(array $formData)
|
||||||
{
|
{
|
||||||
|
$idGroup = (int) $formData['id_ws_customhtml_group'];
|
||||||
|
|
||||||
$block = new CustomHtmlBlock();
|
$block = new CustomHtmlBlock();
|
||||||
$block->id_ws_customhtml_group = (int) $formData['id_ws_customhtml_group'];
|
$block->id_ws_customhtml_group = $idGroup;
|
||||||
$block->title = (string) $formData['title'];
|
$block->title = $formData['title'];
|
||||||
|
$block->type = (string) $formData['type'];
|
||||||
$block->show_title = (int) $formData['show_title'];
|
$block->show_title = (int) $formData['show_title'];
|
||||||
$block->content = (string) $formData['content'];
|
$block->custom_class = (string) ($formData['custom_class'] ?? '');
|
||||||
|
$block->content = $formData['content'];
|
||||||
|
$block->description = $formData['description'] ?? [];
|
||||||
|
$block->extra_description = $formData['extra_description'] ?? [];
|
||||||
|
$block->link = $formData['link'] ?? [];
|
||||||
|
$block->link_text = $formData['link_text'] ?? [];
|
||||||
|
$block->alert_type = (string) ($formData['alert_type'] ?? 'info');
|
||||||
|
$block->timeout = (int) ($formData['timeout'] ?? 0);
|
||||||
|
$block->slider_mode = (string) ($formData['slider_mode'] ?? Config::SLIDER_DEFAULT_MODE);
|
||||||
|
$block->slides_per_view_mobile = (float) ($formData['slides_per_view_mobile'] ?? Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_MOBILE);
|
||||||
|
$block->slides_per_view_tablet = (float) ($formData['slides_per_view_tablet'] ?? Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_TABLET);
|
||||||
|
$block->slides_per_view_desktop = (float) ($formData['slides_per_view_desktop'] ?? 0);
|
||||||
|
$block->autoplay_delay = (int) ($formData['autoplay_delay'] ?? 0);
|
||||||
|
$block->image = $this->saveUploadedImage($formData['image'] ?? null, '');
|
||||||
$block->active = (int) $formData['active'];
|
$block->active = (int) $formData['active'];
|
||||||
$block->ordering = 0;
|
$block->ordering = $this->getNextOrdering($idGroup);
|
||||||
|
|
||||||
if (!$block->add()) {
|
if (!$block->add()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->saveFaqs((int) $block->id, $formData['faqs'] ?? []);
|
||||||
|
$this->saveSlides((int) $block->id, $formData['slides'] ?? []);
|
||||||
|
|
||||||
return $block->id;
|
return $block->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,11 +59,140 @@ final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$block->id_ws_customhtml_group = (int) $formData['id_ws_customhtml_group'];
|
$block->id_ws_customhtml_group = (int) $formData['id_ws_customhtml_group'];
|
||||||
$block->title = (string) $formData['title'];
|
$block->title = $formData['title'];
|
||||||
|
$block->type = (string) $formData['type'];
|
||||||
$block->show_title = (int) $formData['show_title'];
|
$block->show_title = (int) $formData['show_title'];
|
||||||
$block->content = (string) $formData['content'];
|
$block->custom_class = (string) ($formData['custom_class'] ?? '');
|
||||||
|
$block->content = $formData['content'];
|
||||||
|
$block->description = $formData['description'] ?? [];
|
||||||
|
$block->extra_description = $formData['extra_description'] ?? [];
|
||||||
|
$block->link = $formData['link'] ?? [];
|
||||||
|
$block->link_text = $formData['link_text'] ?? [];
|
||||||
|
$block->alert_type = (string) ($formData['alert_type'] ?? 'info');
|
||||||
|
$block->timeout = (int) ($formData['timeout'] ?? 0);
|
||||||
|
$block->slider_mode = (string) ($formData['slider_mode'] ?? Config::SLIDER_DEFAULT_MODE);
|
||||||
|
$block->slides_per_view_mobile = (float) ($formData['slides_per_view_mobile'] ?? Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_MOBILE);
|
||||||
|
$block->slides_per_view_tablet = (float) ($formData['slides_per_view_tablet'] ?? Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_TABLET);
|
||||||
|
$block->slides_per_view_desktop = (float) ($formData['slides_per_view_desktop'] ?? 0);
|
||||||
|
$block->autoplay_delay = (int) ($formData['autoplay_delay'] ?? 0);
|
||||||
|
$block->image = $this->saveUploadedImage($formData['image'] ?? null, $block->image);
|
||||||
$block->active = (int) $formData['active'];
|
$block->active = (int) $formData['active'];
|
||||||
|
|
||||||
return (bool) $block->update();
|
if (!$block->update()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->saveFaqs((int) $id, $formData['faqs'] ?? []);
|
||||||
|
$this->saveSlides((int) $id, $formData['slides'] ?? []);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates and stores an uploaded banner image, replacing the previous
|
||||||
|
* one if any. Never trusts the client-supplied filename or MIME header —
|
||||||
|
* the real MIME type is detected server-side and a random filename is
|
||||||
|
* generated, so nothing from the upload itself ends up on disk.
|
||||||
|
*/
|
||||||
|
private function saveUploadedImage(?UploadedFile $file, string $currentFilename): string
|
||||||
|
{
|
||||||
|
if (null === $file) {
|
||||||
|
return $currentFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$file->isValid()) {
|
||||||
|
throw new Exception('The uploaded image could not be read.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($file->getSize() > Config::BANNER_IMAGE_MAX_SIZE) {
|
||||||
|
throw new Exception('The uploaded image is too large (max 5 MB).');
|
||||||
|
}
|
||||||
|
|
||||||
|
$mimeType = $file->getMimeType();
|
||||||
|
$extension = array_search($mimeType, Config::BANNER_IMAGE_ALLOWED_EXTENSIONS, true);
|
||||||
|
|
||||||
|
if (false === $extension) {
|
||||||
|
throw new Exception('The uploaded file is not a supported image type (jpg, png, gif, webp).');
|
||||||
|
}
|
||||||
|
|
||||||
|
$targetDir = CustomHtmlBlock::getBannerImageDir();
|
||||||
|
|
||||||
|
if (!is_dir($targetDir) && !mkdir($targetDir, 0755, true) && !is_dir($targetDir)) {
|
||||||
|
throw new Exception('Unable to create the banner image directory.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$newFilename = bin2hex(random_bytes(16)) . '.' . $extension;
|
||||||
|
$file->move($targetDir, $newFilename);
|
||||||
|
|
||||||
|
if (!empty($currentFilename) && is_file($targetDir . $currentFilename)) {
|
||||||
|
unlink($targetDir . $currentFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $newFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getNextOrdering(int $idGroup): int
|
||||||
|
{
|
||||||
|
$maxOrdering = Db::getInstance()->getValue(
|
||||||
|
'SELECT MAX(`ordering`) FROM `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||||
|
WHERE `id_ws_customhtml_group` = ' . (int) $idGroup
|
||||||
|
);
|
||||||
|
|
||||||
|
return $maxOrdering === false || $maxOrdering === null ? 0 : ((int) $maxOrdering + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function saveFaqs(int $idBlock, array $faqs): void
|
||||||
|
{
|
||||||
|
CustomHtmlFaq::deleteByBlockId($idBlock);
|
||||||
|
|
||||||
|
foreach (array_values($faqs) as $position => $faqData) {
|
||||||
|
$question = $faqData['question'] ?? [];
|
||||||
|
|
||||||
|
if (empty(array_filter($question, static function ($value) {
|
||||||
|
return trim((string) $value) !== '';
|
||||||
|
}))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$faq = new CustomHtmlFaq();
|
||||||
|
$faq->id_ws_customhtml = $idBlock;
|
||||||
|
$faq->question = $question;
|
||||||
|
$faq->answer = $faqData['answer'] ?? [];
|
||||||
|
$faq->ordering = $position;
|
||||||
|
$faq->add();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slides are fully replaced on every save, like FAQ items — except a
|
||||||
|
* slide's image can't round-trip through its file input, so the previous
|
||||||
|
* filename is looked up by the slide's hidden id and reused whenever no
|
||||||
|
* new file was uploaded for that row.
|
||||||
|
*/
|
||||||
|
private function saveSlides(int $idBlock, array $slides): void
|
||||||
|
{
|
||||||
|
$existingImages = [];
|
||||||
|
|
||||||
|
foreach (CustomHtmlSlide::getByBlockId($idBlock) as $existingSlide) {
|
||||||
|
$existingImages[(int) $existingSlide['id_ws_customhtml_slide']] = $existingSlide['image'];
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomHtmlSlide::deleteByBlockId($idBlock);
|
||||||
|
|
||||||
|
foreach (array_values($slides) as $position => $slideData) {
|
||||||
|
$existingId = (int) ($slideData['id'] ?? 0);
|
||||||
|
$existingImage = $existingImages[$existingId] ?? '';
|
||||||
|
|
||||||
|
$slide = new CustomHtmlSlide();
|
||||||
|
$slide->id_ws_customhtml = $idBlock;
|
||||||
|
$slide->title = $slideData['title'] ?? [];
|
||||||
|
$slide->description = $slideData['description'] ?? [];
|
||||||
|
$slide->extra_description = $slideData['extra_description'] ?? [];
|
||||||
|
$slide->link = $slideData['link'] ?? [];
|
||||||
|
$slide->link_text = $slideData['link_text'] ?? [];
|
||||||
|
$slide->image = $this->saveUploadedImage($slideData['image'] ?? null, $existingImage);
|
||||||
|
$slide->ordering = $position;
|
||||||
|
$slide->add();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace Websmid\CustomHtml\Form\DataHandler;
|
|||||||
use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataHandler\FormDataHandlerInterface;
|
use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataHandler\FormDataHandlerInterface;
|
||||||
use Websmid\CustomHtml\Model\CustomHtmlGroup;
|
use Websmid\CustomHtml\Model\CustomHtmlGroup;
|
||||||
use Context;
|
use Context;
|
||||||
|
use Db;
|
||||||
use Hook;
|
use Hook;
|
||||||
use Module;
|
use Module;
|
||||||
use Validate;
|
use Validate;
|
||||||
@@ -14,10 +15,12 @@ final class CustomHtmlGroupDataHandler implements FormDataHandlerInterface
|
|||||||
public function create(array $formData)
|
public function create(array $formData)
|
||||||
{
|
{
|
||||||
$group = new CustomHtmlGroup();
|
$group = new CustomHtmlGroup();
|
||||||
$group->title = (string) $formData['title'];
|
$group->title = $formData['title'];
|
||||||
$group->hook_name = (string) $formData['hook_name'];
|
$group->hook_name = (string) $formData['hook_name'];
|
||||||
$group->active = (int) $formData['active'];
|
$group->custom_class = (string) ($formData['custom_class'] ?? '');
|
||||||
$group->ordering = 0;
|
$group->default_block_class = (string) ($formData['default_block_class'] ?? '');
|
||||||
|
$group->active = (int) $formData['active'];
|
||||||
|
$group->ordering = $this->getNextOrdering();
|
||||||
|
|
||||||
if (!$group->add()) {
|
if (!$group->add()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -28,6 +31,15 @@ final class CustomHtmlGroupDataHandler implements FormDataHandlerInterface
|
|||||||
return $group->id;
|
return $group->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getNextOrdering(): int
|
||||||
|
{
|
||||||
|
$maxOrdering = Db::getInstance()->getValue(
|
||||||
|
'SELECT MAX(`ordering`) FROM `' . _DB_PREFIX_ . 'ws_customhtml_group`'
|
||||||
|
);
|
||||||
|
|
||||||
|
return $maxOrdering !== false ? ((int) $maxOrdering + 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
public function update($id, array $formData)
|
public function update($id, array $formData)
|
||||||
{
|
{
|
||||||
$group = new CustomHtmlGroup((int) $id);
|
$group = new CustomHtmlGroup((int) $id);
|
||||||
@@ -36,9 +48,11 @@ final class CustomHtmlGroupDataHandler implements FormDataHandlerInterface
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$group->title = (string) $formData['title'];
|
$group->title = $formData['title'];
|
||||||
$group->hook_name = (string) $formData['hook_name'];
|
$group->hook_name = (string) $formData['hook_name'];
|
||||||
$group->active = (int) $formData['active'];
|
$group->custom_class = (string) ($formData['custom_class'] ?? '');
|
||||||
|
$group->default_block_class = (string) ($formData['default_block_class'] ?? '');
|
||||||
|
$group->active = (int) $formData['active'];
|
||||||
|
|
||||||
if (!$group->update()) {
|
if (!$group->update()) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -3,7 +3,10 @@
|
|||||||
namespace Websmid\CustomHtml\Form\DataProvider;
|
namespace Websmid\CustomHtml\Form\DataProvider;
|
||||||
|
|
||||||
use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataProvider\FormDataProviderInterface;
|
use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataProvider\FormDataProviderInterface;
|
||||||
|
use Websmid\CustomHtml\Config\Config;
|
||||||
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
||||||
|
use Websmid\CustomHtml\Model\CustomHtmlFaq;
|
||||||
|
use Websmid\CustomHtml\Model\CustomHtmlSlide;
|
||||||
use Validate;
|
use Validate;
|
||||||
|
|
||||||
final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
||||||
@@ -19,8 +22,24 @@ final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
|||||||
return [
|
return [
|
||||||
'id_ws_customhtml_group' => (int) $block->id_ws_customhtml_group,
|
'id_ws_customhtml_group' => (int) $block->id_ws_customhtml_group,
|
||||||
'title' => $block->title,
|
'title' => $block->title,
|
||||||
|
'type' => $block->type,
|
||||||
'show_title' => (bool) $block->show_title,
|
'show_title' => (bool) $block->show_title,
|
||||||
|
'custom_class' => $block->custom_class,
|
||||||
'content' => $block->content,
|
'content' => $block->content,
|
||||||
|
'image' => null,
|
||||||
|
'description' => $block->description,
|
||||||
|
'extra_description' => $block->extra_description,
|
||||||
|
'link' => $block->link,
|
||||||
|
'link_text' => $block->link_text,
|
||||||
|
'alert_type' => $block->alert_type,
|
||||||
|
'timeout' => (int) $block->timeout,
|
||||||
|
'slider_mode' => $block->slider_mode,
|
||||||
|
'slides_per_view_mobile' => (float) $block->slides_per_view_mobile,
|
||||||
|
'slides_per_view_tablet' => (float) $block->slides_per_view_tablet,
|
||||||
|
'slides_per_view_desktop' => (float) $block->slides_per_view_desktop > 0 ? (float) $block->slides_per_view_desktop : null,
|
||||||
|
'autoplay_delay' => (int) $block->autoplay_delay,
|
||||||
|
'faqs' => $this->loadFaqs((int) $id),
|
||||||
|
'slides' => $this->loadSlides((int) $id),
|
||||||
'active' => (bool) $block->active,
|
'active' => (bool) $block->active,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -29,10 +48,51 @@ final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id_ws_customhtml_group' => 0,
|
'id_ws_customhtml_group' => 0,
|
||||||
'title' => '',
|
'title' => [],
|
||||||
|
'type' => 'html',
|
||||||
'show_title' => false,
|
'show_title' => false,
|
||||||
'content' => '',
|
'custom_class' => '',
|
||||||
|
'content' => [],
|
||||||
|
'image' => null,
|
||||||
|
'description' => [],
|
||||||
|
'extra_description' => [],
|
||||||
|
'link' => [],
|
||||||
|
'link_text' => [],
|
||||||
|
'alert_type' => 'info',
|
||||||
|
'timeout' => 0,
|
||||||
|
'slider_mode' => Config::SLIDER_DEFAULT_MODE,
|
||||||
|
'slides_per_view_mobile' => Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_MOBILE,
|
||||||
|
'slides_per_view_tablet' => Config::SLIDER_DEFAULT_SLIDES_PER_VIEW_TABLET,
|
||||||
|
'slides_per_view_desktop' => null,
|
||||||
|
'autoplay_delay' => 0,
|
||||||
|
'faqs' => [],
|
||||||
|
'slides' => [],
|
||||||
'active' => true,
|
'active' => true,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function loadFaqs(int $idBlock): array
|
||||||
|
{
|
||||||
|
return array_map(static function (array $faq) {
|
||||||
|
return [
|
||||||
|
'question' => $faq['question'],
|
||||||
|
'answer' => $faq['answer'],
|
||||||
|
];
|
||||||
|
}, CustomHtmlFaq::getByBlockId($idBlock));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadSlides(int $idBlock): array
|
||||||
|
{
|
||||||
|
return array_map(static function (array $slide) {
|
||||||
|
return [
|
||||||
|
'id' => (int) $slide['id_ws_customhtml_slide'],
|
||||||
|
'title' => $slide['title'],
|
||||||
|
'description' => $slide['description'],
|
||||||
|
'extra_description' => $slide['extra_description'],
|
||||||
|
'link' => $slide['link'],
|
||||||
|
'link_text' => $slide['link_text'],
|
||||||
|
'image' => null,
|
||||||
|
];
|
||||||
|
}, CustomHtmlSlide::getByBlockId($idBlock));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,18 +17,22 @@ final class CustomHtmlGroupDataProvider implements FormDataProviderInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $group->title,
|
'title' => $group->title,
|
||||||
'hook_name' => $group->hook_name,
|
'hook_name' => $group->hook_name,
|
||||||
'active' => (bool) $group->active,
|
'custom_class' => $group->custom_class,
|
||||||
|
'default_block_class' => $group->default_block_class,
|
||||||
|
'active' => (bool) $group->active,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDefaultData()
|
public function getDefaultData()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'title' => '',
|
'title' => [],
|
||||||
'hook_name' => '',
|
'hook_name' => '',
|
||||||
'active' => true,
|
'custom_class' => '',
|
||||||
|
'default_block_class' => '',
|
||||||
|
'active' => true,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -5,15 +5,23 @@ namespace Websmid\CustomHtml\Form\Type;
|
|||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||||
use PrestaShop\PrestaShop\Core\Form\ConfigurableFormChoiceProviderInterface;
|
use PrestaShop\PrestaShop\Core\Form\ConfigurableFormChoiceProviderInterface;
|
||||||
|
use PrestaShopBundle\Form\Admin\Type\FormattedTextareaType;
|
||||||
use PrestaShopBundle\Form\Admin\Type\SwitchType;
|
use PrestaShopBundle\Form\Admin\Type\SwitchType;
|
||||||
|
use PrestaShopBundle\Form\Admin\Type\TranslatableType;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
use Websmid\CustomHtml\Config\Config;
|
||||||
|
|
||||||
class CustomHtmlBlockType extends AbstractType
|
class CustomHtmlBlockType extends AbstractType
|
||||||
{
|
{
|
||||||
private $translator;
|
private $translator;
|
||||||
|
private $locales;
|
||||||
private $groupChoiceProvider;
|
private $groupChoiceProvider;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
@@ -22,6 +30,7 @@ class CustomHtmlBlockType extends AbstractType
|
|||||||
ConfigurableFormChoiceProviderInterface $groupChoiceProvider
|
ConfigurableFormChoiceProviderInterface $groupChoiceProvider
|
||||||
) {
|
) {
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
|
$this->locales = $locales;
|
||||||
$this->groupChoiceProvider = $groupChoiceProvider;
|
$this->groupChoiceProvider = $groupChoiceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,22 +38,139 @@ class CustomHtmlBlockType extends AbstractType
|
|||||||
{
|
{
|
||||||
$formBuilder
|
$formBuilder
|
||||||
->add('id_ws_customhtml_group', ChoiceType::class, [
|
->add('id_ws_customhtml_group', ChoiceType::class, [
|
||||||
'label' => $this->translator->trans('Group', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Group', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
'choices' => $this->groupChoiceProvider->getChoices(),
|
'choices' => $this->groupChoiceProvider->getChoices(),
|
||||||
|
'choice_attr' => $this->groupChoiceProvider->getChoicesAttributes(),
|
||||||
|
'required' => true,
|
||||||
|
])
|
||||||
|
->add('type', ChoiceType::class, [
|
||||||
|
'label' => $this->translator->trans('Block type', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'choices' => array_flip(Config::BLOCK_TYPES),
|
||||||
'required' => true,
|
'required' => true,
|
||||||
])
|
])
|
||||||
->add('title', TextType::class, [
|
->add('title', TranslatableType::class, [
|
||||||
|
'type' => TextType::class,
|
||||||
'label' => $this->translator->trans('Title', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Title', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
'required' => true,
|
'required' => true,
|
||||||
|
'row_attr' => ['class' => 'col-8'],
|
||||||
])
|
])
|
||||||
->add('show_title', SwitchType::class, [
|
->add('show_title', SwitchType::class, [
|
||||||
'label' => $this->translator->trans('Show title', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Show title', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'row_attr' => ['class' => 'col-3'],
|
||||||
])
|
])
|
||||||
->add('content', TextareaType::class, [
|
->add('content', TranslatableType::class, [
|
||||||
|
'type' => FormattedTextareaType::class,
|
||||||
'label' => $this->translator->trans('Content', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Content', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'attr' => ['class' => 'autoload_rte'],
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-html'],
|
||||||
|
])
|
||||||
|
->add('image', FileType::class, [
|
||||||
|
'label' => $this->translator->trans('Image', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-banner customhtmlblock-type-usp'],
|
||||||
|
])
|
||||||
|
->add('faqs', CollectionType::class, [
|
||||||
|
'entry_type' => CustomHtmlFaqType::class,
|
||||||
|
'allow_add' => true,
|
||||||
|
'allow_delete' => true,
|
||||||
|
'by_reference' => false,
|
||||||
|
'prototype' => true,
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('slides', CollectionType::class, [
|
||||||
|
'entry_type' => CustomHtmlSlideType::class,
|
||||||
|
'allow_add' => true,
|
||||||
|
'allow_delete' => true,
|
||||||
|
'by_reference' => false,
|
||||||
|
'prototype' => true,
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('slider_mode', ChoiceType::class, [
|
||||||
|
'label' => $this->translator->trans('Slider mode', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'choices' => array_flip(Config::SLIDER_MODES),
|
||||||
|
'required' => false,
|
||||||
|
'help' => $this->translator->trans('"Mobile only": slider only on mobile, a static grid shows instead from tablet up.', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-slider'],
|
||||||
|
])
|
||||||
|
->add('slides_per_view_mobile', NumberType::class, [
|
||||||
|
'label' => $this->translator->trans('Slides visible on mobile', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
'scale' => 2,
|
||||||
|
'attr' => ['min' => 0, 'step' => '0.05'],
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-slider col-4'],
|
||||||
|
])
|
||||||
|
->add('slides_per_view_tablet', NumberType::class, [
|
||||||
|
'label' => $this->translator->trans('Slides visible on tablet', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
'scale' => 2,
|
||||||
|
'attr' => ['min' => 0, 'step' => '0.05'],
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-slider col-4'],
|
||||||
|
])
|
||||||
|
->add('slides_per_view_desktop', NumberType::class, [
|
||||||
|
'label' => $this->translator->trans('Slides visible on desktop', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
'scale' => 2,
|
||||||
|
'attr' => ['min' => 0, 'step' => '0.05', 'placeholder' => $this->translator->trans('Auto', [], 'Modules.Wscustomhtml.Admin')],
|
||||||
|
'help' => $this->translator->trans('In "Mobile only" mode this is rounded to the nearest whole number of columns. Leave empty for an equal-width column.', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-slider col-4'],
|
||||||
|
])
|
||||||
|
->add('autoplay_delay', IntegerType::class, [
|
||||||
|
'label' => $this->translator->trans('Autoplay delay (seconds)', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
'attr' => ['min' => 0, 'placeholder' => '0'],
|
||||||
|
'help' => $this->translator->trans('0 means the slider never auto-advances; visitors can still swipe or use the arrows.', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-slider'],
|
||||||
|
])
|
||||||
|
->add('alert_type', ChoiceType::class, [
|
||||||
|
'label' => $this->translator->trans('Alert style', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'choices' => array_flip(Config::ALERT_STYLES),
|
||||||
|
'required' => false,
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-alert'],
|
||||||
|
])
|
||||||
|
->add('timeout', IntegerType::class, [
|
||||||
|
'label' => $this->translator->trans('Auto-dismiss after (seconds)', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
'attr' => ['min' => 0, 'placeholder' => '0'],
|
||||||
|
'help' => $this->translator->trans('0 means the alert never auto-dismisses; visitors can still close it manually.', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-alert'],
|
||||||
|
])
|
||||||
|
->add('description', TranslatableType::class, [
|
||||||
|
'type' => TextareaType::class,
|
||||||
|
'label' => $this->translator->trans('Description', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
|
'required' => false,
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-banner customhtmlblock-type-alert customhtmlblock-type-usp'],
|
||||||
|
])
|
||||||
|
->add('extra_description', TranslatableType::class, [
|
||||||
|
'type' => TextareaType::class,
|
||||||
|
'label' => $this->translator->trans('Extra description', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
|
'required' => false,
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-banner'],
|
||||||
|
])
|
||||||
|
->add('link', TranslatableType::class, [
|
||||||
|
'type' => TextType::class,
|
||||||
|
'label' => $this->translator->trans('Link URL', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
|
'required' => false,
|
||||||
|
'options' => ['attr' => ['placeholder' => 'https://example.com or /internal-page']],
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-banner customhtmlblock-type-usp customhtmlblock-type-alert'],
|
||||||
|
])
|
||||||
|
->add('link_text', TranslatableType::class, [
|
||||||
|
'type' => TextType::class,
|
||||||
|
'label' => $this->translator->trans('Link text', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
|
'required' => false,
|
||||||
|
'options' => ['attr' => ['placeholder' => 'Learn more']],
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-alert col-6'],
|
||||||
|
])
|
||||||
|
->add('custom_class', TextType::class, [
|
||||||
|
'label' => $this->translator->trans('Custom classes', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
'attr' => ['placeholder' => 'col-md-6'],
|
||||||
])
|
])
|
||||||
->add('active', SwitchType::class, [
|
->add('active', SwitchType::class, [
|
||||||
'label' => $this->translator->trans('Active', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Active', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Websmid\CustomHtml\Form\Type;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||||
|
use PrestaShopBundle\Form\Admin\Type\TranslatableType;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
|
class CustomHtmlFaqType extends AbstractType
|
||||||
|
{
|
||||||
|
private $translator;
|
||||||
|
private $locales;
|
||||||
|
|
||||||
|
public function __construct(TranslatorInterface $translator, array $locales)
|
||||||
|
{
|
||||||
|
$this->translator = $translator;
|
||||||
|
$this->locales = $locales;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $formBuilder, array $options): void
|
||||||
|
{
|
||||||
|
$formBuilder
|
||||||
|
->add('question', TranslatableType::class, [
|
||||||
|
'type' => TextType::class,
|
||||||
|
'label' => $this->translator->trans('Question', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('answer', TranslatableType::class, [
|
||||||
|
'type' => TextareaType::class,
|
||||||
|
'label' => $this->translator->trans('Answer', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
|
'required' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,28 +6,44 @@ use Symfony\Component\Form\AbstractType;
|
|||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
use PrestaShopBundle\Form\Admin\Type\SwitchType;
|
use PrestaShopBundle\Form\Admin\Type\SwitchType;
|
||||||
|
use PrestaShopBundle\Form\Admin\Type\TranslatableType;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
class CustomHtmlGroupType extends AbstractType
|
class CustomHtmlGroupType extends AbstractType
|
||||||
{
|
{
|
||||||
private $translator;
|
private $translator;
|
||||||
|
private $locales;
|
||||||
|
|
||||||
public function __construct(TranslatorInterface $translator, array $locales)
|
public function __construct(TranslatorInterface $translator, array $locales)
|
||||||
{
|
{
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
|
$this->locales = $locales;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildForm(FormBuilderInterface $formBuilder, array $options): void
|
public function buildForm(FormBuilderInterface $formBuilder, array $options): void
|
||||||
{
|
{
|
||||||
$formBuilder
|
$formBuilder
|
||||||
->add('title', TextType::class, [
|
->add('title', TranslatableType::class, [
|
||||||
|
'type' => TextType::class,
|
||||||
'label' => $this->translator->trans('Title', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Title', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
'required' => true,
|
'required' => true,
|
||||||
])
|
])
|
||||||
->add('hook_name', TextType::class, [
|
->add('hook_name', TextType::class, [
|
||||||
'label' => $this->translator->trans('Hook name', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Hook name', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
'required' => true,
|
'required' => true,
|
||||||
])
|
])
|
||||||
|
->add('custom_class', TextType::class, [
|
||||||
|
'label' => $this->translator->trans('Custom group classes', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
'attr' => ['placeholder' => 'col-md-6'],
|
||||||
|
])
|
||||||
|
->add('default_block_class', TextType::class, [
|
||||||
|
'label' => $this->translator->trans('Default block class', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
'attr' => ['placeholder' => 'col-12 col-lg-6 col-xl-5'],
|
||||||
|
'help' => $this->translator->trans('Applied to every block in this group automatically, in addition to that block\'s own custom classes. Useful when several blocks need the same column layout.', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
])
|
||||||
->add('active', SwitchType::class, [
|
->add('active', SwitchType::class, [
|
||||||
'label' => $this->translator->trans('Active', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Active', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Websmid\CustomHtml\Form\Type;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||||
|
use PrestaShopBundle\Form\Admin\Type\TranslatableType;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
|
class CustomHtmlSlideType extends AbstractType
|
||||||
|
{
|
||||||
|
private $translator;
|
||||||
|
private $locales;
|
||||||
|
|
||||||
|
public function __construct(TranslatorInterface $translator, array $locales)
|
||||||
|
{
|
||||||
|
$this->translator = $translator;
|
||||||
|
$this->locales = $locales;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $formBuilder, array $options): void
|
||||||
|
{
|
||||||
|
$formBuilder
|
||||||
|
->add('id', HiddenType::class, [
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('title', TranslatableType::class, [
|
||||||
|
'type' => TextType::class,
|
||||||
|
'label' => $this->translator->trans('Title', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('description', TranslatableType::class, [
|
||||||
|
'type' => TextareaType::class,
|
||||||
|
'label' => $this->translator->trans('Description', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('extra_description', TranslatableType::class, [
|
||||||
|
'type' => TextareaType::class,
|
||||||
|
'label' => $this->translator->trans('Extra description', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('link', TranslatableType::class, [
|
||||||
|
'type' => TextType::class,
|
||||||
|
'label' => $this->translator->trans('Link URL', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
|
'required' => false,
|
||||||
|
'options' => ['attr' => ['placeholder' => 'https://example.com or /internal-page']],
|
||||||
|
])
|
||||||
|
->add('link_text', TranslatableType::class, [
|
||||||
|
'type' => TextType::class,
|
||||||
|
'label' => $this->translator->trans('Link text', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'locales' => $this->locales,
|
||||||
|
'required' => false,
|
||||||
|
'options' => ['attr' => ['placeholder' => 'Learn more']],
|
||||||
|
])
|
||||||
|
->add('image', FileType::class, [
|
||||||
|
'label' => $this->translator->trans('Image', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -8,6 +8,7 @@ use PrestaShop\PrestaShop\Core\Grid\Action\Row\Type\LinkRowAction;
|
|||||||
use PrestaShop\PrestaShop\Core\Grid\Action\Type\SimpleGridAction;
|
use PrestaShop\PrestaShop\Core\Grid\Action\Type\SimpleGridAction;
|
||||||
use PrestaShop\PrestaShop\Core\Grid\Column\ColumnCollection;
|
use PrestaShop\PrestaShop\Core\Grid\Column\ColumnCollection;
|
||||||
use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\ActionColumn;
|
use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\ActionColumn;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\PositionColumn;
|
||||||
use PrestaShop\PrestaShop\Core\Grid\Column\Type\DataColumn;
|
use PrestaShop\PrestaShop\Core\Grid\Column\Type\DataColumn;
|
||||||
use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\AbstractGridDefinitionFactory;
|
use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\AbstractGridDefinitionFactory;
|
||||||
use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\DeleteActionTrait;
|
use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\DeleteActionTrait;
|
||||||
@@ -15,7 +16,9 @@ use PrestaShop\PrestaShop\Core\Grid\Filter\Filter;
|
|||||||
use PrestaShop\PrestaShop\Core\Grid\Filter\FilterCollection;
|
use PrestaShop\PrestaShop\Core\Grid\Filter\FilterCollection;
|
||||||
use PrestaShop\PrestaShop\Core\Hook\HookDispatcherInterface;
|
use PrestaShop\PrestaShop\Core\Hook\HookDispatcherInterface;
|
||||||
use PrestaShopBundle\Form\Admin\Type\SearchAndResetType;
|
use PrestaShopBundle\Form\Admin\Type\SearchAndResetType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Websmid\CustomHtml\Config\Config;
|
||||||
|
|
||||||
final class CustomHtmlBlockGridDefinitionFactory extends AbstractGridDefinitionFactory
|
final class CustomHtmlBlockGridDefinitionFactory extends AbstractGridDefinitionFactory
|
||||||
{
|
{
|
||||||
@@ -71,15 +74,29 @@ final class CustomHtmlBlockGridDefinitionFactory extends AbstractGridDefinitionF
|
|||||||
->setName($this->trans('Group', [], 'Modules.Wscustomhtml.Admin'))
|
->setName($this->trans('Group', [], 'Modules.Wscustomhtml.Admin'))
|
||||||
->setOptions(['field' => 'group_title'])
|
->setOptions(['field' => 'group_title'])
|
||||||
)
|
)
|
||||||
|
->add(
|
||||||
|
(new DataColumn('type'))
|
||||||
|
->setName($this->trans('Type', [], 'Modules.Wscustomhtml.Admin'))
|
||||||
|
->setOptions(['field' => 'type'])
|
||||||
|
)
|
||||||
->add(
|
->add(
|
||||||
(new DataColumn('active'))
|
(new DataColumn('active'))
|
||||||
->setName($this->trans('Active', [], 'Admin.Global'))
|
->setName($this->trans('Active', [], 'Admin.Global'))
|
||||||
->setOptions(['field' => 'active'])
|
->setOptions(['field' => 'active'])
|
||||||
)
|
)
|
||||||
->add(
|
->add(
|
||||||
(new DataColumn('ordering'))
|
(new PositionColumn('position'))
|
||||||
->setName($this->trans('Position', [], 'Modules.Wscustomhtml.Admin'))
|
->setName($this->trans('Position', [], 'Modules.Wscustomhtml.Admin'))
|
||||||
->setOptions(['field' => 'ordering'])
|
->setOptions([
|
||||||
|
'id_field' => 'id_ws_customhtml',
|
||||||
|
'position_field' => 'ordering',
|
||||||
|
'update_method' => 'POST',
|
||||||
|
'update_route' => 'customhtmlblock_update_position',
|
||||||
|
'record_route_params' => [
|
||||||
|
'id_ws_customhtml_group' => 'idGroup',
|
||||||
|
],
|
||||||
|
'required_filter' => 'id_ws_customhtml_group',
|
||||||
|
])
|
||||||
)
|
)
|
||||||
->add(
|
->add(
|
||||||
(new DataColumn('date_add'))
|
(new DataColumn('date_add'))
|
||||||
@@ -120,6 +137,15 @@ final class CustomHtmlBlockGridDefinitionFactory extends AbstractGridDefinitionF
|
|||||||
'attr' => ['placeholder' => $this->trans('Group', [], 'Modules.Wscustomhtml.Admin')],
|
'attr' => ['placeholder' => $this->trans('Group', [], 'Modules.Wscustomhtml.Admin')],
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
->add(
|
||||||
|
(new Filter('type', ChoiceType::class))
|
||||||
|
->setAssociatedColumn('type')
|
||||||
|
->setTypeOptions([
|
||||||
|
'required' => false,
|
||||||
|
'choices' => array_flip(Config::BLOCK_TYPES),
|
||||||
|
'placeholder' => $this->trans('All', [], 'Admin.Global'),
|
||||||
|
])
|
||||||
|
)
|
||||||
->add(
|
->add(
|
||||||
(new Filter('actions', SearchAndResetType::class))
|
(new Filter('actions', SearchAndResetType::class))
|
||||||
->setAssociatedColumn('actions')
|
->setAssociatedColumn('actions')
|
||||||
@@ -144,10 +170,17 @@ final class CustomHtmlBlockGridDefinitionFactory extends AbstractGridDefinitionF
|
|||||||
'route_param_field' => 'id_ws_customhtml',
|
'route_param_field' => 'id_ws_customhtml',
|
||||||
'use_inline_display' => true,
|
'use_inline_display' => true,
|
||||||
'clickable_row' => true,
|
'clickable_row' => true,
|
||||||
|
'extra_route_params' => ['idGroup' => 'id_ws_customhtml_group'],
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
->add(
|
->add(
|
||||||
$this->buildDeleteAction('customhtmlblock_delete', 'idCustomHtmlBlock', 'id_ws_customhtml')
|
$this->buildDeleteAction(
|
||||||
|
'customhtmlblock_delete',
|
||||||
|
'idCustomHtmlBlock',
|
||||||
|
'id_ws_customhtml',
|
||||||
|
'POST',
|
||||||
|
['idGroup' => 'id_ws_customhtml_group']
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ use PrestaShop\PrestaShop\Core\Grid\Action\Row\Type\LinkRowAction;
|
|||||||
use PrestaShop\PrestaShop\Core\Grid\Action\Type\SimpleGridAction;
|
use PrestaShop\PrestaShop\Core\Grid\Action\Type\SimpleGridAction;
|
||||||
use PrestaShop\PrestaShop\Core\Grid\Column\ColumnCollection;
|
use PrestaShop\PrestaShop\Core\Grid\Column\ColumnCollection;
|
||||||
use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\ActionColumn;
|
use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\ActionColumn;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\PositionColumn;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\ToggleColumn;
|
||||||
use PrestaShop\PrestaShop\Core\Grid\Column\Type\DataColumn;
|
use PrestaShop\PrestaShop\Core\Grid\Column\Type\DataColumn;
|
||||||
use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\AbstractGridDefinitionFactory;
|
use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\AbstractGridDefinitionFactory;
|
||||||
use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\DeleteActionTrait;
|
use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\DeleteActionTrait;
|
||||||
@@ -77,9 +79,24 @@ final class CustomHtmlGroupGridDefinitionFactory extends AbstractGridDefinitionF
|
|||||||
->setOptions(['field' => 'blocks_count', 'sortable' => false])
|
->setOptions(['field' => 'blocks_count', 'sortable' => false])
|
||||||
)
|
)
|
||||||
->add(
|
->add(
|
||||||
(new DataColumn('active'))
|
(new ToggleColumn('active'))
|
||||||
->setName($this->trans('Active', [], 'Admin.Global'))
|
->setName($this->trans('Active', [], 'Admin.Global'))
|
||||||
->setOptions(['field' => 'active'])
|
->setOptions([
|
||||||
|
'field' => 'active',
|
||||||
|
'primary_field' => 'id_ws_customhtml_group',
|
||||||
|
'route' => 'customhtmlgroup_toggle',
|
||||||
|
'route_param_name' => 'idCustomHtmlGroup',
|
||||||
|
])
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
(new PositionColumn('position'))
|
||||||
|
->setName($this->trans('Position', [], 'Admin.Global'))
|
||||||
|
->setOptions([
|
||||||
|
'id_field' => 'id_ws_customhtml_group',
|
||||||
|
'position_field' => 'ordering',
|
||||||
|
'update_method' => 'POST',
|
||||||
|
'update_route' => 'customhtmlgroup_update_position',
|
||||||
|
])
|
||||||
)
|
)
|
||||||
->add(
|
->add(
|
||||||
(new DataColumn('date_add'))
|
(new DataColumn('date_add'))
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -14,7 +14,7 @@ final class CustomHtmlBlockFilters extends Filters
|
|||||||
return [
|
return [
|
||||||
'limit' => 10,
|
'limit' => 10,
|
||||||
'offset' => 0,
|
'offset' => 0,
|
||||||
'orderBy' => 'wchb.id_ws_customhtml',
|
'orderBy' => 'position',
|
||||||
'sortOrder' => 'asc',
|
'sortOrder' => 'asc',
|
||||||
'filters' => [],
|
'filters' => [],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ final class CustomHtmlGroupFilters extends Filters
|
|||||||
return [
|
return [
|
||||||
'limit' => 10,
|
'limit' => 10,
|
||||||
'offset' => 0,
|
'offset' => 0,
|
||||||
'orderBy' => 'wchg.id_ws_customhtml_group',
|
'orderBy' => 'position',
|
||||||
'sortOrder' => 'asc',
|
'sortOrder' => 'asc',
|
||||||
'filters' => [],
|
'filters' => [],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -11,12 +11,7 @@ use PrestaShop\PrestaShop\Core\Grid\Search\SearchCriteriaInterface;
|
|||||||
|
|
||||||
final class CustomHtmlBlockQueryBuilder extends AbstractDoctrineQueryBuilder
|
final class CustomHtmlBlockQueryBuilder extends AbstractDoctrineQueryBuilder
|
||||||
{
|
{
|
||||||
private $searchCriteriaApplicator;
|
|
||||||
private $contextLanguageId;
|
private $contextLanguageId;
|
||||||
private $contextShopId;
|
|
||||||
private $contextShopGroupId;
|
|
||||||
private $filterApplicator;
|
|
||||||
private $configuration;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Connection $connection,
|
Connection $connection,
|
||||||
@@ -29,12 +24,8 @@ final class CustomHtmlBlockQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
Configuration $configuration
|
Configuration $configuration
|
||||||
) {
|
) {
|
||||||
parent::__construct($connection, $dbPrefix);
|
parent::__construct($connection, $dbPrefix);
|
||||||
$this->searchCriteriaApplicator = $searchCriteriaApplicator;
|
|
||||||
$this->contextLanguageId = $contextLanguageId;
|
$this->contextLanguageId = $contextLanguageId;
|
||||||
$this->contextShopId = $contextShopId;
|
|
||||||
$this->contextShopGroupId = $contextShopGroupId;
|
|
||||||
$this->filterApplicator = $filterApplicator;
|
|
||||||
$this->configuration = $configuration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSearchQueryBuilder(SearchCriteriaInterface $searchCriteria)
|
public function getSearchQueryBuilder(SearchCriteriaInterface $searchCriteria)
|
||||||
@@ -43,8 +34,10 @@ final class CustomHtmlBlockQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
|
|
||||||
$qb->select(
|
$qb->select(
|
||||||
'wchb.`id_ws_customhtml`',
|
'wchb.`id_ws_customhtml`',
|
||||||
'wchb.`title`',
|
'wchb.`id_ws_customhtml_group`',
|
||||||
'wchg.`title` AS group_title',
|
'wchbl.`title`',
|
||||||
|
'wchgl.`title` AS group_title',
|
||||||
|
'wchb.`type`',
|
||||||
'wchb.`active`',
|
'wchb.`active`',
|
||||||
'wchb.`ordering`',
|
'wchb.`ordering`',
|
||||||
'wchb.`date_add`'
|
'wchb.`date_add`'
|
||||||
@@ -52,8 +45,10 @@ final class CustomHtmlBlockQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
|
|
||||||
$this->applyFilters($qb, $searchCriteria);
|
$this->applyFilters($qb, $searchCriteria);
|
||||||
|
|
||||||
|
$orderBy = $searchCriteria->getOrderBy() === 'position' ? 'wchb.ordering' : $searchCriteria->getOrderBy();
|
||||||
|
|
||||||
$qb
|
$qb
|
||||||
->orderBy($searchCriteria->getOrderBy(), $searchCriteria->getOrderWay())
|
->orderBy($orderBy, $searchCriteria->getOrderWay())
|
||||||
->setFirstResult($searchCriteria->getOffset() ?? 0)
|
->setFirstResult($searchCriteria->getOffset() ?? 0)
|
||||||
->setMaxResults($searchCriteria->getLimit());
|
->setMaxResults($searchCriteria->getLimit());
|
||||||
|
|
||||||
@@ -80,6 +75,18 @@ final class CustomHtmlBlockQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
$this->dbPrefix . 'ws_customhtml_group',
|
$this->dbPrefix . 'ws_customhtml_group',
|
||||||
'wchg',
|
'wchg',
|
||||||
'wchg.`id_ws_customhtml_group` = wchb.`id_ws_customhtml_group`'
|
'wchg.`id_ws_customhtml_group` = wchb.`id_ws_customhtml_group`'
|
||||||
|
)
|
||||||
|
->leftJoin(
|
||||||
|
'wchb',
|
||||||
|
$this->dbPrefix . 'ws_customhtml_group_lang',
|
||||||
|
'wchgl',
|
||||||
|
'wchgl.`id_ws_customhtml_group` = wchb.`id_ws_customhtml_group` AND wchgl.`id_lang` = ' . (int) $this->contextLanguageId
|
||||||
|
)
|
||||||
|
->leftJoin(
|
||||||
|
'wchb',
|
||||||
|
$this->dbPrefix . 'ws_customhtml_lang',
|
||||||
|
'wchbl',
|
||||||
|
'wchbl.`id_ws_customhtml` = wchb.`id_ws_customhtml` AND wchbl.`id_lang` = ' . (int) $this->contextLanguageId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,12 +109,24 @@ final class CustomHtmlBlockQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($filterName === 'title') {
|
||||||
|
$qb->andWhere('wchbl.`title` LIKE :title')
|
||||||
|
->setParameter('title', '%' . pSQL($filterValue) . '%');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ($filterName === 'group_title') {
|
if ($filterName === 'group_title') {
|
||||||
$qb->andWhere('wchg.`title` LIKE :group_title')
|
$qb->andWhere('wchgl.`title` LIKE :group_title')
|
||||||
->setParameter('group_title', '%' . pSQL($filterValue) . '%');
|
->setParameter('group_title', '%' . pSQL($filterValue) . '%');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($filterName === 'type') {
|
||||||
|
$qb->andWhere('wchb.`type` = :type')
|
||||||
|
->setParameter('type', pSQL($filterValue));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$qb->andWhere('wchb.`' . $filterName . '` LIKE :' . $filterName)
|
$qb->andWhere('wchb.`' . $filterName . '` LIKE :' . $filterName)
|
||||||
->setParameter($filterName, '%' . pSQL($filterValue) . '%');
|
->setParameter($filterName, '%' . pSQL($filterValue) . '%');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,7 @@ use PrestaShop\PrestaShop\Core\Grid\Search\SearchCriteriaInterface;
|
|||||||
|
|
||||||
final class CustomHtmlGroupQueryBuilder extends AbstractDoctrineQueryBuilder
|
final class CustomHtmlGroupQueryBuilder extends AbstractDoctrineQueryBuilder
|
||||||
{
|
{
|
||||||
private $searchCriteriaApplicator;
|
|
||||||
private $contextLanguageId;
|
private $contextLanguageId;
|
||||||
private $contextShopId;
|
|
||||||
private $contextShopGroupId;
|
|
||||||
private $filterApplicator;
|
|
||||||
private $configuration;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Connection $connection,
|
Connection $connection,
|
||||||
@@ -29,12 +24,8 @@ final class CustomHtmlGroupQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
Configuration $configuration
|
Configuration $configuration
|
||||||
) {
|
) {
|
||||||
parent::__construct($connection, $dbPrefix);
|
parent::__construct($connection, $dbPrefix);
|
||||||
$this->searchCriteriaApplicator = $searchCriteriaApplicator;
|
|
||||||
$this->contextLanguageId = $contextLanguageId;
|
$this->contextLanguageId = $contextLanguageId;
|
||||||
$this->contextShopId = $contextShopId;
|
|
||||||
$this->contextShopGroupId = $contextShopGroupId;
|
|
||||||
$this->filterApplicator = $filterApplicator;
|
|
||||||
$this->configuration = $configuration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSearchQueryBuilder(SearchCriteriaInterface $searchCriteria)
|
public function getSearchQueryBuilder(SearchCriteriaInterface $searchCriteria)
|
||||||
@@ -43,9 +34,11 @@ final class CustomHtmlGroupQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
|
|
||||||
$qb->select(
|
$qb->select(
|
||||||
'wchg.`id_ws_customhtml_group`',
|
'wchg.`id_ws_customhtml_group`',
|
||||||
'wchg.`title`',
|
'wchgl.`title`',
|
||||||
'wchg.`hook_name`',
|
'wchg.`hook_name`',
|
||||||
|
'wchg.`custom_class`',
|
||||||
'wchg.`active`',
|
'wchg.`active`',
|
||||||
|
'wchg.`ordering`',
|
||||||
'wchg.`date_add`',
|
'wchg.`date_add`',
|
||||||
'(SELECT COUNT(*) FROM `' . $this->dbPrefix . 'ws_customhtml` wch
|
'(SELECT COUNT(*) FROM `' . $this->dbPrefix . 'ws_customhtml` wch
|
||||||
WHERE wch.`id_ws_customhtml_group` = wchg.`id_ws_customhtml_group`) AS blocks_count'
|
WHERE wch.`id_ws_customhtml_group` = wchg.`id_ws_customhtml_group`) AS blocks_count'
|
||||||
@@ -53,8 +46,10 @@ final class CustomHtmlGroupQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
|
|
||||||
$this->applyFilters($qb, $searchCriteria);
|
$this->applyFilters($qb, $searchCriteria);
|
||||||
|
|
||||||
|
$orderBy = $searchCriteria->getOrderBy() === 'position' ? 'wchg.ordering' : $searchCriteria->getOrderBy();
|
||||||
|
|
||||||
$qb
|
$qb
|
||||||
->orderBy($searchCriteria->getOrderBy(), $searchCriteria->getOrderWay())
|
->orderBy($orderBy, $searchCriteria->getOrderWay())
|
||||||
->setFirstResult($searchCriteria->getOffset() ?? 0)
|
->setFirstResult($searchCriteria->getOffset() ?? 0)
|
||||||
->setMaxResults($searchCriteria->getLimit());
|
->setMaxResults($searchCriteria->getLimit());
|
||||||
|
|
||||||
@@ -75,7 +70,13 @@ final class CustomHtmlGroupQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
{
|
{
|
||||||
return $this->connection
|
return $this->connection
|
||||||
->createQueryBuilder()
|
->createQueryBuilder()
|
||||||
->from($this->dbPrefix . 'ws_customhtml_group', 'wchg');
|
->from($this->dbPrefix . 'ws_customhtml_group', 'wchg')
|
||||||
|
->leftJoin(
|
||||||
|
'wchg',
|
||||||
|
$this->dbPrefix . 'ws_customhtml_group_lang',
|
||||||
|
'wchgl',
|
||||||
|
'wchgl.`id_ws_customhtml_group` = wchg.`id_ws_customhtml_group` AND wchgl.`id_lang` = ' . (int) $this->contextLanguageId
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function applyFilters($qb, SearchCriteriaInterface $searchCriteria): void
|
private function applyFilters($qb, SearchCriteriaInterface $searchCriteria): void
|
||||||
@@ -91,6 +92,12 @@ final class CustomHtmlGroupQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($filterName === 'title') {
|
||||||
|
$qb->andWhere('wchgl.`title` LIKE :title')
|
||||||
|
->setParameter('title', '%' . pSQL($filterValue) . '%');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$qb->andWhere('wchg.`' . $filterName . '` LIKE :' . $filterName)
|
$qb->andWhere('wchg.`' . $filterName . '` LIKE :' . $filterName)
|
||||||
->setParameter($filterName, '%' . pSQL($filterValue) . '%');
|
->setParameter($filterName, '%' . pSQL($filterValue) . '%');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -16,9 +16,51 @@ class CustomHtmlBlock extends ObjectModel
|
|||||||
/** @var string */
|
/** @var string */
|
||||||
public $title = '';
|
public $title = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $type = 'html';
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $content = '';
|
public $content = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $custom_class = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $description = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $extra_description = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $link = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $link_text = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $image = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $alert_type = 'info';
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
public $timeout = 0;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $slider_mode = 'always';
|
||||||
|
|
||||||
|
/** @var float */
|
||||||
|
public $slides_per_view_mobile = 1;
|
||||||
|
|
||||||
|
/** @var float */
|
||||||
|
public $slides_per_view_tablet = 2;
|
||||||
|
|
||||||
|
/** @var float */
|
||||||
|
public $slides_per_view_desktop = 3;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
public $autoplay_delay = 0;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $active = 1;
|
public $active = 1;
|
||||||
|
|
||||||
@@ -35,12 +77,27 @@ class CustomHtmlBlock extends ObjectModel
|
|||||||
public $date_upd;
|
public $date_upd;
|
||||||
|
|
||||||
public static $definition = [
|
public static $definition = [
|
||||||
'table' => 'ws_customhtml',
|
'table' => 'ws_customhtml',
|
||||||
'primary' => 'id_ws_customhtml',
|
'primary' => 'id_ws_customhtml',
|
||||||
'fields' => [
|
'multilang' => true,
|
||||||
|
'fields' => [
|
||||||
'id_ws_customhtml_group' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
'id_ws_customhtml_group' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||||
'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 256],
|
'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 256, 'lang' => true],
|
||||||
'content' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'],
|
'type' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32],
|
||||||
|
'content' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'lang' => true],
|
||||||
|
'custom_class' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 128],
|
||||||
|
'description' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 1024, 'lang' => true],
|
||||||
|
'extra_description' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 1024, 'lang' => true],
|
||||||
|
'link' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 512, 'lang' => true],
|
||||||
|
'link_text' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 128, 'lang' => true],
|
||||||
|
'image' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 255],
|
||||||
|
'alert_type' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 16],
|
||||||
|
'timeout' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => false],
|
||||||
|
'slider_mode' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 16],
|
||||||
|
'slides_per_view_mobile' => ['type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => false],
|
||||||
|
'slides_per_view_tablet' => ['type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => false],
|
||||||
|
'slides_per_view_desktop' => ['type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => false],
|
||||||
|
'autoplay_delay' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => false],
|
||||||
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||||
'show_title' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
'show_title' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||||
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||||
@@ -49,7 +106,21 @@ class CustomHtmlBlock extends ObjectModel
|
|||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function getActiveByGroupIds(array $groupIds): array
|
public static function getBannerImageDir(): string
|
||||||
|
{
|
||||||
|
return _PS_MODULE_DIR_ . 'ws_customhtml/views/img/banners/';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getBannerImageUrl(string $filename): string
|
||||||
|
{
|
||||||
|
if (empty($filename)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return _MODULE_DIR_ . 'ws_customhtml/views/img/banners/' . $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getActiveByGroupIds(array $groupIds, int $idLang): array
|
||||||
{
|
{
|
||||||
$groupIds = array_map('intval', $groupIds);
|
$groupIds = array_map('intval', $groupIds);
|
||||||
|
|
||||||
@@ -58,11 +129,16 @@ class CustomHtmlBlock extends ObjectModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
$result = Db::getInstance()->executeS(
|
$result = Db::getInstance()->executeS(
|
||||||
'SELECT `id_ws_customhtml`, `id_ws_customhtml_group`, `title`, `content`, `active`, `show_title`, `ordering`
|
'SELECT wch.`id_ws_customhtml`, wch.`id_ws_customhtml_group`, wchl.`title`, wch.`type`, wchl.`content`, wch.`custom_class`,
|
||||||
FROM `' . _DB_PREFIX_ . 'ws_customhtml`
|
wchl.`description`, wchl.`extra_description`, wchl.`link`, wchl.`link_text`, wch.`image`, wch.`alert_type`, wch.`timeout`,
|
||||||
WHERE `id_ws_customhtml_group` IN (' . implode(',', $groupIds) . ')
|
wch.`slider_mode`, wch.`slides_per_view_mobile`, wch.`slides_per_view_tablet`, wch.`slides_per_view_desktop`, wch.`autoplay_delay`,
|
||||||
AND `active` = 1
|
wch.`active`, wch.`show_title`, wch.`ordering`
|
||||||
ORDER BY `ordering` ASC'
|
FROM `' . _DB_PREFIX_ . 'ws_customhtml` wch
|
||||||
|
LEFT JOIN `' . _DB_PREFIX_ . 'ws_customhtml_lang` wchl
|
||||||
|
ON wchl.`id_ws_customhtml` = wch.`id_ws_customhtml` AND wchl.`id_lang` = ' . (int) $idLang . '
|
||||||
|
WHERE wch.`id_ws_customhtml_group` IN (' . implode(',', $groupIds) . ')
|
||||||
|
AND wch.`active` = 1
|
||||||
|
ORDER BY wch.`ordering` ASC'
|
||||||
);
|
);
|
||||||
|
|
||||||
$blocksByGroup = [];
|
$blocksByGroup = [];
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Websmid\CustomHtml\Model;
|
||||||
|
|
||||||
|
use ObjectModel;
|
||||||
|
use Db;
|
||||||
|
|
||||||
|
class CustomHtmlFaq extends ObjectModel
|
||||||
|
{
|
||||||
|
/** @var int */
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
public $id_ws_customhtml;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $question = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $answer = '';
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
public $ordering = 0;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $date_add;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $date_upd;
|
||||||
|
|
||||||
|
public static $definition = [
|
||||||
|
'table' => 'ws_customhtml_faq',
|
||||||
|
'primary' => 'id_ws_customhtml_faq',
|
||||||
|
'multilang' => true,
|
||||||
|
'fields' => [
|
||||||
|
'id_ws_customhtml' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||||
|
'question' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 512, 'lang' => true],
|
||||||
|
'answer' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'lang' => true],
|
||||||
|
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||||
|
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||||
|
'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin use — loads every language into lang fields as [id_lang => value] arrays.
|
||||||
|
*/
|
||||||
|
public static function getByBlockId(int $idBlock): array
|
||||||
|
{
|
||||||
|
$ids = Db::getInstance()->executeS(
|
||||||
|
'SELECT `id_ws_customhtml_faq` FROM `' . _DB_PREFIX_ . 'ws_customhtml_faq`
|
||||||
|
WHERE `id_ws_customhtml` = ' . (int) $idBlock . '
|
||||||
|
ORDER BY `ordering` ASC'
|
||||||
|
);
|
||||||
|
|
||||||
|
return array_map(static function (array $row) {
|
||||||
|
$faq = new self((int) $row['id_ws_customhtml_faq']);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id_ws_customhtml_faq' => (int) $faq->id,
|
||||||
|
'question' => $faq->question,
|
||||||
|
'answer' => $faq->answer,
|
||||||
|
'ordering' => (int) $faq->ordering,
|
||||||
|
];
|
||||||
|
}, $ids ?: []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Front-end use — resolves lang fields to plain strings for one language.
|
||||||
|
*/
|
||||||
|
public static function getByBlockIdForLang(int $idBlock, int $idLang): array
|
||||||
|
{
|
||||||
|
$result = Db::getInstance()->executeS(
|
||||||
|
'SELECT wcf.`id_ws_customhtml_faq`, wcfl.`question`, wcfl.`answer`, wcf.`ordering`
|
||||||
|
FROM `' . _DB_PREFIX_ . 'ws_customhtml_faq` wcf
|
||||||
|
LEFT JOIN `' . _DB_PREFIX_ . 'ws_customhtml_faq_lang` wcfl
|
||||||
|
ON wcfl.`id_ws_customhtml_faq` = wcf.`id_ws_customhtml_faq` AND wcfl.`id_lang` = ' . (int) $idLang . '
|
||||||
|
WHERE wcf.`id_ws_customhtml` = ' . (int) $idBlock . '
|
||||||
|
ORDER BY wcf.`ordering` ASC'
|
||||||
|
);
|
||||||
|
|
||||||
|
return $result ?: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function deleteByBlockId(int $idBlock): void
|
||||||
|
{
|
||||||
|
Db::getInstance()->delete('ws_customhtml_faq', '`id_ws_customhtml` = ' . (int) $idBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,12 @@ class CustomHtmlGroup extends ObjectModel
|
|||||||
/** @var string */
|
/** @var string */
|
||||||
public $title = '';
|
public $title = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $custom_class = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $default_block_class = '';
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $active = 1;
|
public $active = 1;
|
||||||
|
|
||||||
@@ -29,11 +35,14 @@ class CustomHtmlGroup extends ObjectModel
|
|||||||
public $date_upd;
|
public $date_upd;
|
||||||
|
|
||||||
public static $definition = [
|
public static $definition = [
|
||||||
'table' => 'ws_customhtml_group',
|
'table' => 'ws_customhtml_group',
|
||||||
'primary' => 'id_ws_customhtml_group',
|
'primary' => 'id_ws_customhtml_group',
|
||||||
'fields' => [
|
'multilang' => true,
|
||||||
|
'fields' => [
|
||||||
'hook_name' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64],
|
'hook_name' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64],
|
||||||
'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 256],
|
'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 256, 'lang' => true],
|
||||||
|
'custom_class' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 128],
|
||||||
|
'default_block_class' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 128],
|
||||||
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||||
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||||
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||||
@@ -44,7 +53,7 @@ class CustomHtmlGroup extends ObjectModel
|
|||||||
public static function getActiveByHookName(string $hookName): array
|
public static function getActiveByHookName(string $hookName): array
|
||||||
{
|
{
|
||||||
$result = Db::getInstance()->executeS(
|
$result = Db::getInstance()->executeS(
|
||||||
'SELECT `id_ws_customhtml_group`, `title`, `active`, `ordering`
|
'SELECT `id_ws_customhtml_group`, `active`, `custom_class`, `default_block_class`, `ordering`
|
||||||
FROM `' . _DB_PREFIX_ . 'ws_customhtml_group`
|
FROM `' . _DB_PREFIX_ . 'ws_customhtml_group`
|
||||||
WHERE `hook_name` = \'' . pSQL($hookName) . '\'
|
WHERE `hook_name` = \'' . pSQL($hookName) . '\'
|
||||||
AND `active` = 1
|
AND `active` = 1
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Websmid\CustomHtml\Model;
|
||||||
|
|
||||||
|
use ObjectModel;
|
||||||
|
use Db;
|
||||||
|
|
||||||
|
class CustomHtmlSlide extends ObjectModel
|
||||||
|
{
|
||||||
|
/** @var int */
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
public $id_ws_customhtml;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $title = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $description = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $extra_description = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $link = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $link_text = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $image = '';
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
public $ordering = 0;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $date_add;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $date_upd;
|
||||||
|
|
||||||
|
public static $definition = [
|
||||||
|
'table' => 'ws_customhtml_slide',
|
||||||
|
'primary' => 'id_ws_customhtml_slide',
|
||||||
|
'multilang' => true,
|
||||||
|
'fields' => [
|
||||||
|
'id_ws_customhtml' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||||
|
'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 256, 'lang' => true],
|
||||||
|
'description' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 1024, 'lang' => true],
|
||||||
|
'extra_description' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 1024, 'lang' => true],
|
||||||
|
'link' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 512, 'lang' => true],
|
||||||
|
'link_text' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 128, 'lang' => true],
|
||||||
|
'image' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 255],
|
||||||
|
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||||
|
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||||
|
'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin use — loads every language into lang fields as [id_lang => value] arrays.
|
||||||
|
*/
|
||||||
|
public static function getByBlockId(int $idBlock): array
|
||||||
|
{
|
||||||
|
$ids = Db::getInstance()->executeS(
|
||||||
|
'SELECT `id_ws_customhtml_slide` FROM `' . _DB_PREFIX_ . 'ws_customhtml_slide`
|
||||||
|
WHERE `id_ws_customhtml` = ' . (int) $idBlock . '
|
||||||
|
ORDER BY `ordering` ASC'
|
||||||
|
);
|
||||||
|
|
||||||
|
return array_map(static function (array $row) {
|
||||||
|
$slide = new self((int) $row['id_ws_customhtml_slide']);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id_ws_customhtml_slide' => (int) $slide->id,
|
||||||
|
'title' => $slide->title,
|
||||||
|
'description' => $slide->description,
|
||||||
|
'extra_description' => $slide->extra_description,
|
||||||
|
'link' => $slide->link,
|
||||||
|
'link_text' => $slide->link_text,
|
||||||
|
'image' => $slide->image,
|
||||||
|
'ordering' => (int) $slide->ordering,
|
||||||
|
];
|
||||||
|
}, $ids ?: []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Front-end use — resolves lang fields to plain strings for one language.
|
||||||
|
*/
|
||||||
|
public static function getByBlockIdForLang(int $idBlock, int $idLang): array
|
||||||
|
{
|
||||||
|
$result = Db::getInstance()->executeS(
|
||||||
|
'SELECT wcs.`id_ws_customhtml_slide`, wcsl.`title`, wcsl.`description`, wcsl.`extra_description`,
|
||||||
|
wcsl.`link`, wcsl.`link_text`, wcs.`image`, wcs.`ordering`
|
||||||
|
FROM `' . _DB_PREFIX_ . 'ws_customhtml_slide` wcs
|
||||||
|
LEFT JOIN `' . _DB_PREFIX_ . 'ws_customhtml_slide_lang` wcsl
|
||||||
|
ON wcsl.`id_ws_customhtml_slide` = wcs.`id_ws_customhtml_slide` AND wcsl.`id_lang` = ' . (int) $idLang . '
|
||||||
|
WHERE wcs.`id_ws_customhtml` = ' . (int) $idBlock . '
|
||||||
|
ORDER BY wcs.`ordering` ASC'
|
||||||
|
);
|
||||||
|
|
||||||
|
return $result ?: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function deleteByBlockId(int $idBlock): void
|
||||||
|
{
|
||||||
|
Db::getInstance()->delete('ws_customhtml_slide', '`id_ws_customhtml` = ' . (int) $idBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -3,6 +3,9 @@
|
|||||||
namespace Websmid\CustomHtml\Module;
|
namespace Websmid\CustomHtml\Module;
|
||||||
|
|
||||||
use Websmid\CustomHtml\Config\Config;
|
use Websmid\CustomHtml\Config\Config;
|
||||||
|
use PrestaShop\PrestaShop\Adapter\SymfonyContainer;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Data\GridData;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Record\RecordCollection;
|
||||||
use Tools;
|
use Tools;
|
||||||
|
|
||||||
trait AdminHooks
|
trait AdminHooks
|
||||||
@@ -19,12 +22,26 @@ trait AdminHooks
|
|||||||
|
|
||||||
public function hookActionAdminControllerSetMedia(): void
|
public function hookActionAdminControllerSetMedia(): void
|
||||||
{
|
{
|
||||||
$controllerName = $this->context->controller->controller_name ?? '';
|
$request = SymfonyContainer::getInstance()->get('request_stack')->getCurrentRequest();
|
||||||
|
$routeName = $request ? (string) $request->attributes->get('_route') : '';
|
||||||
|
|
||||||
if (!in_array($controllerName, Config::ADMIN_CONTROLLERS, true)) {
|
if (0 !== strpos($routeName, 'customhtml')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->context->controller->addCSS($this->getPathUri() . 'views/css/admin/grid.css');
|
$this->context->controller->addCSS($this->getPathUri() . 'views/css/admin/grid.css');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hookActionCustomhtmlblockGridDataModifier(array $params): void
|
||||||
|
{
|
||||||
|
$gridData = $params['data'];
|
||||||
|
|
||||||
|
$records = array_map(static function (array $row) {
|
||||||
|
$row['type'] = Config::BLOCK_TYPES[$row['type']] ?? $row['type'];
|
||||||
|
|
||||||
|
return $row;
|
||||||
|
}, $gridData->getRecords()->all());
|
||||||
|
|
||||||
|
$params['data'] = new GridData(new RecordCollection($records), $gridData->getRecordsTotal(), $gridData->getQuery());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+119
-3
@@ -2,12 +2,28 @@
|
|||||||
|
|
||||||
namespace Websmid\CustomHtml\Module;
|
namespace Websmid\CustomHtml\Module;
|
||||||
|
|
||||||
|
use Websmid\CustomHtml\Config\Config;
|
||||||
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
||||||
|
use Websmid\CustomHtml\Model\CustomHtmlFaq;
|
||||||
use Websmid\CustomHtml\Model\CustomHtmlGroup;
|
use Websmid\CustomHtml\Model\CustomHtmlGroup;
|
||||||
|
use Websmid\CustomHtml\Model\CustomHtmlSlide;
|
||||||
use Context;
|
use Context;
|
||||||
|
|
||||||
trait DisplayHooks
|
trait DisplayHooks
|
||||||
{
|
{
|
||||||
|
public function hookActionFrontControllerSetMedia(): void
|
||||||
|
{
|
||||||
|
$this->context->controller->registerStylesheet(
|
||||||
|
'ws_customhtml_front',
|
||||||
|
'/modules/' . $this->name . '/views/css/front/customhtml.css'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->context->controller->registerJavascript(
|
||||||
|
'ws_customhtml_front',
|
||||||
|
'/modules/' . $this->name . '/views/js/front/customhtml.js'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function renderWidget($hookName = null, array $configuration = [])
|
public function renderWidget($hookName = null, array $configuration = [])
|
||||||
{
|
{
|
||||||
if (empty($hookName)) {
|
if (empty($hookName)) {
|
||||||
@@ -33,7 +49,8 @@ trait DisplayHooks
|
|||||||
|
|
||||||
public function getWidgetVariables($hookName = null, array $configuration = [])
|
public function getWidgetVariables($hookName = null, array $configuration = [])
|
||||||
{
|
{
|
||||||
$groupList = $this->loadActiveGroupsWithBlocks((string) $hookName);
|
$idLang = (int) Context::getContext()->language->id;
|
||||||
|
$groupList = $this->loadActiveGroupsWithBlocks((string) $hookName, $idLang);
|
||||||
|
|
||||||
if (empty($groupList)) {
|
if (empty($groupList)) {
|
||||||
return [];
|
return [];
|
||||||
@@ -45,7 +62,7 @@ trait DisplayHooks
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadActiveGroupsWithBlocks(string $hookName): array
|
private function loadActiveGroupsWithBlocks(string $hookName, int $idLang): array
|
||||||
{
|
{
|
||||||
$groups = CustomHtmlGroup::getActiveByHookName($hookName);
|
$groups = CustomHtmlGroup::getActiveByHookName($hookName);
|
||||||
|
|
||||||
@@ -53,7 +70,10 @@ trait DisplayHooks
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$blocksByGroup = CustomHtmlBlock::getActiveByGroupIds(array_column($groups, 'id_ws_customhtml_group'));
|
$blocksByGroup = CustomHtmlBlock::getActiveByGroupIds(array_column($groups, 'id_ws_customhtml_group'), $idLang);
|
||||||
|
$blocksByGroup = $this->attachFaqsToBlocks($blocksByGroup, $idLang);
|
||||||
|
$blocksByGroup = $this->attachImageUrls($blocksByGroup);
|
||||||
|
$blocksByGroup = $this->attachSlidesToBlocks($blocksByGroup, $idLang);
|
||||||
|
|
||||||
$groups = array_map(static function (array $group) use ($blocksByGroup) {
|
$groups = array_map(static function (array $group) use ($blocksByGroup) {
|
||||||
$group['blocks'] = $blocksByGroup[(int) $group['id_ws_customhtml_group']] ?? [];
|
$group['blocks'] = $blocksByGroup[(int) $group['id_ws_customhtml_group']] ?? [];
|
||||||
@@ -65,4 +85,100 @@ trait DisplayHooks
|
|||||||
return !empty($group['blocks']);
|
return !empty($group['blocks']);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function attachFaqsToBlocks(array $blocksByGroup, int $idLang): array
|
||||||
|
{
|
||||||
|
return array_map(static function (array $blocks) use ($idLang) {
|
||||||
|
return array_map(static function (array $block) use ($idLang) {
|
||||||
|
if ($block['type'] === 'faq') {
|
||||||
|
$block['faqs'] = CustomHtmlFaq::getByBlockIdForLang((int) $block['id_ws_customhtml'], $idLang);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $block;
|
||||||
|
}, $blocks);
|
||||||
|
}, $blocksByGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function attachImageUrls(array $blocksByGroup): array
|
||||||
|
{
|
||||||
|
return array_map(static function (array $blocks) {
|
||||||
|
return array_map(static function (array $block) {
|
||||||
|
if (in_array($block['type'], ['banner', 'usp'], true)) {
|
||||||
|
$block['image_url'] = CustomHtmlBlock::getBannerImageUrl($block['image']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $block;
|
||||||
|
}, $blocks);
|
||||||
|
}, $blocksByGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function attachSlidesToBlocks(array $blocksByGroup, int $idLang): array
|
||||||
|
{
|
||||||
|
return array_map(function (array $blocks) use ($idLang) {
|
||||||
|
return array_map(function (array $block) use ($idLang) {
|
||||||
|
if ($block['type'] === 'slider') {
|
||||||
|
$block['slides'] = $this->loadSlidesForBlock((int) $block['id_ws_customhtml'], $idLang);
|
||||||
|
$block['slider_config'] = $this->buildSliderConfig($block);
|
||||||
|
$block['slider_desktop_column_width'] = $this->buildSliderDesktopColumnWidth($block);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $block;
|
||||||
|
}, $blocks);
|
||||||
|
}, $blocksByGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadSlidesForBlock(int $idBlock, int $idLang): array
|
||||||
|
{
|
||||||
|
return array_map(static function (array $slide) {
|
||||||
|
$slide['image_url'] = CustomHtmlBlock::getBannerImageUrl($slide['image']);
|
||||||
|
$slide['show_title'] = true;
|
||||||
|
|
||||||
|
return $slide;
|
||||||
|
}, CustomHtmlSlide::getByBlockIdForLang($idBlock, $idLang));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildSliderConfig(array $block): string
|
||||||
|
{
|
||||||
|
$config = [
|
||||||
|
'slidesPerView' => (float) $block['slides_per_view_mobile'],
|
||||||
|
'spaceBetween' => 16,
|
||||||
|
'speed' => 500,
|
||||||
|
'watchOverflow' => true,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($block['slider_mode'] === 'responsive') {
|
||||||
|
$config['breakpoints'] = [
|
||||||
|
Config::SLIDER_RESPONSIVE_BREAKPOINT => ['slidesPerView' => (float) $block['slides_per_view_tablet']],
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$config['breakpoints'] = [
|
||||||
|
768 => ['slidesPerView' => (float) $block['slides_per_view_tablet']],
|
||||||
|
];
|
||||||
|
|
||||||
|
if ((float) $block['slides_per_view_desktop'] > 0) {
|
||||||
|
$config['breakpoints'][992] = ['slidesPerView' => (float) $block['slides_per_view_desktop']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int) $block['autoplay_delay'] > 0) {
|
||||||
|
$config['loop'] = true;
|
||||||
|
$config['autoplay'] = [
|
||||||
|
'delay' => (int) $block['autoplay_delay'] * 1000,
|
||||||
|
'disableOnInteraction' => false,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_encode($config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildSliderDesktopColumnWidth(array $block): ?string
|
||||||
|
{
|
||||||
|
if ((float) $block['slides_per_view_desktop'] <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$columns = max(1, (int) round((float) $block['slides_per_view_desktop']));
|
||||||
|
|
||||||
|
return round(100 / $columns, 4) . '%';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+111
-3
@@ -3,7 +3,9 @@
|
|||||||
namespace Websmid\CustomHtml\Module;
|
namespace Websmid\CustomHtml\Module;
|
||||||
|
|
||||||
use Websmid\CustomHtml\Config\Config;
|
use Websmid\CustomHtml\Config\Config;
|
||||||
|
use Context;
|
||||||
use Db;
|
use Db;
|
||||||
|
use Hook;
|
||||||
use Language;
|
use Language;
|
||||||
use Tab;
|
use Tab;
|
||||||
|
|
||||||
@@ -31,6 +33,11 @@ trait Install
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$this->registerGroupHooks()) {
|
||||||
|
error_log('[ws_customhtml] registerGroupHooks() failed');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +49,8 @@ trait Install
|
|||||||
CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml_group (
|
CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml_group (
|
||||||
`id_ws_customhtml_group` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
`id_ws_customhtml_group` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
`hook_name` VARCHAR(64) NOT NULL,
|
`hook_name` VARCHAR(64) NOT NULL,
|
||||||
`title` VARCHAR(256) NOT NULL DEFAULT \'\',
|
`custom_class` VARCHAR(128) NOT NULL DEFAULT \'\',
|
||||||
|
`default_block_class` VARCHAR(128) NOT NULL DEFAULT \'\',
|
||||||
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||||
`ordering` INT(11) NOT NULL DEFAULT 0,
|
`ordering` INT(11) NOT NULL DEFAULT 0,
|
||||||
`date_add` DATETIME NOT NULL,
|
`date_add` DATETIME NOT NULL,
|
||||||
@@ -50,12 +58,29 @@ trait Install
|
|||||||
);
|
);
|
||||||
';
|
';
|
||||||
|
|
||||||
|
$sqlToExec[] = '
|
||||||
|
CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml_group_lang (
|
||||||
|
`id_ws_customhtml_group` INT(11) NOT NULL,
|
||||||
|
`id_lang` INT(11) NOT NULL,
|
||||||
|
`title` VARCHAR(256) NOT NULL DEFAULT \'\',
|
||||||
|
PRIMARY KEY (`id_ws_customhtml_group`, `id_lang`)
|
||||||
|
);
|
||||||
|
';
|
||||||
|
|
||||||
$sqlToExec[] = '
|
$sqlToExec[] = '
|
||||||
CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml (
|
CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml (
|
||||||
`id_ws_customhtml` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
`id_ws_customhtml` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
`id_ws_customhtml_group` INT(11) NOT NULL,
|
`id_ws_customhtml_group` INT(11) NOT NULL,
|
||||||
`title` VARCHAR(256) NOT NULL DEFAULT \'\',
|
`type` VARCHAR(32) NOT NULL DEFAULT \'html\',
|
||||||
`content` LONGTEXT,
|
`custom_class` VARCHAR(128) NOT NULL DEFAULT \'\',
|
||||||
|
`image` VARCHAR(255) NOT NULL DEFAULT \'\',
|
||||||
|
`alert_type` VARCHAR(16) NOT NULL DEFAULT \'info\',
|
||||||
|
`timeout` INT(11) NOT NULL DEFAULT 0,
|
||||||
|
`slider_mode` VARCHAR(16) NOT NULL DEFAULT \'always\',
|
||||||
|
`slides_per_view_mobile` DECIMAL(4,2) NOT NULL DEFAULT 1,
|
||||||
|
`slides_per_view_tablet` DECIMAL(4,2) NOT NULL DEFAULT 2,
|
||||||
|
`slides_per_view_desktop` DECIMAL(4,2) NOT NULL DEFAULT 3,
|
||||||
|
`autoplay_delay` INT(11) NOT NULL DEFAULT 0,
|
||||||
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||||
`show_title` TINYINT(1) NOT NULL DEFAULT 0,
|
`show_title` TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
`ordering` INT(11) NOT NULL DEFAULT 0,
|
`ordering` INT(11) NOT NULL DEFAULT 0,
|
||||||
@@ -65,6 +90,66 @@ trait Install
|
|||||||
);
|
);
|
||||||
';
|
';
|
||||||
|
|
||||||
|
$sqlToExec[] = '
|
||||||
|
CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml_lang (
|
||||||
|
`id_ws_customhtml` INT(11) NOT NULL,
|
||||||
|
`id_lang` INT(11) NOT NULL,
|
||||||
|
`title` VARCHAR(256) NOT NULL DEFAULT \'\',
|
||||||
|
`content` LONGTEXT,
|
||||||
|
`description` TEXT,
|
||||||
|
`extra_description` TEXT,
|
||||||
|
`link` VARCHAR(512) NOT NULL DEFAULT \'\',
|
||||||
|
`link_text` VARCHAR(128) NOT NULL DEFAULT \'\',
|
||||||
|
PRIMARY KEY (`id_ws_customhtml`, `id_lang`)
|
||||||
|
);
|
||||||
|
';
|
||||||
|
|
||||||
|
$sqlToExec[] = '
|
||||||
|
CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml_faq (
|
||||||
|
`id_ws_customhtml_faq` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`id_ws_customhtml` INT(11) NOT NULL,
|
||||||
|
`ordering` INT(11) NOT NULL DEFAULT 0,
|
||||||
|
`date_add` DATETIME NOT NULL,
|
||||||
|
`date_upd` DATETIME NOT NULL,
|
||||||
|
KEY `id_ws_customhtml` (`id_ws_customhtml`)
|
||||||
|
);
|
||||||
|
';
|
||||||
|
|
||||||
|
$sqlToExec[] = '
|
||||||
|
CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml_faq_lang (
|
||||||
|
`id_ws_customhtml_faq` INT(11) NOT NULL,
|
||||||
|
`id_lang` INT(11) NOT NULL,
|
||||||
|
`question` VARCHAR(512) NOT NULL DEFAULT \'\',
|
||||||
|
`answer` TEXT,
|
||||||
|
PRIMARY KEY (`id_ws_customhtml_faq`, `id_lang`)
|
||||||
|
);
|
||||||
|
';
|
||||||
|
|
||||||
|
$sqlToExec[] = '
|
||||||
|
CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml_slide (
|
||||||
|
`id_ws_customhtml_slide` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`id_ws_customhtml` INT(11) NOT NULL,
|
||||||
|
`image` VARCHAR(255) NOT NULL DEFAULT \'\',
|
||||||
|
`ordering` INT(11) NOT NULL DEFAULT 0,
|
||||||
|
`date_add` DATETIME NOT NULL,
|
||||||
|
`date_upd` DATETIME NOT NULL,
|
||||||
|
KEY `id_ws_customhtml` (`id_ws_customhtml`)
|
||||||
|
);
|
||||||
|
';
|
||||||
|
|
||||||
|
$sqlToExec[] = '
|
||||||
|
CREATE TABLE IF NOT EXISTS ' . _DB_PREFIX_ . 'ws_customhtml_slide_lang (
|
||||||
|
`id_ws_customhtml_slide` INT(11) NOT NULL,
|
||||||
|
`id_lang` INT(11) NOT NULL,
|
||||||
|
`title` VARCHAR(256) NOT NULL DEFAULT \'\',
|
||||||
|
`description` TEXT,
|
||||||
|
`extra_description` TEXT,
|
||||||
|
`link` VARCHAR(512) NOT NULL DEFAULT \'\',
|
||||||
|
`link_text` VARCHAR(128) NOT NULL DEFAULT \'\',
|
||||||
|
PRIMARY KEY (`id_ws_customhtml_slide`, `id_lang`)
|
||||||
|
);
|
||||||
|
';
|
||||||
|
|
||||||
foreach ($sqlToExec as $sqlBlock) {
|
foreach ($sqlToExec as $sqlBlock) {
|
||||||
Db::getInstance()->execute(trim($sqlBlock));
|
Db::getInstance()->execute(trim($sqlBlock));
|
||||||
}
|
}
|
||||||
@@ -83,6 +168,29 @@ trait Install
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function registerGroupHooks(): bool
|
||||||
|
{
|
||||||
|
$hookNames = Db::getInstance()->executeS(
|
||||||
|
'SELECT DISTINCT `hook_name` FROM `' . _DB_PREFIX_ . 'ws_customhtml_group`'
|
||||||
|
);
|
||||||
|
|
||||||
|
$idShop = (int) Context::getContext()->shop->id;
|
||||||
|
|
||||||
|
foreach ($hookNames as $row) {
|
||||||
|
$hookName = $row['hook_name'];
|
||||||
|
|
||||||
|
if (Hook::isModuleRegisteredOnHook($this, $hookName, $idShop)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->registerHook($hookName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private function registerTabs(array $moduleTabs): bool
|
private function registerTabs(array $moduleTabs): bool
|
||||||
{
|
{
|
||||||
$languages = Language::getLanguages(false);
|
$languages = Language::getLanguages(false);
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file original="Modules.Wscustomhtml.Admin.xlf" source-language="en" target-language="nl" datatype="plaintext">
|
||||||
|
<body>
|
||||||
|
<trans-unit id="512923e3b931df3400cc06287e7541cc" approved="yes">
|
||||||
|
<source>Custom HTML</source>
|
||||||
|
<target state="final">Aangepaste HTML</target>
|
||||||
|
<note>File: ws_customhtml.php [Line: 39]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="7831af914461a744912d0579b8bb9d1a" approved="yes">
|
||||||
|
<source>Create and manage custom HTML blocks for frontend hooks.</source>
|
||||||
|
<target state="final">Aangepaste HTML-blokken maken en beheren voor frontend hooks.</target>
|
||||||
|
<note>File: ws_customhtml.php [Line: 40]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="b78a3223503896721cca1303f776159b" approved="yes">
|
||||||
|
<source>Title</source>
|
||||||
|
<target state="final">Titel</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlGroupType.php [Line: 28]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="26f548bcbdeea5047396db341a10a2bf" approved="yes">
|
||||||
|
<source>Hook name</source>
|
||||||
|
<target state="final">Hooknaam</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlGroupType.php [Line: 33]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="843575e3d0942a474aed722856631ec1" approved="yes">
|
||||||
|
<source>Custom group classes</source>
|
||||||
|
<target state="final">Aangepaste groepsklassen</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlGroupType.php [Line: 37]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="c9339c0b1a199af41f690392077119af" approved="yes">
|
||||||
|
<source>Default block class</source>
|
||||||
|
<target state="final">Standaard blokklasse</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlGroupType.php [Line: 42]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="dee82074a8fdd944350a8ed6ef7000ba" approved="yes">
|
||||||
|
<source>Applied to every block in this group automatically, in addition to that block's own custom classes. Useful when several blocks need the same column layout.</source>
|
||||||
|
<target state="final">Wordt automatisch toegepast op elk blok in deze groep, naast de eigen aangepaste klassen van dat blok. Handig wanneer meerdere blokken dezelfde kolomindeling nodig hebben.</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlGroupType.php [Line: 45]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="4d3d769b812b6faa6b76e1a8abaece2d" approved="yes">
|
||||||
|
<source>Active</source>
|
||||||
|
<target state="final">Actief</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlGroupType.php [Line: 48]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="3c889850381b0603721d568824ecfd18" approved="yes">
|
||||||
|
<source>Custom HTML Groups</source>
|
||||||
|
<target state="final">Aangepaste HTML-groepen</target>
|
||||||
|
<note>File: src/Grid/Definition/Factory/CustomHtmlGroupGridDefinitionFactory.php [Line: 40]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="b9b371458ab7c314f88b81c553f6ce51" approved="yes">
|
||||||
|
<source>Hook</source>
|
||||||
|
<target state="final">Hook</target>
|
||||||
|
<note>File: src/Grid/Definition/Factory/CustomHtmlGroupGridDefinitionFactory.php [Line: 73]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="04c4f9f595c4f21d1de65eb07056c15a" approved="yes">
|
||||||
|
<source>Blocks</source>
|
||||||
|
<target state="final">Blokken</target>
|
||||||
|
<note>File: src/Grid/Definition/Factory/CustomHtmlGroupGridDefinitionFactory.php [Line: 78]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="195a8106bcb998b48a86acb2fee032c5" approved="yes">
|
||||||
|
<source>View blocks</source>
|
||||||
|
<target state="final">Blokken bekijken</target>
|
||||||
|
<note>File: src/Grid/Definition/Factory/CustomHtmlGroupGridDefinitionFactory.php [Line: 156]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="2ff8071bcd15a31f9a743f1b06d0d00f" approved="yes">
|
||||||
|
<source>Add block</source>
|
||||||
|
<target state="final">Blok toevoegen</target>
|
||||||
|
<note>File: src/Grid/Definition/Factory/CustomHtmlGroupGridDefinitionFactory.php [Line: 166]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="93ee75bea0afaff1edf1444b1f8d4757" approved="yes">
|
||||||
|
<source>Custom HTML Blocks</source>
|
||||||
|
<target state="final">Aangepaste HTML-blokken</target>
|
||||||
|
<note>File: src/Grid/Definition/Factory/CustomHtmlBlockGridDefinitionFactory.php [Line: 41]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="03937134cedab9078be39a77ee3a48a0" approved="yes">
|
||||||
|
<source>Group</source>
|
||||||
|
<target state="final">Groep</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 41]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="a1fa27779242b4902f7ae3bdd5c6d508" approved="yes">
|
||||||
|
<source>Type</source>
|
||||||
|
<target state="final">Type</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 47]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="52f5e0bc3859bc5f5e25130b6c7e8881" approved="yes">
|
||||||
|
<source>Position</source>
|
||||||
|
<target state="final">Positie</target>
|
||||||
|
<note>File: src/Grid/Definition/Factory/CustomHtmlBlockGridDefinitionFactory.php [Line: 89]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="7c060faccd05262f4901c16573f645a9" approved="yes">
|
||||||
|
<source>Unable to find the group.</source>
|
||||||
|
<target state="final">Kan de groep niet vinden.</target>
|
||||||
|
<note>File: src/Controller/CustomHtmlGroupController.php [Line: 98]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="d738152dd177b4600836d2db542e8845" approved="yes">
|
||||||
|
<source>Unable to find the block.</source>
|
||||||
|
<target state="final">Kan het blok niet vinden.</target>
|
||||||
|
<note>File: src/Controller/CustomHtmlBlockController.php [Line: 125]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="b5a812dff3c33b63cf77f0ce007da42e" approved="yes">
|
||||||
|
<source>Block type</source>
|
||||||
|
<target state="final">Bloktype</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 47]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="507b7246f245b8935c5aafd81e80c4ee" approved="yes">
|
||||||
|
<source>Show title</source>
|
||||||
|
<target state="final">Titel tonen</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 59]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="f15c1cae7882448b3fb0404682e17e61" approved="yes">
|
||||||
|
<source>Content</source>
|
||||||
|
<target state="final">Inhoud</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 65]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="be53a0541a6d36f6ecb879fa2c584b08" approved="yes">
|
||||||
|
<source>Image</source>
|
||||||
|
<target state="final">Afbeelding</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 71]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="d60bc7c265eb450473afbd22ececda09" approved="yes">
|
||||||
|
<source>Slider mode</source>
|
||||||
|
<target state="final">Slidermodus</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 92]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="9e2352975b97b9b49e97dcd80788ed88" approved="yes">
|
||||||
|
<source>"Mobile only": slider only on mobile, a static grid shows instead from tablet up.</source>
|
||||||
|
<target state="final">"Alleen mobiel": slider alleen op mobiel, vanaf tablet wordt in plaats daarvan een statisch raster getoond.</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 95]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="0cffdd608d41a4c9c7bac7cf621ca5b9" approved="yes">
|
||||||
|
<source>Slides visible on mobile</source>
|
||||||
|
<target state="final">Zichtbare slides op mobiel</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 99]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="35bf3a5e2797e56b2d06b18acaae41f9" approved="yes">
|
||||||
|
<source>Slides visible on tablet</source>
|
||||||
|
<target state="final">Zichtbare slides op tablet</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 106]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="40d77e75964dd04ea925f34300dd8b48" approved="yes">
|
||||||
|
<source>Slides visible on desktop</source>
|
||||||
|
<target state="final">Zichtbare slides op desktop</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 113]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="06b9281e396db002010bde1de57262eb" approved="yes">
|
||||||
|
<source>Auto</source>
|
||||||
|
<target state="final">Automatisch</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 116]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="921048c199ee33279927fc77d2dc213a" approved="yes">
|
||||||
|
<source>In "Mobile only" mode this is rounded to the nearest whole number of columns. Leave empty for an equal-width column.</source>
|
||||||
|
<target state="final">In de modus "Alleen mobiel" wordt dit afgerond naar het dichtstbijzijnde hele aantal kolommen. Laat leeg voor een kolom met gelijke breedte.</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 117]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="db03b62817b3b2f4657b679c13bb5b28" approved="yes">
|
||||||
|
<source>Autoplay delay (seconds)</source>
|
||||||
|
<target state="final">Vertraging automatisch afspelen (seconden)</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 121]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="ae8c3292c47fef302c93202badd63109" approved="yes">
|
||||||
|
<source>0 means the slider never auto-advances; visitors can still swipe or use the arrows.</source>
|
||||||
|
<target state="final">0 betekent dat de slider nooit automatisch doorschuift; bezoekers kunnen nog wel swipen of de pijlen gebruiken.</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 124]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="d479cd75faccc438f93b8b6414a2a329" approved="yes">
|
||||||
|
<source>Alert style</source>
|
||||||
|
<target state="final">Waarschuwingsstijl</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 128]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="4527eae2e84aed7a238504cbbf509272" approved="yes">
|
||||||
|
<source>Auto-dismiss after (seconds)</source>
|
||||||
|
<target state="final">Automatisch sluiten na (seconden)</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 134]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="e59eb2e617eb720ae30bbf71010a7a97" approved="yes">
|
||||||
|
<source>0 means the alert never auto-dismisses; visitors can still close it manually.</source>
|
||||||
|
<target state="final">0 betekent dat de melding nooit automatisch sluit; bezoekers kunnen deze nog wel handmatig sluiten.</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 137]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="b5a7adde1af5c87d7fd797b6245c2a39" approved="yes">
|
||||||
|
<source>Description</source>
|
||||||
|
<target state="final">Beschrijving</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 142]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="7cc0fd746c5cec9842dd8d5251ee2352" approved="yes">
|
||||||
|
<source>Extra description</source>
|
||||||
|
<target state="final">Extra beschrijving</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 149]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="5e4e1bd6f922fed062b62c446ca34f84" approved="yes">
|
||||||
|
<source>Link URL</source>
|
||||||
|
<target state="final">Link-URL</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 156]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="63a11faa3a692d4e00fa8e03bbe8a0d6" approved="yes">
|
||||||
|
<source>Link text</source>
|
||||||
|
<target state="final">Linktekst</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 163]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="c15a6ec85c9e2dfc65fde2c60b592564" approved="yes">
|
||||||
|
<source>Custom classes</source>
|
||||||
|
<target state="final">Aangepaste klassen</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlBlockType.php [Line: 171]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="a97ea56b0e00b2379736ae60869ff66a" approved="yes">
|
||||||
|
<source>Question</source>
|
||||||
|
<target state="final">Vraag</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlFaqType.php [Line: 24]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="3751695c17afed4055a7a5ad5d46f6f5" approved="yes">
|
||||||
|
<source>Answer</source>
|
||||||
|
<target state="final">Antwoord</target>
|
||||||
|
<note>File: src/Form/Type/CustomHtmlFaqType.php [Line: 28]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="c28fc5d6c4a0a5ee47e06d56bab36dec" approved="yes">
|
||||||
|
<source>Custom HTML Block</source>
|
||||||
|
<target state="final">Aangepast HTML-blok</target>
|
||||||
|
<note>File: views/templates/admin/form/blocks/block_form.html.twig [Line: 26]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="73be1b885def51a0ff0d8905365b3eeb" approved="yes">
|
||||||
|
<source>Current image</source>
|
||||||
|
<target state="final">Huidige afbeelding</target>
|
||||||
|
<note>File: views/templates/admin/form/blocks/block_form.html.twig [Line: 42]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="4dfb7691cbfd8ee3a0f42018bcb2db65" approved="yes">
|
||||||
|
<source>FAQ items</source>
|
||||||
|
<target state="final">FAQ-items</target>
|
||||||
|
<note>File: views/templates/admin/form/blocks/block_form.html.twig [Line: 50]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="a4156d4998aa5183e106a57342f7315a" approved="yes">
|
||||||
|
<source>Add FAQ item</source>
|
||||||
|
<target state="final">FAQ-item toevoegen</target>
|
||||||
|
<note>File: views/templates/admin/form/blocks/block_form.html.twig [Line: 70]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="a8d90ed8f17c347c8d46e0ef22c85ecb" approved="yes">
|
||||||
|
<source>Slides</source>
|
||||||
|
<target state="final">Slides</target>
|
||||||
|
<note>File: views/templates/admin/form/blocks/block_form.html.twig [Line: 76]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="056f53405bf3cf4bde3731c26d725365" approved="yes">
|
||||||
|
<source>Add slide</source>
|
||||||
|
<target state="final">Slide toevoegen</target>
|
||||||
|
<note>File: views/templates/admin/form/blocks/block_form.html.twig [Line: 96]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="5ff997cff41cb8eeb86e6e484233a8af" approved="yes">
|
||||||
|
<source>The group that this block belongs to applies the classes "%s%" to every block. Edit the group to change this - it is stored under the "Default block class" input.</source>
|
||||||
|
<target state="final">De groep waartoe dit blok behoort past de klassen "%s%" toe op elk blok. Bewerk de groep om dit te wijzigen - dit wordt opgeslagen onder het veld "Standaard blokklasse".</target>
|
||||||
|
<note>File: views/templates/admin/form/blocks/block_form.html.twig [Line: 118]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="5973aee626e71dba35de5485ccde9481" approved="yes">
|
||||||
|
<source>Custom HTML Group</source>
|
||||||
|
<target state="final">Aangepaste HTML-groep</target>
|
||||||
|
<note>File: views/templates/admin/form/blocks/group_form.html.twig [Line: 9]</note>
|
||||||
|
</trans-unit>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file original="Modules.Wscustomhtml.Shop.xlf" source-language="en" target-language="nl" datatype="plaintext">
|
||||||
|
<body>
|
||||||
|
<trans-unit id="d59048f21fd887ad520398ce677be586" approved="yes">
|
||||||
|
<source>Learn more</source>
|
||||||
|
<target state="final">Meer informatie</target>
|
||||||
|
<note>File: views/templates/hook/_alert.tpl [Line: 20]</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="d3d2e617335f08df83599665eef8a418" approved="yes">
|
||||||
|
<source>Close</source>
|
||||||
|
<target state="final">Sluiten</target>
|
||||||
|
<note>File: views/templates/hook/_alert.tpl [Line: 23]</note>
|
||||||
|
</trans-unit>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -9,3 +9,36 @@ td.action-type .btn-group-action {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 544px) {
|
||||||
|
.form-horizontal
|
||||||
|
.form-group.row
|
||||||
|
> .form-control-label:first-of-type:not(.label-on-top) {
|
||||||
|
flex: 0 0 auto !important;
|
||||||
|
max-width: unset !important;
|
||||||
|
text-align: left !important;
|
||||||
|
}
|
||||||
|
form[name="custom_html_block"] .card-body,
|
||||||
|
form[name="custom_html_group"] .card-body {
|
||||||
|
padding: 25px 50px !important;
|
||||||
|
}
|
||||||
|
form[name="custom_html_block"] .card-header,
|
||||||
|
form[name="custom_html_block"] .card-footer,
|
||||||
|
form[name="custom_html_group"] .card-header,
|
||||||
|
form[name="custom_html_group"] .card-footer {
|
||||||
|
padding: 20px 50px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1500px) {
|
||||||
|
form[name="custom_html_block"] .card-body,
|
||||||
|
form[name="custom_html_group"] .card-body {
|
||||||
|
padding: 25px 300px !important;
|
||||||
|
}
|
||||||
|
form[name="custom_html_block"] .card-header,
|
||||||
|
form[name="custom_html_block"] .card-footer,
|
||||||
|
form[name="custom_html_group"] .card-header,
|
||||||
|
form[name="custom_html_group"] .card-footer {
|
||||||
|
padding: 20px 300px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/* Banners */
|
||||||
|
.customhtml-block img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.customhtml-banner-content {
|
||||||
|
padding: 2rem;
|
||||||
|
bottom: 0px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-banner-title {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-banner-description,
|
||||||
|
.customhtml-banner-extra-description {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-banner-image {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-banner-image--gradient {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
/* Alert */
|
||||||
|
.customhtml-alert {
|
||||||
|
max-height: 500px;
|
||||||
|
overflow: hidden;
|
||||||
|
transition:
|
||||||
|
max-height 0.4s ease,
|
||||||
|
padding 0.4s ease,
|
||||||
|
margin 0.4s ease,
|
||||||
|
opacity 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-alert.customhtml-alert-collapsing {
|
||||||
|
max-height: 0;
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-alert-title {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-alert-btn {
|
||||||
|
margin-left: 0.75rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-usp {
|
||||||
|
gap: 0.5rem;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-usp-icon img {
|
||||||
|
max-height: 32px;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-usp-text {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Slider */
|
||||||
|
.customhtml-slider-grid-item {
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Home banners slider (migrated from ws_extrabanner's home-banners section) */
|
||||||
|
.displayHomeBannersSlider--container .customhtml-banner-image {
|
||||||
|
min-height: 220px;
|
||||||
|
background-color: #f2f0e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.displayHomeBannersSlider--container .customhtml-banner-content * {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.displayHomeBannersSlider--container .customhtml-banner-description,
|
||||||
|
.displayHomeBannersSlider--container .customhtml-banner-extra-description {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.displayHomeBannersSlider--container .customhtml-banner-extra-description {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FAQ */
|
||||||
|
.accordion-icon-minus {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-icon-plus {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-faq-accordion .btn.collapsed .accordion-icon-minus {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customhtml-faq-accordion .btn.collapsed .accordion-icon-plus {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
$(document).ready(function () {
|
||||||
|
window.prestashop.component.initComponents([
|
||||||
|
'TinyMCEEditor',
|
||||||
|
'TranslatableField',
|
||||||
|
'TranslatableInput',
|
||||||
|
]);
|
||||||
|
|
||||||
|
function toggleBlockTypeFields() {
|
||||||
|
var type = $('#custom_html_block_type').val();
|
||||||
|
|
||||||
|
$('.customhtmlblock-type-html').hide();
|
||||||
|
$('.customhtmlblock-type-faq').hide();
|
||||||
|
$('.customhtmlblock-type-banner').hide();
|
||||||
|
$('.customhtmlblock-type-alert').hide();
|
||||||
|
$('.customhtmlblock-type-usp').hide();
|
||||||
|
$('.customhtmlblock-type-slider').hide();
|
||||||
|
$('.customhtmlblock-type-' + type).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#custom_html_block_type').on('change', toggleBlockTypeFields);
|
||||||
|
toggleBlockTypeFields();
|
||||||
|
|
||||||
|
function toggleGroupDefaultClassHint() {
|
||||||
|
var hint = $('#customhtmlblock-group-default-class-hint');
|
||||||
|
var defaultClass = $('#custom_html_block_id_ws_customhtml_group option:selected').data('defaultBlockClass');
|
||||||
|
|
||||||
|
if (defaultClass) {
|
||||||
|
hint.text(hint.data('template').replace('%s%', defaultClass)).show();
|
||||||
|
} else {
|
||||||
|
hint.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#custom_html_block_id_ws_customhtml_group').on('change', toggleGroupDefaultClassHint);
|
||||||
|
toggleGroupDefaultClassHint();
|
||||||
|
|
||||||
|
function initRepeater(containerSelector, addButtonSelector, itemClass, removeButtonClass) {
|
||||||
|
var container = $(containerSelector);
|
||||||
|
var removeLabel = container.data('removeLabel');
|
||||||
|
|
||||||
|
$(addButtonSelector).on('click', function () {
|
||||||
|
var index = container.data('index');
|
||||||
|
var prototype = container.data('prototype').replace(/__name__/g, index);
|
||||||
|
|
||||||
|
var item = $('<div class="' + itemClass + ' card mb-2"><div class="card-body"></div></div>');
|
||||||
|
item.find('.card-body')
|
||||||
|
.append(prototype)
|
||||||
|
.append(
|
||||||
|
'<button type="button" class="btn btn-outline-danger btn-sm ' + removeButtonClass + '">' +
|
||||||
|
'<i class="material-icons">delete</i> ' + removeLabel + '</button>'
|
||||||
|
);
|
||||||
|
|
||||||
|
container.append(item);
|
||||||
|
container.data('index', index + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
container.on('click', '.' + removeButtonClass, function () {
|
||||||
|
$(this).closest('.' + itemClass).remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initRepeater('#customhtmlblock-faq-items', '#customhtmlblock-add-faq', 'customhtmlblock-faq-item', 'customhtmlblock-remove-faq');
|
||||||
|
initRepeater('#customhtmlblock-slide-items', '#customhtmlblock-add-slide', 'customhtmlblock-slide-item', 'customhtmlblock-remove-slide');
|
||||||
|
});
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
$(document).ready(function () {
|
||||||
|
const customhtmlblockGrid = new window.prestashop.component.Grid('customhtmlblock');
|
||||||
|
|
||||||
|
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.SortingExtension());
|
||||||
|
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.FiltersResetExtension());
|
||||||
|
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.ColumnTogglingExtension());
|
||||||
|
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension());
|
||||||
|
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.PositionExtension());
|
||||||
|
});
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
$(document).ready(function () {
|
||||||
|
window.prestashop.component.initComponents([
|
||||||
|
'TranslatableField',
|
||||||
|
'TranslatableInput',
|
||||||
|
]);
|
||||||
|
});
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
$(document).ready(function () {
|
||||||
|
const customhtmlgroupGrid = new window.prestashop.component.Grid('customhtmlgroup');
|
||||||
|
|
||||||
|
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.SortingExtension());
|
||||||
|
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.FiltersResetExtension());
|
||||||
|
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.ColumnTogglingExtension());
|
||||||
|
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension());
|
||||||
|
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.PositionExtension());
|
||||||
|
});
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
document.querySelectorAll('.customhtml-alert').forEach(function (alertEl) {
|
||||||
|
var timeout = parseInt(alertEl.getAttribute('data-timeout'), 10) || 0;
|
||||||
|
var timer = null;
|
||||||
|
|
||||||
|
var dismiss = function () {
|
||||||
|
alertEl.classList.add('customhtml-alert-collapsing');
|
||||||
|
};
|
||||||
|
|
||||||
|
if (timeout > 0) {
|
||||||
|
timer = setTimeout(dismiss, timeout * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
var closeButton = alertEl.querySelector('.customhtml-alert-close');
|
||||||
|
|
||||||
|
if (closeButton) {
|
||||||
|
closeButton.addEventListener('click', function () {
|
||||||
|
if (timer) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -1,6 +1,23 @@
|
|||||||
{% import '@PrestaShop/Admin/macros.html.twig' as ps %}
|
{% import '@PrestaShop/Admin/macros.html.twig' as ps %}
|
||||||
{% form_theme customHtmlBlockForm '@PrestaShop/Admin/TwigTemplateForm/prestashop_ui_kit.html.twig' %}
|
{% form_theme customHtmlBlockForm '@PrestaShop/Admin/TwigTemplateForm/prestashop_ui_kit.html.twig' %}
|
||||||
|
|
||||||
|
{% macro faqFields(faqForm) %}
|
||||||
|
{{ form_row(faqForm.question) }}
|
||||||
|
{{ form_row(faqForm.answer) }}
|
||||||
|
{% endmacro %}
|
||||||
|
{% import _self as faqMacros %}
|
||||||
|
|
||||||
|
{% macro slideFields(slideForm) %}
|
||||||
|
{{ form_widget(slideForm.id) }}
|
||||||
|
{{ form_row(slideForm.title) }}
|
||||||
|
{{ form_row(slideForm.description) }}
|
||||||
|
{{ form_row(slideForm.extra_description) }}
|
||||||
|
{{ form_row(slideForm.link) }}
|
||||||
|
{{ form_row(slideForm.link_text) }}
|
||||||
|
{{ form_row(slideForm.image) }}
|
||||||
|
{% endmacro %}
|
||||||
|
{% import _self as slideMacros %}
|
||||||
|
|
||||||
{% block customhtmlblock_form_block %}
|
{% block customhtmlblock_form_block %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
{{ form_start(customHtmlBlockForm) }}
|
{{ form_start(customHtmlBlockForm) }}
|
||||||
@@ -10,10 +27,102 @@
|
|||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
{{ form_row(customHtmlBlockForm.id_ws_customhtml_group) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.type) }}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
{{ form_row(customHtmlBlockForm.title) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.show_title) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ form_row(customHtmlBlockForm.content) }}
|
||||||
|
|
||||||
|
{% if currentImageUrl is defined and currentImageUrl %}
|
||||||
|
<div class="customhtmlblock-type-field customhtmlblock-type-banner customhtmlblock-type-usp customhtmlblock-current-image">
|
||||||
|
<label class="form-control-label">{{ 'Current image'|trans({}, 'Modules.Wscustomhtml.Admin') }}</label>
|
||||||
|
<div><img src="{{ currentImageUrl }}" alt="" style="max-width: 200px; max-height: 200px;"></div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{{ form_row(customHtmlBlockForm.image) }}
|
||||||
|
|
||||||
|
<div class="customhtmlblock-type-field customhtmlblock-type-faq">
|
||||||
|
<label class="form-control-label">
|
||||||
|
{{ 'FAQ items'|trans({}, 'Modules.Wscustomhtml.Admin') }}
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
id="customhtmlblock-faq-items"
|
||||||
|
data-prototype="{{ faqMacros.faqFields(customHtmlBlockForm.faqs.vars.prototype)|e('html_attr') }}"
|
||||||
|
data-index="{{ customHtmlBlockForm.faqs|length }}"
|
||||||
|
data-remove-label="{{ 'Remove'|trans({}, 'Admin.Actions')|e('html_attr') }}"
|
||||||
|
>
|
||||||
|
{% for faqRow in customHtmlBlockForm.faqs %}
|
||||||
|
<div class="customhtmlblock-faq-item card mb-2">
|
||||||
|
<div class="card-body">
|
||||||
|
{{ faqMacros.faqFields(faqRow) }}
|
||||||
|
<button type="button" class="btn btn-outline-danger btn-sm customhtmlblock-remove-faq">
|
||||||
|
<i class="material-icons">delete</i> {{ 'Remove'|trans({}, 'Admin.Actions') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<button type="button" id="customhtmlblock-add-faq" class="btn btn-outline-primary btn-sm">
|
||||||
|
<i class="material-icons">add</i> {{ 'Add FAQ item'|trans({}, 'Modules.Wscustomhtml.Admin') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="customhtmlblock-type-field customhtmlblock-type-slider">
|
||||||
|
<label class="form-control-label">
|
||||||
|
{{ 'Slides'|trans({}, 'Modules.Wscustomhtml.Admin') }}
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
id="customhtmlblock-slide-items"
|
||||||
|
data-prototype="{{ slideMacros.slideFields(customHtmlBlockForm.slides.vars.prototype)|e('html_attr') }}"
|
||||||
|
data-index="{{ customHtmlBlockForm.slides|length }}"
|
||||||
|
data-remove-label="{{ 'Remove'|trans({}, 'Admin.Actions')|e('html_attr') }}"
|
||||||
|
>
|
||||||
|
{% for slideRow in customHtmlBlockForm.slides %}
|
||||||
|
<div class="customhtmlblock-slide-item card mb-2">
|
||||||
|
<div class="card-body">
|
||||||
|
{{ slideMacros.slideFields(slideRow) }}
|
||||||
|
<button type="button" class="btn btn-outline-danger btn-sm customhtmlblock-remove-slide">
|
||||||
|
<i class="material-icons">delete</i> {{ 'Remove'|trans({}, 'Admin.Actions') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<button type="button" id="customhtmlblock-add-slide" class="btn btn-outline-primary btn-sm">
|
||||||
|
<i class="material-icons">add</i> {{ 'Add slide'|trans({}, 'Modules.Wscustomhtml.Admin') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ form_row(customHtmlBlockForm.slider_mode) }}
|
||||||
|
<div class="row">
|
||||||
|
{{ form_row(customHtmlBlockForm.slides_per_view_mobile) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.slides_per_view_tablet) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.slides_per_view_desktop) }}
|
||||||
|
</div>
|
||||||
|
{{ form_row(customHtmlBlockForm.autoplay_delay) }}
|
||||||
|
|
||||||
|
{{ form_row(customHtmlBlockForm.alert_type) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.timeout) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.description) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.extra_description) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.link) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.link_text) }}
|
||||||
|
|
||||||
|
<p
|
||||||
|
id="customhtmlblock-group-default-class-hint"
|
||||||
|
class="alert alert-warning"
|
||||||
|
data-template="{{ 'The group that this block belongs to applies the classes "%s%" to every block. Edit the group to change this - it is stored under the "Default block class" input.'|trans({}, 'Modules.Wscustomhtml.Admin')|e('html_attr') }}"
|
||||||
|
></p>
|
||||||
|
{{ form_row(customHtmlBlockForm.custom_class) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.active) }}
|
||||||
{{ form_rest(customHtmlBlockForm) }}
|
{{ form_rest(customHtmlBlockForm) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<a href="{{ path('customhtmlblock_index') }}" class="btn btn-outline-secondary">
|
<a href="{{ path('customhtmlblock_index', idGroup is defined and idGroup ? {'idGroup': idGroup} : {}) }}" class="btn btn-outline-secondary">
|
||||||
{{ 'Cancel'|trans({}, 'Admin.Actions') }}
|
{{ 'Cancel'|trans({}, 'Admin.Actions') }}
|
||||||
</a>
|
</a>
|
||||||
<button class="btn btn-primary float-right">
|
<button class="btn btn-primary float-right">
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
{{ 'Cancel'|trans({}, 'Admin.Actions') }}
|
{{ 'Cancel'|trans({}, 'Admin.Actions') }}
|
||||||
</a>
|
</a>
|
||||||
{% if idCustomHtmlGroup is defined %}
|
{% if idCustomHtmlGroup is defined %}
|
||||||
|
<a href="{{ path('customhtmlblock_index', {'idGroup': idCustomHtmlGroup}) }}" class="btn btn-outline-primary">
|
||||||
|
{{ 'View blocks'|trans({}, 'Modules.Wscustomhtml.Admin') }}
|
||||||
|
</a>
|
||||||
<a href="{{ path('customhtmlblock_create', {'idGroup': idCustomHtmlGroup}) }}" class="btn btn-outline-primary">
|
<a href="{{ path('customhtmlblock_create', {'idGroup': idCustomHtmlGroup}) }}" class="btn btn-outline-primary">
|
||||||
{{ 'Add block'|trans({}, 'Modules.Wscustomhtml.Admin') }}
|
{{ 'Add block'|trans({}, 'Modules.Wscustomhtml.Admin') }}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -8,11 +8,5 @@
|
|||||||
|
|
||||||
{% block javascripts %}
|
{% block javascripts %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
<script>
|
<script src="{{ asset('../modules/ws_customhtml/views/js/admin/customhtmlblock_form.js') }}"></script>
|
||||||
$(document).ready(function () {
|
|
||||||
window.prestashop.component.initComponents([
|
|
||||||
'TinyMCEEditor',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -8,11 +8,5 @@
|
|||||||
|
|
||||||
{% block javascripts %}
|
{% block javascripts %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
<script>
|
<script src="{{ asset('../modules/ws_customhtml/views/js/admin/customhtmlblock_form.js') }}"></script>
|
||||||
$(document).ready(function () {
|
|
||||||
window.prestashop.component.initComponents([
|
|
||||||
'TinyMCEEditor',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -5,3 +5,8 @@
|
|||||||
{% include '@Modules/ws_customhtml/views/templates/admin/form/blocks/group_form.html.twig' %}
|
{% include '@Modules/ws_customhtml/views/templates/admin/form/blocks/group_form.html.twig' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
{{ parent() }}
|
||||||
|
<script src="{{ asset('../modules/ws_customhtml/views/js/admin/customhtmlgroup_form.js') }}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|||||||
@@ -5,3 +5,8 @@
|
|||||||
{% include '@Modules/ws_customhtml/views/templates/admin/form/blocks/group_form.html.twig' %}
|
{% include '@Modules/ws_customhtml/views/templates/admin/form/blocks/group_form.html.twig' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
{{ parent() }}
|
||||||
|
<script src="{{ asset('../modules/ws_customhtml/views/js/admin/customhtmlgroup_form.js') }}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -12,14 +12,6 @@
|
|||||||
|
|
||||||
{% block javascripts %}
|
{% block javascripts %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
<script>
|
<script src="{{ asset('themes/default/js/bundle/pagination.js') }}"></script>
|
||||||
$(document).ready(function () {
|
<script src="{{ asset('../modules/ws_customhtml/views/js/admin/customhtmlblock_grid.js') }}"></script>
|
||||||
const customhtmlblockGrid = new window.prestashop.component.Grid('customhtmlblock');
|
|
||||||
|
|
||||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.SortingExtension());
|
|
||||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.FiltersResetExtension());
|
|
||||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.ColumnTogglingExtension());
|
|
||||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension());
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -12,14 +12,6 @@
|
|||||||
|
|
||||||
{% block javascripts %}
|
{% block javascripts %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
<script>
|
<script src="{{ asset('themes/default/js/bundle/pagination.js') }}"></script>
|
||||||
$(document).ready(function () {
|
<script src="{{ asset('../modules/ws_customhtml/views/js/admin/customhtmlgroup_grid.js') }}"></script>
|
||||||
const customhtmlgroupGrid = new window.prestashop.component.Grid('customhtmlgroup');
|
|
||||||
|
|
||||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.SortingExtension());
|
|
||||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.FiltersResetExtension());
|
|
||||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.ColumnTogglingExtension());
|
|
||||||
customhtmlgroupGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension());
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
{if !empty($block.description)}
|
||||||
|
<div
|
||||||
|
class="alert alert-{$block.alert_type|escape:'html':'UTF-8'} alert-dismissible customhtml-alert"
|
||||||
|
role="alert"
|
||||||
|
data-timeout="{$block.timeout|intval}"
|
||||||
|
>
|
||||||
|
<div class="row">
|
||||||
|
{block name=alert_content}
|
||||||
|
<div class="col d-flex align-items-center">
|
||||||
|
{if $block.show_title && !empty($block.title)}
|
||||||
|
<strong class="customhtml-alert-title">{$block.title|escape:'html':'UTF-8'}</strong>
|
||||||
|
{/if}
|
||||||
|
<span class="customhtml-alert-text">{$block.description|escape:'html':'UTF-8'|nl2br}</span>
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
{block name=alert_actions}
|
||||||
|
<div class="col-auto">
|
||||||
|
{if !empty($block.link)}
|
||||||
|
<a href="{$block.link|escape:'html':'UTF-8'}" class="btn btn-{$block.alert_type|escape:'html':'UTF-8'} customhtml-alert-btn">
|
||||||
|
{if !empty($block.link_text)}{$block.link_text|escape:'html':'UTF-8'}{else}{l s='Learn more' d='Modules.Wscustomhtml.Shop'}{/if}
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
<button type="button" class="close customhtml-alert-close" aria-label="{l s='Close' d='Modules.Wscustomhtml.Shop'}">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<div class="customhtml-banner row flex-column position-relative">
|
||||||
|
{block name=banner_image}
|
||||||
|
<div class="customhtml-banner-image">
|
||||||
|
<div class="customhtml-banner-image--gradient"></div>
|
||||||
|
{if !empty($block.image_url)}
|
||||||
|
<img src="{$block.image_url|escape:'html':'UTF-8'}" alt="{$block.title|escape:'html':'UTF-8'}">
|
||||||
|
{else}
|
||||||
|
<img
|
||||||
|
src="{$urls.img_ps_url}noimageavailable.jpg"
|
||||||
|
alt="{$block.title|escape:'html':'UTF-8'}"
|
||||||
|
width="100%"
|
||||||
|
class="img-fluid rounded lazyload"
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
{block name=banner_content}
|
||||||
|
<div class="customhtml-banner-content">
|
||||||
|
{if !empty($count)}
|
||||||
|
<span class="customhtml-banner-count font-monospace">{$count}</span>
|
||||||
|
{/if}
|
||||||
|
{if $block.show_title && !empty($block.title)}
|
||||||
|
<h3 class="customhtml-banner-title">{$block.title|escape:'html':'UTF-8'}</h3>
|
||||||
|
{/if}
|
||||||
|
{if !empty($block.description)}
|
||||||
|
<div class="customhtml-banner-description">{$block.description|escape:'html':'UTF-8'|nl2br}</div>
|
||||||
|
{/if}
|
||||||
|
{if !empty($block.extra_description)}
|
||||||
|
<div class="customhtml-banner-extra-description">{$block.extra_description|escape:'html':'UTF-8'|nl2br}</div>
|
||||||
|
{/if}
|
||||||
|
{if !empty($block.link)}
|
||||||
|
<a href="{$block.link|escape:'html':'UTF-8'}" class="btn btn-primary customhtml-banner-link">
|
||||||
|
{if !empty($block.link_text)}{$block.link_text|escape:'html':'UTF-8'}{else}{l s='Learn more' d='Modules.Wscustomhtml.Shop'}{/if}
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
{if !empty($block.faqs)}
|
||||||
|
<div class="accordion customhtml-faq-accordion" id="customhtml-faq-{$block.id_ws_customhtml|intval}">
|
||||||
|
{foreach from=$block.faqs item="faq" name="customhtmlFaqLoop"}
|
||||||
|
<div class="card">
|
||||||
|
{block name=faq_question}
|
||||||
|
<div class="card-header" id="customhtml-faq-heading-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}">
|
||||||
|
|
||||||
|
{if !empty($faq.answer)}
|
||||||
|
<button
|
||||||
|
class="btn btn-link col-12 d-flex text-left{if !$smarty.foreach.customhtmlFaqLoop.first} collapsed{/if}"
|
||||||
|
type="button"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-target="#customhtml-faq-collapse-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||||
|
aria-expanded="{if $smarty.foreach.customhtmlFaqLoop.first}true{else}false{/if}"
|
||||||
|
aria-controls="customhtml-faq-collapse-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="faq-question col pl-0">
|
||||||
|
{$faq.question|escape:'html':'UTF-8'}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{if !empty($faq.answer)}
|
||||||
|
<div class="col-auto d-flex align-items-center">
|
||||||
|
<span class="accordion-icons accordion-icon-minus">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="2" viewBox="0 0 28 2">
|
||||||
|
<line id="Line_18" data-name="Line 18" x2="26" transform="translate(1 1)" fill="none" stroke="#272727" stroke-linecap="round" stroke-width="2"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span class="accordion-icons accordion-icon-plus">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28">
|
||||||
|
<g id="Group_31" data-name="Group 31" transform="translate(-1615 -4031.5)">
|
||||||
|
<line id="Line_21" data-name="Line 21" x2="26" transform="translate(1616 4045.5)" fill="none" stroke="#272727" stroke-linecap="round" stroke-width="2"/>
|
||||||
|
<line id="Line_22" data-name="Line 22" x2="26" transform="translate(1629 4032.5) rotate(90)" fill="none" stroke="#272727" stroke-linecap="round" stroke-width="2"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
{if !empty($faq.answer)}
|
||||||
|
{block name=faq_answer}
|
||||||
|
<div
|
||||||
|
id="customhtml-faq-collapse-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||||
|
class="collapse{if $smarty.foreach.customhtmlFaqLoop.first} show{/if}"
|
||||||
|
aria-labelledby="customhtml-faq-heading-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}"
|
||||||
|
data-parent="#customhtml-faq-{$block.id_ws_customhtml|intval}"
|
||||||
|
>
|
||||||
|
<div class="card-body">
|
||||||
|
{$faq.answer nofilter}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{extends file="module:ws_customhtml/views/templates/hook/_banner.tpl"}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
{if !empty($block.slides)}
|
||||||
|
{if $block.slider_mode == 'responsive'}
|
||||||
|
{block name=slider_responsive}
|
||||||
|
<div class="d-lg-none">
|
||||||
|
<div class="swiper customhtml-slider" data-swiper="{$block.slider_config|escape:'html':'UTF-8'}">
|
||||||
|
<div class="swiper-wrapper">
|
||||||
|
{foreach from=$block.slides item="slide" name="slides"}
|
||||||
|
{assign var="count" value=$smarty.foreach.slides.iteration|string_format:"%02d"}
|
||||||
|
<div class="swiper-slide">
|
||||||
|
{assign var="customhtmlOverridePath" value="{$smarty.const._PS_THEME_DIR_}modules/ws_customhtml/views/templates/hook/{$hookName}/slide.tpl"}
|
||||||
|
{if file_exists($customhtmlOverridePath)}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/`$hookName`/slide.tpl" block=$slide group=$group hookName=$hookName count=$count}
|
||||||
|
{else}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/_slide.tpl" block=$slide count=$count}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row d-none d-lg-flex customhtml-slider-grid">
|
||||||
|
{foreach from=$block.slides item="slide" name="slides"}
|
||||||
|
{assign var="count" value=$smarty.foreach.slides.iteration|string_format:"%02d"}
|
||||||
|
{if !empty($block.slider_desktop_column_width)}
|
||||||
|
<div class="customhtml-slider-grid-item" style="flex: 0 0 {$block.slider_desktop_column_width|escape:'html':'UTF-8'}; max-width: {$block.slider_desktop_column_width|escape:'html':'UTF-8'};">
|
||||||
|
{else}
|
||||||
|
<div class="customhtml-slider-grid-item col">
|
||||||
|
{/if}
|
||||||
|
{assign var="customhtmlOverridePath" value="{$smarty.const._PS_THEME_DIR_}modules/ws_customhtml/views/templates/hook/{$hookName}/slide.tpl"}
|
||||||
|
{if file_exists($customhtmlOverridePath)}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/`$hookName`/slide.tpl" block=$slide group=$group hookName=$hookName count=$count}
|
||||||
|
{else}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/_slide.tpl" block=$slide count=$count}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
{/if}
|
||||||
|
{if $block.slider_mode != 'responsive'}
|
||||||
|
{block name=slider_always}
|
||||||
|
<div class="swiper customhtml-slider" data-swiper="{$block.slider_config|escape:'html':'UTF-8'}">
|
||||||
|
<div class="swiper-wrapper">
|
||||||
|
{foreach from=$block.slides item="slide" name="slides"}
|
||||||
|
{assign var="count" value=$smarty.foreach.slides.iteration|string_format:"%02d"}
|
||||||
|
<div class="swiper-slide">
|
||||||
|
{assign var="customhtmlOverridePath" value="{$smarty.const._PS_THEME_DIR_}modules/ws_customhtml/views/templates/hook/{$hookName}/slide.tpl"}
|
||||||
|
{if file_exists($customhtmlOverridePath)}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/`$hookName`/slide.tpl" block=$slide group=$group hookName=$hookName count=$count}
|
||||||
|
{else}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/_slide.tpl" block=$slide count=$count}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
{if !empty($block.image_url) || ($block.show_title && !empty($block.title)) || !empty($block.description)}
|
||||||
|
{if !empty($block.link)}
|
||||||
|
<a href="{$block.link|escape:'html':'UTF-8'}" class="customhtml-usp d-flex align-items-center">
|
||||||
|
{else}
|
||||||
|
<div class="customhtml-usp d-flex align-items-center">
|
||||||
|
{/if}
|
||||||
|
{block name=usp_icon}
|
||||||
|
{if !empty($block.image_url)}
|
||||||
|
<span class="customhtml-usp-icon">
|
||||||
|
<img src="{$block.image_url|escape:'html':'UTF-8'}" alt="">
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
{/block}
|
||||||
|
{block name=usp_content}
|
||||||
|
{if $block.show_title && !empty($block.title)}
|
||||||
|
<span class="customhtml-usp-text">{$block.title|escape:'html':'UTF-8'}</span>
|
||||||
|
{/if}
|
||||||
|
{if !empty($block.description)}
|
||||||
|
<span class="customhtml-usp-description">{$block.description|escape:'html':'UTF-8'|nl2br}</span>
|
||||||
|
{/if}
|
||||||
|
{/block}
|
||||||
|
{if !empty($block.link)}
|
||||||
|
</a>
|
||||||
|
{else}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
@@ -1,13 +1,35 @@
|
|||||||
{if !empty($groupList)}
|
{if !empty($groupList)}
|
||||||
<div class="customhtml-container {$hookName|escape:'html':'UTF-8'}--container">
|
<div class="customhtml-container {$hookName|escape:'html':'UTF-8'}--container">
|
||||||
{foreach from=$groupList item="group"}
|
{foreach from=$groupList item="group"}
|
||||||
<div class="customhtml-group">
|
<div class="customhtml-group row{if !empty($group.custom_class)} {$group.custom_class|escape:'html':'UTF-8'}{/if}">
|
||||||
{foreach from=$group.blocks item="block"}
|
{foreach from=$group.blocks item="block" name="blocks"}
|
||||||
<div class="customhtml-block">
|
<div class="customhtml-block col{if !empty($group.default_block_class)} {$group.default_block_class|escape:'html':'UTF-8'}{/if}{if !empty($block.custom_class)} {$block.custom_class|escape:'html':'UTF-8'}{/if}">
|
||||||
{if $block.show_title && !empty($block.title)}
|
{assign var="customhtmlOverridePath" value="{$smarty.const._PS_THEME_DIR_}modules/ws_customhtml/views/templates/hook/{$hookName}/{$block.type}.tpl"}
|
||||||
<div class="customhtml-title">{$block.title|escape:'html':'UTF-8'}</div>
|
|
||||||
|
{if file_exists($customhtmlOverridePath)}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/`$hookName`/`$block.type`.tpl" block=$block group=$group hookName=$hookName iteration=$smarty.foreach.blocks.iteration}
|
||||||
|
{elseif $block.type == 'faq'}
|
||||||
|
{if $block.show_title && !empty($block.title)}
|
||||||
|
<div class="customhtml-title">{$block.title|escape:'html':'UTF-8'}</div>
|
||||||
|
{/if}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/_faq_accordion.tpl" block=$block}
|
||||||
|
{elseif $block.type == 'banner'}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/_banner.tpl" block=$block}
|
||||||
|
{elseif $block.type == 'alert'}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/_alert.tpl" block=$block}
|
||||||
|
{elseif $block.type == 'usp'}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/_usp.tpl" block=$block}
|
||||||
|
{elseif $block.type == 'slider'}
|
||||||
|
{if $block.show_title && !empty($block.title)}
|
||||||
|
<div class="customhtml-title">{$block.title|escape:'html':'UTF-8'}</div>
|
||||||
|
{/if}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/_slider.tpl" block=$block}
|
||||||
|
{else}
|
||||||
|
{if $block.show_title && !empty($block.title)}
|
||||||
|
<div class="customhtml-title">{$block.title|escape:'html':'UTF-8'}</div>
|
||||||
|
{/if}
|
||||||
|
<div class="customhtml-content">{$block.content nofilter}</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="customhtml-content">{$block.content nofilter}</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||||
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||||
|
header('Pragma: no-cache');
|
||||||
|
header('Location: ../');
|
||||||
|
exit;
|
||||||
+1
-1
@@ -29,7 +29,7 @@ class Ws_CustomHtml extends Module implements WidgetInterface
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->name = 'ws_customhtml';
|
$this->name = 'ws_customhtml';
|
||||||
$this->version = '1.1.0';
|
$this->version = '1.24.0';
|
||||||
$this->author = 'Isabelle Oving-Anno | De Websmid BV';
|
$this->author = 'Isabelle Oving-Anno | De Websmid BV';
|
||||||
$this->need_instance = 0;
|
$this->need_instance = 0;
|
||||||
$this->bootstrap = true;
|
$this->bootstrap = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user