diff --git a/composer.json b/composer.json index 7fd43d81d..63c3ffaf5 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "require": { "php": "^8.2", "ext-dom": "*", - "contao-community-alliance/dc-general": "^2.4.2", + "contao-community-alliance/dc-general": "^2.4.12", "contao-community-alliance/events-contao-bindings": "^5.0", "contao-community-alliance/meta-palettes": "^2.0.10", "contao-community-alliance/translator": "^2.5", diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 58db16bac..6152b0680 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2025 The MetaModels team. + * (c) 2012-2026 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -19,7 +19,7 @@ * @author David Molineus * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2025 The MetaModels team. + * @copyright 2012-2026 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -526,6 +526,7 @@ private function setBaseEval($fieldDefinition, $overrides) 'preserveTags', 'decodeEntities', 'rte', + 'highlight', 'rows', 'cols', 'spaceToUnderscore', diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AceHighlightVisibilityListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AceHighlightVisibilityListener.php new file mode 100644 index 000000000..a356e00bc --- /dev/null +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AceHighlightVisibilityListener.php @@ -0,0 +1,109 @@ + + * @copyright 2012-2026 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting; + +use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; +use ContaoCommunityAlliance\DcGeneral\Data\PropertyValueBag; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Property\PropertyCallbackCondition; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Property\PropertyConditionChain; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Property\PropertyValueCondition; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\PropertyInterface; +use ContaoCommunityAlliance\DcGeneral\Factory\Event\BuildDataDefinitionEvent; + +/** + * Replaces the exact-match condition for the "highlight" property's "rte" selector with a prefix match, + * so that "highlight" is visible for all ACE editor template variants (e.g. "ace", "ace_mm"). + */ +final class AceHighlightVisibilityListener +{ + /** + * Replace the PropertyValueCondition('rte', 'ace') on the "highlight" property with a callback + * condition that matches any rte value starting with 'ace'. + * + * @param BuildDataDefinitionEvent $event The event. + * + * @return void + */ + public function handle(BuildDataDefinitionEvent $event): void + { + if ($event->getContainer()->getName() !== 'tl_metamodel_dcasetting') { + return; + } + + if (!$event->getContainer()->hasPalettesDefinition()) { + return; + } + + $palettesDefinition = $event->getContainer()->getPalettesDefinition(); + + foreach ($palettesDefinition->getPalettes() as $palette) { + foreach ($palette->getLegends() as $legend) { + foreach ($legend->getProperties() as $property) { + if ($property->getName() !== 'highlight') { + continue; + } + + $this->replaceRteValueCondition($property); + } + } + } + } + + /** + * Replace PropertyValueCondition('rte', *) in the property's AND chain with a prefix callback. + * + * @param PropertyInterface $property The palette property. + * + * @return void + */ + private function replaceRteValueCondition(PropertyInterface $property): void + { + $condition = $property->getVisibleCondition(); + if (!($condition instanceof PropertyConditionChain)) { + return; + } + + foreach ($condition->getConditions() as $subCondition) { + if ( + ($subCondition instanceof PropertyValueCondition) + && ($subCondition->getPropertyName() === 'rte') + ) { + $condition->removeCondition($subCondition); + $condition->addCondition( + new PropertyCallbackCondition( + static function (?ModelInterface $model, ?PropertyValueBag $input): bool { + if (null !== $input && $input->hasPropertyValue('rte')) { + $value = $input->getPropertyValue('rte'); + } elseif (null !== $model) { + $value = $model->getProperty('rte'); + } else { + return false; + } + + return \is_string($value) && \str_starts_with($value, 'ace'); + } + ) + ); + + return; + } + } + } +} diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/RichTextOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/RichTextOptionListener.php index 3d7b62db6..8f0f83f40 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/RichTextOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/RichTextOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2026 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -14,7 +14,7 @@ * @author Christian Schiffler * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2026 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -64,9 +64,14 @@ public function handle(GetPropertyOptionsEvent $event) $configs = []; // Delete 'be_' prefix from keys. + // Add tiny templates. foreach ($this->templateList->getTemplatesForBase('be_tiny') as $key => $value) { $configs[substr($key, 3)] = $value; } + // Add ace templates. + foreach ($this->templateList->getTemplatesForBase('be_ace') as $key => $value) { + $configs[substr($key, 3)] = $value; + } $event->setOptions($configs); } diff --git a/src/CoreBundle/Resources/config/dc-general/table/tl_dcasetting.yml b/src/CoreBundle/Resources/config/dc-general/table/tl_dcasetting.yml index 0e306f3c3..88c56677d 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_dcasetting.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_dcasetting.yml @@ -99,6 +99,14 @@ services: event: dc-general.factory.build-data-definition method: handle + metamodels.listener.table.tl_metamodel_dcasetting.ace_highlight_visibility: + class: MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting\AceHighlightVisibilityListener + tags: + - name: kernel.event_listener + event: dc-general.factory.build-data-definition + method: handle + priority: -100 + metamodels.listener.table.tl_metamodel_dcasetting.rich_text_options: class: MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting\RichTextOptionListener arguments: @@ -154,3 +162,4 @@ services: - name: kernel.event_listener event: dc-general.view.contao2backend.manipulate-widget method: handle + diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php index 7d4e1b2ef..62854fe21 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php @@ -244,6 +244,7 @@ // * preserveTags do not encode html tags. // * decodeEntities do decode HTML entities. // * rte enable richtext editor on this + // * highlight set type of highlighting for ACE editor // * rows amount of rows in longtext and tables. // * cols amount of columns in longtext and tables. // * trailingSlash allow trailing slash, 2 => do nothing, 1 => add one on save, 0 => strip it on save. @@ -253,7 +254,14 @@ // * readonly readonly. // * be_template widget template for backend. // * fe_template form template for frontend. - ] + ], + 'rte' => [ + 'ace' => [ + 'presentation after rte' => [ + 'highlight', + ] + ] + ], ], 'fields' => [ 'id' => [ @@ -442,9 +450,43 @@ 'eval' => [ 'tl_class' => 'w50', 'includeBlankOption' => true, + 'submitOnChange' => true, ], 'sql' => "varchar(64) NOT NULL default 'tinyMCE'" ], + 'highlight' => [ + 'label' => 'highlight.label', + 'description' => 'highlight.description', + 'inputType' => 'select', + 'options' => [ + 'Apache', + 'Bash', + 'C#', + 'C++', + 'CSS', + 'Diff', + 'HTML', + 'HTTP', + 'Ini', + 'JSON', + 'Java', + 'JavaScript', + 'Markdown', + 'Nginx', + 'Perl', + 'PHP', + 'PowerShell', + 'Python', + 'Ruby', + 'SCSS', + 'SQL', + 'Twig', + 'YAML', + 'XML' + ], + 'eval' => ['includeBlankOption' => true, 'decodeEntities' => true, 'tl_class' => 'w50'], + 'sql' => "varchar(32) COLLATE ascii_bin NOT NULL default ''" + ], 'rows' => [ 'label' => 'rows.label', 'description' => 'rows.description', @@ -452,7 +494,7 @@ 'inputType' => 'text', 'eval' => [ - 'tl_class' => 'w50', + 'tl_class' => 'clr w50', 'rgxp' => 'digit' ], 'sql' => "int(10) NOT NULL default '0'" diff --git a/src/CoreBundle/Resources/contao/templates/be_ace_mm.html5 b/src/CoreBundle/Resources/contao/templates/be_ace_mm.html5 new file mode 100644 index 000000000..3adec21a3 --- /dev/null +++ b/src/CoreBundle/Resources/contao/templates/be_ace_mm.html5 @@ -0,0 +1,79 @@ + + + + diff --git a/src/CoreBundle/Resources/contao/templates/be_tinyMCE_mm.html5 b/src/CoreBundle/Resources/contao/templates/be_tinyMCE_mm.html5 new file mode 100644 index 000000000..bbf82c72a --- /dev/null +++ b/src/CoreBundle/Resources/contao/templates/be_tinyMCE_mm.html5 @@ -0,0 +1,7 @@ +extend('be_tinyMCE'); ?> + +block('custom'); ?> +rows)): ?> + max_height: rows ?>, + +endblock(); ?> diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.de.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.de.xlf index 71c3b9862..542015134 100644 --- a/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.de.xlf +++ b/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.de.xlf @@ -269,6 +269,14 @@ Select the rich text configuration that shall be used on this field (if any). Wählen Sie eine Voreinstellung für den Richtext-Editor aus, die für dieses Feld benutzt werden soll (falls vorhanden). + + Syntax highlighting mode + Syntax-Hervorhebungsmodus + + + Select the syntax highlighting mode for the ACE editor (e.g. "html", "css", "javascript"). Only relevant when an ACE editor configuration is selected. + Wählen Sie den Syntax-Hervorhebungsmodus für den ACE-Editor (z.B. "html", "css", "javascript"). Nur relevant, wenn eine ACE-Editor-Konfiguration ausgewählt ist. + Rows Zeilen diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.en.xlf index 5dee9627d..afa148e6c 100644 --- a/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.en.xlf +++ b/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.en.xlf @@ -205,6 +205,12 @@ Select the rich text configuration that shall be used on this field (if any). + + Syntax highlighting mode + + + Select the syntax highlighting mode for the ACE editor (e.g. "html", "css", "javascript"). Only relevant when an ACE editor configuration is selected. + Rows