Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb641fc236 | ||
|
|
d0da05845a | ||
|
|
1493081602 |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -33,6 +33,14 @@ 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'
|
||||||
|
arguments:
|
||||||
|
- '@translator'
|
||||||
|
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'
|
||||||
|
|||||||
@@ -68,3 +68,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
|
||||||
|
|||||||
@@ -71,3 +71,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'
|
||||||
|
|||||||
@@ -6,6 +6,13 @@ class Config
|
|||||||
{
|
{
|
||||||
const HOOKS = [
|
const HOOKS = [
|
||||||
'actionAdminControllerSetMedia',
|
'actionAdminControllerSetMedia',
|
||||||
|
'actionCustomhtmlblockGridDataModifier',
|
||||||
|
'actionFrontControllerSetMedia',
|
||||||
|
];
|
||||||
|
|
||||||
|
const BLOCK_TYPES = [
|
||||||
|
'html' => 'HTML',
|
||||||
|
'faq' => 'FAQ Accordion',
|
||||||
];
|
];
|
||||||
|
|
||||||
const ADMIN_CONTROLLERS = [
|
const ADMIN_CONTROLLERS = [
|
||||||
|
|||||||
@@ -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,6 +14,7 @@ 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
|
||||||
@@ -107,12 +111,35 @@ class CustomHtmlBlockController extends FrameworkBundleAdminController
|
|||||||
return $this->redirectToRoute('customhtmlblock_index');
|
return $this->redirectToRoute('customhtmlblock_index');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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): array
|
private function getToolbarButtons(?string $securitySubject): array
|
||||||
{
|
{
|
||||||
$toolbarButtons = [];
|
$toolbarButtons = [];
|
||||||
|
|||||||
@@ -4,24 +4,32 @@ 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\CustomHtmlBlock;
|
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
||||||
|
use Websmid\CustomHtml\Model\CustomHtmlFaq;
|
||||||
|
use Db;
|
||||||
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 = (string) $formData['title'];
|
||||||
|
$block->type = (string) $formData['type'];
|
||||||
$block->show_title = (int) $formData['show_title'];
|
$block->show_title = (int) $formData['show_title'];
|
||||||
|
$block->custom_class = (string) ($formData['custom_class'] ?? '');
|
||||||
$block->content = (string) $formData['content'];
|
$block->content = (string) $formData['content'];
|
||||||
$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'] ?? []);
|
||||||
|
|
||||||
return $block->id;
|
return $block->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,10 +43,46 @@ 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 = (string) $formData['title'];
|
||||||
|
$block->type = (string) $formData['type'];
|
||||||
$block->show_title = (int) $formData['show_title'];
|
$block->show_title = (int) $formData['show_title'];
|
||||||
|
$block->custom_class = (string) ($formData['custom_class'] ?? '');
|
||||||
$block->content = (string) $formData['content'];
|
$block->content = (string) $formData['content'];
|
||||||
$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'] ?? []);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getNextOrdering(int $idGroup): int
|
||||||
|
{
|
||||||
|
$maxOrdering = Db::getInstance()->getValue(
|
||||||
|
'SELECT MAX(`ordering`) FROM `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||||
|
WHERE `id_ws_customhtml_group` = ' . $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) {
|
||||||
|
if (empty($faqData['question'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$faq = new CustomHtmlFaq();
|
||||||
|
$faq->id_ws_customhtml = $idBlock;
|
||||||
|
$faq->question = (string) $faqData['question'];
|
||||||
|
$faq->answer = (string) ($faqData['answer'] ?? '');
|
||||||
|
$faq->ordering = $position;
|
||||||
|
$faq->add();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace Websmid\CustomHtml\Form\DataProvider;
|
|||||||
|
|
||||||
use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataProvider\FormDataProviderInterface;
|
use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataProvider\FormDataProviderInterface;
|
||||||
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
use Websmid\CustomHtml\Model\CustomHtmlBlock;
|
||||||
|
use Websmid\CustomHtml\Model\CustomHtmlFaq;
|
||||||
use Validate;
|
use Validate;
|
||||||
|
|
||||||
final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
final class CustomHtmlBlockDataProvider implements FormDataProviderInterface
|
||||||
@@ -19,8 +20,11 @@ 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,
|
||||||
|
'faqs' => $this->loadFaqs((int) $id),
|
||||||
'active' => (bool) $block->active,
|
'active' => (bool) $block->active,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -30,9 +34,22 @@ 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,
|
||||||
|
'custom_class' => '',
|
||||||
'content' => '',
|
'content' => '',
|
||||||
|
'faqs' => [],
|
||||||
'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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ 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\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\SwitchType;
|
use PrestaShopBundle\Form\Admin\Type\SwitchType;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
use Websmid\CustomHtml\Config\Config;
|
||||||
|
|
||||||
class CustomHtmlBlockType extends AbstractType
|
class CustomHtmlBlockType extends AbstractType
|
||||||
{
|
{
|
||||||
@@ -37,14 +39,33 @@ class CustomHtmlBlockType extends AbstractType
|
|||||||
'label' => $this->translator->trans('Title', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Title', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
'required' => true,
|
'required' => true,
|
||||||
])
|
])
|
||||||
|
->add('type', ChoiceType::class, [
|
||||||
|
'label' => $this->translator->trans('Block type', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'choices' => array_flip(Config::BLOCK_TYPES),
|
||||||
|
'required' => true,
|
||||||
|
])
|
||||||
->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,
|
||||||
])
|
])
|
||||||
|
->add('custom_class', TextType::class, [
|
||||||
|
'label' => $this->translator->trans('Custom classes', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
'attr' => ['placeholder' => 'col-md-6'],
|
||||||
|
])
|
||||||
->add('content', TextareaType::class, [
|
->add('content', TextareaType::class, [
|
||||||
'label' => $this->translator->trans('Content', [], 'Modules.Wscustomhtml.Admin'),
|
'label' => $this->translator->trans('Content', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'attr' => ['class' => 'autoload_rte'],
|
'attr' => ['class' => 'autoload_rte'],
|
||||||
|
'row_attr' => ['class' => 'customhtmlblock-type-field customhtmlblock-type-html'],
|
||||||
|
])
|
||||||
|
->add('faqs', CollectionType::class, [
|
||||||
|
'entry_type' => CustomHtmlFaqType::class,
|
||||||
|
'allow_add' => true,
|
||||||
|
'allow_delete' => true,
|
||||||
|
'by_reference' => false,
|
||||||
|
'prototype' => true,
|
||||||
|
'required' => false,
|
||||||
])
|
])
|
||||||
->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,32 @@
|
|||||||
|
<?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 Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
|
class CustomHtmlFaqType extends AbstractType
|
||||||
|
{
|
||||||
|
private $translator;
|
||||||
|
|
||||||
|
public function __construct(TranslatorInterface $translator)
|
||||||
|
{
|
||||||
|
$this->translator = $translator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $formBuilder, array $options): void
|
||||||
|
{
|
||||||
|
$formBuilder
|
||||||
|
->add('question', TextType::class, [
|
||||||
|
'label' => $this->translator->trans('Question', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('answer', TextareaType::class, [
|
||||||
|
'label' => $this->translator->trans('Answer', [], 'Modules.Wscustomhtml.Admin'),
|
||||||
|
'required' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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')
|
||||||
|
|||||||
@@ -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' => [],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -43,8 +43,10 @@ final class CustomHtmlBlockQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
|
|
||||||
$qb->select(
|
$qb->select(
|
||||||
'wchb.`id_ws_customhtml`',
|
'wchb.`id_ws_customhtml`',
|
||||||
|
'wchb.`id_ws_customhtml_group`',
|
||||||
'wchb.`title`',
|
'wchb.`title`',
|
||||||
'wchg.`title` AS group_title',
|
'wchg.`title` AS group_title',
|
||||||
|
'wchb.`type`',
|
||||||
'wchb.`active`',
|
'wchb.`active`',
|
||||||
'wchb.`ordering`',
|
'wchb.`ordering`',
|
||||||
'wchb.`date_add`'
|
'wchb.`date_add`'
|
||||||
@@ -52,8 +54,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());
|
||||||
|
|
||||||
@@ -108,6 +112,12 @@ final class CustomHtmlBlockQueryBuilder extends AbstractDoctrineQueryBuilder
|
|||||||
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) . '%');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,15 @@ 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 int */
|
/** @var int */
|
||||||
public $active = 1;
|
public $active = 1;
|
||||||
|
|
||||||
@@ -40,7 +46,9 @@ class CustomHtmlBlock extends ObjectModel
|
|||||||
'fields' => [
|
'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],
|
||||||
|
'type' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32],
|
||||||
'content' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'],
|
'content' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'],
|
||||||
|
'custom_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'],
|
||||||
'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'],
|
||||||
@@ -58,7 +66,7 @@ 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 `id_ws_customhtml`, `id_ws_customhtml_group`, `title`, `type`, `content`, `custom_class`, `active`, `show_title`, `ordering`
|
||||||
FROM `' . _DB_PREFIX_ . 'ws_customhtml`
|
FROM `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||||
WHERE `id_ws_customhtml_group` IN (' . implode(',', $groupIds) . ')
|
WHERE `id_ws_customhtml_group` IN (' . implode(',', $groupIds) . ')
|
||||||
AND `active` = 1
|
AND `active` = 1
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<?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',
|
||||||
|
'fields' => [
|
||||||
|
'id_ws_customhtml' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||||
|
'question' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 512],
|
||||||
|
'answer' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'],
|
||||||
|
'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||||
|
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||||
|
'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
public static function getByBlockId(int $idBlock): array
|
||||||
|
{
|
||||||
|
$result = Db::getInstance()->executeS(
|
||||||
|
'SELECT `id_ws_customhtml_faq`, `question`, `answer`, `ordering`
|
||||||
|
FROM `' . _DB_PREFIX_ . 'ws_customhtml_faq`
|
||||||
|
WHERE `id_ws_customhtml` = ' . (int) $idBlock . '
|
||||||
|
ORDER BY `ordering` ASC'
|
||||||
|
);
|
||||||
|
|
||||||
|
return $result ?: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function deleteByBlockId(int $idBlock): void
|
||||||
|
{
|
||||||
|
Db::getInstance()->delete('ws_customhtml_faq', '`id_ws_customhtml` = ' . (int) $idBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
namespace Websmid\CustomHtml\Module;
|
namespace Websmid\CustomHtml\Module;
|
||||||
|
|
||||||
use Websmid\CustomHtml\Config\Config;
|
use Websmid\CustomHtml\Config\Config;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Data\GridData;
|
||||||
|
use PrestaShop\PrestaShop\Core\Grid\Record\RecordCollection;
|
||||||
use Tools;
|
use Tools;
|
||||||
|
|
||||||
trait AdminHooks
|
trait AdminHooks
|
||||||
@@ -27,4 +29,17 @@ trait AdminHooks
|
|||||||
|
|
||||||
$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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,20 @@
|
|||||||
namespace Websmid\CustomHtml\Module;
|
namespace Websmid\CustomHtml\Module;
|
||||||
|
|
||||||
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 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'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function renderWidget($hookName = null, array $configuration = [])
|
public function renderWidget($hookName = null, array $configuration = [])
|
||||||
{
|
{
|
||||||
if (empty($hookName)) {
|
if (empty($hookName)) {
|
||||||
@@ -54,6 +63,7 @@ trait DisplayHooks
|
|||||||
}
|
}
|
||||||
|
|
||||||
$blocksByGroup = CustomHtmlBlock::getActiveByGroupIds(array_column($groups, 'id_ws_customhtml_group'));
|
$blocksByGroup = CustomHtmlBlock::getActiveByGroupIds(array_column($groups, 'id_ws_customhtml_group'));
|
||||||
|
$blocksByGroup = $this->attachFaqsToBlocks($blocksByGroup);
|
||||||
|
|
||||||
$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 +75,17 @@ trait DisplayHooks
|
|||||||
return !empty($group['blocks']);
|
return !empty($group['blocks']);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function attachFaqsToBlocks(array $blocksByGroup): array
|
||||||
|
{
|
||||||
|
return array_map(static function (array $blocks) {
|
||||||
|
return array_map(static function (array $block) {
|
||||||
|
if ($block['type'] === 'faq') {
|
||||||
|
$block['faqs'] = CustomHtmlFaq::getByBlockId((int) $block['id_ws_customhtml']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $block;
|
||||||
|
}, $blocks);
|
||||||
|
}, $blocksByGroup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +62,9 @@ trait Install
|
|||||||
`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 \'\',
|
`title` VARCHAR(256) NOT NULL DEFAULT \'\',
|
||||||
|
`type` VARCHAR(32) NOT NULL DEFAULT \'html\',
|
||||||
`content` LONGTEXT,
|
`content` LONGTEXT,
|
||||||
|
`custom_class` VARCHAR(128) NOT NULL DEFAULT \'\',
|
||||||
`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 +74,19 @@ trait Install
|
|||||||
);
|
);
|
||||||
';
|
';
|
||||||
|
|
||||||
|
$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,
|
||||||
|
`question` VARCHAR(512) NOT NULL DEFAULT \'\',
|
||||||
|
`answer` TEXT,
|
||||||
|
`ordering` INT(11) NOT NULL DEFAULT 0,
|
||||||
|
`date_add` DATETIME NOT NULL,
|
||||||
|
`date_upd` DATETIME NOT NULL,
|
||||||
|
KEY `id_ws_customhtml` (`id_ws_customhtml`)
|
||||||
|
);
|
||||||
|
';
|
||||||
|
|
||||||
foreach ($sqlToExec as $sqlBlock) {
|
foreach ($sqlToExec as $sqlBlock) {
|
||||||
Db::getInstance()->execute(trim($sqlBlock));
|
Db::getInstance()->execute(trim($sqlBlock));
|
||||||
}
|
}
|
||||||
@@ -83,6 +105,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,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('_PS_VERSION_')) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function upgrade_module_1_2_0($module)
|
||||||
|
{
|
||||||
|
$columns = Db::getInstance()->executeS(
|
||||||
|
'SHOW COLUMNS FROM `' . _DB_PREFIX_ . 'ws_customhtml` LIKE \'type\''
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($columns)) {
|
||||||
|
if (!Db::getInstance()->execute(
|
||||||
|
'ALTER TABLE `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||||
|
ADD COLUMN `type` VARCHAR(32) NOT NULL DEFAULT \'html\' AFTER `title`'
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Db::getInstance()->execute(
|
||||||
|
'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,
|
||||||
|
`question` VARCHAR(512) NOT NULL DEFAULT \'\',
|
||||||
|
`answer` TEXT,
|
||||||
|
`ordering` INT(11) NOT NULL DEFAULT 0,
|
||||||
|
`date_add` DATETIME NOT NULL,
|
||||||
|
`date_upd` DATETIME NOT NULL,
|
||||||
|
KEY `id_ws_customhtml` (`id_ws_customhtml`)
|
||||||
|
)'
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $module->registerHook('actionCustomhtmlblockGridDataModifier');
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('_PS_VERSION_')) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function upgrade_module_1_3_0($module)
|
||||||
|
{
|
||||||
|
$columns = Db::getInstance()->executeS(
|
||||||
|
'SHOW COLUMNS FROM `' . _DB_PREFIX_ . 'ws_customhtml` LIKE \'column_class\''
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($columns)) {
|
||||||
|
if (!Db::getInstance()->execute(
|
||||||
|
'ALTER TABLE `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||||
|
ADD COLUMN `column_class` VARCHAR(128) NOT NULL DEFAULT \'col-12\' AFTER `content`'
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('_PS_VERSION_')) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function upgrade_module_1_4_0($module)
|
||||||
|
{
|
||||||
|
if (!Hook::isModuleRegisteredOnHook($module, 'actionFrontControllerSetMedia', (int) Context::getContext()->shop->id)) {
|
||||||
|
return $module->registerHook('actionFrontControllerSetMedia');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('_PS_VERSION_')) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function upgrade_module_1_5_0($module)
|
||||||
|
{
|
||||||
|
$newColumn = Db::getInstance()->executeS(
|
||||||
|
'SHOW COLUMNS FROM `' . _DB_PREFIX_ . 'ws_customhtml` LIKE \'custom_class\''
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!empty($newColumn)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oldColumn = Db::getInstance()->executeS(
|
||||||
|
'SHOW COLUMNS FROM `' . _DB_PREFIX_ . 'ws_customhtml` LIKE \'column_class\''
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!empty($oldColumn)) {
|
||||||
|
return Db::getInstance()->execute(
|
||||||
|
'ALTER TABLE `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||||
|
CHANGE `column_class` `custom_class` VARCHAR(128) NOT NULL DEFAULT \'\''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Db::getInstance()->execute(
|
||||||
|
'ALTER TABLE `' . _DB_PREFIX_ . 'ws_customhtml`
|
||||||
|
ADD COLUMN `custom_class` VARCHAR(128) NOT NULL DEFAULT \'\' AFTER `content`'
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
.customhtml-block img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
{% 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 %}
|
||||||
|
|
||||||
{% block customhtmlblock_form_block %}
|
{% block customhtmlblock_form_block %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
{{ form_start(customHtmlBlockForm) }}
|
{{ form_start(customHtmlBlockForm) }}
|
||||||
@@ -10,6 +16,39 @@
|
|||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
{{ form_row(customHtmlBlockForm.id_ws_customhtml_group) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.title) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.type) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.show_title) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.custom_class) }}
|
||||||
|
{{ form_row(customHtmlBlockForm.content) }}
|
||||||
|
|
||||||
|
<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 }}"
|
||||||
|
>
|
||||||
|
{% 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>
|
||||||
|
|
||||||
|
{{ form_row(customHtmlBlockForm.active) }}
|
||||||
{{ form_rest(customHtmlBlockForm) }}
|
{{ form_rest(customHtmlBlockForm) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
|
|||||||
@@ -13,6 +13,44 @@
|
|||||||
window.prestashop.component.initComponents([
|
window.prestashop.component.initComponents([
|
||||||
'TinyMCEEditor',
|
'TinyMCEEditor',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
function toggleBlockTypeFields() {
|
||||||
|
var type = $('#custom_html_block_type').val();
|
||||||
|
|
||||||
|
if (type === 'html') {
|
||||||
|
$('.customhtmlblock-type-html').show();
|
||||||
|
$('.customhtmlblock-type-faq').hide();
|
||||||
|
} else {
|
||||||
|
$('.customhtmlblock-type-html').hide();
|
||||||
|
$('.customhtmlblock-type-faq').show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#custom_html_block_type').on('change', toggleBlockTypeFields);
|
||||||
|
toggleBlockTypeFields();
|
||||||
|
|
||||||
|
var removeFaqLabel = '{{ 'Remove'|trans({}, 'Admin.Actions')|e('js') }}';
|
||||||
|
var faqContainer = $('#customhtmlblock-faq-items');
|
||||||
|
|
||||||
|
$('#customhtmlblock-add-faq').on('click', function () {
|
||||||
|
var index = faqContainer.data('index');
|
||||||
|
var prototype = faqContainer.data('prototype').replace(/__name__/g, index);
|
||||||
|
|
||||||
|
var item = $('<div class="customhtmlblock-faq-item 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 customhtmlblock-remove-faq">' +
|
||||||
|
'<i class="material-icons">delete</i> ' + removeFaqLabel + '</button>'
|
||||||
|
);
|
||||||
|
|
||||||
|
faqContainer.append(item);
|
||||||
|
faqContainer.data('index', index + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
faqContainer.on('click', '.customhtmlblock-remove-faq', function () {
|
||||||
|
$(this).closest('.customhtmlblock-faq-item').remove();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -13,6 +13,44 @@
|
|||||||
window.prestashop.component.initComponents([
|
window.prestashop.component.initComponents([
|
||||||
'TinyMCEEditor',
|
'TinyMCEEditor',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
function toggleBlockTypeFields() {
|
||||||
|
var type = $('#custom_html_block_type').val();
|
||||||
|
|
||||||
|
if (type === 'html') {
|
||||||
|
$('.customhtmlblock-type-html').show();
|
||||||
|
$('.customhtmlblock-type-faq').hide();
|
||||||
|
} else {
|
||||||
|
$('.customhtmlblock-type-html').hide();
|
||||||
|
$('.customhtmlblock-type-faq').show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#custom_html_block_type').on('change', toggleBlockTypeFields);
|
||||||
|
toggleBlockTypeFields();
|
||||||
|
|
||||||
|
var removeFaqLabel = '{{ 'Remove'|trans({}, 'Admin.Actions')|e('js') }}';
|
||||||
|
var faqContainer = $('#customhtmlblock-faq-items');
|
||||||
|
|
||||||
|
$('#customhtmlblock-add-faq').on('click', function () {
|
||||||
|
var index = faqContainer.data('index');
|
||||||
|
var prototype = faqContainer.data('prototype').replace(/__name__/g, index);
|
||||||
|
|
||||||
|
var item = $('<div class="customhtmlblock-faq-item 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 customhtmlblock-remove-faq">' +
|
||||||
|
'<i class="material-icons">delete</i> ' + removeFaqLabel + '</button>'
|
||||||
|
);
|
||||||
|
|
||||||
|
faqContainer.append(item);
|
||||||
|
faqContainer.data('index', index + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
faqContainer.on('click', '.customhtmlblock-remove-faq', function () {
|
||||||
|
$(this).closest('.customhtmlblock-faq-item').remove();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.FiltersResetExtension());
|
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.FiltersResetExtension());
|
||||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.ColumnTogglingExtension());
|
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.ColumnTogglingExtension());
|
||||||
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension());
|
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.SubmitRowActionExtension());
|
||||||
|
customhtmlblockGrid.addExtension(new window.prestashop.component.GridExtensions.PositionExtension());
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
{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">
|
||||||
|
<div class="card-header" id="customhtml-faq-heading-{$block.id_ws_customhtml|intval}-{$faq.id_ws_customhtml_faq|intval}">
|
||||||
|
<button
|
||||||
|
class="btn btn-link{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}"
|
||||||
|
>
|
||||||
|
{$faq.question|escape:'html':'UTF-8'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -1,13 +1,17 @@
|
|||||||
{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 customhtml-group-{$group.id_ws_customhtml_group|intval} row">
|
||||||
{foreach from=$group.blocks item="block"}
|
{foreach from=$group.blocks item="block"}
|
||||||
<div class="customhtml-block">
|
<div class="customhtml-block col{if !empty($block.custom_class)} {$block.custom_class|escape:'html':'UTF-8'}{/if}">
|
||||||
{if $block.show_title && !empty($block.title)}
|
{if $block.show_title && !empty($block.title)}
|
||||||
<div class="customhtml-title">{$block.title|escape:'html':'UTF-8'}</div>
|
<div class="customhtml-title">{$block.title|escape:'html':'UTF-8'}</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
{if $block.type == 'faq'}
|
||||||
|
{include file="module:ws_customhtml/views/templates/hook/_faq_accordion.tpl" block=$block}
|
||||||
|
{else}
|
||||||
<div class="customhtml-content">{$block.content nofilter}</div>
|
<div class="customhtml-content">{$block.content nofilter}</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+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.5.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