From 1377465cd23fd4ac29f25ea617aad4d62c88e7f7 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 30 Jul 2025 22:37:32 +0200 Subject: [PATCH 1/4] Add preset for FE filter --- .../Contao/Hooks/ContentElementCallback.php | 6 ++- .../Hooks/FilterContentElementCallback.php | 46 +++++++++++++++++ .../Contao/Hooks/FilterModuleCallback.php | 46 +++++++++++++++++ .../Contao/Hooks/ModuleCallback.php | 4 ++ src/CoreBundle/Resources/config/hooks.yml | 24 +++++++++ .../Resources/contao/dca/tl_content.php | 7 ++- .../Resources/contao/dca/tl_module.php | 7 ++- src/FrontendIntegration/FrontendFilter.php | 50 ++++++++++++++++++- 8 files changed, 184 insertions(+), 6 deletions(-) create mode 100644 src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php create mode 100644 src/CoreBundle/Contao/Hooks/FilterModuleCallback.php diff --git a/src/CoreBundle/Contao/Hooks/ContentElementCallback.php b/src/CoreBundle/Contao/Hooks/ContentElementCallback.php index 0a370a7dc..ca0789eb5 100644 --- a/src/CoreBundle/Contao/Hooks/ContentElementCallback.php +++ b/src/CoreBundle/Contao/Hooks/ContentElementCallback.php @@ -45,7 +45,11 @@ class ContentElementCallback extends AbstractContentElementAndModuleCallback */ public function buildFilterParameterList(DC_Table $dataContainer) { - parent::buildFilterParamsFor($dataContainer, 'metamodel_content'); + if ($dataContainer->getCurrentRecord()['type'] !== 'metamodel_content') { + return; + } + + $this->buildFilterParamsFor($dataContainer, 'metamodel_content'); } /** diff --git a/src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php b/src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php new file mode 100644 index 000000000..3a12a688b --- /dev/null +++ b/src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php @@ -0,0 +1,46 @@ + + * @copyright 2012-2025 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\Contao\Hooks; + +use Contao\DC_Table; +use MetaModels\CoreBundle\Contao\Hooks\AbstractContentElementAndModuleCallback; + +/** + * This class provides callbacks for tl_content. + */ +class FilterContentElementCallback extends AbstractContentElementAndModuleCallback +{ + /** + * The table name. + * + * @var string + */ + protected static $tableName = 'tl_content'; + + /** Called from tl_content.onload_callback. */ + public function buildFilterParameterList(DC_Table $dataContainer): void + { + if ($dataContainer->getCurrentRecord()['type'] !== 'metamodels_frontendfilter') { + return; + } + + $this->buildFilterParamsFor($dataContainer, 'metamodels_frontendfilter'); + } +} diff --git a/src/CoreBundle/Contao/Hooks/FilterModuleCallback.php b/src/CoreBundle/Contao/Hooks/FilterModuleCallback.php new file mode 100644 index 000000000..b69443868 --- /dev/null +++ b/src/CoreBundle/Contao/Hooks/FilterModuleCallback.php @@ -0,0 +1,46 @@ + + * @copyright 2012-2025 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\Contao\Hooks; + +use Contao\DC_Table; +use MetaModels\CoreBundle\Contao\Hooks\AbstractContentElementAndModuleCallback; + +/** + * This class provides callbacks for tl_module. + */ +class FilterModuleCallback extends AbstractContentElementAndModuleCallback +{ + /** + * The table name. + * + * @var string + */ + protected static $tableName = 'tl_module'; + + /** Called from tl_module.onload_callback. */ + public function buildFilterParameterList(DC_Table $dataContainer): void + { + if ($dataContainer->getCurrentRecord()['type'] !== 'metamodels_frontendfilter') { + return; + } + + $this->buildFilterParamsFor($dataContainer, 'metamodels_frontendfilter'); + } +} diff --git a/src/CoreBundle/Contao/Hooks/ModuleCallback.php b/src/CoreBundle/Contao/Hooks/ModuleCallback.php index 87d88d890..dc092d550 100644 --- a/src/CoreBundle/Contao/Hooks/ModuleCallback.php +++ b/src/CoreBundle/Contao/Hooks/ModuleCallback.php @@ -43,6 +43,10 @@ class ModuleCallback extends AbstractContentElementAndModuleCallback */ public function buildFilterParameterList(DC_Table $dataContainer) { + if ($dataContainer->getCurrentRecord()['type'] !== 'metamodel_list') { + return; + } + parent::buildFilterParamsFor($dataContainer, 'metamodel_list'); } diff --git a/src/CoreBundle/Resources/config/hooks.yml b/src/CoreBundle/Resources/config/hooks.yml index 2b7dbe781..7c392872a 100644 --- a/src/CoreBundle/Resources/config/hooks.yml +++ b/src/CoreBundle/Resources/config/hooks.yml @@ -34,6 +34,30 @@ services: - '@translator' public: true + MetaModels\CoreBundle\Contao\Hooks\FilterContentElementCallback: + arguments: + - '@metamodels.assets.icon_builder' + - '@metamodels.backend.url-builder-factory' + - '@metamodels.factory' + - '@metamodels.filter_setting_factory' + - '@database_connection' + - '@metamodels.template_list' + - '@request_stack' + - '@translator' + public: true + + MetaModels\CoreBundle\Contao\Hooks\FilterModuleCallback: + arguments: + - '@metamodels.assets.icon_builder' + - '@metamodels.backend.url-builder-factory' + - '@metamodels.factory' + - '@metamodels.filter_setting_factory' + - '@database_connection' + - '@metamodels.template_list' + - '@request_stack' + - '@translator' + public: true + MetaModels\CoreBundle\EventListener\GetSearchablePagesListener: arguments: - '@database_connection' diff --git a/src/CoreBundle/Resources/contao/dca/tl_content.php b/src/CoreBundle/Resources/contao/dca/tl_content.php index 34c0fd5d0..7985b3300 100755 --- a/src/CoreBundle/Resources/contao/dca/tl_content.php +++ b/src/CoreBundle/Resources/contao/dca/tl_content.php @@ -24,9 +24,12 @@ */ use MetaModels\CoreBundle\Contao\Hooks\ContentElementCallback; +use MetaModels\CoreBundle\Contao\Hooks\FilterContentElementCallback; $GLOBALS['TL_DCA']['tl_content']['config']['onload_callback'][] = [ContentElementCallback::class, 'buildFilterParameterList']; +$GLOBALS['TL_DCA']['tl_content']['config']['onload_callback'][] = + [FilterContentElementCallback::class, 'buildFilterParameterList']; $GLOBALS['TL_DCA']['tl_content']['palettes']['metamodel_content'] = '{type_legend},type,headline;' . @@ -45,8 +48,8 @@ $GLOBALS['TL_DCA']['tl_content']['palettes']['metamodels_frontendfilter'] = '{type_legend},type,headline;' . - '{mm_filter_legend},metamodel,metamodel_filtering,metamodel_fef_template,metamodel_fef_params,' . - 'metamodel_fef_autosubmit,metamodel_fef_hideclearfilter,metamodel_available_values,' . + '{mm_filter_legend},metamodel,metamodel_filtering,metamodel_fef_template,metamodel_filterparams,' . + 'metamodel_fef_params,metamodel_fef_autosubmit,metamodel_fef_hideclearfilter,metamodel_available_values,' . 'metamodel_jumpTo,metamodel_fef_id,metamodel_fef_urlfragment;' . '{protected_legend:hide},protected;' . '{expert_legend:hide},guests,cssID,space;' . diff --git a/src/CoreBundle/Resources/contao/dca/tl_module.php b/src/CoreBundle/Resources/contao/dca/tl_module.php index 9552c1264..e3120623c 100755 --- a/src/CoreBundle/Resources/contao/dca/tl_module.php +++ b/src/CoreBundle/Resources/contao/dca/tl_module.php @@ -24,8 +24,11 @@ */ use MetaModels\CoreBundle\Contao\Hooks\ModuleCallback; +use MetaModels\CoreBundle\Contao\Hooks\FilterModuleCallback; $GLOBALS['TL_DCA']['tl_module']['config']['onload_callback'][] = [ModuleCallback::class, 'buildFilterParameterList']; +$GLOBALS['TL_DCA']['tl_module']['config']['onload_callback'][] = + [FilterModuleCallback::class, 'buildFilterParameterList']; $GLOBALS['TL_DCA']['tl_module']['palettes']['metamodel_list'] = '{title_legend},name,headline,type;' . @@ -43,8 +46,8 @@ $GLOBALS['TL_DCA']['tl_module']['palettes']['metamodels_frontendfilter'] = '{title_legend},name,headline,type;' . - '{mm_filter_legend},metamodel,metamodel_filtering,metamodel_fef_template,metamodel_fef_params,' . - 'metamodel_fef_autosubmit,metamodel_fef_hideclearfilter,metamodel_available_values,' . + '{mm_filter_legend},metamodel,metamodel_filtering,metamodel_fef_template,metamodel_filterparams,' . + 'metamodel_fef_params,metamodel_fef_autosubmit,metamodel_fef_hideclearfilter,metamodel_available_values,' . 'metamodel_jumpTo,metamodel_fef_id,metamodel_fef_urlfragment;' . '{protected_legend:hide},protected;' . '{expert_legend:hide},guests,cssID,space'; diff --git a/src/FrontendIntegration/FrontendFilter.php b/src/FrontendIntegration/FrontendFilter.php index 23029c476..f4ace7119 100644 --- a/src/FrontendIntegration/FrontendFilter.php +++ b/src/FrontendIntegration/FrontendFilter.php @@ -28,6 +28,7 @@ namespace MetaModels\FrontendIntegration; +use Contao\StringUtil; use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; use ContaoCommunityAlliance\Contao\Bindings\Events\Controller\RedirectEvent; use Contao\CoreBundle\Csrf\ContaoCsrfTokenManager; @@ -427,8 +428,13 @@ protected function getFilters() } } + // TODO: hier presets einbauen... + $values = \array_merge($all->getSlugParameters(), $all->getGetParameters()); + $baseParameters = $this->getBaseParameters($values); + //$baseParameters = ['select' => 'abteilung-a']; $arrWidgets = $filterSetting->getParameterFilterWidgets( - \array_merge($all->getSlugParameters(), $all->getGetParameters()), + \array_merge($baseParameters, $values), + //\array_merge($all->getSlugParameters(), $all->getGetParameters()), $jumpToInformation, $filterOptions ); @@ -622,4 +628,46 @@ public function generateClearAll($strContent, $strTemplate) return $strContent; } + + private function getBaseParameters($values): array + { + if ([] === ($presets = StringUtil::deserialize($this->objFilterConfig->metamodel_filterparams, true))) { + return []; + } + + if (null === ($filterSetting = $this->objFilterConfig->getFilterCollection())) { + throw new RuntimeException( + 'Error: no filter object defined, call setFilterSettings() before setFilterParameters().' + ); + } + + $presetNames = $filterSetting->getParameters(); + $filterParamKeys = \array_keys($filterSetting->getParameterFilterNames()); + + $processed = []; + + // We have to use all the preset values we want first. + foreach ($presets as $presetName => $presetValues) { + if (\in_array($presetName, $presetNames, true)) { + $processed[$presetName] = $presetValues['value']; + } + } + + // Now we have to use all FE filter params, that are either: + // * not contained within the presets + // * or are overridable. + foreach ($filterParamKeys as $filterParameterKey) { + // Unknown parameter? - next please. + if (!\array_key_exists($filterParameterKey, $values)) { + continue; + } + + // Not a preset or allowed to override? - use value. + if ((!\array_key_exists($filterParameterKey, $presets)) || (bool) $presets[$filterParameterKey]['use_get']) { + $processed[$filterParameterKey] = $values[$filterParameterKey]; + } + } + + return $processed; + } } From 454be5cb3c70172873b229457d689761a4b7e872 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 30 Jul 2025 23:04:46 +0200 Subject: [PATCH 2/4] Add preset for FE filter --- .../Contao/Hooks/ContentElementCallback.php | 5 ++++- .../Contao/Hooks/FilterContentElementCallback.php | 7 +++++-- .../Contao/Hooks/FilterModuleCallback.php | 7 +++++-- src/CoreBundle/Contao/Hooks/ModuleCallback.php | 5 ++++- src/FrontendIntegration/FrontendFilter.php | 14 ++++++++------ 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/CoreBundle/Contao/Hooks/ContentElementCallback.php b/src/CoreBundle/Contao/Hooks/ContentElementCallback.php index ca0789eb5..13c024b14 100644 --- a/src/CoreBundle/Contao/Hooks/ContentElementCallback.php +++ b/src/CoreBundle/Contao/Hooks/ContentElementCallback.php @@ -45,7 +45,10 @@ class ContentElementCallback extends AbstractContentElementAndModuleCallback */ public function buildFilterParameterList(DC_Table $dataContainer) { - if ($dataContainer->getCurrentRecord()['type'] !== 'metamodel_content') { + if ( + null === ($currentRecord = $dataContainer->getCurrentRecord()) + || $currentRecord['type'] !== 'metamodel_content' + ) { return; } diff --git a/src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php b/src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php index 3a12a688b..5d35b1a68 100644 --- a/src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php +++ b/src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php @@ -25,7 +25,7 @@ /** * This class provides callbacks for tl_content. */ -class FilterContentElementCallback extends AbstractContentElementAndModuleCallback +final class FilterContentElementCallback extends AbstractContentElementAndModuleCallback { /** * The table name. @@ -37,7 +37,10 @@ class FilterContentElementCallback extends AbstractContentElementAndModuleCallba /** Called from tl_content.onload_callback. */ public function buildFilterParameterList(DC_Table $dataContainer): void { - if ($dataContainer->getCurrentRecord()['type'] !== 'metamodels_frontendfilter') { + if ( + null === ($currentRecord = $dataContainer->getCurrentRecord()) + || $currentRecord['type'] !== 'metamodels_frontendfilter' + ) { return; } diff --git a/src/CoreBundle/Contao/Hooks/FilterModuleCallback.php b/src/CoreBundle/Contao/Hooks/FilterModuleCallback.php index b69443868..42b45871a 100644 --- a/src/CoreBundle/Contao/Hooks/FilterModuleCallback.php +++ b/src/CoreBundle/Contao/Hooks/FilterModuleCallback.php @@ -25,7 +25,7 @@ /** * This class provides callbacks for tl_module. */ -class FilterModuleCallback extends AbstractContentElementAndModuleCallback +final class FilterModuleCallback extends AbstractContentElementAndModuleCallback { /** * The table name. @@ -37,7 +37,10 @@ class FilterModuleCallback extends AbstractContentElementAndModuleCallback /** Called from tl_module.onload_callback. */ public function buildFilterParameterList(DC_Table $dataContainer): void { - if ($dataContainer->getCurrentRecord()['type'] !== 'metamodels_frontendfilter') { + if ( + null === ($currentRecord = $dataContainer->getCurrentRecord()) + || $currentRecord['type'] !== 'metamodels_frontendfilter' + ) { return; } diff --git a/src/CoreBundle/Contao/Hooks/ModuleCallback.php b/src/CoreBundle/Contao/Hooks/ModuleCallback.php index dc092d550..a21e83d39 100644 --- a/src/CoreBundle/Contao/Hooks/ModuleCallback.php +++ b/src/CoreBundle/Contao/Hooks/ModuleCallback.php @@ -43,7 +43,10 @@ class ModuleCallback extends AbstractContentElementAndModuleCallback */ public function buildFilterParameterList(DC_Table $dataContainer) { - if ($dataContainer->getCurrentRecord()['type'] !== 'metamodel_list') { + if ( + null === ($currentRecord = $dataContainer->getCurrentRecord()) + || $currentRecord['type'] !== 'metamodel_list' + ) { return; } diff --git a/src/FrontendIntegration/FrontendFilter.php b/src/FrontendIntegration/FrontendFilter.php index f4ace7119..62752897b 100644 --- a/src/FrontendIntegration/FrontendFilter.php +++ b/src/FrontendIntegration/FrontendFilter.php @@ -428,13 +428,11 @@ protected function getFilters() } } - // TODO: hier presets einbauen... $values = \array_merge($all->getSlugParameters(), $all->getGetParameters()); $baseParameters = $this->getBaseParameters($values); - //$baseParameters = ['select' => 'abteilung-a']; + $arrWidgets = $filterSetting->getParameterFilterWidgets( \array_merge($baseParameters, $values), - //\array_merge($all->getSlugParameters(), $all->getGetParameters()), $jumpToInformation, $filterOptions ); @@ -629,8 +627,9 @@ public function generateClearAll($strContent, $strTemplate) return $strContent; } - private function getBaseParameters($values): array + private function getBaseParameters(array $values): array { + /** @psalm-suppress UndefinedMagicPropertyFetch */ if ([] === ($presets = StringUtil::deserialize($this->objFilterConfig->metamodel_filterparams, true))) { return []; } @@ -657,13 +656,16 @@ private function getBaseParameters($values): array // * not contained within the presets // * or are overridable. foreach ($filterParamKeys as $filterParameterKey) { - // Unknown parameter? - next please. + // Unknown parameter? - next, please. if (!\array_key_exists($filterParameterKey, $values)) { continue; } // Not a preset or allowed to override? - use value. - if ((!\array_key_exists($filterParameterKey, $presets)) || (bool) $presets[$filterParameterKey]['use_get']) { + if ( + (!\array_key_exists($filterParameterKey, $presets)) + || (bool) $presets[$filterParameterKey]['use_get'] + ) { $processed[$filterParameterKey] = $values[$filterParameterKey]; } } From b3c49960b26c8776f4223870994a64764805c39c Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 2 Aug 2025 19:25:11 +0200 Subject: [PATCH 3/4] Add preset for FE filter --- src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php | 1 - src/CoreBundle/Contao/Hooks/FilterModuleCallback.php | 1 - 2 files changed, 2 deletions(-) diff --git a/src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php b/src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php index 5d35b1a68..274ffef58 100644 --- a/src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php +++ b/src/CoreBundle/Contao/Hooks/FilterContentElementCallback.php @@ -20,7 +20,6 @@ namespace MetaModels\CoreBundle\Contao\Hooks; use Contao\DC_Table; -use MetaModels\CoreBundle\Contao\Hooks\AbstractContentElementAndModuleCallback; /** * This class provides callbacks for tl_content. diff --git a/src/CoreBundle/Contao/Hooks/FilterModuleCallback.php b/src/CoreBundle/Contao/Hooks/FilterModuleCallback.php index 42b45871a..b08d5f7ce 100644 --- a/src/CoreBundle/Contao/Hooks/FilterModuleCallback.php +++ b/src/CoreBundle/Contao/Hooks/FilterModuleCallback.php @@ -20,7 +20,6 @@ namespace MetaModels\CoreBundle\Contao\Hooks; use Contao\DC_Table; -use MetaModels\CoreBundle\Contao\Hooks\AbstractContentElementAndModuleCallback; /** * This class provides callbacks for tl_module. From 6554510ecf2b500ab08065ebfd1d507b694b5e1b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 4 Aug 2025 14:04:06 +0200 Subject: [PATCH 4/4] Add preset for FE filter --- src/FrontendIntegration/FrontendFilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FrontendIntegration/FrontendFilter.php b/src/FrontendIntegration/FrontendFilter.php index 62752897b..d2f1c2114 100644 --- a/src/FrontendIntegration/FrontendFilter.php +++ b/src/FrontendIntegration/FrontendFilter.php @@ -432,7 +432,7 @@ protected function getFilters() $baseParameters = $this->getBaseParameters($values); $arrWidgets = $filterSetting->getParameterFilterWidgets( - \array_merge($baseParameters, $values), + \array_merge($values, $baseParameters), $jumpToInformation, $filterOptions );