From fb641fc23620459778a6458b2174540aa1c1a3d8 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Thu, 13 Aug 2026 11:33:24 +0200 Subject: [PATCH] feat(main): Add custom CSS classes to HTML blocks This feature allows administrators to define custom CSS classes for individual HTML blocks. It enhances styling flexibility and integrates with common grid systems (e.g., Bootstrap `col-md-6`) by applying user-defined classes to the block's wrapper element. Includes: - A new `custom_class` field in the block model, form, and data handlers. - Database schema updates with an upgrade path to handle potential renames from `column_class`. - Frontend rendering to apply the classes. - Registration of `actionFrontControllerSetMedia` hook to load front-end CSS. - Basic responsive image styling for blocks. --- src/Config/Config.php | 1 + .../CustomHtmlBlockDataHandler.php | 2 ++ .../CustomHtmlBlockDataProvider.php | 2 ++ src/Form/Type/CustomHtmlBlockType.php | 5 +++ src/Model/CustomHtmlBlock.php | 6 +++- src/Module/DisplayHooks.php | 8 +++++ src/Module/Install.php | 1 + upgrade/upgrade-1.3.0.php | 23 +++++++++++++ upgrade/upgrade-1.4.0.php | 14 ++++++++ upgrade/upgrade-1.5.0.php | 32 +++++++++++++++++++ views/css/front/customhtml.css | 4 +++ .../admin/form/blocks/block_form.html.twig | 1 + views/templates/hook/customhtml_block.tpl | 4 +-- ws_customhtml.php | 2 +- 14 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 upgrade/upgrade-1.3.0.php create mode 100644 upgrade/upgrade-1.4.0.php create mode 100644 upgrade/upgrade-1.5.0.php create mode 100644 views/css/front/customhtml.css diff --git a/src/Config/Config.php b/src/Config/Config.php index 27b5bc0..49a3bfc 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -7,6 +7,7 @@ class Config const HOOKS = [ 'actionAdminControllerSetMedia', 'actionCustomhtmlblockGridDataModifier', + 'actionFrontControllerSetMedia', ]; const BLOCK_TYPES = [ diff --git a/src/Form/DataHandler/CustomHtmlBlockDataHandler.php b/src/Form/DataHandler/CustomHtmlBlockDataHandler.php index 60b827b..6e4af5d 100644 --- a/src/Form/DataHandler/CustomHtmlBlockDataHandler.php +++ b/src/Form/DataHandler/CustomHtmlBlockDataHandler.php @@ -19,6 +19,7 @@ final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface $block->title = (string) $formData['title']; $block->type = (string) $formData['type']; $block->show_title = (int) $formData['show_title']; + $block->custom_class = (string) ($formData['custom_class'] ?? ''); $block->content = (string) $formData['content']; $block->active = (int) $formData['active']; $block->ordering = $this->getNextOrdering($idGroup); @@ -44,6 +45,7 @@ final class CustomHtmlBlockDataHandler implements FormDataHandlerInterface $block->title = (string) $formData['title']; $block->type = (string) $formData['type']; $block->show_title = (int) $formData['show_title']; + $block->custom_class = (string) ($formData['custom_class'] ?? ''); $block->content = (string) $formData['content']; $block->active = (int) $formData['active']; diff --git a/src/Form/DataProvider/CustomHtmlBlockDataProvider.php b/src/Form/DataProvider/CustomHtmlBlockDataProvider.php index 4149bbd..974e700 100644 --- a/src/Form/DataProvider/CustomHtmlBlockDataProvider.php +++ b/src/Form/DataProvider/CustomHtmlBlockDataProvider.php @@ -22,6 +22,7 @@ final class CustomHtmlBlockDataProvider implements FormDataProviderInterface 'title' => $block->title, 'type' => $block->type, 'show_title' => (bool) $block->show_title, + 'custom_class' => $block->custom_class, 'content' => $block->content, 'faqs' => $this->loadFaqs((int) $id), 'active' => (bool) $block->active, @@ -35,6 +36,7 @@ final class CustomHtmlBlockDataProvider implements FormDataProviderInterface 'title' => '', 'type' => 'html', 'show_title' => false, + 'custom_class' => '', 'content' => '', 'faqs' => [], 'active' => true, diff --git a/src/Form/Type/CustomHtmlBlockType.php b/src/Form/Type/CustomHtmlBlockType.php index 945eaf9..d9907c3 100644 --- a/src/Form/Type/CustomHtmlBlockType.php +++ b/src/Form/Type/CustomHtmlBlockType.php @@ -48,6 +48,11 @@ class CustomHtmlBlockType extends AbstractType 'label' => $this->translator->trans('Show title', [], 'Modules.Wscustomhtml.Admin'), '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, [ 'label' => $this->translator->trans('Content', [], 'Modules.Wscustomhtml.Admin'), 'required' => false, diff --git a/src/Model/CustomHtmlBlock.php b/src/Model/CustomHtmlBlock.php index 87ac2d3..a33ddc2 100644 --- a/src/Model/CustomHtmlBlock.php +++ b/src/Model/CustomHtmlBlock.php @@ -22,6 +22,9 @@ class CustomHtmlBlock extends ObjectModel /** @var string */ public $content = ''; + /** @var string */ + public $custom_class = ''; + /** @var int */ public $active = 1; @@ -45,6 +48,7 @@ class CustomHtmlBlock extends ObjectModel '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'], + 'custom_class' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => false, 'size' => 128], 'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'], 'show_title' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'], 'ordering' => ['type' => self::TYPE_INT, 'validate' => 'isInt'], @@ -62,7 +66,7 @@ class CustomHtmlBlock extends ObjectModel } $result = Db::getInstance()->executeS( - 'SELECT `id_ws_customhtml`, `id_ws_customhtml_group`, `title`, `type`, `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` WHERE `id_ws_customhtml_group` IN (' . implode(',', $groupIds) . ') AND `active` = 1 diff --git a/src/Module/DisplayHooks.php b/src/Module/DisplayHooks.php index 09e3e9a..b9b5337 100644 --- a/src/Module/DisplayHooks.php +++ b/src/Module/DisplayHooks.php @@ -9,6 +9,14 @@ use Context; 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 = []) { if (empty($hookName)) { diff --git a/src/Module/Install.php b/src/Module/Install.php index 85fc1a1..089bdd4 100644 --- a/src/Module/Install.php +++ b/src/Module/Install.php @@ -64,6 +64,7 @@ trait Install `title` VARCHAR(256) NOT NULL DEFAULT \'\', `type` VARCHAR(32) NOT NULL DEFAULT \'html\', `content` LONGTEXT, + `custom_class` VARCHAR(128) NOT NULL DEFAULT \'\', `active` TINYINT(1) NOT NULL DEFAULT 1, `show_title` TINYINT(1) NOT NULL DEFAULT 0, `ordering` INT(11) NOT NULL DEFAULT 0, diff --git a/upgrade/upgrade-1.3.0.php b/upgrade/upgrade-1.3.0.php new file mode 100644 index 0000000..e3e8e84 --- /dev/null +++ b/upgrade/upgrade-1.3.0.php @@ -0,0 +1,23 @@ +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; +} diff --git a/upgrade/upgrade-1.4.0.php b/upgrade/upgrade-1.4.0.php new file mode 100644 index 0000000..b333ba7 --- /dev/null +++ b/upgrade/upgrade-1.4.0.php @@ -0,0 +1,14 @@ +shop->id)) { + return $module->registerHook('actionFrontControllerSetMedia'); + } + + return true; +} diff --git a/upgrade/upgrade-1.5.0.php b/upgrade/upgrade-1.5.0.php new file mode 100644 index 0000000..60d48a0 --- /dev/null +++ b/upgrade/upgrade-1.5.0.php @@ -0,0 +1,32 @@ +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`' + ); +} diff --git a/views/css/front/customhtml.css b/views/css/front/customhtml.css new file mode 100644 index 0000000..7c5acd1 --- /dev/null +++ b/views/css/front/customhtml.css @@ -0,0 +1,4 @@ +.customhtml-block img { + max-width: 100%; + height: auto; +} diff --git a/views/templates/admin/form/blocks/block_form.html.twig b/views/templates/admin/form/blocks/block_form.html.twig index 3267dc6..edc354d 100644 --- a/views/templates/admin/form/blocks/block_form.html.twig +++ b/views/templates/admin/form/blocks/block_form.html.twig @@ -20,6 +20,7 @@ {{ form_row(customHtmlBlockForm.title) }} {{ form_row(customHtmlBlockForm.type) }} {{ form_row(customHtmlBlockForm.show_title) }} + {{ form_row(customHtmlBlockForm.custom_class) }} {{ form_row(customHtmlBlockForm.content) }}
diff --git a/views/templates/hook/customhtml_block.tpl b/views/templates/hook/customhtml_block.tpl index 057130b..5d472a5 100644 --- a/views/templates/hook/customhtml_block.tpl +++ b/views/templates/hook/customhtml_block.tpl @@ -1,9 +1,9 @@ {if !empty($groupList)}
{foreach from=$groupList item="group"} -
+
{foreach from=$group.blocks item="block"} -
+
{if $block.show_title && !empty($block.title)}
{$block.title|escape:'html':'UTF-8'}
{/if} diff --git a/ws_customhtml.php b/ws_customhtml.php index b305729..f8fc807 100644 --- a/ws_customhtml.php +++ b/ws_customhtml.php @@ -29,7 +29,7 @@ class Ws_CustomHtml extends Module implements WidgetInterface public function __construct() { $this->name = 'ws_customhtml'; - $this->version = '1.2.0'; + $this->version = '1.5.0'; $this->author = 'Isabelle Oving-Anno | De Websmid BV'; $this->need_instance = 0; $this->bootstrap = true;