From 7db1bcc88ed37442bb199439bb06dcf3ce6f5c0f Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 16 Feb 2022 18:59:35 +0100 Subject: [PATCH 001/224] First commit MM 2.3 for Contao 4.13 --- composer.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 45996a7ea..16e718337 100644 --- a/composer.json +++ b/composer.json @@ -7,13 +7,13 @@ "core" ], "type": "contao-bundle", - "homepage": "http://now.metamodel.me/", + "homepage": "https://now.metamodel.me/", "license": "LGPL-3.0-or-later", "authors": [ { "name": "Christian Schiffler", "email": "c.schiffler@cyberspectrum.de", - "homepage": "http://www.cyberspectrum.de", + "homepage": "https://www.cyberspectrum.de", "role": "Developer" }, { @@ -36,7 +36,7 @@ "contao-community-alliance/meta-palettes": "~2.0", "contao-community-alliance/translator": "^2.2", "contao-community-alliance/url-builder": "~1.3", - "contao/core-bundle": "^4.9.0, <4.13.0", + "contao/core-bundle": "^4.13.0, <5.0", "discordier/justtextwidgets": "^1.2", "doctrine/cache": "~1.6", "menatwork/contao-multicolumnwizard-bundle": "^3.4", @@ -76,7 +76,7 @@ ] }, "branch-alias": { - "dev-feature/2.2.0": "2.2.x-dev" + "dev-feature/2.3.0": "2.3.x-dev" } }, "config": { From 546fb0086e3a0a0778db968e8a251b44752cdf3e Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 19 Feb 2022 12:35:32 +0100 Subject: [PATCH 002/224] Fix composer.json --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 16e718337..2ccd1840f 100644 --- a/composer.json +++ b/composer.json @@ -31,8 +31,8 @@ }, "require": { "php": "^7.4", - "contao-community-alliance/dc-general": "^2.2", - "contao-community-alliance/events-contao-bindings": "^4.9", + "contao-community-alliance/dc-general": "^2.3@dev", + "contao-community-alliance/events-contao-bindings": "^4.9@dev", "contao-community-alliance/meta-palettes": "~2.0", "contao-community-alliance/translator": "^2.2", "contao-community-alliance/url-builder": "~1.3", From a2a03729e2e04a0ea2ae1d3698c5cb3d941c0c1a Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 19 Feb 2022 16:35:22 +0100 Subject: [PATCH 003/224] Update composer --- composer.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 2ccd1840f..5b751529e 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "require": { "php": "^7.4", "contao-community-alliance/dc-general": "^2.3@dev", - "contao-community-alliance/events-contao-bindings": "^4.9@dev", + "contao-community-alliance/events-contao-bindings": "^4.10@dev", "contao-community-alliance/meta-palettes": "~2.0", "contao-community-alliance/translator": "^2.2", "contao-community-alliance/url-builder": "~1.3", @@ -40,12 +40,12 @@ "discordier/justtextwidgets": "^1.2", "doctrine/cache": "~1.6", "menatwork/contao-multicolumnwizard-bundle": "^3.4", - "symfony/asset": "^4.4.6", - "symfony/config": "^4.4.6", - "symfony/dependency-injection": "^4.4.6", - "symfony/event-dispatcher": "^4.4.6", - "symfony/filesystem": "^4.4.6", - "symfony/finder": "^4.4.6", + "symfony/asset": "^5.4", + "symfony/config": "^5.4", + "symfony/dependency-injection": "^5.4", + "symfony/event-dispatcher": "^5.4", + "symfony/filesystem": "^5.4", + "symfony/finder": "^5.4", "terminal42/service-annotation-bundle": "^1.0", "webmozart/path-util": "~2.3" }, From 36cae7397c3b98e05c1feb963e0744183c343406 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 20 Feb 2022 18:34:10 +0100 Subject: [PATCH 004/224] Fix TreeBuilder --- src/CoreBundle/DependencyInjection/Configuration.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/CoreBundle/DependencyInjection/Configuration.php b/src/CoreBundle/DependencyInjection/Configuration.php index a72d9b4a4..26a62eb21 100644 --- a/src/CoreBundle/DependencyInjection/Configuration.php +++ b/src/CoreBundle/DependencyInjection/Configuration.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -62,10 +63,10 @@ public function __construct($debug, $rootDir) */ public function getConfigTreeBuilder() { - $treeBuilder = new TreeBuilder(); - $rootNode = $treeBuilder->root('metamodels'); + $treeBuilder = new TreeBuilder('metamodels'); - $rootNode + $treeBuilder + ->getRootNode() ->children() ->booleanNode('enable_cache') ->defaultValue(!$this->debug) From 82644dc9300a65910235e63a0888a92bf9b1645d Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 22 Feb 2022 18:41:40 +0100 Subject: [PATCH 005/224] Fix doctrine cache --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5b751529e..aa594a136 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,7 @@ "contao-community-alliance/url-builder": "~1.3", "contao/core-bundle": "^4.13.0, <5.0", "discordier/justtextwidgets": "^1.2", - "doctrine/cache": "~1.6", + "doctrine/cache": "~2.1", "menatwork/contao-multicolumnwizard-bundle": "^3.4", "symfony/asset": "^5.4", "symfony/config": "^5.4", From 45b174618a3d3777acb9a348b6eb57737af303a0 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 22 Feb 2022 18:45:01 +0100 Subject: [PATCH 006/224] Fix webmozart --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index aa594a136..5be104408 100644 --- a/composer.json +++ b/composer.json @@ -46,8 +46,7 @@ "symfony/event-dispatcher": "^5.4", "symfony/filesystem": "^5.4", "symfony/finder": "^5.4", - "terminal42/service-annotation-bundle": "^1.0", - "webmozart/path-util": "~2.3" + "terminal42/service-annotation-bundle": "^1.0" }, "require-dev": { "contao/manager-plugin": "^2.8", From 55b4bc3a5e2f3d2c54a0f519966877f88b28daf5 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 24 Feb 2022 21:21:59 +0100 Subject: [PATCH 007/224] Fix doctrine/cache at composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5be104408..f8135878f 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,7 @@ "contao-community-alliance/url-builder": "~1.3", "contao/core-bundle": "^4.13.0, <5.0", "discordier/justtextwidgets": "^1.2", - "doctrine/cache": "~2.1", + "doctrine/cache": "^2.1", "menatwork/contao-multicolumnwizard-bundle": "^3.4", "symfony/asset": "^5.4", "symfony/config": "^5.4", From c36673e71d389bacfac16ece8566002b51e2b217 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 25 Feb 2022 19:32:29 +0100 Subject: [PATCH 008/224] Fix symfony dependency --- composer.json | 3 ++- .../DependencyInjection/MetaModelsCoreExtension.php | 10 +++++----- .../EventListener/BackendNavigationListener.php | 6 +++--- .../DcGeneral/DefinitionBuilder/CommandBuilder.php | 2 +- src/CoreBundle/EventListener/UserListener.php | 6 +++--- src/CoreBundle/Resources/config/services.yml | 13 +++++++++++-- src/Events/CollectMetaModelTableNamesEvent.php | 2 +- src/Events/CreateMetaModelEvent.php | 2 +- src/Events/CreatePropertyConditionEvent.php | 2 +- src/Events/GetMetaModelNameFromIdEvent.php | 2 +- src/Events/MetaModelsBootEvent.php | 2 +- src/Events/ParseItemEvent.php | 2 +- src/Events/RenderItemListEvent.php | 7 ++++--- 13 files changed, 35 insertions(+), 24 deletions(-) diff --git a/composer.json b/composer.json index f8135878f..7be922240 100644 --- a/composer.json +++ b/composer.json @@ -36,11 +36,12 @@ "contao-community-alliance/meta-palettes": "~2.0", "contao-community-alliance/translator": "^2.2", "contao-community-alliance/url-builder": "~1.3", - "contao/core-bundle": "^4.13.0, <5.0", + "contao/core-bundle": "^4.13.0", "discordier/justtextwidgets": "^1.2", "doctrine/cache": "^2.1", "menatwork/contao-multicolumnwizard-bundle": "^3.4", "symfony/asset": "^5.4", + "symfony/cache": "^5.4", "symfony/config": "^5.4", "symfony/dependency-injection": "^5.4", "symfony/event-dispatcher": "^5.4", diff --git a/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php b/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php index cddb6d7ee..71be7c640 100644 --- a/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php +++ b/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,15 +16,15 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author Richard Henkenjohann - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\DependencyInjection; -use Doctrine\Common\Cache\ArrayCache; use MetaModels\CoreBundle\Migration\TableCollationMigration; +use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\Extension; @@ -127,8 +127,8 @@ private function buildCacheService(ContainerBuilder $container, array $config) { // if cache disabled, swap it out with the dummy cache. if (!$config['enable_cache']) { - $cache = $container->getDefinition('metamodels.cache'); - $cache->setClass(ArrayCache::class); + $cache = $container->getDefinition('metamodels.cache_internal'); + $cache->setClass(ArrayAdapter::class); $cache->setArguments([]); $container->setParameter('metamodels.cache_dir', null); return; diff --git a/src/CoreBundle/EventListener/BackendNavigationListener.php b/src/CoreBundle/EventListener/BackendNavigationListener.php index 200b150a9..1ee915378 100644 --- a/src/CoreBundle/EventListener/BackendNavigationListener.php +++ b/src/CoreBundle/EventListener/BackendNavigationListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 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 Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -29,7 +29,7 @@ use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This registers the backend navigation of MetaModels. diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php index 4e70036b2..3a1bbba7c 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php @@ -37,7 +37,7 @@ use MetaModels\IMetaModel; use MetaModels\ViewCombination\ViewCombination; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This class builds the commands. diff --git a/src/CoreBundle/EventListener/UserListener.php b/src/CoreBundle/EventListener/UserListener.php index c13a325f5..d350b6f07 100644 --- a/src/CoreBundle/EventListener/UserListener.php +++ b/src/CoreBundle/EventListener/UserListener.php @@ -24,7 +24,7 @@ use Contao\CoreBundle\Routing\ScopeMatcher; use MetaModels\BackendIntegration\Module; use MetaModels\ViewCombination\ViewCombination; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; @@ -84,14 +84,14 @@ public function __construct( /** * Replaces the current session data with the stored session data. * - * @param GetResponseEvent $event The event. + * @param RequestEvent $event The event. * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) * * @return void */ - public function onKernelRequest(GetResponseEvent $event) + public function onKernelRequest(RequestEvent $event) { if (!$this->scopeMatcher->isBackendMasterRequest($event)) { return; diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index 24baa37c7..b5aad8431 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -16,9 +16,18 @@ services: - "%contao.web_dir%" metamodels.cache: - class: Doctrine\Common\Cache\FilesystemCache + class: Doctrine\Common\Cache\Psr6\DoctrineProvider + factory: ['Doctrine\Common\Cache\Psr6\DoctrineProvider', 'wrap'] arguments: - - "%metamodels.cache_dir%" + - "@metamodels.cache_internal" + public: true + + metamodels.cache_internal: + class: Symfony\Component\Cache\Adapter\FilesystemAdapter + arguments: + $namespace: '' + $defaultLifetime: 0 + $directory: "%metamodels.cache_dir%" public: true metamodels.cache.purger: diff --git a/src/Events/CollectMetaModelTableNamesEvent.php b/src/Events/CollectMetaModelTableNamesEvent.php index f2298fa7d..0d442d351 100644 --- a/src/Events/CollectMetaModelTableNamesEvent.php +++ b/src/Events/CollectMetaModelTableNamesEvent.php @@ -21,7 +21,7 @@ namespace MetaModels\Events; use MetaModels\IFactory; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * This event is triggered to collect the names of all known MetaModels. diff --git a/src/Events/CreateMetaModelEvent.php b/src/Events/CreateMetaModelEvent.php index d99401e3e..6c134213d 100644 --- a/src/Events/CreateMetaModelEvent.php +++ b/src/Events/CreateMetaModelEvent.php @@ -22,7 +22,7 @@ use MetaModels\IFactory; use MetaModels\IMetaModel; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * This event is triggered for every metamodel when a factory wants to create an instance. diff --git a/src/Events/CreatePropertyConditionEvent.php b/src/Events/CreatePropertyConditionEvent.php index e95c46699..1d67df5fa 100644 --- a/src/Events/CreatePropertyConditionEvent.php +++ b/src/Events/CreatePropertyConditionEvent.php @@ -22,7 +22,7 @@ use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Property\PropertyConditionInterface; use MetaModels\IMetaModel; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * This event is dispatched, whenever a MetaModels property condition shall be transformed into an object instance. diff --git a/src/Events/GetMetaModelNameFromIdEvent.php b/src/Events/GetMetaModelNameFromIdEvent.php index 57f5fe3eb..125d2888d 100644 --- a/src/Events/GetMetaModelNameFromIdEvent.php +++ b/src/Events/GetMetaModelNameFromIdEvent.php @@ -20,7 +20,7 @@ namespace MetaModels\Events; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * This event is triggered when a MetaModel id must get translated to a MetaModel name. diff --git a/src/Events/MetaModelsBootEvent.php b/src/Events/MetaModelsBootEvent.php index 05acf7950..abd2222be 100644 --- a/src/Events/MetaModelsBootEvent.php +++ b/src/Events/MetaModelsBootEvent.php @@ -24,7 +24,7 @@ use Contao\System; use MetaModels\IMetaModelsServiceContainer; use MetaModels\MetaModelsServiceContainer; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * This event is triggered when a metamodels sub system is booted. diff --git a/src/Events/ParseItemEvent.php b/src/Events/ParseItemEvent.php index a9cfc11ef..0cefb61a0 100644 --- a/src/Events/ParseItemEvent.php +++ b/src/Events/ParseItemEvent.php @@ -22,7 +22,7 @@ use MetaModels\IItem; use MetaModels\Render\Setting\ICollection; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * This event is triggered when a MetaModels item is parsed. diff --git a/src/Events/RenderItemListEvent.php b/src/Events/RenderItemListEvent.php index 00ee9745d..33b05fa36 100644 --- a/src/Events/RenderItemListEvent.php +++ b/src/Events/RenderItemListEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,7 +23,7 @@ use MetaModels\ItemList; use MetaModels\Render\Template; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * This event is fired when a MetaModels list get's rendered. From 1fcb91fb64496068b03cf1346436ed99a02733dd Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 28 Feb 2022 18:20:49 +0100 Subject: [PATCH 009/224] Fix symfony deprecations --- .../EventListener/DcGeneral/Breadcrumb/BreadcrumbStore.php | 7 ++++--- .../DcGeneral/Breadcrumb/BreadcrumbStoreFactory.php | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStore.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStore.php index 3040ff26a..1bc98a253 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStore.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStore.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,7 +23,7 @@ use Contao\StringUtil; use MetaModels\CoreBundle\Assets\IconBuilder; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * The breadcrumb store. diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStoreFactory.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStoreFactory.php index d82f43e66..86cc1de55 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStoreFactory.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStoreFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,7 +23,7 @@ use MetaModels\CoreBundle\Assets\IconBuilder; use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This class creates an instance of a breadcrumb store. From df5b3269776e4f1469410b7a2675c6ec909c2dc8 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 28 Feb 2022 18:50:41 +0100 Subject: [PATCH 010/224] Fix symfony deprecations --- .../Controller/Backend/AbstractAddAllController.php | 2 +- .../Controller/Backend/SupportMetaModelsController.php | 7 ++++--- .../Table/Attribute/NameAndDescriptionListener.php | 7 ++++--- .../Table/DcaSetting/DisableMandatoryListener.php | 6 +++--- .../DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php | 6 +++--- .../DcGeneral/Table/DcaSetting/ModelToLabelListener.php | 2 +- .../Table/DcaSettingCondition/ModelToLabelListener.php | 7 ++++--- .../Table/DcaSettingCondition/TypeOptionsListener.php | 7 ++++--- .../DcGeneral/Table/DcaSortGroup/ModelToLabelListener.php | 7 ++++--- .../DcGeneral/Table/RenderSetting/ModelToLabelListener.php | 2 +- .../DcGeneral/Table/RenderSettings/JumpToListener.php | 6 +++--- 11 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/CoreBundle/Controller/Backend/AbstractAddAllController.php b/src/CoreBundle/Controller/Backend/AbstractAddAllController.php index 8928d6293..4390d3456 100644 --- a/src/CoreBundle/Controller/Backend/AbstractAddAllController.php +++ b/src/CoreBundle/Controller/Backend/AbstractAddAllController.php @@ -32,7 +32,7 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; use Twig\Environment as TwigEnvironment; /** diff --git a/src/CoreBundle/Controller/Backend/SupportMetaModelsController.php b/src/CoreBundle/Controller/Backend/SupportMetaModelsController.php index 68c004008..9335e1c90 100644 --- a/src/CoreBundle/Controller/Backend/SupportMetaModelsController.php +++ b/src/CoreBundle/Controller/Backend/SupportMetaModelsController.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 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,8 @@ * @author Christian Schiffler * @author Sven Baumann * @author Richard Henkenjohann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,7 +23,7 @@ namespace MetaModels\CoreBundle\Controller\Backend; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; use Twig\Environment as TwigEnvironment; /** diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/NameAndDescriptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/NameAndDescriptionListener.php index ef06f56a0..79b79e2b4 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/NameAndDescriptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/NameAndDescriptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 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,8 @@ * @author Christian Schiffler * @author Sven Baumann * @author Stefan Heimes - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -29,7 +30,7 @@ use MetaModels\Attribute\IAttributeFactory; use MetaModels\Dca\Helper; use MetaModels\IFactory; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This class provides the attribute type names. diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php index 9f41f92c5..65fdc7a23 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Ingolf Steinhardt * @author Richard Henkenjohann * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -27,7 +27,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\BuildWidgetEvent; use Doctrine\DBAL\Connection; use MetaModels\IFactory; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This handles disabling of the mandatory field. diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php index 28d1a16a1..d9a93c73b 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 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-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,7 +26,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\BuildWidgetEvent; use Doctrine\DBAL\Connection; use MetaModels\IFactory; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This handles disabling of the readonly field diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php index 7b4cfd9f8..2514f77c5 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php @@ -28,7 +28,7 @@ use MetaModels\Attribute\IAttributeFactory; use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\IFactory; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This handles the rendering of models to labels. diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php index d2324c473..f3674cd57 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,7 +27,7 @@ use Doctrine\DBAL\Connection; use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\IFactory; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This handles the rendering of models to labels. diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/TypeOptionsListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/TypeOptionsListener.php index d3bc07d08..caf51b690 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/TypeOptionsListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/TypeOptionsListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,7 +27,7 @@ use Doctrine\DBAL\Connection; use MetaModels\CoreBundle\DcGeneral\PropertyConditionFactory; use MetaModels\IFactory; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This handles the type options for conditions. diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/ModelToLabelListener.php index ed0f058f9..ecee9d311 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/ModelToLabelListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,7 +25,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\ModelToLabelEvent; use Doctrine\DBAL\Connection; use MetaModels\IFactory; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This handles the rendering of models to labels. diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php index de661750a..4d5fd497d 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php @@ -27,7 +27,7 @@ use MetaModels\Attribute\IAttributeFactory; use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\IFactory; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This handles the rendering of models to labels. diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php index b5681f852..61af623c0 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -29,7 +29,7 @@ use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; use Doctrine\DBAL\Connection; use MetaModels\IFactory; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This handles the rendering of models to labels. From d81486e2d57634c835dc57b1c2dbb5ba626b26ca Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 16 Feb 2022 18:59:35 +0100 Subject: [PATCH 011/224] First commit MM 2.3 for Contao 4.13 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7be922240..cbef8cef6 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "contao-community-alliance/meta-palettes": "~2.0", "contao-community-alliance/translator": "^2.2", "contao-community-alliance/url-builder": "~1.3", - "contao/core-bundle": "^4.13.0", + "contao/core-bundle": "^4.13.0, <5.0", "discordier/justtextwidgets": "^1.2", "doctrine/cache": "^2.1", "menatwork/contao-multicolumnwizard-bundle": "^3.4", From ec08873e25b391475454e4f49419189c386da555 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 19 Feb 2022 12:35:32 +0100 Subject: [PATCH 012/224] Fix composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index cbef8cef6..2161f90c9 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "source": "https://github.com/MetaModels/core" }, "require": { - "php": "^7.4", + "php": "^7.4 || ^8.0", "contao-community-alliance/dc-general": "^2.3@dev", "contao-community-alliance/events-contao-bindings": "^4.10@dev", "contao-community-alliance/meta-palettes": "~2.0", From 36baac93d92dbe9d238a0ab6ceb493db8f1dae7c Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 25 Feb 2022 19:32:29 +0100 Subject: [PATCH 013/224] Fix symfony dependency --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2161f90c9..b6f3b6575 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "contao-community-alliance/meta-palettes": "~2.0", "contao-community-alliance/translator": "^2.2", "contao-community-alliance/url-builder": "~1.3", - "contao/core-bundle": "^4.13.0, <5.0", + "contao/core-bundle": "^4.13.0", "discordier/justtextwidgets": "^1.2", "doctrine/cache": "^2.1", "menatwork/contao-multicolumnwizard-bundle": "^3.4", From dd9c2b140312a7446e78da1e45532218cef84d14 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 16 Feb 2022 18:59:35 +0100 Subject: [PATCH 014/224] First commit MM 2.3 for Contao 4.13 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b6f3b6575..2161f90c9 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "contao-community-alliance/meta-palettes": "~2.0", "contao-community-alliance/translator": "^2.2", "contao-community-alliance/url-builder": "~1.3", - "contao/core-bundle": "^4.13.0", + "contao/core-bundle": "^4.13.0, <5.0", "discordier/justtextwidgets": "^1.2", "doctrine/cache": "^2.1", "menatwork/contao-multicolumnwizard-bundle": "^3.4", From b9d8ff322914510b946d287f27be5fb1484afdd2 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 22 Feb 2022 18:41:40 +0100 Subject: [PATCH 015/224] Fix doctrine cache --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2161f90c9..c5eb18dd9 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,7 @@ "contao-community-alliance/url-builder": "~1.3", "contao/core-bundle": "^4.13.0, <5.0", "discordier/justtextwidgets": "^1.2", - "doctrine/cache": "^2.1", + "doctrine/cache": "~2.1", "menatwork/contao-multicolumnwizard-bundle": "^3.4", "symfony/asset": "^5.4", "symfony/cache": "^5.4", From e405347ba3545fd754b41c7e36a484b138d251d8 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 24 Feb 2022 21:21:59 +0100 Subject: [PATCH 016/224] Fix doctrine/cache at composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c5eb18dd9..2161f90c9 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,7 @@ "contao-community-alliance/url-builder": "~1.3", "contao/core-bundle": "^4.13.0, <5.0", "discordier/justtextwidgets": "^1.2", - "doctrine/cache": "~2.1", + "doctrine/cache": "^2.1", "menatwork/contao-multicolumnwizard-bundle": "^3.4", "symfony/asset": "^5.4", "symfony/cache": "^5.4", From 50a7f8555a4a6086db07b4bec2b779229f5f1fd5 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 25 Feb 2022 19:32:29 +0100 Subject: [PATCH 017/224] Fix symfony dependency --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2161f90c9..b6f3b6575 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "contao-community-alliance/meta-palettes": "~2.0", "contao-community-alliance/translator": "^2.2", "contao-community-alliance/url-builder": "~1.3", - "contao/core-bundle": "^4.13.0, <5.0", + "contao/core-bundle": "^4.13.0", "discordier/justtextwidgets": "^1.2", "doctrine/cache": "^2.1", "menatwork/contao-multicolumnwizard-bundle": "^3.4", From 90680cf446171c440a8e35ea62260a059119813d Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 15 May 2022 17:37:56 +0200 Subject: [PATCH 018/224] Fix ModelToLabel --- .../DcGeneral/Table/MetaModel/ModelToLabelListener.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php index bb0a342e3..04bf72835 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php @@ -13,6 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann + * @author Ingolf Steinhardt * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource @@ -23,7 +24,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\ModelToLabelEvent; use Doctrine\DBAL\Connection; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This handles the rendering of models to labels. @@ -68,6 +69,7 @@ public function __construct( * @param ModelToLabelEvent $event The event. * * @return void + * @throws \Doctrine\DBAL\Exception */ public function handle(ModelToLabelEvent $event) { @@ -89,8 +91,8 @@ public function handle(ModelToLabelEvent $event) ->createQueryBuilder() ->select('COUNT(t.id) AS itemCount') ->from($tableName, 't') - ->execute() - ->fetchColumn(); + ->executeQuery() + ->fetchOne(); switch ($count) { case 0: From 2599257de613528f330f0601425a2458f408b32a Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 15 May 2022 20:49:05 +0200 Subject: [PATCH 019/224] Fix Contracts --- ...lectMetaModelAttributeInformationEvent.php | 222 +++++++++--------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php b/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php index f43f56de6..ebd0c0d10 100644 --- a/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php +++ b/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php @@ -1,111 +1,111 @@ - - * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -namespace MetaModels\Attribute\Events; - -use MetaModels\IMetaModel; -use Symfony\Component\EventDispatcher\Event; - -/** - * This event is triggered for every metamodel when the attribute information for the MetaModel shall be retrieved. - * - * @SuppressWarnings(PHPMD.LongClassName) - */ -class CollectMetaModelAttributeInformationEvent extends Event -{ - /** - * The event name. - */ - const NAME = 'metamodels.metamodel.collect-metamodel-attribute-information'; - - /** - * The MetaModel instance being created. - * - * @var IMetaModel - */ - protected $metaModel; - - /** - * The attribute information. - * - * @var array[] - */ - protected $attributeInformation = array(); - - /** - * Create a new instance. - * - * @param IMetaModel $metaModel The name of the MetaModel to collect the attribute information for. - */ - public function __construct(IMetaModel $metaModel) - { - $this->metaModel = $metaModel; - } - - /** - * Retrieve the MetaModel instance. - * - * @return IMetaModel - */ - public function getMetaModel() - { - return $this->metaModel; - } - - /** - * Retrieve the attribute information. - * - * @return array - */ - public function getAttributeInformation() - { - return $this->attributeInformation; - } - - /** - * Set the attribute information. - * - * @param array[] $attributeInformation The attribute information. - * - * @return CollectMetaModelAttributeInformationEvent - */ - public function setAttributeInformation($attributeInformation) - { - $this->attributeInformation = $attributeInformation; - - return $this; - } - - /** - * Set the MetaModel instance. - * - * @param string $attributeName The internal name of the attribute (column name). - * - * @param array $attributeInformation The attribute information. - * - * @return CollectMetaModelAttributeInformationEvent - */ - public function addAttributeInformation($attributeName, $attributeInformation) - { - $this->attributeInformation[$attributeName] = $attributeInformation; - - return $this; - } -} + + * @author Sven Baumann + * @copyright 2012-2022 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\Attribute\Events; + +use MetaModels\IMetaModel; +use Symfony\Contracts\EventDispatcher\Event; + +/** + * This event is triggered for every metamodel when the attribute information for the MetaModel shall be retrieved. + * + * @SuppressWarnings(PHPMD.LongClassName) + */ +class CollectMetaModelAttributeInformationEvent extends Event +{ + /** + * The event name. + */ + const NAME = 'metamodels.metamodel.collect-metamodel-attribute-information'; + + /** + * The MetaModel instance being created. + * + * @var IMetaModel + */ + protected $metaModel; + + /** + * The attribute information. + * + * @var array[] + */ + protected $attributeInformation = array(); + + /** + * Create a new instance. + * + * @param IMetaModel $metaModel The name of the MetaModel to collect the attribute information for. + */ + public function __construct(IMetaModel $metaModel) + { + $this->metaModel = $metaModel; + } + + /** + * Retrieve the MetaModel instance. + * + * @return IMetaModel + */ + public function getMetaModel() + { + return $this->metaModel; + } + + /** + * Retrieve the attribute information. + * + * @return array + */ + public function getAttributeInformation() + { + return $this->attributeInformation; + } + + /** + * Set the attribute information. + * + * @param array[] $attributeInformation The attribute information. + * + * @return CollectMetaModelAttributeInformationEvent + */ + public function setAttributeInformation($attributeInformation) + { + $this->attributeInformation = $attributeInformation; + + return $this; + } + + /** + * Set the MetaModel instance. + * + * @param string $attributeName The internal name of the attribute (column name). + * + * @param array $attributeInformation The attribute information. + * + * @return CollectMetaModelAttributeInformationEvent + */ + public function addAttributeInformation($attributeName, $attributeInformation) + { + $this->attributeInformation[$attributeName] = $attributeInformation; + + return $this; + } +} From 9d71e76d4e5d2f279fc5605df77f3af88dba90a4 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 15 May 2022 20:51:26 +0200 Subject: [PATCH 020/224] Fix author --- .../Events/CollectMetaModelAttributeInformationEvent.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php b/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php index ebd0c0d10..e2dce95aa 100644 --- a/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php +++ b/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php @@ -13,6 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann + * @author Ingolf Steinhardt * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource From f0a83fe270df0b2fcc6c4f7377ea9e9046c288b8 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 17 May 2022 08:43:08 +0200 Subject: [PATCH 021/224] Change fetchOne() to fetchOne() --- .../DcGeneral/Table/DcaSetting/AbstractListener.php | 5 +++-- .../Table/DcaSetting/AddAllButtonListener.php | 6 ++++-- .../Table/DcaSettingCondition/AbstractListener.php | 7 ++++--- .../DcGeneral/Table/DcaSortGroup/AbstractListener.php | 5 +++-- .../Table/RenderSetting/AbstractListener.php | 5 +++-- .../Table/RenderSetting/AddAllButtonListener.php | 11 +++++++---- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractListener.php index 4d094f2b2..e2d5fd476 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractListener.php @@ -72,6 +72,7 @@ public function __construct( * @return IMetaModel * * @throws DcGeneralInvalidArgumentException When an invalid model has been passed or the model does not have an id. + * @throws \Doctrine\DBAL\Exception */ protected function getMetaModelFromModel(ModelInterface $model) { @@ -92,8 +93,8 @@ protected function getMetaModelFromModel(ModelInterface $model) ->from('tl_metamodel_dca', 't') ->where('t.id=:id') ->setParameter('id', $model->getProperty('pid')) - ->execute() - ->fetchColumn(); + ->executeQuery() + ->fetchOne(); $tableName = $this->factory->translateIdToMetaModelName($metaModelId); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php index 6f2e2055f..ea3456e01 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php @@ -72,6 +72,8 @@ public function __construct(Connection $connection, IFactory $factory, UrlGenera * @param GetGlobalButtonEvent $event The event. * * @return void + * + * @throws \Doctrine\DBAL\Exception */ public function getGlobalButton(GetGlobalButtonEvent $event) { @@ -88,8 +90,8 @@ public function getGlobalButton(GetGlobalButtonEvent $event) ->from('tl_metamodel_dca', 'd') ->where('d.id=:pid') ->setParameter('pid', $inputScreen) - ->execute() - ->fetchColumn(); + ->executeQuery() + ->fetchOne(); $name = $this->factory->translateIdToMetaModelName($modelId); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AbstractListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AbstractListener.php index 08751fc77..27dc2926f 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AbstractListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AbstractListener.php @@ -79,7 +79,8 @@ public function __construct( * * @return \MetaModels\IMetaModel * - * @throws \RuntimeException Throws if could not retrieve metamodel. + * @throws \RuntimeException Throws if you could not retrieve metamodel. + * @throws \Doctrine\DBAL\Exception */ public function getMetaModel(EnvironmentInterface $interface) { @@ -90,9 +91,9 @@ public function getMetaModel(EnvironmentInterface $interface) ->leftJoin('d', 'tl_metamodel_dcasetting', 's', 'd.id=s.pid') ->where('s.id=:id') ->setParameter('id', ModelId::fromSerialized($interface->getInputProvider()->getParameter('pid'))->getId()) - ->execute(); + ->executeQuery(); - if ($tableName = $this->factory->translateIdToMetaModelName($metaModelId = $metaModelId->fetchColumn())) { + if ($tableName = $this->factory->translateIdToMetaModelName($metaModelId = $metaModelId->fetchOne())) { return $this->factory->getMetaModel($tableName); } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractListener.php index 16b3a2b5e..3fe8d5983 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractListener.php @@ -72,6 +72,7 @@ public function __construct( * @return IMetaModel * * @throws DcGeneralInvalidArgumentException When an invalid model has been passed or the model does not have an id. + * @throws \Doctrine\DBAL\Exception */ protected function getMetaModelFromModel(ModelInterface $model) { @@ -92,8 +93,8 @@ protected function getMetaModelFromModel(ModelInterface $model) ->from('tl_metamodel_dca', 't') ->where('t.id=:id') ->setParameter('id', $model->getProperty('pid')) - ->execute() - ->fetchColumn(); + ->executeQuery() + ->fetchOne(); $tableName = $this->factory->translateIdToMetaModelName($metaModelId); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractListener.php index a9531577f..1c99d883e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractListener.php @@ -72,6 +72,7 @@ public function __construct( * @return IMetaModel * * @throws DcGeneralInvalidArgumentException When an invalid model has been passed or the model does not have an id. + * @throws \Doctrine\DBAL\Exception */ protected function getMetaModelFromModel(ModelInterface $model) { @@ -92,8 +93,8 @@ protected function getMetaModelFromModel(ModelInterface $model) ->from('tl_metamodel_rendersettings', 't') ->where('t.id=:id') ->setParameter('id', $model->getProperty('pid')) - ->execute() - ->fetchColumn(); + ->executeQuery() + ->fetchOne(); $tableName = $this->factory->translateIdToMetaModelName($metaModelId); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AddAllButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AddAllButtonListener.php index 9f7ff3e52..4ae6c644d 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AddAllButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AddAllButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -72,6 +73,8 @@ public function __construct(Connection $connection, IFactory $factory, UrlGenera * @param GetGlobalButtonEvent $event The event. * * @return void + * + * @throws \Doctrine\DBAL\Exception */ public function getGlobalButton(GetGlobalButtonEvent $event) { @@ -88,8 +91,8 @@ public function getGlobalButton(GetGlobalButtonEvent $event) ->from('tl_metamodel_rendersettings', 'r') ->where('r.id=:pid') ->setParameter('pid', $renderSetting) - ->execute() - ->fetchColumn(); + ->executeQuery() + ->fetchOne(); $name = $this->factory->translateIdToMetaModelName($modelId); From b0e1c6d63b0293cdcd758bef0d5dadf7d3f82153 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 17 May 2022 09:11:32 +0200 Subject: [PATCH 022/224] Fix InputScreen --- .../Condition/Property/InputScreenRenderModeIs.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenRenderModeIs.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenRenderModeIs.php index 0049e299e..f15a9b910 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenRenderModeIs.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenRenderModeIs.php @@ -30,7 +30,7 @@ use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Property\PropertyConditionInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\LegendInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\PropertyInterface; -use Doctrine\DBAL\Driver\Connection; +use Doctrine\DBAL\Connection; use MetaModels\IMetaModelsServiceContainer; use MetaModels\MetaModelsServiceContainer; @@ -114,6 +114,8 @@ public function getRenderMode() * @param int $value The id of an input screen. * * @return string + * + * @throws \Doctrine\DBAL\Exception */ public function getInputScreenRenderMode($value) { @@ -125,9 +127,9 @@ public function getInputScreenRenderMode($value) ->where('t.id=:id') ->setParameter('id', $value) ->setMaxResults(1) - ->execute(); + ->executeQuery(); - self::$stateBuffer[$value] = $statement->fetch(\PDO::FETCH_OBJ)->rendermode; + self::$stateBuffer[$value] = $statement->fetchAssociative()['rendermode']; } return self::$stateBuffer[$value]; From 1de354f012d571245cd505bd4d8f3ebaadff3e78 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 17 May 2022 09:14:05 +0200 Subject: [PATCH 023/224] Fix header --- .../DcGeneral/Table/DcaSetting/AddAllButtonListener.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php index ea3456e01..927e2109b 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ From a1ce8deffc9870a1c523ad6896c546a9b719957b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 22 May 2022 13:16:23 +0200 Subject: [PATCH 024/224] Fix symfony --- src/Attribute/Events/CreateAttributeEvent.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Attribute/Events/CreateAttributeEvent.php b/src/Attribute/Events/CreateAttributeEvent.php index cbaf752f7..e0740ef09 100644 --- a/src/Attribute/Events/CreateAttributeEvent.php +++ b/src/Attribute/Events/CreateAttributeEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,7 +23,7 @@ use MetaModels\Attribute\IAttribute; use MetaModels\IMetaModel; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * This event is triggered for every attribute when the factory wants to create an instance. From 67505faf341d56f03fb8a39ebcba115c08941ea8 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 22 May 2022 13:19:13 +0200 Subject: [PATCH 025/224] Fix symfony --- src/Attribute/Events/CreateAttributeFactoryEvent.php | 7 ++++--- .../Setting/Events/CreateFilterSettingFactoryEvent.php | 7 ++++--- .../Setting/Events/CreateRenderSettingFactoryEvent.php | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/Attribute/Events/CreateAttributeFactoryEvent.php b/src/Attribute/Events/CreateAttributeFactoryEvent.php index 12fec04bf..22146d7f8 100644 --- a/src/Attribute/Events/CreateAttributeFactoryEvent.php +++ b/src/Attribute/Events/CreateAttributeFactoryEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,7 +22,7 @@ namespace MetaModels\Attribute\Events; use MetaModels\Attribute\IAttributeFactory; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * This event is triggered for every attribute factory instance that is created. diff --git a/src/Filter/Setting/Events/CreateFilterSettingFactoryEvent.php b/src/Filter/Setting/Events/CreateFilterSettingFactoryEvent.php index add795f8d..a1f488fa7 100644 --- a/src/Filter/Setting/Events/CreateFilterSettingFactoryEvent.php +++ b/src/Filter/Setting/Events/CreateFilterSettingFactoryEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,7 +22,7 @@ namespace MetaModels\Filter\Setting\Events; use MetaModels\Filter\Setting\IFilterSettingFactory; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * This event is triggered for every attribute factory instance that is created. diff --git a/src/Render/Setting/Events/CreateRenderSettingFactoryEvent.php b/src/Render/Setting/Events/CreateRenderSettingFactoryEvent.php index bd22f4d35..39a28a6d5 100644 --- a/src/Render/Setting/Events/CreateRenderSettingFactoryEvent.php +++ b/src/Render/Setting/Events/CreateRenderSettingFactoryEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,7 +21,7 @@ namespace MetaModels\Render\Setting\Events; use MetaModels\Render\Setting\IRenderSettingFactory; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * This event is triggered for every render setting factory instance that is created. From 66365da1b21adfa9bab52cbd083d7adf00c24533 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 22 May 2022 16:00:43 +0200 Subject: [PATCH 026/224] Fix queryBuilder --- src/Attribute/BaseSimple.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Attribute/BaseSimple.php b/src/Attribute/BaseSimple.php index b16d135c3..3b2aff60f 100644 --- a/src/Attribute/BaseSimple.php +++ b/src/Attribute/BaseSimple.php @@ -146,7 +146,7 @@ public function setDataFor($arrValues) ->set('t.' . $strColName, ':' . $strColName) ->setParameter($strColName, is_array($varData) ? serialize($varData) : $varData) ->setParameter('id', $intId) - ->execute(); + ->executeQuery(); } } @@ -169,23 +169,23 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) ->groupBy('t.' . $strCol) ->orderBy('MIN(FIELD(t.id, :ids))') ->setParameter('ids', $idList, Connection::PARAM_STR_ARRAY) - ->execute(); + ->executeQuery(); } else { $statement = $this->connection->createQueryBuilder() ->select('t.' . $strCol . ', COUNT(t.' . $strCol . ') as mm_count') ->from($this->getMetaModel()->getTableName(), 't') ->groupBy('t.' . $strCol) ->orderBy('t.' . $strCol) - ->execute(); + ->executeQuery(); } $arrResult = []; - while ($objRow = $statement->fetch(\PDO::FETCH_OBJ)) { + while ($objRow = $statement->fetchAllAssociative()) { if (is_array($arrCount)) { - $arrCount[$objRow->$strCol] = $objRow->mm_count; + $arrCount[$objRow[$strCol]] = $objRow['mm_count']; } - $arrResult[$objRow->$strCol] = $objRow->$strCol; + $arrResult[$objRow[$strCol]] = $objRow[$strCol]; } return $arrResult; } @@ -204,8 +204,8 @@ public function sortIds($idList, $strDirection) ->where('t.id IN (:ids)') ->setParameter('ids', $idList, Connection::PARAM_STR_ARRAY) ->orderBy('t.' . $this->getColName(), $strDirection) - ->execute() - ->fetchAll(\PDO::FETCH_COLUMN, 'id'); + ->executeQuery() + ->fetchFirstColumn(); return $idList; } @@ -229,8 +229,8 @@ public function searchFor($strPattern) ->from($this->getMetaModel()->getTableName(), 't') ->where('t.' . $this->getColName() . ' LIKE :pattern') ->setParameter('pattern', $strPattern) - ->execute() - ->fetchAll(\PDO::FETCH_COLUMN, 'id'); + ->executeQuery() + ->fetchFirstColumn(); } /** From b526ebd43e36cb0c133ab26c3008221d572fda7b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 23 May 2022 13:05:07 +0200 Subject: [PATCH 027/224] Fix ListControllerTrait --- .../ContentElement/ItemListController.php | 11 +-- .../FrontendModule/ItemListController.php | 13 ++- .../Controller/ListControllerTrait.php | 82 +++++++++++++++++-- .../Resources/config/content-elements.yml | 3 + src/CoreBundle/Resources/config/modules.yml | 3 + 5 files changed, 96 insertions(+), 16 deletions(-) diff --git a/src/CoreBundle/Controller/ContentElement/ItemListController.php b/src/CoreBundle/Controller/ContentElement/ItemListController.php index 0180b7258..f694d366b 100644 --- a/src/CoreBundle/Controller/ContentElement/ItemListController.php +++ b/src/CoreBundle/Controller/ContentElement/ItemListController.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Ingolf Steinhardt * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +26,7 @@ use Contao\CoreBundle\Controller\ContentElement\AbstractContentElementController; use Contao\CoreBundle\ServiceAnnotation\ContentElement; use Contao\PageModel; +use Contao\System; use Contao\Template; use MetaModels\CoreBundle\Controller\ListControllerTrait; use Symfony\Component\HttpFoundation\Request; @@ -58,7 +59,7 @@ public function __invoke( array $classes = null, PageModel $pageModel = null ): Response { - if ($this->get('contao.routing.scope_matcher')->isBackendRequest($request)) { + if ($this->scopeMatcher->isBackendRequest($request)) { return $this->getBackendWildcard($model); } @@ -95,8 +96,8 @@ protected function getResponse(Template $template, ContentModel $model, Request */ private function getBackendWildcard(ContentModel $model): Response { - $name = $this->get('translator')->trans('CTE.' . $this->getType() . '.0', [], 'contao_modules'); - $href = $this->get('router')->generate( + $name = $this->translator->trans('CTE.' . $this->getType() . '.0', [], 'contao_modules'); + $href = $this->router->generate( 'contao_backend', ['do' => 'article', 'table' => 'tl_content', 'act' => 'edit', 'id' => $model->id] ); diff --git a/src/CoreBundle/Controller/FrontendModule/ItemListController.php b/src/CoreBundle/Controller/FrontendModule/ItemListController.php index 35fff15e7..3d01d27bc 100644 --- a/src/CoreBundle/Controller/FrontendModule/ItemListController.php +++ b/src/CoreBundle/Controller/FrontendModule/ItemListController.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 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,8 @@ * @author Richard Henkenjohann * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2020 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -57,6 +58,10 @@ public function __invoke( array $classes = null, PageModel $pageModel = null ): Response { + if ($this->scopeMatcher->isBackendRequest($request)) { + return $this->getBackendWildcard($model); + } + if (!empty($model->metamodel_layout)) { $model->customTpl = $model->metamodel_layout; } @@ -73,8 +78,8 @@ public function __invoke( */ protected function getBackendWildcard(ModuleModel $module): Response { - $name = $this->get('translator')->trans('FMD.'.$this->getType().'.0', [], 'contao_modules'); - $href = $this->get('router')->generate( + $name = $this->translator->trans('FMD.'.$this->getType().'.0', [], 'contao_modules'); + $href = $this->router->generate( 'contao_backend', ['do' => 'themes', 'table' => 'tl_module', 'act' => 'edit', 'id' => $module->id] ); diff --git a/src/CoreBundle/Controller/ListControllerTrait.php b/src/CoreBundle/Controller/ListControllerTrait.php index 973af587d..7c19d131a 100644 --- a/src/CoreBundle/Controller/ListControllerTrait.php +++ b/src/CoreBundle/Controller/ListControllerTrait.php @@ -23,9 +23,11 @@ namespace MetaModels\CoreBundle\Controller; use Contao\BackendTemplate; +use Contao\CoreBundle\Routing\ScopeMatcher; use Contao\Input; use Contao\Model; use Contao\StringUtil; +use Contao\System; use Contao\Template; use MetaModels\Filter\FilterUrl; use MetaModels\Filter\FilterUrlBuilder; @@ -37,6 +39,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\RouterInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * Helper trait for lists (CE and MOD). @@ -78,6 +82,27 @@ trait ListControllerTrait */ private FilterUrlBuilder $filterUrlBuilder; + /** + * The translator. + * + * @var TranslatorInterface + */ + private TranslatorInterface $translator; + + /** + * The router. + * + * @var RouterInterface + */ + private RouterInterface $router; + + /** + * The scope matcher. + * + * @var ScopeMatcher + */ + private ScopeMatcher $scopeMatcher; + /** * ItemListController constructor. * @@ -86,19 +111,62 @@ trait ListControllerTrait * @param IRenderSettingFactory $renderSettingFactory The render setting factory (required in MetaModels 3.0). * @param EventDispatcherInterface $eventDispatcher The event dispatcher (required in MetaModels 3.0). * @param FilterUrlBuilder $filterUrlBuilder The filter url builder. + * @param TranslatorInterface|null $translator The translator. + * @param RouterInterface|null $router The router. + * @param ScopeMatcher|null $scopeMatcher The scope matcher. */ public function __construct( IFactory $factory, IFilterSettingFactory $filterFactory, IRenderSettingFactory $renderSettingFactory, EventDispatcherInterface $eventDispatcher, - FilterUrlBuilder $filterUrlBuilder + FilterUrlBuilder $filterUrlBuilder, + TranslatorInterface $translator = null, + RouterInterface $router = null, + ScopeMatcher $scopeMatcher = null ) { $this->factory = $factory; $this->filterFactory = $filterFactory; $this->renderSettingFactory = $renderSettingFactory; $this->eventDispatcher = $eventDispatcher; $this->filterUrlBuilder = $filterUrlBuilder; + + if (null === $translator) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Translator is missing. It has to be passed in the constructor. Fallback will be dropped.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + + $translator = System::getContainer()->get('translator'); + } + + if (null === $router) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Router is missing. It has to be passed in the constructor. Fallback will be dropped.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + + $router = System::getContainer()->get('router'); + } + + if (null === $scopeMatcher) { + // @codingStandardsIgnoreStart + @trigger_error( + 'ScopeMatcher is missing. It has to be passed in the constructor. Fallback will be dropped.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + + $scopeMatcher = System::getContainer()->get('contao.routing.scope_matcher'); + } + + $this->translator = $translator; + $this->router = $router; + $this->scopeMatcher = $scopeMatcher; } /** @@ -312,8 +380,8 @@ private function getWildcardInfoText(Model $model, string $href, string $name): } $infoText = sprintf( $infoTemplate, - $this->get('translator')->trans('MSC.mm_be_info_name.1', [], 'contao_default'), - $this->get('translator')->trans('MSC.mm_be_info_name.0', [], 'contao_default'), + $this->translator->trans('MSC.mm_be_info_name.1', [], 'contao_default'), + $this->translator->trans('MSC.mm_be_info_name.0', [], 'contao_default'), $header ); @@ -330,8 +398,8 @@ private function getWildcardInfoText(Model $model, string $href, string $name): if ($infoFi) { $infoText .= sprintf( $infoTemplate, - $this->get('translator')->trans('MSC.mm_be_info_filter.1', [], 'contao_default'), - $this->get('translator')->trans('MSC.mm_be_info_filter.0', [], 'contao_default'), + $this->translator->trans('MSC.mm_be_info_filter.1', [], 'contao_default'), + $this->translator->trans('MSC.mm_be_info_filter.0', [], 'contao_default'), $infoFi . $infoFiPa ); } @@ -345,8 +413,8 @@ private function getWildcardInfoText(Model $model, string $href, string $name): if ($infoRs) { $infoText .= sprintf( $infoTemplate, - $this->get('translator')->trans('MSC.mm_be_info_render_setting.1', [], 'contao_default'), - $this->get('translator')->trans('MSC.mm_be_info_render_setting.0', [], 'contao_default'), + $this->translator->trans('MSC.mm_be_info_render_setting.1', [], 'contao_default'), + $this->translator->trans('MSC.mm_be_info_render_setting.0', [], 'contao_default'), $infoRs ); } diff --git a/src/CoreBundle/Resources/config/content-elements.yml b/src/CoreBundle/Resources/config/content-elements.yml index b8e814e58..ba6262b05 100644 --- a/src/CoreBundle/Resources/config/content-elements.yml +++ b/src/CoreBundle/Resources/config/content-elements.yml @@ -9,3 +9,6 @@ services: - '@metamodels.render_setting_factory' - '@event_dispatcher' - '@MetaModels\Filter\FilterUrlBuilder' + - "@contao.translation.translator" + - '@router' + - '@contao.routing.scope_matcher' diff --git a/src/CoreBundle/Resources/config/modules.yml b/src/CoreBundle/Resources/config/modules.yml index 2f7d91cd1..5d604d18a 100644 --- a/src/CoreBundle/Resources/config/modules.yml +++ b/src/CoreBundle/Resources/config/modules.yml @@ -9,3 +9,6 @@ services: - '@metamodels.render_setting_factory' - '@event_dispatcher' - '@MetaModels\Filter\FilterUrlBuilder' + - "@contao.translation.translator" + - '@router' + - '@contao.routing.scope_matcher' From a7003fe19f1a858380dc0be10a1104211e9e930c Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 23 May 2022 13:20:47 +0200 Subject: [PATCH 028/224] Fix AssetPopulator --- .../DcGeneral/EnvironmentPopulator/AssetPopulator.php | 11 ++++++++--- .../EnvironmentPopulator/MetaModelPopulatorTrait.php | 5 +++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AssetPopulator.php b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AssetPopulator.php index e9ee94d16..775b99cb3 100644 --- a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AssetPopulator.php +++ b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AssetPopulator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,13 +13,16 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\EnvironmentPopulator; +use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; + /** * This class adds the style sheet. */ @@ -30,12 +33,14 @@ class AssetPopulator /** * Populate the environment. * + * @param EnvironmentInterface $environment The environment. + * * @return void * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - public function populate() + public function populate(EnvironmentInterface $environment) { $GLOBALS['TL_CSS'][] = 'bundles/metamodelscore/css/style.css'; } diff --git a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/MetaModelPopulatorTrait.php b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/MetaModelPopulatorTrait.php index df78c1361..fd395f086 100644 --- a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/MetaModelPopulatorTrait.php +++ b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/MetaModelPopulatorTrait.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ From b2f312903c798e9f35d1de14f03adf3c336d65a2 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 24 May 2022 14:17:20 +0200 Subject: [PATCH 029/224] Fix symfony warning --- src/Render/Setting/Collection.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Render/Setting/Collection.php b/src/Render/Setting/Collection.php index 7d1d46ad8..b7a468992 100644 --- a/src/Render/Setting/Collection.php +++ b/src/Render/Setting/Collection.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Ingolf Steinhardt * @author Sven Baumann * @author Richard Henkenjohann - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -151,7 +151,7 @@ public function __construct( */ public function get($strName) { - return $this->arrBase[$strName]; + return !isset($this->arrBase[$strName]) ?? $this->arrBase[$strName]; } /** From 2531fe415a7161a7b8e1eb7a71f58d7b6338e23f Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 24 May 2022 14:24:07 +0200 Subject: [PATCH 030/224] Fix symfony warnings --- src/ItemList.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ItemList.php b/src/ItemList.php index fe8ee0679..933f18a22 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -787,9 +787,9 @@ protected function getAttributeNames(): array if (!$this->getMetaModel()->isTranslated() || $jumpTo['langcode'] == $desiredLanguage || $jumpTo['langcode'] == $fallbackLanguage) { - $filterSettingsId = $jumpTo['filter']; - // If the desired language, break. Otherwise try to get the desired one until all have been evaluated. - if ($desiredLanguage === $jumpTo['langcode']) { + $filterSettingsId = !isset($jumpTo['filter']) ?? $jumpTo['filter']; + // If the desired language, break. Otherwise, try to get the desired one until all have been evaluated. + if (isset($jumpTo['langcode']) && $desiredLanguage === $jumpTo['langcode']) { break; } } From e1d79641b5e481be2bcefc37e3c73327a772c0f8 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 24 May 2022 15:23:30 +0200 Subject: [PATCH 031/224] Fix symfony error --- src/Filter/Setting/CustomSql.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Filter/Setting/CustomSql.php b/src/Filter/Setting/CustomSql.php index a6ceb4e83..94a9078ae 100644 --- a/src/Filter/Setting/CustomSql.php +++ b/src/Filter/Setting/CustomSql.php @@ -37,7 +37,7 @@ use MetaModels\IMetaModelsServiceContainer; use MetaModels\Render\Setting\ICollection as IRenderSettings; use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; +use Symfony\Contracts\Service\ServiceSubscriberInterface; /** * This filter condition generates a filter rule for a predefined SQL query. From 6935ff53d8be58b6c2b23e356610b54466a593f1 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 24 May 2022 16:33:24 +0200 Subject: [PATCH 032/224] Fix PHP 8 warnings --- .../DcGeneral/DefinitionBuilder/PaletteBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php index 08607124d..9d1281a66 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php @@ -111,7 +111,7 @@ protected function build(IMetaModelDataDefinition $container) $legend->setInitialVisibility(!$legendInfo['hide']); $palette->addLegend($legend); - $legendConditions = $this->buildCondition($legendInfo['condition'], $metaModel); + $legendConditions = $this->buildCondition(($legendInfo['condition'] ?? null), $metaModel); foreach ($legendInfo['properties'] as $property) { $legend->addProperty( $this->createProperty( From 2ee9730257972dabf1007c75f7ad1f654fa05e0b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 24 May 2022 16:38:48 +0200 Subject: [PATCH 033/224] Fix PHP 8 warnings --- src/DcGeneral/Data/Driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DcGeneral/Data/Driver.php b/src/DcGeneral/Data/Driver.php index 90906d839..0f102b1a2 100644 --- a/src/DcGeneral/Data/Driver.php +++ b/src/DcGeneral/Data/Driver.php @@ -310,7 +310,7 @@ public function setBaseConfig(array $arrConfig) } $this->strTable = $arrConfig['source']; - $this->metaModel = $arrConfig['metaModel']; + $this->metaModel = $arrConfig['metaModel'] ?? null; } /** From 90fc1d349121363ef07b93d75a6cd58c3987867b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 24 May 2022 17:02:06 +0200 Subject: [PATCH 034/224] Fix PHP 8 warnings --- src/Render/Setting/Collection.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Render/Setting/Collection.php b/src/Render/Setting/Collection.php index b7a468992..51cde4f7d 100644 --- a/src/Render/Setting/Collection.php +++ b/src/Render/Setting/Collection.php @@ -282,13 +282,13 @@ private function lookupJumpTo(bool $translated, string $desired = null, string $ $jumpToPageId = ''; $filterSettingId = ''; foreach ((array) $this->get('jumpTo') as $jumpTo) { - $langCode = $jumpTo['langcode']; + $langCode = $jumpTo['langcode'] ?? null; // If either desired language or fallback, keep the result. if (!$translated || ($langCode === $desired) || ($langCode === $fallback)) { - $jumpToPageId = $jumpTo['value']; - $filterSettingId = $jumpTo['filter']; + $jumpToPageId = $jumpTo['value'] ?? ''; + $filterSettingId = $jumpTo['filter'] ?? ''; // If the desired language, break. - // Otherwise try to get the desired one until all have been evaluated. + // Otherwise, try to get the desired one until all have been evaluated. if (!$translated || ($desired === $jumpTo['langcode'])) { break; } @@ -306,7 +306,7 @@ private function lookupJumpTo(bool $translated, string $desired = null, string $ 'filter' => $filterSettingId, 'filterSetting' => $filterSetting, // Mask out the "all languages" language key (See #687). - 'language' => $pageDetails['language'], + 'language' => $pageDetails['language'] ?? '', 'label' => $this->getJumpToLabel() ]; } From dd8b5d3209994c6d83458a2a2fa73719ee621866 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 24 May 2022 17:03:47 +0200 Subject: [PATCH 035/224] Fix PHP 8 warnings --- src/Item.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Item.php b/src/Item.php index 067444a62..998f2b25b 100644 --- a/src/Item.php +++ b/src/Item.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2022 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 Richard Henkenjohann * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -414,7 +414,7 @@ protected function registerAssets($objSettings) $arrCss = $objSettings->get('additionalCss'); foreach ((array) $arrCss as $arrFile) { - if ($arrFile['published']) { + if (isset($arrFile['published']) && $arrFile['published']) { $GLOBALS['TL_CSS'][md5($arrFile['file'])] = $arrFile['file']; } } @@ -423,7 +423,7 @@ protected function registerAssets($objSettings) $arrJs = $objSettings->get('additionalJs'); foreach ((array) $arrJs as $arrFile) { - if ($arrFile['published']) { + if (isset($arrFile['published']) && $arrFile['published']) { $GLOBALS['TL_JAVASCRIPT'][md5($arrFile['file'])] = $arrFile['file']; } } @@ -433,7 +433,6 @@ protected function registerAssets($objSettings) * Renders the item in the given output format. * * @param string $strOutputFormat The desired output format (optional - default: text). - * * @param ICollection $objSettings The render settings to use (optional - default: null). * * @return array attribute name => format => value @@ -462,9 +461,9 @@ public function parseValue($strOutputFormat = 'text', $objSettings = null) return $arrResult; } - // Add jumpTo link + // Add jumpTo link. $jumpTo = $this->buildJumpToLink($objSettings); - if ($jumpTo['url']) { + if (isset($jumpTo['url']) && $jumpTo['url']) { $arrResult['actions']['jumpTo'] = [ 'href' => $jumpTo['url'], 'deep' => $jumpTo['deep'], From 01c5e0ddbb6ab0d94d90365c05ca847af0cff424 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 24 May 2022 17:37:57 +0200 Subject: [PATCH 036/224] Cast model property attribute id to int --- .../Table/DcaSetting/DisableMandatoryListener.php | 2 +- .../DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php | 2 +- .../DcGeneral/Table/DcaSetting/ModelToLabelListener.php | 2 +- .../Table/DcaSettingCondition/ModelToLabelListener.php | 2 +- .../DcGeneral/Table/DcaSettingCondition/ValueListener.php | 2 +- .../FilterSetting/AbstractFilterSettingTypeRenderer.php | 2 +- .../DcGeneral/Table/RenderSetting/ModelToLabelListener.php | 2 +- .../Table/RenderSetting/TemplateOptionListener.php | 7 ++++--- .../Property/FilterSettingTypeSubPaletteCondition.php | 6 +++--- 9 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php index 65fdc7a23..9005fb25d 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php @@ -77,7 +77,7 @@ public function handle(BuildWidgetEvent $event) $model = $event->getModel(); $metaModel = $this->getMetaModelFromModel($model); - $attribute = $metaModel->getAttributeById($model->getProperty('attr_id')); + $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); if (null === $attribute) { return; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php index d9a93c73b..b6a1cccde 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php @@ -77,7 +77,7 @@ public function handle(BuildWidgetEvent $event) $model = $event->getModel(); $metaModel = $this->getMetaModelFromModel($model); - if ($metaModel->getAttributeById($model->getProperty('attr_id'))->get('force_alias')) { + if ($metaModel->getAttributeById((int) $model->getProperty('attr_id'))->get('force_alias')) { Message::addInfo( $this->translator->trans( 'tl_metamodel_dcasetting.readonly_for_force_alias', diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php index 2514f77c5..f8dc0f06d 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php @@ -120,7 +120,7 @@ private function drawAttribute(ModelToLabelEvent $event) { $model = $event->getModel(); $metaModel = $this->getMetaModelFromModel($model); - $attribute = $metaModel->getAttributeById($model->getProperty('attr_id')); + $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); if ($attribute) { $type = $attribute->get('type'); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php index f3674cd57..5122c9711 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php @@ -88,7 +88,7 @@ public function handle(ModelToLabelEvent $event) $environment = $event->getEnvironment(); $model = $event->getModel(); $metaModel = $this->getMetaModel($environment); - $attribute = $metaModel->getAttributeById($model->getProperty('attr_id')); + $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); $type = $model->getProperty('type'); $parameterValue = (\is_array($model->getProperty('value')) ? implode(', ', $model->getProperty('value')) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php index 8757cde29..090622508 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php @@ -163,7 +163,7 @@ public function setValueOptionsMultiple(ManipulateWidgetEvent $event) } $metaModel = $this->getMetaModel($event->getEnvironment()); - $attribute = $metaModel->getAttributeById($event->getModel()->getProperty('attr_id')); + $attribute = $metaModel->getAttributeById((int) $event->getModel()->getProperty('attr_id')); if (!($attribute && ($attribute->get('type') == 'tags'))) { return; diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php index 77096e8ad..edd0b039b 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php @@ -240,7 +240,7 @@ protected function getLabelParametersWithAttributeAndUrlParam( ) { $translator = $environment->getTranslator(); $metamodel = $this->getMetaModel($model); - $attribute = $metamodel->getAttributeById($model->getProperty('attr_id')); + $attribute = $metamodel->getAttributeById((int) $model->getProperty('attr_id')); if ($attribute) { $attributeColumnName = $attribute->getColName(); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php index 4d5fd497d..ef44c4b82 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php @@ -94,7 +94,7 @@ public function handle(ModelToLabelEvent $event) $model = $event->getModel(); $metaModel = $this->getMetaModelFromModel($model); - $attribute = $metaModel->getAttributeById($model->getProperty('attr_id')); + $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); if ($attribute) { $type = $attribute->get('type'); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/TemplateOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/TemplateOptionListener.php index c2101005f..461544bf4 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/TemplateOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/TemplateOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -71,7 +72,7 @@ public function handle(GetPropertyOptionsEvent $event) $model = $event->getModel(); $metaModel = $this->getMetaModelFromModel($model); - $attribute = $metaModel->getAttributeById($model->getProperty('attr_id')); + $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); if (!$attribute) { return; diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/FilterSettingTypeSubPaletteCondition.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/FilterSettingTypeSubPaletteCondition.php index 8289a4211..73fad186b 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/FilterSettingTypeSubPaletteCondition.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/FilterSettingTypeSubPaletteCondition.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,7 @@ * * @package MetaModels/core * @author David Molineus - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -72,7 +72,7 @@ public function match( } $metaModel = $this->getMetaModel($model); - $attribute = $metaModel->getAttributeById($model->getProperty('attr_id')); + $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); if (!$attribute) { return false; From c4112bafff2effe4bc44fe27fafeeb027e93a737 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 24 May 2022 17:54:35 +0200 Subject: [PATCH 037/224] Fix query --- src/Attribute/BaseSimple.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Attribute/BaseSimple.php b/src/Attribute/BaseSimple.php index 3b2aff60f..a70d0037f 100644 --- a/src/Attribute/BaseSimple.php +++ b/src/Attribute/BaseSimple.php @@ -180,7 +180,7 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) } $arrResult = []; - while ($objRow = $statement->fetchAllAssociative()) { + while ($objRow = $statement->fetchAssociative()) { if (is_array($arrCount)) { $arrCount[$objRow[$strCol]] = $objRow['mm_count']; } From bd84616d0bb13d55248fa1cdc5c39713debdd988 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 25 May 2022 22:19:46 +0200 Subject: [PATCH 038/224] Add change for Xtra fix in DCG --- .../Resources/contao/dca/tl_metamodel_dca_combine.php | 6 +++--- .../contao/languages/en/tl_metamodel_dca_combine.php | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php index c0d0f8c79..78fc38153 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -71,7 +71,7 @@ ], ], 'palettes' => [ - 'default' => 'rows' + 'default' => '{dca_combiner_legend},rows' ], 'fields' => [ 'id' => [ diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_combine.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_combine.php index 706149da0..2f611a1b5 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_combine.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_combine.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,11 +15,13 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ +$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['dca_combiner_legend'] = 'Combination configuration'; + $GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['dca_combiner'][0] = 'Permissions for input screen and views'; $GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['dca_combiner'][1] = 'For selected frontend user group (if any) and selected backend user group (if any) use the selected palette and ' . From 183b0586644f1e7a5b01d9d8058ac43cad4d1d21 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 26 May 2022 16:01:19 +0200 Subject: [PATCH 039/224] Cast attribute id to int --- src/BackendIntegration/InputScreen/InputScreen.php | 4 ++-- .../InputScreen/InputScreenGroupingAndSorting.php | 9 +++++---- .../DcGeneral/AbstractAttributeConditionFactory.php | 9 +++++---- .../Breadcrumb/BreadcrumbDcaSettingConditionListener.php | 2 +- .../Table/DcaSettingCondition/AttributeIdListener.php | 6 +++--- .../Table/DcaSettingCondition/ValueListener.php | 3 +-- .../DcGeneral/Table/FilterSetting/AttributeListener.php | 6 +++--- .../Table/FilterSetting/DefaultOptionListener.php | 7 ++++--- src/Filter/Setting/SimpleLookup.php | 2 +- src/ViewCombination/InputScreenInformationBuilder.php | 4 ++-- 10 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/BackendIntegration/InputScreen/InputScreen.php b/src/BackendIntegration/InputScreen/InputScreen.php index 152195367..3ec8de583 100644 --- a/src/BackendIntegration/InputScreen/InputScreen.php +++ b/src/BackendIntegration/InputScreen/InputScreen.php @@ -211,7 +211,7 @@ private function extractLegendName(array $legend, IMetaModel $metaModel): string */ protected function translateProperty($property, $metaModel, $legend) { - $attribute = $metaModel->getAttributeById($property['attr_id']); + $attribute = $metaModel->getAttributeById((int) $property['attr_id']); // Dead meat. if (!$attribute) { @@ -278,7 +278,7 @@ protected function translateRows($rows) continue; } - $attribute = $metaModel->getAttributeById($row['attr_id']); + $attribute = $metaModel->getAttributeById((int) $row['attr_id']); if ($attribute) { $columnNames[$row['id']] = $attribute->getColName(); } diff --git a/src/BackendIntegration/InputScreen/InputScreenGroupingAndSorting.php b/src/BackendIntegration/InputScreen/InputScreenGroupingAndSorting.php index 4de9e4ae3..18629a46a 100644 --- a/src/BackendIntegration/InputScreen/InputScreenGroupingAndSorting.php +++ b/src/BackendIntegration/InputScreen/InputScreenGroupingAndSorting.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 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,8 @@ * @author Christian Schiffler * @author David Molineus * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -89,7 +90,7 @@ public function getRenderGroupAttribute() if (!empty($this->data['rendergroupattr'])) { $metaModel = $this->getMetaModel(); if ($metaModel) { - $attribute = $metaModel->getAttributeById($this->data['rendergroupattr']); + $attribute = $metaModel->getAttributeById((int) $this->data['rendergroupattr']); if ($attribute) { return $attribute->getColName(); } @@ -115,7 +116,7 @@ public function getRenderSortAttribute() if (!empty($this->data['rendersortattr'])) { $metaModel = $this->getMetaModel(); if ($metaModel) { - $attribute = $metaModel->getAttributeById($this->data['rendersortattr']); + $attribute = $metaModel->getAttributeById((int) $this->data['rendersortattr']); if ($attribute) { return $attribute->getColName(); } diff --git a/src/CoreBundle/DcGeneral/AbstractAttributeConditionFactory.php b/src/CoreBundle/DcGeneral/AbstractAttributeConditionFactory.php index 82ec437b5..bcc4421b6 100644 --- a/src/CoreBundle/DcGeneral/AbstractAttributeConditionFactory.php +++ b/src/CoreBundle/DcGeneral/AbstractAttributeConditionFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,8 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -31,7 +32,7 @@ abstract class AbstractAttributeConditionFactory implements AttributeAwareProper * * @param IMetaModel $metaModel The MetaModel instance. * - * @param string $attributeId The attribute id. + * @param int $attributeId The attribute id. * * @return string * @@ -39,7 +40,7 @@ abstract class AbstractAttributeConditionFactory implements AttributeAwareProper */ protected function attributeIdToName(IMetaModel $metaModel, $attributeId) { - if (null === $attribute = $metaModel->getAttributeById($attributeId)) { + if (null === $attribute = $metaModel->getAttributeById((int) $attributeId)) { throw new \RuntimeException(sprintf( 'Could not retrieve attribute %s from MetaModel %s.', $attributeId, diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php index fe9cd64a2..23f49dfbb 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php @@ -94,7 +94,7 @@ private function getConditionAttribute($settingId) if ($setting->dcatype == 'attribute') { $attribute = (object) $this->getRow($setting->attr_id, 'tl_metamodel_attribute'); $metaModelName = $this->factory->translateIdToMetaModelName($attribute->pid); - $attribute = $this->factory->getMetaModel($metaModelName)->getAttributeById($attribute->id); + $attribute = $this->factory->getMetaModel($metaModelName)->getAttributeById((int) $attribute->id); if ($attribute) { return $attribute->getName(); } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AttributeIdListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AttributeIdListener.php index 8ccf9524c..1786a93ed 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AttributeIdListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AttributeIdListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -109,7 +109,7 @@ public function decodeAttributeValue(DecodePropertyValueForWidgetEvent $event) return; } - $attribute = $metaModel->getAttributeById($value); + $attribute = $metaModel->getAttributeById((int) $value); if ($attribute) { $event->setValue($metaModel->getTableName() .'_' . $attribute->getColName()); } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php index 090622508..b79cbd07f 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php @@ -62,8 +62,7 @@ public function getValueOptions(GetPropertyOptionsEvent $event) return; } - $attribute = $metaModel->getAttributeById($attributeId); - + $attribute = $metaModel->getAttributeById((int) $attributeId); if ($attribute) { $options = $this->getOptionsViaDcGeneral($metaModel, $event->getEnvironment(), $attribute); $mangled = []; diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AttributeListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AttributeListener.php index e9c353b78..2da468f6c 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AttributeListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AttributeListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -117,7 +117,7 @@ public function decodeValue(DecodePropertyValueForWidgetEvent $event) return; } - $attribute = $metaModel->getAttributeById($value); + $attribute = $metaModel->getAttributeById((int) $value); if ($attribute) { $event->setValue($metaModel->getTableName() .'_' . $attribute->getColName()); } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/DefaultOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/DefaultOptionListener.php index 51e6471b0..f897c50ac 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/DefaultOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/DefaultOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -68,7 +69,7 @@ public function handle(GetPropertyOptionsEvent $event) return; } - if (null === $attribute = $metaModel->getAttributeById($attributeId)) { + if (null === $attribute = $metaModel->getAttributeById((int) $attributeId)) { return; } diff --git a/src/Filter/Setting/SimpleLookup.php b/src/Filter/Setting/SimpleLookup.php index 5aace97c9..3c25c130a 100644 --- a/src/Filter/Setting/SimpleLookup.php +++ b/src/Filter/Setting/SimpleLookup.php @@ -329,7 +329,7 @@ protected function getFilteredAttribute() return null; } - if ($attribute = $this->getMetaModel()->getAttributeById($attributeId)) { + if ($attribute = $this->getMetaModel()->getAttributeById((int) $attributeId)) { return $attribute; } diff --git a/src/ViewCombination/InputScreenInformationBuilder.php b/src/ViewCombination/InputScreenInformationBuilder.php index 1b3f101bd..75570d5cc 100644 --- a/src/ViewCombination/InputScreenInformationBuilder.php +++ b/src/ViewCombination/InputScreenInformationBuilder.php @@ -194,7 +194,7 @@ private function fetchPropertiesFor($inputScreenId, IMetaModel $metaModel): arra if ('attribute' !== $column['dcatype']) { return $column; } - if (!($attribute = $metaModel->getAttributeById($column['attr_id']))) { + if (!($attribute = $metaModel->getAttributeById((int) $column['attr_id']))) { // @codingStandardsIgnoreStart @trigger_error( 'Unknown attribute "' . $column['attr_id'] . '" in input screen "' . $inputScreenId . '"', @@ -271,7 +271,7 @@ private function fetchGroupSort($inputScreenId, IMetaModel $metaModel): array } if (!empty($information['rendersortattr'])) { - if (!($attribute = $metaModel->getAttributeById($information['rendersortattr']))) { + if (!($attribute = $metaModel->getAttributeById((int) $information['rendersortattr']))) { // @codingStandardsIgnoreStart @trigger_error( sprintf( From a5b52989024a3bbc12993144a01c2718cd2077d5 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 26 May 2022 16:17:05 +0200 Subject: [PATCH 040/224] Fix collection PHP8 warning --- src/Render/Setting/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Render/Setting/Collection.php b/src/Render/Setting/Collection.php index 51cde4f7d..ab8be42b8 100644 --- a/src/Render/Setting/Collection.php +++ b/src/Render/Setting/Collection.php @@ -151,7 +151,7 @@ public function __construct( */ public function get($strName) { - return !isset($this->arrBase[$strName]) ?? $this->arrBase[$strName]; + return $this->arrBase[$strName] ?? null; } /** From 167995cff7e8d55388798464ad8395e3d83594e6 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 26 May 2022 16:26:21 +0200 Subject: [PATCH 041/224] Fix querybuilder --- src/Render/Setting/RenderSettingFactory.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Render/Setting/RenderSettingFactory.php b/src/Render/Setting/RenderSettingFactory.php index ea6991c38..dfbab6ed5 100644 --- a/src/Render/Setting/RenderSettingFactory.php +++ b/src/Render/Setting/RenderSettingFactory.php @@ -164,10 +164,10 @@ public function getServiceContainer() * Collect the attribute settings for the given render setting. * * @param IMetaModel $metaModel The MetaModel instance to retrieve the settings for. - * * @param ICollection $renderSetting The render setting. * * @return void + * @throws \Doctrine\DBAL\Exception */ public function collectAttributeSettings(IMetaModel $metaModel, $renderSetting) { @@ -180,10 +180,10 @@ public function collectAttributeSettings(IMetaModel $metaModel, $renderSetting) ->andWhere('t.enabled=1') ->orderBy('t.sorting') ->setParameter('pid', $renderSetting->get('id')) - ->execute(); + ->executeQuery(); - foreach ($attributeRows->fetchAll(\PDO::FETCH_ASSOC) as $attributeRow) { - $attribute = $metaModel->getAttributeById($attributeRow['attr_id']); + foreach ($attributeRows->fetchAllAssociative() as $attributeRow) { + $attribute = $metaModel->getAttributeById((int) $attributeRow['attr_id']); if (!$attribute) { continue; } @@ -206,10 +206,10 @@ public function collectAttributeSettings(IMetaModel $metaModel, $renderSetting) * Create a ICollection instance from the id. * * @param IMetaModel $metaModel The MetaModel for which to retrieve the render setting. - * * @param string $settingId The id of the ICollection. * * @return ICollection The instance or null if not found. + * @throws \Doctrine\DBAL\Exception */ protected function internalCreateRenderSetting(IMetaModel $metaModel, $settingId) { @@ -223,8 +223,8 @@ protected function internalCreateRenderSetting(IMetaModel $metaModel, $settingId ->setParameter('pid', $metaModel->get('id')) ->setParameter('id', $settingId ?: 0) ->setMaxResults(1) - ->execute() - ->fetch(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAssociative(); if (!$row) { $row = []; From 5e35770554245dfcb14f3bf041256b16d564d3c9 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 26 May 2022 16:45:15 +0200 Subject: [PATCH 042/224] Fix PHP8 warning --- src/ItemList.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ItemList.php b/src/ItemList.php index 933f18a22..34e24fca3 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -787,7 +787,7 @@ protected function getAttributeNames(): array if (!$this->getMetaModel()->isTranslated() || $jumpTo['langcode'] == $desiredLanguage || $jumpTo['langcode'] == $fallbackLanguage) { - $filterSettingsId = !isset($jumpTo['filter']) ?? $jumpTo['filter']; + $filterSettingsId = $jumpTo['filter'] ?? ''; // If the desired language, break. Otherwise, try to get the desired one until all have been evaluated. if (isset($jumpTo['langcode']) && $desiredLanguage === $jumpTo['langcode']) { break; From 24e1763ceeef3d23f2448da63f71b065bf71086b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 26 May 2022 16:47:50 +0200 Subject: [PATCH 043/224] Fix PHP8 warning --- src/ItemList.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ItemList.php b/src/ItemList.php index 34e24fca3..5a1ab0b4e 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -787,7 +787,7 @@ protected function getAttributeNames(): array if (!$this->getMetaModel()->isTranslated() || $jumpTo['langcode'] == $desiredLanguage || $jumpTo['langcode'] == $fallbackLanguage) { - $filterSettingsId = $jumpTo['filter'] ?? ''; + $filterSettingsId = $jumpTo['filter'] ?? 0; // If the desired language, break. Otherwise, try to get the desired one until all have been evaluated. if (isset($jumpTo['langcode']) && $desiredLanguage === $jumpTo['langcode']) { break; From 0288b80c1e6bb3195f0da4bf72719f53e4af2995 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 28 May 2022 16:32:31 +0200 Subject: [PATCH 044/224] Fix PHP 8 warnings --- src/Filter/Setting/Simple.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Filter/Setting/Simple.php b/src/Filter/Setting/Simple.php index 3970be434..9cd3b76ea 100644 --- a/src/Filter/Setting/Simple.php +++ b/src/Filter/Setting/Simple.php @@ -468,18 +468,18 @@ protected function prepareFrontendFilterWidget( $strField = $objWidget->generate(); return [ - 'cssID' => $arrWidget['eval']['cssID'], + 'cssID' => $arrWidget['eval']['cssID'] ?? '', 'class' => sprintf( 'mm_%s %s%s%s%s', $arrWidget['inputType'], $arrWidget['eval']['urlparam'], (($arrWidget['value'] !== null) ? ' used' : ' unused'), ($objFrontendFilterOptions->isAutoSubmit() ? ' submitonchange' : ''), - $arrWidget['eval']['class'] + $arrWidget['eval']['class'] ?? '' ), 'label' => $objWidget->generateLabel(), 'legend' => $this->generateLegend($arrWidget), - 'hide_label' => $arrWidget['eval']['hide_label'], + 'hide_label' => $arrWidget['eval']['hide_label'] ?? false, 'formfield' => $strField, 'raw' => $arrWidget, 'urlparam' => $arrWidget['eval']['urlparam'], From 9d575580e6de3d6cbe0911b059d4562b3f73b6ed Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 28 May 2022 19:47:57 +0200 Subject: [PATCH 045/224] Fix PHP 8 warnings --- src/FrontendIntegration/FrontendFilter.php | 29 +++++++++--------- src/FrontendIntegration/MetaModelHybrid.php | 33 +++++++++++---------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/FrontendIntegration/FrontendFilter.php b/src/FrontendIntegration/FrontendFilter.php index 7f7c5553e..6d3c712e0 100644 --- a/src/FrontendIntegration/FrontendFilter.php +++ b/src/FrontendIntegration/FrontendFilter.php @@ -414,13 +414,13 @@ protected function getFilters() return [ 'action' => $this->filterUrlBuilder->generate($other) . ($this->objFilterConfig->metamodel_fef_urlfragment - ? '#' . $this->objFilterConfig->metamodel_fef_urlfragment - : ''), + ? '#' . $this->objFilterConfig->metamodel_fef_urlfragment + : ''), 'formid' => $this->formId, 'filters' => $renderedWidgets, 'submit' => ($filterOptions->isAutoSubmit() - ? '' - : $GLOBALS['TL_LANG']['metamodels_frontendfilter']['submit'] + ? '' + : $GLOBALS['TL_LANG']['metamodels_frontendfilter']['submit'] ) ]; } @@ -437,10 +437,10 @@ protected function getFilters() protected function buildParameters(FilterUrl $other, FilterUrl $all, array $wantedNames): void { $current = $this->filterUrlBuilder->getCurrentFilterUrl([ - 'postAsSlug' => $wantedNames, - 'postAsGet' => [], - 'preserveGet' => true - ]); + 'postAsSlug' => $wantedNames, + 'postAsGet' => [], + 'preserveGet' => true + ]); foreach ($current->getSlugParameters() as $name => $value) { $all->setSlug($name, $value); if (!in_array($name, $wantedNames)) { @@ -494,10 +494,11 @@ protected function generateModule($content, $replace, $moduleId) * @return string * * @throws \Doctrine\DBAL\DBALException When a database error occur. + * @throws \Doctrine\DBAL\Exception */ protected function generateElement($table, $content, $replace, $elementId) { - $objDbResult = $this->connection + $result = $this->connection ->createQueryBuilder() ->select('t.*') ->from($table, 't') @@ -505,19 +506,19 @@ protected function generateElement($table, $content, $replace, $elementId) ->andWhere('t.type=:type') ->setParameter('id', $elementId) ->setParameter('type', 'metamodels_frontendclearall') - ->execute() - ->fetch(\PDO::FETCH_OBJ); + ->executeQuery() + ->fetchAssociative(); // Check if we have an existing module or ce element. - if ($objDbResult === false) { + if ($result === false) { return str_replace($replace, '', $content); } // Get instance and call generate function. if ($table == 'tl_module') { - $objElement = new ModuleFilterClearAll($objDbResult); + $objElement = new ModuleFilterClearAll((object) $result); } elseif ($table == 'tl_content') { - $objElement = new ContentElementFilterClearAll($objDbResult); + $objElement = new ContentElementFilterClearAll((object) $result); } else { return str_replace($replace, '', $content); } diff --git a/src/FrontendIntegration/MetaModelHybrid.php b/src/FrontendIntegration/MetaModelHybrid.php index 40f23f790..44ca23733 100644 --- a/src/FrontendIntegration/MetaModelHybrid.php +++ b/src/FrontendIntegration/MetaModelHybrid.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Ingolf Steinhardt * @author David Molineus * @author Richard Henkenjohann - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -139,7 +139,7 @@ public function __construct($objElement, $strColumn = 'main') // Get CSS ID and headline from the parent element (!). $this->cssID = StringUtil::deserialize($objElement->cssID, true); - $this->typePrefix = $objElement->typePrefix; + $this->typePrefix = $objElement->typePrefix ?? ''; $this->strKey = $objElement->type; $arrHeadline = StringUtil::deserialize($objElement->headline); $this->headline = is_array($arrHeadline) ? $arrHeadline['value'] : $arrHeadline; @@ -153,6 +153,7 @@ public function __construct($objElement, $strColumn = 'main') * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) + * @throws \Doctrine\DBAL\Exception */ public function generate() { @@ -184,19 +185,20 @@ public function generate() if ($this->metamodel_filtering) { $infoFi = $database ->createQueryBuilder() - ->select('name') - ->from('tl_metamodel_filter') - ->where('id=:id') + ->select('t.name') + ->from('tl_metamodel_filter', 't') + ->where('t.id=:id') ->setParameter('id', $this->metamodel_filtering) - ->execute() - ->fetch(\PDO::FETCH_COLUMN); + ->setMaxResults(1) + ->executeQuery() + ->fetchFirstColumn(); if ($infoFi) { $strInfo .= sprintf( $infoTemplate, $GLOBALS['TL_LANG']['MSC']['mm_be_info_filter'][1], $GLOBALS['TL_LANG']['MSC']['mm_be_info_filter'][0], - $infoFi + $infoFi[0] ); } } @@ -205,19 +207,20 @@ public function generate() if ($this->metamodel_rendersettings) { $infoRs = $database ->createQueryBuilder() - ->select('name') - ->from('tl_metamodel_rendersettings') - ->where('id=:id') + ->select('t.name') + ->from('tl_metamodel_rendersettings', 't') + ->where('t.id=:id') ->setParameter('id', $this->metamodel_rendersettings) - ->execute() - ->fetch(\PDO::FETCH_COLUMN); + ->setMaxResults(1) + ->executeQuery() + ->fetchFirstColumn(); if ($infoRs) { $strInfo .= sprintf( $infoTemplate, $GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting'][1], $GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting'][0], - $infoRs + $infoRs[0] ); } } From a0ca0e6ee5d0ff697368b839892e8b6f8cd068ad Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 28 Jun 2022 11:55:23 +0200 Subject: [PATCH 046/224] Fix contao requirements --- composer.json | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index b6f3b6575..6944bd8d8 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "contao-community-alliance/meta-palettes": "~2.0", "contao-community-alliance/translator": "^2.2", "contao-community-alliance/url-builder": "~1.3", - "contao/core-bundle": "^4.13.0", + "contao/core-bundle": "^4.13.0, <5.0", "discordier/justtextwidgets": "^1.2", "doctrine/cache": "^2.1", "menatwork/contao-multicolumnwizard-bundle": "^3.4", @@ -51,13 +51,10 @@ }, "require-dev": { "contao/manager-plugin": "^2.8", - "contao/manager-bundle": "^4.9.0, <4.13.0", + "contao/manager-bundle": "^4.13.0, <5.0", "doctrine/doctrine-bundle": "^1.8", "phpcq/all-tasks": "^1.3" }, - "conflict": { - "contao/manager-bundle": "4.9.27" - }, "autoload": { "psr-4": { "MetaModels\\": "src/" From 014cffaf7e4de8ccfc25123aec888240276fdf69 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 28 Jun 2022 12:32:32 +0200 Subject: [PATCH 047/224] Fix diagnostics --- .github/workflows/diagnostics.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/diagnostics.yml b/.github/workflows/diagnostics.yml index 487b294ff..9519e503d 100644 --- a/.github/workflows/diagnostics.yml +++ b/.github/workflows/diagnostics.yml @@ -11,8 +11,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: [7.4] - contao: [~4.9.0] + php: [7.4, 8,0] + contao: [~4.13.0] steps: - name: PHP ${{ matrix.php }} ${{ matrix.contao }} Pull source From bf4e90c2c6b5c6eeab245bc6de296a322f4fabba Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 28 Jun 2022 12:46:02 +0200 Subject: [PATCH 048/224] Fix deprecated collate to collation see https://github.com/doctrine/DoctrineBundle/issues/1468 see https://github.com/contao/contao/issues/4560 --- composer.json | 1 + .../Migration/TableCollationMigration.php | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 6944bd8d8..e2af7dd69 100644 --- a/composer.json +++ b/composer.json @@ -39,6 +39,7 @@ "contao/core-bundle": "^4.13.0, <5.0", "discordier/justtextwidgets": "^1.2", "doctrine/cache": "^2.1", + "doctrine/dbal": "^3.3.2", "menatwork/contao-multicolumnwizard-bundle": "^3.4", "symfony/asset": "^5.4", "symfony/cache": "^5.4", diff --git a/src/CoreBundle/Migration/TableCollationMigration.php b/src/CoreBundle/Migration/TableCollationMigration.php index 9f126adc6..93b1ede75 100644 --- a/src/CoreBundle/Migration/TableCollationMigration.php +++ b/src/CoreBundle/Migration/TableCollationMigration.php @@ -67,7 +67,7 @@ public function getName(): string { return \sprintf( 'Change collation to %1$s and/or DB engine to %2$s of all mm_* tables.', - $this->defaultTableOptions['collate'], + $this->defaultTableOptions['collation'], $this->defaultTableOptions['engine'] ); } @@ -76,9 +76,10 @@ public function getName(): string * Must only run if: * - the mm_* tables are present AND * - there collation is not utf8mb4_unicode_ci OR - * - these engine is not InnoDB. + * - the engine is not InnoDB. * * @return bool + * @throws \Doctrine\DBAL\Exception */ public function shouldRun(): bool { @@ -94,6 +95,7 @@ public function shouldRun(): bool * Collect the tables to be updated and update them. * * @return MigrationResult + * @throws \Doctrine\DBAL\Exception */ public function run(): MigrationResult { @@ -111,6 +113,7 @@ public function run(): MigrationResult * Fetch all tables that are not right collection or DB engine yet. * * @return array + * @throws \Doctrine\DBAL\Exception */ private function fetchPendingTables(): array { @@ -120,17 +123,17 @@ private function fetchPendingTables(): array $results = []; foreach ($tableNames as $tableName) { // Only MM model tables. - if ('mm_' !== substr($tableName, 0, 3)) { + if ('mm_' !== \substr($tableName, 0, 3)) { continue; } // Retrieve table data. $result = $this->connection ->executeQuery(sprintf('SHOW TABLE STATUS LIKE \'%1$s\'', $tableName)) - ->fetch(); + ->fetchAllAssociative(); // Check collation and DB engine and collect tables with false data. - if (($this->defaultTableOptions['collate'] !== $result['Collation']) + if (($this->defaultTableOptions['collation'] !== $result['Collation']) || ($this->defaultTableOptions['engine'] !== $result['Engine']) ) { $results[] = $tableName; @@ -146,11 +149,12 @@ private function fetchPendingTables(): array * @param string $tableName The name of the table. * * @return void + * @throws \Doctrine\DBAL\Exception */ private function fixTable(string $tableName): void { $this->connection->executeQuery( - sprintf( + \sprintf( 'ALTER TABLE %1$s ENGINE=%2$s DEFAULT CHARSET=%3$s COLLATE %4$s @@ -158,7 +162,7 @@ private function fixTable(string $tableName): void $tableName, $this->defaultTableOptions['engine'], $this->defaultTableOptions['charset'], - $this->defaultTableOptions['collate'] + $this->defaultTableOptions['collation'] ) ); } From 964543910a0e59313bf1cf09ef2a66718c433940 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 28 Jun 2022 13:08:24 +0200 Subject: [PATCH 049/224] Fix collation --- src/CoreBundle/Migration/TableCollationMigration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/Migration/TableCollationMigration.php b/src/CoreBundle/Migration/TableCollationMigration.php index 93b1ede75..0b7932c2f 100644 --- a/src/CoreBundle/Migration/TableCollationMigration.php +++ b/src/CoreBundle/Migration/TableCollationMigration.php @@ -130,7 +130,7 @@ private function fetchPendingTables(): array // Retrieve table data. $result = $this->connection ->executeQuery(sprintf('SHOW TABLE STATUS LIKE \'%1$s\'', $tableName)) - ->fetchAllAssociative(); + ->fetchAssociative(); // Check collation and DB engine and collect tables with false data. if (($this->defaultTableOptions['collation'] !== $result['Collation']) From 0fa5e6c8270d56397d5865edad73c520c20ba023 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 28 Jun 2022 20:15:02 +0200 Subject: [PATCH 050/224] Fix collation --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e2af7dd69..84065d7a2 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "contao-community-alliance/meta-palettes": "~2.0", "contao-community-alliance/translator": "^2.2", "contao-community-alliance/url-builder": "~1.3", - "contao/core-bundle": "^4.13.0, <5.0", + "contao/core-bundle": "^4.13.5, <5.0", "discordier/justtextwidgets": "^1.2", "doctrine/cache": "^2.1", "doctrine/dbal": "^3.3.2", From 18cdece29f93277894cc0ce033c12416decc1549 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 29 Jun 2022 17:44:22 +0200 Subject: [PATCH 051/224] Fix deleteConfirm with own language key --- .../Resources/contao/dca/tl_metamodel.php | 4 +--- .../contao/dca/tl_metamodel_attribute.php | 2 +- .../Resources/contao/dca/tl_metamodel_dca.php | 6 +++--- .../contao/dca/tl_metamodel_dca_sortgroup.php | 6 +++--- .../contao/dca/tl_metamodel_dcasetting.php | 2 +- .../dca/tl_metamodel_dcasetting_condition.php | 6 +++--- .../Resources/contao/dca/tl_metamodel_filter.php | 6 +++--- .../contao/dca/tl_metamodel_filtersetting.php | 2 +- .../contao/dca/tl_metamodel_rendersetting.php | 6 +++--- .../contao/dca/tl_metamodel_rendersettings.php | 6 +++--- .../contao/dca/tl_metamodel_searchable_pages.php | 6 +++--- .../contao/languages/en/tl_metamodel.php | 2 ++ .../languages/en/tl_metamodel_attribute.php | 7 +++++-- .../contao/languages/en/tl_metamodel_dca.php | 6 ++++-- .../languages/en/tl_metamodel_dca_sortgroup.php | 11 +++++++---- .../languages/en/tl_metamodel_dcasetting.php | 10 ++++++---- .../en/tl_metamodel_dcasetting_condition.php | 16 ++++++++++------ .../contao/languages/en/tl_metamodel_filter.php | 13 ++++++++----- .../languages/en/tl_metamodel_filtersetting.php | 11 +++++++---- .../languages/en/tl_metamodel_rendersetting.php | 13 ++++++++----- .../languages/en/tl_metamodel_rendersettings.php | 12 +++++++----- .../en/tl_metamodel_searchable_pages.php | 3 +++ 22 files changed, 92 insertions(+), 64 deletions(-) diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel.php index 6f52f702f..49f8d9df8 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel.php @@ -26,8 +26,6 @@ * @filesource */ -$this->loadLanguageFile('languages'); - $GLOBALS['TL_DCA']['tl_metamodel'] = [ 'config' => [ 'dataContainer' => 'General', @@ -339,7 +337,7 @@ 'icon' => 'delete.svg', 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] + $GLOBALS['TL_LANG']['tl_metamodel']['deleteConfirm'] ?? '' ) ], 'show' => [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php index bff838993..6a2513a5b 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php @@ -198,7 +198,7 @@ 'icon' => 'delete.svg', 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] + $GLOBALS['TL_LANG']['tl_metamodel_attribute']['deleteConfirm'] ?? '' ) ], 'show' => [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php index d5722fa5f..37085b7a9 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,7 +21,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Cliff Parnitzky - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -155,7 +155,7 @@ 'icon' => 'delete.svg', 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] + $GLOBALS['TL_LANG']['tl_metamodel_dca']['deleteConfirm'] ?? '' ) ], 'show' => [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php index bac414b1f..f19e6eb05 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Cliff Parnitzky - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -128,7 +128,7 @@ 'icon' => 'delete.svg', 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] + $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['deleteConfirm'] ?? '' ) ], 'show' => [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php index 49e518acb..16be0964b 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php @@ -166,7 +166,7 @@ 'icon' => 'delete.svg', 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] + $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['deleteConfirm'] ?? '' ) ], 'show' => [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php index 516289ed7..8bc11dcf3 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Ingolf Steinhardt * @author Richard Henkenjohann * @author Sven Baumann - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -185,7 +185,7 @@ 'icon' => 'delete.svg', 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] + $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['deleteConfirm'] ?? '' ) ], 'show' => [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php index 06dcb593d..188022c74 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Cliff Parnitzky - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -172,7 +172,7 @@ 'icon' => 'delete.svg', 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] + $GLOBALS['TL_LANG']['tl_metamodel_filter']['deleteConfirm'] ?? '' ) ), 'show' => array diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php index 72ae5eb2f..17436edfb 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php @@ -177,7 +177,7 @@ 'icon' => 'delete.svg', 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] + $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['deleteConfirm'] ?? '' ) ], 'show' => [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php index e1060923d..b79fb1604 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -20,7 +20,7 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author David Molineus - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -182,7 +182,7 @@ 'icon' => 'delete.svg', 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] + $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['deleteConfirm'] ?? '' ) ), 'show' => array diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php index ec708ef56..7508e8aa8 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,7 +21,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Cliff Parnitzky - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -145,7 +145,7 @@ 'icon' => 'delete.svg', 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] + $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['deleteConfirm'] ?? '' ) ], 'show' => [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php index dfcc6055b..0be4560e6 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Richard Henkenjohann * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -108,7 +108,7 @@ 'icon' => 'delete.svg', 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] + $GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['deleteConfirm'] ?? '' ) ], 'show' => [ diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php index e8214ccf3..131a5cbfe 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php @@ -84,3 +84,5 @@ $GLOBALS['TL_LANG']['tl_metamodel']['itemFormatCount']['0'] = '%s items'; $GLOBALS['TL_LANG']['tl_metamodel']['itemFormatCount']['1'] = '%s item'; $GLOBALS['TL_LANG']['tl_metamodel']['itemFormatCount']['2:'] = '%s items'; + +$GLOBALS['TL_LANG']['tl_metamodel']['deleteConfirm'] = 'Do you really want to delete MetaModel ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php index 4de4d0716..fc69c261c 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2018 The MetaModels team. + * (c) 2012-2022 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,8 @@ * @subpackage Core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2018 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -64,3 +65,5 @@ $GLOBALS['TL_LANG']['tl_metamodel_attribute']['error_unknown_attribute'][0] = 'Unknown attribute!'; $GLOBALS['TL_LANG']['tl_metamodel_attribute']['error_unknown_attribute'][1] = 'Extension missing? The attribute type "%s" is not installed.'; + +$GLOBALS['TL_LANG']['tl_metamodel_attribute']['deleteConfirm'] = 'Do you really want to delete attribute ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php index 566c92f8f..d43962439 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -95,3 +95,5 @@ $GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermodes']['flat'] = 'Flat'; $GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermodes']['parented'] = 'Parented'; $GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermodes']['hierarchical'] = 'Hierarchical'; + +$GLOBALS['TL_LANG']['tl_metamodel_dca']['deleteConfirm'] = 'Do you really want to delete input screen ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php index 7a2e101ec..e522b76e7 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2018 The MetaModels team. + * (c) 2012-2022 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,8 @@ * @subpackage Core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2018 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -64,9 +65,9 @@ $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['edit'][0] = 'Edit definition'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['edit'][1] = 'Edit the definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['copy'][0] = 'Copy definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['copy'][1] = 'Copy definition ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['copy'][1] = 'Copy the definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'][0] = 'Delete definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'][1] = 'Delete definition ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'][1] = 'Delete the definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][0] = 'Definition details'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][1] = 'Show details of definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][0] = 'Definition settings'; @@ -82,3 +83,5 @@ $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptypes']['year'] = 'Group by year of date'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendersortdirections']['asc'] = 'Ascending'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendersortdirections']['desc'] = 'Descending'; + +$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['deleteConfirm'] = 'Do you really want to delete definition ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php index 7c69c2eb7..dc56d7e97 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php @@ -101,13 +101,13 @@ $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['new'][0] = 'New'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['new'][1] = 'Create new setting.'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['edit'][0] = 'Edit setting'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['edit'][1] = 'Edit setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['edit'][1] = 'Edit the setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['cut'][0] = 'Cut setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['cut'][1] = 'Cut setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['cut'][1] = 'Cut the setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['copy'][0] = 'Copy setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['copy'][1] = 'Copy setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['copy'][1] = 'Copy the setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['delete'][0] = 'Delete setting'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['delete'][1] = 'Delete setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['delete'][1] = 'Delete the setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['conditions'][0] = 'Manage visibility conditions'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['conditions'][1] = 'Manage the visibility conditions of property ID %s'; @@ -138,3 +138,5 @@ 'Unique attribues are automatically mandatory (this is not changable).'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['readonly_for_force_alias'] = 'Attribues with force alias are automatically readonly (this is not changable).'; + +$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['deleteConfirm'] = 'Do you really want to delete setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting_condition.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting_condition.php index 2ef0a06b6..703ed8719 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting_condition.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting_condition.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 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,8 @@ * @subpackage Core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2020 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -50,19 +51,19 @@ $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['edit'][0] = 'Edit setting'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['edit'][1] = - 'Edit setting ID %s'; + 'Edit the setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['cut'][0] = 'Cut setting definition'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['cut'][1] = - 'Cut setting ID %s'; + 'Cut the setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['copy'][0] = 'Copy setting definition'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['copy'][1] = - 'Copy setting ID %s'; + 'Copy the setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['delete'][0] = 'Delete setting'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['delete'][1] = - 'Delete setting ID %s'; + 'Delete the setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['conditions'][0] = 'Manage conditions'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['conditions'][1] = @@ -104,3 +105,6 @@ '%s %s
all sub conditions must be fulfilled'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['typedesc']['conditionnot'] = '%s %s
invert the result of the contained condition'; + +$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['deleteConfirm'] = + 'Do you really want to delete setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filter.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filter.php index d0ab64afb..3ae002946 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filter.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filter.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2018 The MetaModels team. + * (c) 2012-2022 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,8 @@ * @subpackage Core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2018 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -31,12 +32,14 @@ $GLOBALS['TL_LANG']['tl_metamodel_filter']['new'][0] = 'New'; $GLOBALS['TL_LANG']['tl_metamodel_filter']['new'][1] = 'Create new filter setting'; $GLOBALS['TL_LANG']['tl_metamodel_filter']['edit'][0] = 'Edit setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['edit'][1] = 'Edit filter setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_filter']['edit'][1] = 'Edit the filter setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_filter']['copy'][0] = 'Copy filter setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['copy'][1] = 'Copy filter setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_filter']['copy'][1] = 'Copy the filter setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_filter']['delete'][0] = 'Delete filter setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['delete'][1] = 'Delete filter setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_filter']['delete'][1] = 'Delete the filter setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_filter']['show'][0] = 'Filter setting details'; $GLOBALS['TL_LANG']['tl_metamodel_filter']['show'][1] = 'Show details of filter setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_filter']['settings'][0] = 'Define attribute settings'; $GLOBALS['TL_LANG']['tl_metamodel_filter']['settings'][1] = 'Define attribute settings for filter setting ID %s'; + +$GLOBALS['TL_LANG']['tl_metamodel_filter']['deleteConfirm'] = 'Do you really want to delete filter setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filtersetting.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filtersetting.php index b9ec9c907..dcc972a7d 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filtersetting.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filtersetting.php @@ -109,15 +109,15 @@ $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['new'][0] = 'New'; $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['new'][1] = 'Create new setting.'; $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['edit'][0] = 'Edit setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['edit'][1] = 'Edit filter setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['edit'][1] = 'Edit the filter setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['copy'][0] = 'Copy filter setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['copy'][1] = 'Copy filter setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['copy'][1] = 'Copy the filter setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['cut'][0] = 'Cut filter setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['cut'][1] = 'Cut filter setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['cut'][1] = 'Cut the filter setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['delete'][0] = 'Delete filter setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['delete'][1] = 'Delete filter setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['delete'][1] = 'Delete the filter setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['show'][0] = 'Filter setting details'; $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['show'][1] = 'Show details of filter setting ID %s'; @@ -152,3 +152,6 @@ $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['items'][0] = 'Items'; $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['items'][1] = 'Please enter the IDs of the items for filtering as comma-separated list.'; + +$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['deleteConfirm'] = + 'Do you really want to delete filter setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersetting.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersetting.php index b6f4ce1df..ced2a7268 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersetting.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersetting.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -36,11 +36,11 @@ $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit'][0] = 'Edit setting'; $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit'][1] = 'Edit render setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['cut'][0] = 'Cut render setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['cut'][1] = 'Cut render setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['cut'][1] = 'Cut the render setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['copy'][0] = 'Copy render setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['copy'][1] = 'Copy render setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['copy'][1] = 'Copy the render setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['delete'][0] = 'Delete render setting'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['delete'][1] = 'Delete render setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['delete'][1] = 'Delete the render setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['show'][0] = 'Render setting details'; $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['show'][1] = 'Show details of render setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle'][0] = 'Toggle'; @@ -58,3 +58,6 @@ $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addAll_addsuccess'] = 'Added attribute "%s" [%s] to rendersetting.'; $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addAll_activate'] = 'Add new settings enabled.'; + +$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['deleteConfirm'] = + 'Do you really want to render filter setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersettings.php index 574b75dad..d9f247b07 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersettings.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersettings.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -64,11 +64,11 @@ $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['new'][0] = 'New'; $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['new'][1] = 'Create new setting'; $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['edit'][0] = 'Edit setting'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['edit'][1] = 'Edit setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['edit'][1] = 'Edit the setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['copy'][0] = 'Copy setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['copy'][1] = 'Copy setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['copy'][1] = 'Copy the setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['delete'][0] = 'Delete setting'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['delete'][1] = 'Delete setting ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['delete'][1] = 'Delete the setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['show'][0] = 'Filter details'; $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['show'][1] = 'Show details of setting ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['settings'][0] = 'Define attribute settings'; @@ -81,3 +81,5 @@ $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['error_unknown_id'] = 'unknown ID: %s'; $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['error_unknown_attribute'] = 'unknown attribute'; $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['error_unknown_column'] = 'unknown column'; + +$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['deleteConfirm'] = 'Do you really want to render setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_searchable_pages.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_searchable_pages.php index 2822003b2..3faeef908 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_searchable_pages.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_searchable_pages.php @@ -53,3 +53,6 @@ $GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['settings'][0] = 'Searchable page settings'; $GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['settings'][1] = 'Edit the settings of searchable page setting ID %s'; + +$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['deleteConfirm'] = + 'Do you really want to searchable page setting ID %s?'; From 05d644a6b0b314a32f27cbec070336f8c1244e96 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 29 Jun 2022 22:48:20 +0200 Subject: [PATCH 052/224] Fix action buttons --- src/CoreBundle/Resources/contao/templates/mm_actionbutton.html5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/Resources/contao/templates/mm_actionbutton.html5 b/src/CoreBundle/Resources/contao/templates/mm_actionbutton.html5 index 512d14986..3dc69aaef 100644 --- a/src/CoreBundle/Resources/contao/templates/mm_actionbutton.html5 +++ b/src/CoreBundle/Resources/contao/templates/mm_actionbutton.html5 @@ -1,5 +1,5 @@ action['html'])): ?> - action['class']): ?> class="action['class']; ?>"action['title']): ?> title="action['title']; ?>"action['attribute']; ?>>action['label']; ?> + action['class'] ?? null): ?> class="action['class'] ?? ''; ?>"action['title'] ?? null): ?> title="action['title']; ?>"action['attribute'] ?? ''; ?>>action['label']; ?> action['html'] ?> From 3261a521bf0cb17763ec314a7e0fa581981efaff Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 2 Jul 2022 14:21:21 +0200 Subject: [PATCH 053/224] Fic doctrine --- src/Attribute/TranslatedReference.php | 14 ++++----- src/BackendIntegration/TemplateList.php | 4 +-- ...bstractContentElementAndModuleCallback.php | 12 ++++---- .../Backend/AbstractAddAllController.php | 4 +-- .../DcGeneral/Breadcrumb/ConnectionTrait.php | 4 +-- .../Table/DcaCombine/GroupOptionListener.php | 4 +-- .../DcaCombine/InputScreenOptionListener.php | 8 ++--- .../RenderSettingOptionListener.php | 8 ++--- .../DcaSetting/AttributeOptionListener.php | 2 +- .../DcaSettingCondition/ValueListener.php | 4 +-- .../AttributeOptionsListener.php | 2 +- .../Table/RenderSettings/JumpToListener.php | 4 +-- .../SearchablePages/FilterOptionListener.php | 8 ++--- .../RenderSettingOptionListener.php | 9 +++--- .../Palette/RenderSettingAttributeIs.php | 4 +-- .../Property/AttributeByIdIsOfType.php | 4 +-- src/Events/DatabaseBackedListener.php | 16 +++++----- src/Filter/Rules/SimpleQuery.php | 7 +++-- src/Filter/Setting/FilterSettingFactory.php | 12 ++++---- src/FrontendIntegration/HybridFilterBlock.php | 4 +-- src/Helper/ViewCombinations.php | 30 +++++++++---------- src/MetaModel.php | 28 ++++++++--------- .../InputScreenInformationBuilder.php | 16 +++++----- .../ViewCombinationBuilder.php | 4 +-- 24 files changed, 107 insertions(+), 105 deletions(-) diff --git a/src/Attribute/TranslatedReference.php b/src/Attribute/TranslatedReference.php index 95e347113..6019bc02a 100644 --- a/src/Attribute/TranslatedReference.php +++ b/src/Attribute/TranslatedReference.php @@ -334,7 +334,7 @@ public function sortIds($idList, $strDirection) [Connection::PARAM_STR_ARRAY, Connection::PARAM_STR_ARRAY] ); - return $statement->fetchAll(\PDO::FETCH_COLUMN, 0); + return $statement->fetchFirstColumn(); } /** @@ -348,11 +348,11 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) $this->buildWhere($queryBuilder, $idList, $this->getActiveLanguage()); - $statement = $queryBuilder->execute(); + $statement = $queryBuilder->executeQuery(); $arrOptionizer = $this->getOptionizer(); $arrReturn = []; - while ($objValue = $statement->fetch(\PDO::FETCH_OBJ)) { + while ($objValue = $statement->fetchAssociative()) { $arrReturn[$objValue->{$arrOptionizer['key']}] = $objValue->{$arrOptionizer['value']}; } return $arrReturn; @@ -418,9 +418,9 @@ protected function fetchExistingIdsFor($idList, $langCode) ->from($this->getValueTable(), 't'); $this->buildWhere($queryBuilder, $idList, $langCode); - $statement = $queryBuilder->execute(); + $statement = $queryBuilder->executeQuery(); - return $statement->fetchAll(\PDO::FETCH_COLUMN); + return $statement->fetchFirstColumn(); } /** @@ -434,9 +434,9 @@ public function getTranslatedDataFor($arrIds, $strLangCode) $this->buildWhere($queryBuilder, $arrIds, $strLangCode); - $statement = $queryBuilder->execute(); + $statement = $queryBuilder->executeQuery(); $arrReturn = []; - while ($value = $statement->fetch(\PDO::FETCH_ASSOC)) { + while ($value = $statement->fetchAssociative()) { /** @noinspection PhpUndefinedFieldInspection */ $arrReturn[$value['item_id']] = $value; } diff --git a/src/BackendIntegration/TemplateList.php b/src/BackendIntegration/TemplateList.php index d8ec2babf..a5de5d86b 100644 --- a/src/BackendIntegration/TemplateList.php +++ b/src/BackendIntegration/TemplateList.php @@ -140,8 +140,8 @@ private function fetchTemplatesFromThemes($templateBaseName) ->createQueryBuilder() ->select('t.id, t.name, t.templates') ->from('tl_theme', 't') - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); // Add all the theme templates folders. foreach ($themes as $theme) { diff --git a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php index 6d67df856..67470edc9 100644 --- a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php +++ b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php @@ -261,8 +261,8 @@ public function getFilterSettings(DC_Table $objDC) ->from('tl_metamodel_filter', 'f') ->where('f.pid=:id') ->setParameter('id', $objDC->activeRecord->metamodel) - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); $result = []; foreach ($filterSettings as $filterSetting) { @@ -337,8 +337,8 @@ protected function buildFilterParamsFor(DC_Table $dataContainer, $elementName) ->andWhere('c.type=:type') ->setParameter('type', $elementName) ->setMaxResults(1) - ->execute() - ->fetch(\PDO::FETCH_COLUMN); + ->executeQuery() + ->fetchFirstColumn(); if (!$filterId) { unset($GLOBALS['TL_DCA'][static::$tableName]['fields']['metamodel_filterparams']); @@ -449,8 +449,8 @@ public function getRenderSettings(DC_Table $objDC) ->from('tl_metamodel_rendersettings', 'r') ->where('r.pid=:id') ->setParameter('id', $objDC->activeRecord->metamodel) - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); $result = []; foreach ($filterSettings as $filterSetting) { diff --git a/src/CoreBundle/Controller/Backend/AbstractAddAllController.php b/src/CoreBundle/Controller/Backend/AbstractAddAllController.php index 4390d3456..a66220f25 100644 --- a/src/CoreBundle/Controller/Backend/AbstractAddAllController.php +++ b/src/CoreBundle/Controller/Backend/AbstractAddAllController.php @@ -232,9 +232,9 @@ private function fetchExisting($table, $parentId) ->where('t.pid=:pid') ->setParameter('pid', $parentId) ->orderBy('t.sorting') - ->execute(); + ->executeQuery(); - foreach ($alreadyExisting->fetchAll(\PDO::FETCH_ASSOC) as $item) { + foreach ($alreadyExisting->fetchAllAssociative() as $item) { $this->knownAttributes[$item['attr_id']] = $item; $this->startSort = $item['sorting']; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/ConnectionTrait.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/ConnectionTrait.php index 9ad8b6788..88db17130 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/ConnectionTrait.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/ConnectionTrait.php @@ -65,7 +65,7 @@ private function getRow($rowId, $table) ->where('t.id=:id') ->setParameter('id', $rowId) ->setMaxResults(1) - ->execute() - ->fetch(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAssociative(); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/GroupOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/GroupOptionListener.php index 672ae1148..0ef7cb44a 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/GroupOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/GroupOptionListener.php @@ -68,8 +68,8 @@ public function handle(GetOptionsEvent $event) ->select('t.id') ->addSelect('t.name') ->from($isBackend ? 'tl_user_group' : 'tl_member_group', 't') - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); $result = []; $result[-1] = $event->getEnvironment()->getTranslator()->translate( diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/InputScreenOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/InputScreenOptionListener.php index 98ced78a9..35a75c0dd 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/InputScreenOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/InputScreenOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -69,8 +69,8 @@ public function handle(GetOptionsEvent $event) ->from('tl_metamodel_dca', 't') ->where('t.pid=:pid') ->setParameter('pid', $event->getModel()->getProperty('id')) - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); $result = []; foreach ($screens as $screen) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/RenderSettingOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/RenderSettingOptionListener.php index 8d16cde12..9bc98e182 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/RenderSettingOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/RenderSettingOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -69,8 +69,8 @@ public function handle(GetOptionsEvent $event) ->from('tl_metamodel_rendersettings', 't') ->where('t.pid=:pid') ->setParameter('pid', $event->getModel()->getProperty('id')) - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); $result = []; foreach ($screens as $screen) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AttributeOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AttributeOptionListener.php index af570933e..ac30decbe 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AttributeOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AttributeOptionListener.php @@ -90,7 +90,7 @@ public function getAttributeOptions(GetPropertyOptionsEvent $event) ->andWhere('t.attr_id<>:id') ->setParameter('id', $attributeId); } - $alreadyTaken = $alreadyTaken->execute()->fetchAll(\PDO::FETCH_COLUMN); + $alreadyTaken = $alreadyTaken->executeQuery()->fetchFirstColumn(); foreach ($metaModel->getAttributes() as $attribute) { if ($attribute instanceof IInternal || in_array($attribute->get('id'), $alreadyTaken)) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php index b79cbd07f..c46983ea0 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php @@ -93,7 +93,7 @@ public function decodeValue(DecodePropertyValueForWidgetEvent $event) if (null === $attributeId = $model->getProperty('attr_id')) { return; } - $attribute = $metaModel->getAttributeById($attributeId); + $attribute = $metaModel->getAttributeById((int) $attributeId); $currentLanguage = $this->extractCurrentLanguageContext($metaModel); if (is_array($event->getValue())) { @@ -128,7 +128,7 @@ public function encodeValue(EncodePropertyValueFromWidgetEvent $event) if (null === $attributeId = $model->getPropertyValue('attr_id')) { return; } - $attribute = $metaModel->getAttributeById($attributeId); + $attribute = $metaModel->getAttributeById((int) $attributeId); $currentLanguage = $this->extractCurrentLanguageContext($metaModel); if (is_array($event->getValue())) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AttributeOptionsListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AttributeOptionsListener.php index 441fdd843..ab3dc3c5d 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AttributeOptionsListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AttributeOptionsListener.php @@ -88,7 +88,7 @@ public function handle(GetPropertyOptionsEvent $event) ->andWhere('t.attr_id<>:id') ->setParameter('id', $attributeId); } - $alreadyTaken = $alreadyTaken->execute()->fetchAll(\PDO::FETCH_COLUMN); + $alreadyTaken = $alreadyTaken->executeQuery()->fetchFirstColumn(); $options = []; foreach ($metaModel->getAttributes() as $attribute) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php index 61af623c0..c50f058e5 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php @@ -216,8 +216,8 @@ private function getFilterSettings(ModelInterface $model) ->from('tl_metamodel_filter', 't') ->where('t.pid=:id') ->setParameter('id', $model->getProperty('pid')) - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); $result = []; foreach ($filters as $filter) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/FilterOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/FilterOptionListener.php index 12d5c3ed1..ca4f8dd2a 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/FilterOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/FilterOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -72,8 +72,8 @@ public function handle(GetPropertyOptionsEvent $event) ->from('tl_metamodel_filter', 't') ->where('t.pid=:id') ->setParameter('id', $model->getProperty('pid')) - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); $options = []; foreach ($filters as $filter) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/RenderSettingOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/RenderSettingOptionListener.php index 64e896c08..6f4e26b5a 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/RenderSettingOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/RenderSettingOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -71,8 +72,8 @@ public function handle(GetPropertyOptionsEvent $event) ->from('tl_metamodel_rendersettings') ->where('pid=:id') ->setParameter('id', $model->getProperty('pid')) - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); $options = []; foreach ($filters as $filter) { diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php b/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php index 7aa9ede9b..2ca51d532 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php @@ -128,9 +128,9 @@ public function getTypeOfAttribute($value) ->where('t.id=:id') ->setParameter('id', $value) ->setMaxResults(1) - ->execute(); + ->executeQuery(); - self::$attributeTypes[$value] = $statement->fetch(\PDO::FETCH_OBJ)->type; + self::$attributeTypes[$value] = $statement->fetchAssociative()['type']; } return self::$attributeTypes[$value]; diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php index 5c184a919..42513c807 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php @@ -116,9 +116,9 @@ public function getTypeOfAttribute($value) ->where('t.id=:id') ->setParameter('id', $value) ->setMaxResults(1) - ->execute(); + ->executeQuery(); - self::$attributeTypes[$value] = $statement->fetch(\PDO::FETCH_COLUMN); + self::$attributeTypes[$value] = $statement->fetchFirstColumn(); } return self::$attributeTypes[$value]; diff --git a/src/Events/DatabaseBackedListener.php b/src/Events/DatabaseBackedListener.php index acd0bf8e6..6b0e72aba 100644 --- a/src/Events/DatabaseBackedListener.php +++ b/src/Events/DatabaseBackedListener.php @@ -156,8 +156,8 @@ public function getMetaModelNameFromId(GetMetaModelNameFromIdEvent $event) ->where('t.id=:id') ->setParameter('id', $metaModelId) ->setMaxResults(1) - ->execute() - ->fetch(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAssociative(); if ($table) { $this->tableNames[$metaModelId] = $table['tableName']; @@ -264,8 +264,8 @@ public function createMetaModel(CreateMetaModelEvent $event) ->where('t.tableName=:tableName') ->setParameter('tableName', $metaModelName) ->setMaxResults(1) - ->execute() - ->fetch(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAssociative(); if ($table) { $table['system_columns'] = $this->systemColumns; @@ -295,8 +295,8 @@ public function collectMetaModelTableNames(CollectMetaModelTableNamesEvent $even ->select('*') ->from('tl_metamodel', 't') ->orderBy('t.sorting') - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); foreach ($tables as $table) { $this->tableNames[$table['id']] = $table['tableName']; @@ -325,8 +325,8 @@ public function collectMetaModelAttributeInformation(CollectMetaModelAttributeIn ->where('t.pid=:pid') ->setParameter('pid', $event->getMetaModel()->get('id')) ->orderBy('t.sorting') - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); $this->attributeInformation[$metaModelName] = []; foreach ($attributes as $attribute) { diff --git a/src/Filter/Rules/SimpleQuery.php b/src/Filter/Rules/SimpleQuery.php index 0092c8c33..6a4545375 100644 --- a/src/Filter/Rules/SimpleQuery.php +++ b/src/Filter/Rules/SimpleQuery.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 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,8 @@ * @author Christian Schiffler * @author Sven Baumann * @author Cliff Parnitzky - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -120,7 +121,7 @@ public function getMatchingIds() { $matches = $this->connection->executeQuery($this->queryString, $this->params, $this->types); $ids = []; - foreach ($matches->fetchAll(\PDO::FETCH_ASSOC) as $value) { + foreach ($matches->fetchAllAssociative() as $value) { $ids[] = $value[$this->idColumn]; } diff --git a/src/Filter/Setting/FilterSettingFactory.php b/src/Filter/Setting/FilterSettingFactory.php index 43e6d3548..bb9007c17 100644 --- a/src/Filter/Setting/FilterSettingFactory.php +++ b/src/Filter/Setting/FilterSettingFactory.php @@ -209,9 +209,9 @@ private function collectRulesFor($parentSetting, $filterSettings) ->andWhere('t.enabled=1') ->orderBy('t.sorting', 'ASC') ->setParameter('pid', $parentSetting->get('id')) - ->execute(); + ->executeQuery(); - foreach ($childInformation->fetchAll(\PDO::FETCH_ASSOC) as $item) { + foreach ($childInformation->fetchAllAssociative() as $item) { $childSetting = $this->createSetting($item, $filterSettings); if ($childSetting) { $parentSetting->addChild($childSetting); @@ -237,9 +237,9 @@ public function collectRules($filterSettings) ->andWhere('t.enabled=1') ->orderBy('t.sorting', 'ASC') ->setParameter('fid', $filterSettings->get('id')) - ->execute(); + ->executeQuery(); - foreach ($information->fetchAll(\PDO::FETCH_ASSOC) as $item) { + foreach ($information->fetchAllAssociative() as $item) { $newSetting = $this->createSetting($item, $filterSettings); if ($newSetting) { $filterSettings->addSetting($newSetting); @@ -261,12 +261,12 @@ public function createCollection($settingId) ->where('t.id=:id') ->setMaxResults(1) ->setParameter('id', $settingId) - ->execute(); + ->executeQuery(); if (!$query) { throw new \RuntimeException('Could not retrieve filter setting'); } - if (!empty($information = $query->fetch(\PDO::FETCH_ASSOC))) { + if (!empty($information = $query->fetchAssociative())) { $metaModel = $this->factory->getMetaModel($this->factory->translateIdToMetaModelName($information['pid'])); if ($metaModel === null) { throw new \RuntimeException('Could not retrieve MetaModel ' . $information['pid']); diff --git a/src/FrontendIntegration/HybridFilterBlock.php b/src/FrontendIntegration/HybridFilterBlock.php index 39466707b..0a32cc75d 100644 --- a/src/FrontendIntegration/HybridFilterBlock.php +++ b/src/FrontendIntegration/HybridFilterBlock.php @@ -95,10 +95,10 @@ public function getJumpTo() ->where('t.id=:id') ->setParameter('id', $this->metamodel_jumpTo) ->setMaxResults(1) - ->execute(); + ->executeQuery(); if ($statement->rowCount()) { - $this->setJumpTo($statement->fetch(\PDO::FETCH_ASSOC)); + $this->setJumpTo($statement->fetchAssociative()); } } } diff --git a/src/Helper/ViewCombinations.php b/src/Helper/ViewCombinations.php index 133eb782b..64672c626 100644 --- a/src/Helper/ViewCombinations.php +++ b/src/Helper/ViewCombinations.php @@ -343,9 +343,9 @@ protected function getCombinationsFromDatabase() ->orderBy('t.pid') ->addOrderBy('t.sorting', 'ASC') ->setParameter('groups', $groups) - ->execute(); + ->executeQuery(); - return $statement->fetchAll(\PDO::FETCH_OBJ); + return $statement->fetchAllAssociative(); } /** @@ -367,7 +367,7 @@ protected function getPaletteCombinationRows() foreach ($combinations as $combination) { /** @noinspection PhpUndefinedFieldInspection */ - $modelId = $combination->pid; + $modelId = $combination['pid']; $modelName = $this->tableNameFromId($modelId); // Already a combination present, continue with next one. @@ -380,8 +380,8 @@ protected function getPaletteCombinationRows() /** @noinspection PhpUndefinedFieldInspection */ $this->information[$modelName][self::COMBINATION] = array( - 'dca_id' => $combination->dca_id, - 'view_id' => $combination->view_id + 'dca_id' => $combination['dca_id'], + 'view_id' => $combination['view_id'] ); $this->setTableMapping($modelId, $modelName); @@ -417,13 +417,13 @@ protected function fetchInputScreenDetails() ->from('tl_metamodel_dca', 't') ->where('t.id IN (:ids)') ->setParameter('id', $inputScreenIds, Connection::PARAM_STR_ARRAY) - ->execute(); + ->executeQuery(); - while ($inputScreens = $statement->fetch(\PDO::FETCH_OBJ)) { + while ($inputScreens = $statement->fetchAssociative()) { /** @noinspection PhpUndefinedFieldInspection */ - $screenId = $inputScreens->id; + $screenId = $inputScreens['id']; /** @noinspection PhpUndefinedFieldInspection */ - $metaModelId = $inputScreens->pid; + $metaModelId = $inputScreens['pid']; $metaModelName = $this->tableNameFromId($metaModelId); $propertyRows = $this->connection @@ -434,7 +434,7 @@ protected function fetchInputScreenDetails() ->andWhere('t.published=1') ->setParameter('id', $screenId) ->orderBy('t.sorting', 'ASC') - ->execute(); + ->executeQuery(); $conditions = $this->connection ->createQueryBuilder() @@ -447,7 +447,7 @@ protected function fetchInputScreenDetails() ->andWhere('cond.enabled=1') ->setParameter('id', $screenId) ->orderBy('cond.sorting', 'ASC') - ->execute(); + ->executeQuery(); $groupSort = $this->connection ->createQueryBuilder() @@ -456,13 +456,13 @@ protected function fetchInputScreenDetails() ->where('t.pid=:pid') ->setParameter('pid', $screenId) ->orderBy('t.sorting', 'ASC') - ->execute(); + ->executeQuery(); $inputScreen = array( 'row' => $inputScreens->row(), - 'properties' => $propertyRows->fetchAll(\PDO::FETCH_ASSOC), - 'conditions' => $conditions->fetchAll(\PDO::FETCH_ASSOC), - 'groupSort' => $groupSort->fetchAll(\PDO::FETCH_ASSOC) + 'properties' => $propertyRows->fetchAllAssociative(), + 'conditions' => $conditions->fetchAllAssociative(), + 'groupSort' => $groupSort->fetchAllAssociative() ); $this->information[$metaModelName][self::INPUTSCREEN] = $inputScreen; diff --git a/src/MetaModel.php b/src/MetaModel.php index cb63a9a9c..5fe2e74b9 100644 --- a/src/MetaModel.php +++ b/src/MetaModel.php @@ -362,8 +362,8 @@ protected function getMatchingIds($objFilter) return $this->getConnection()->createQueryBuilder() ->select('t.id') ->from($this->getTableName(), 't') - ->execute() - ->fetchAll(\PDO::FETCH_COLUMN); + ->executeQuery() + ->fetchFirstColumn(); } /** @@ -404,7 +404,7 @@ protected function fetchRows($arrIds, $arrAttrOnly = array()) ->where($builder->expr()->in('t.id', ':values')) ->setParameter('values', $arrIds, Connection::PARAM_STR_ARRAY) ->orderBy('FIELD(id, :values)') - ->execute(); + ->executeQuery(); // If we have an attribute restriction, make sure we keep the system columns. See #196. if ($arrAttrOnly) { @@ -412,7 +412,7 @@ protected function fetchRows($arrIds, $arrAttrOnly = array()) } $result = []; - while ($row = $query->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $query->fetchAssociative()) { $data = []; foreach ($row as $attribute => $value) { if ((!$arrAttrOnly) || (in_array($attribute, $arrAttrOnly, true))) { @@ -945,8 +945,8 @@ public function getIdsFromFilter($objFilter, $strSortBy = '', $intOffset = 0, $i ->where($builder->expr()->in('t.id', ':values')) ->setParameter('values', $arrFilteredIds, Connection::PARAM_STR_ARRAY) ->orderBy($strSortBy, $strSortOrder) - ->execute() - ->fetchAll(\PDO::FETCH_COLUMN); + ->executeQuery() + ->fetchFirstColumn(); // Add the new sorted Id's to the cache and use only the wanted. $this->existingIds[$sortKey] = $arrSortedFilteredIds; @@ -980,8 +980,8 @@ public function getCount($objFilter) ->from($this->getTableName(), 't') ->where($builder->expr()->in('t.id', ':values')) ->setParameter('values', $arrFilteredIds, Connection::PARAM_STR_ARRAY) - ->execute() - ->fetch(\PDO::FETCH_COLUMN); + ->executeQuery() + ->fetchFirstColumn(); } /** @@ -997,8 +997,8 @@ public function findVariantBase($objFilter) ->select('t.id') ->from($this->getTableName(), 't') ->where('t.varbase=1') - ->execute() - ->fetchAll(\PDO::FETCH_COLUMN); + ->executeQuery() + ->fetchFirstColumn(); $objNewFilter->addFilterRule(new StaticIdList($idList)); return $this->findByFilter($objNewFilter); @@ -1023,8 +1023,8 @@ public function findVariants($arrIds, $objFilter) ->where('t.varbase=0') ->andWhere($builder->expr()->in('t.vargroup', ':ids')) ->setParameter('ids', $arrIds, Connection::PARAM_STR_ARRAY) - ->execute() - ->fetchAll(\PDO::FETCH_COLUMN); + ->executeQuery() + ->fetchFirstColumn(); $objNewFilter->addFilterRule(new StaticIdList($idList)); return $this->findByFilter($objNewFilter); @@ -1049,8 +1049,8 @@ public function findVariantsWithBase($arrIds, $objFilter) ->leftJoin('t', $this->getTableName(), 't2', 't.vargroup=t2.vargroup') ->where($builder->expr()->in('t2.id', ':ids')) ->setParameter('ids', $arrIds, Connection::PARAM_STR_ARRAY) - ->execute() - ->fetchAll(\PDO::FETCH_COLUMN); + ->executeQuery() + ->fetchFirstColumn(); $objNewFilter->addFilterRule(new StaticIdList($idList)); return $this->findByFilter($objNewFilter); diff --git a/src/ViewCombination/InputScreenInformationBuilder.php b/src/ViewCombination/InputScreenInformationBuilder.php index 75570d5cc..58477025c 100644 --- a/src/ViewCombination/InputScreenInformationBuilder.php +++ b/src/ViewCombination/InputScreenInformationBuilder.php @@ -77,8 +77,8 @@ public function fetchInputScreens($idList): array ->where($builder->expr()->in('d.id', ':idList')) ->setParameter('idList', $idList, Connection::PARAM_STR_ARRAY) ->orderBy('m.sorting') - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); $result = []; $keys = array_flip($idList); @@ -220,8 +220,8 @@ private function fetchPropertiesFor($inputScreenId, IMetaModel $metaModel): arra ->setParameter('pid', $inputScreenId) ->setParameter('published', 1) ->orderBy('t.sorting') - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC)); + ->executeQuery() + ->fetchAllAssociative()); } /** @@ -246,8 +246,8 @@ private function fetchConditions($inputScreenId): array ->setParameter('screenId', $inputScreenId) ->orderBy('cond.pid') ->addOrderBy('cond.sorting') - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); } /** @@ -296,8 +296,8 @@ private function fetchGroupSort($inputScreenId, IMetaModel $metaModel): array ->where('t.pid=:screenId') ->setParameter('screenId', $inputScreenId) ->orderBy('t.sorting') - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC)); + ->executeQuery() + ->fetchAllAssociative()); } /** diff --git a/src/ViewCombination/ViewCombinationBuilder.php b/src/ViewCombination/ViewCombinationBuilder.php index 9154bf45b..bdab6c657 100644 --- a/src/ViewCombination/ViewCombinationBuilder.php +++ b/src/ViewCombination/ViewCombinationBuilder.php @@ -101,8 +101,8 @@ private function getCombinationsFromDatabase($userGroups, $userType) ->orWhere('t.' . $userType . '_group=0') ->orderBy('t.pid') ->addOrderBy('t.sorting') - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); $result = [ 'byName' => [], From f2922ca20a9b7516f7677c2c42828aff641c2100 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 2 Jul 2022 23:11:23 +0200 Subject: [PATCH 054/224] Fix doctrine --- .../Palette/Condition/Palette/RenderSettingAttributeIs.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php b/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php index 2ca51d532..b5eb05d05 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php @@ -120,6 +120,7 @@ public function getAttributeType() */ public function getTypeOfAttribute($value) { + if (!isset(self::$attributeTypes[$value])) { $statement = $this->connection ->createQueryBuilder() @@ -141,6 +142,7 @@ public function getTypeOfAttribute($value) */ public function getMatchCount(ModelInterface $model = null, PropertyValueBag $input = null) { + $value = null; if ($input && $input->hasPropertyValue('attr_id')) { $value = $input->getPropertyValue('attr_id'); } elseif ($model) { @@ -149,6 +151,10 @@ public function getMatchCount(ModelInterface $model = null, PropertyValueBag $in return false; } + if (null === $value) { + return false; + } + return ($this->getTypeOfAttribute($value) == $this->getAttributeType()) ? $this->getWeight() : false; } From 55878ef92c4798aa8b0d520c576951f5ed4cb0d4 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 6 Jul 2022 22:41:18 +0200 Subject: [PATCH 055/224] Fix PHP8 warnings --- src/Helper/ToolboxFile.php | 98 ++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/src/Helper/ToolboxFile.php b/src/Helper/ToolboxFile.php index 7286153ce..22e800780 100644 --- a/src/Helper/ToolboxFile.php +++ b/src/Helper/ToolboxFile.php @@ -140,21 +140,21 @@ class ToolboxFile * * @var array */ - protected $foundFiles = array(); + protected $foundFiles = []; /** * The pending paths to collect from DB. * * @var string[] */ - protected $pendingPaths = array(); + protected $pendingPaths = []; /** * The pending uuids to collect from DB. * * @var array */ - protected $pendingIds = array(); + protected $pendingIds = []; /** * Flag if download keys shall be generated. @@ -173,7 +173,7 @@ class ToolboxFile * * @var string[] */ - protected $uuidMap = array(); + protected $uuidMap = []; /** * Buffered file information. @@ -475,14 +475,14 @@ protected function collectFiles() { $table = FilesModel::getTable(); - $conditions = array(); - $parameters = array(); + $conditions = []; + $parameters = []; if (count($this->pendingIds)) { $conditions[] = $table . '.uuid IN(' . implode(',', array_fill(0, count($this->pendingIds), 'UNHEX(?)')) . ')'; $parameters = array_map('bin2hex', $this->pendingIds); - $this->pendingIds = array(); + $this->pendingIds = []; } if (count($this->pendingPaths)) { $slug = $table . '.path LIKE ?'; @@ -490,14 +490,14 @@ protected function collectFiles() $conditions[] = $slug; $parameters[] = $pendingPath . '%'; } - $this->pendingPaths = array(); + $this->pendingPaths = []; } if (!count($conditions)) { return; } - if ($files = FilesModel::findBy(array(implode(' OR ', $conditions)), $parameters)) { + if ($files = FilesModel::findBy([implode(' OR ', $conditions)], $parameters)) { $this->addFileModels($files); } @@ -548,8 +548,8 @@ protected function getDownloadLink($strFile) */ protected function fetchAdditionalData() { - $this->modifiedTime = array(); - $this->outputBuffer = array(); + $this->modifiedTime = []; + $this->outputBuffer = []; if (!$this->foundFiles) { return; @@ -577,8 +577,8 @@ protected function fetchAdditionalData() */ protected function remapSorting($arrFiles, $arrSource) { - $files = array(); - $source = array(); + $files = []; + $source = []; foreach (array_keys($arrFiles) as $k) { $files[] = $arrFiles[$k]; @@ -587,11 +587,10 @@ protected function remapSorting($arrFiles, $arrSource) $this->addClasses($source); - return array - ( - 'files' => $files, + return [ + 'files' => $files, 'source' => $source - ); + ]; } /** @@ -611,7 +610,7 @@ protected function remapSorting($arrFiles, $arrSource) * * @return array The sorted file list. */ - public function sortFiles($sortType, $sortIds = array()) + public function sortFiles($sortType, $sortIds = []) { switch ($sortType) { case 'name_desc': @@ -664,7 +663,7 @@ protected function sortByName($blnAscending = true) $arrFiles = $this->foundFiles; if (!$arrFiles) { - return array('files' => array(), 'source' => array()); + return ['files' => [], 'source' => []]; } \uasort($arrFiles, ($blnAscending) ? '\basename_natcasecmp' : '\basename_natcasercmp'); @@ -685,7 +684,7 @@ protected function sortByDate($blnAscending = true) $arrDates = $this->modifiedTime; if (!$arrFiles) { - return array('files' => array(), 'source' => array()); + return ['files' => [], 'source' => []]; } if ($blnAscending) { @@ -708,10 +707,10 @@ protected function sortByIdList($sortIds) { $fileMap = $this->foundFiles; if (!$fileMap) { - return array('files' => array(), 'source' => array()); + return ['files' => [], 'source' => []]; } $fileKeys = array_flip(array_keys($this->uuidMap)); - $sorted = array(); + $sorted = []; foreach ($sortIds as $sortStringId) { $key = $fileKeys[$sortStringId]; $sorted[$key] = $fileMap[$key]; @@ -734,11 +733,11 @@ protected function sortByRandom() $arrSource = $this->outputBuffer; if (!$arrFiles) { - return array('files' => array(), 'source' => array()); + return ['files' => [], 'source' => []]; } $keys = array_keys($arrFiles); - $files = array(); + $files = []; shuffle($keys); foreach ($keys as $key) { $files[$key] = $arrFiles[$key]; @@ -886,16 +885,18 @@ public static function convertValuesToMetaModels($values) } // Convert UUIDs to binary and clean empty values out. - $values = array_filter(array_map(function ($fileId) { - return Validator::isStringUuid($fileId) ? StringUtil::uuidToBin($fileId) : $fileId; - }, $values)); - - $result = array( - 'bin' => array(), - 'value' => array(), - 'path' => array(), - 'meta' => array() + $values = array_filter( + array_map(function ($fileId) { + return Validator::isStringUuid($fileId) ? StringUtil::uuidToBin($fileId) : $fileId; + }, $values) ); + + $result = [ + 'bin' => [], + 'value' => [], + 'path' => [], + 'meta' => [] + ]; if (empty($values)) { return $result; } @@ -937,12 +938,12 @@ public static function convertUuidsOrPathsToMetaModels($values) { $values = array_filter((array) $values); if (empty($values)) { - return array( - 'bin' => array(), - 'value' => array(), - 'path' => array(), - 'meta' => array() - ); + return [ + 'bin' => [], + 'value' => [], + 'path' => [], + 'meta' => [] + ]; } foreach ($values as $key => $value) { @@ -974,7 +975,7 @@ public static function convertUuidsOrPathsToMetaModels($values) * * @return void */ - private function addFileModels($files, $skipPaths = array()) + private function addFileModels($files, $skipPaths = []) { $baseLanguage = $this->getBaseLanguage(); $fallbackLanguage = $this->getFallbackLanguage(); @@ -983,8 +984,11 @@ private function addFileModels($files, $skipPaths = array()) $this->pendingPaths[] = $file->path . '/'; continue; } - if (is_file(TL_ROOT . DIRECTORY_SEPARATOR . $file->path) && - in_array(strtolower(pathinfo($file->path, PATHINFO_EXTENSION)), $this->acceptedExtensions) + if (is_file(TL_ROOT . DIRECTORY_SEPARATOR . $file->path) + && in_array( + strtolower(pathinfo($file->path, PATHINFO_EXTENSION)), + $this->acceptedExtensions + ) ) { $path = $file->path; $this->foundFiles[] = $path; @@ -1010,9 +1014,11 @@ private function addFileModels($files, $skipPaths = array()) private function processFile($fileName) { $file = new File($fileName); - $meta = $this->metaInformation[dirname($fileName)][$file->basename]; - $title = strlen($meta['title']) ? $meta['title'] : StringUtil::specialchars($file->basename); - if (strlen($meta['caption'])) { + $meta = $this->metaInformation[dirname($fileName)][$file->basename] ?? []; + $title = isset($meta['title']) && strlen($meta['title']) + ? $meta['title'] + : StringUtil::specialchars($file->basename); + if (isset($meta['caption']) && strlen($meta['caption'])) { $altText = $meta['caption']; } else { $altText = ucfirst(str_replace('_', ' ', preg_replace('/^[0-9]+_/', '', $file->filename))); @@ -1052,7 +1058,7 @@ private function processFile($fileName) } // Prepare the picture for provide the image size. - if ($file->isImage && ($information['isPicture'] = (int) $this->resizeImages[2])) { + if ($file->isImage && ($information['isPicture'] = (int) ($this->resizeImages[2] ?? 0))) { $projectDir = $this->rootDir; $staticUrl = $this->filesContext->getStaticUrl(); $picture = $this->pictureFactory->create($projectDir . '/' . $file->path, $this->getResizeImages()); From 4bc6d174cb68fbbe615e178a369741270947ccfe Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 7 Jul 2022 23:36:32 +0200 Subject: [PATCH 056/224] Fix doctrine change --- .../Condition/Property/AttributeByIdIsOfType.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php index 42513c807..286c3097e 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php @@ -103,7 +103,8 @@ public function getAttributeType() * * @param int $value The id of an attribute. * - * @return string + * @return ?string Return the id or null if not found. + * @throws \Doctrine\DBAL\Exception */ public function getTypeOfAttribute($value) { @@ -118,7 +119,12 @@ public function getTypeOfAttribute($value) ->setMaxResults(1) ->executeQuery(); - self::$attributeTypes[$value] = $statement->fetchFirstColumn(); + $result = $statement->fetchFirstColumn(); + if(count($result) > 0){ + self::$attributeTypes[$value] = $result[0]; + }else { + self::$attributeTypes[$value] = null; + } } return self::$attributeTypes[$value]; From fd535a0558075499b11fdf1d1eba0601436d4aa7 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 8 Jul 2022 19:59:13 +0200 Subject: [PATCH 057/224] Fix PHP 8 warnings --- src/Filter/Setting/Simple.php | 10 +++++----- src/Widgets/MultiTextWidget.php | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Filter/Setting/Simple.php b/src/Filter/Setting/Simple.php index 9cd3b76ea..f9fa4dca8 100644 --- a/src/Filter/Setting/Simple.php +++ b/src/Filter/Setting/Simple.php @@ -372,17 +372,17 @@ protected function prepareFrontendFilterOptions($arrWidget, $arrFilterUrl, $arrJ $filterUrl->setSlug($name, (string) $value); } - $parameterName = $arrWidget['eval']['urlparam']; + $parameterName = $arrWidget['eval']['urlparam'] ?? ''; - if ($arrWidget['eval']['includeBlankOption']) { + if ($arrWidget['eval']['includeBlankOption'] ?? null) { $blnActive = $this->isActiveFrontendFilterValue($arrWidget, $arrFilterUrl, ''); $arrOptions[] = [ 'key' => '', 'value' => ( - $arrWidget['eval']['blankOptionLabel'] - ? $arrWidget['eval']['blankOptionLabel'] - : $GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'] + !$arrWidget['eval']['blankOptionLabel'] + ? $GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'] + : $arrWidget['eval']['blankOptionLabel'] ), 'href' => $this->filterUrlBuilder->generate($filterUrl->clone()->setSlug($parameterName, '')), 'active' => $blnActive, diff --git a/src/Widgets/MultiTextWidget.php b/src/Widgets/MultiTextWidget.php index 5b5996d28..915b8035e 100644 --- a/src/Widgets/MultiTextWidget.php +++ b/src/Widgets/MultiTextWidget.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2022 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -119,7 +119,7 @@ public function generate() $i, '', (strlen($this->strClass) ? ' ' . $this->strClass : ''), - StringUtil::specialchars($this->varValue[$i]), + StringUtil::specialchars(isset($this->varValue) ? $this->varValue[$i] : ''), $this->getAttributes(), $this->strTagEnding ); From 1497965b4d644b8508d255173f8dc54fbc929424 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 10 Jul 2022 15:08:38 +0200 Subject: [PATCH 058/224] Fix doctrine --- .../Contao/Hooks/AbstractContentElementAndModuleCallback.php | 3 ++- src/Filter/Setting/FilterSettingFactory.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php index 67470edc9..ce84a354e 100644 --- a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php +++ b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php @@ -319,6 +319,7 @@ public function getMetaDescriptionAttributes(DC_Table $objDC) * * @return void * + * @throws \Doctrine\DBAL\Exception * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ @@ -345,7 +346,7 @@ protected function buildFilterParamsFor(DC_Table $dataContainer, $elementName) return; } - $collection = $this->filterFactory->createCollection($filterId); + $collection = $this->filterFactory->createCollection(current($filterId)); $dca = $collection->getParameterDCA(); foreach ($dca as $fieldName => $subField) { $options = []; diff --git a/src/Filter/Setting/FilterSettingFactory.php b/src/Filter/Setting/FilterSettingFactory.php index bb9007c17..dee98d6c7 100644 --- a/src/Filter/Setting/FilterSettingFactory.php +++ b/src/Filter/Setting/FilterSettingFactory.php @@ -262,7 +262,7 @@ public function createCollection($settingId) ->setMaxResults(1) ->setParameter('id', $settingId) ->executeQuery(); - if (!$query) { + if (!$query->rowCount()) { throw new \RuntimeException('Could not retrieve filter setting'); } From a9cb34d6df5e8422435ca478986f4dc1dc6ac42b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 10 Jul 2022 15:26:14 +0200 Subject: [PATCH 059/224] Fix doctrine --- .../EventListener/InsertTagsListener.php | 16 ++++++++-------- .../Condition/Property/AttributeByIdIsOfType.php | 2 +- src/FrontendIntegration/MetaModelHybrid.php | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/CoreBundle/EventListener/InsertTagsListener.php b/src/CoreBundle/EventListener/InsertTagsListener.php index b084e55d4..1abcd7eda 100644 --- a/src/CoreBundle/EventListener/InsertTagsListener.php +++ b/src/CoreBundle/EventListener/InsertTagsListener.php @@ -315,14 +315,14 @@ protected function getCount(string $type, $identifier, int $filterId = null): in // From module, can be a MetaModel list or filter. case 'mod': if (null !== ($result = $this->getMetaModelDataFrom('tl_module', $identifier))) { - return $this->getCountFor($result->metamodel, $result->metamodel_filtering); + return $this->getCountFor($result['metamodel'], $result['metamodel_filtering']); } break; // From content element, can be a MetaModel list or filter. case 'ce': if (null !== ($result = $this->getMetaModelDataFrom('tl_content', $identifier))) { - return $this->getCountFor($result->metamodel, $result->metamodel_filtering); + return $this->getCountFor($result['metamodel'], $result['metamodel_filtering']); } break; @@ -387,14 +387,14 @@ protected function getMetaModelDataFrom($strTable, $intID) ->from($strTable, 't') ->where('t.id=:id') ->setParameter('id', $intID) - ->execute(); + ->executeQuery(); // Check if we have some data. if ($statement->rowCount() < 1) { return null; } - return $statement->fetch(FetchMode::STANDARD_OBJECT); + return $statement->fetchAssociative(); } /** @@ -448,13 +448,13 @@ protected function isPublishedItem($metaModel, $intItemId): bool ->andWhere('t.check_publish=1') ->setParameter('pid', $metaModel->get('id')) ->setMaxResults(1) - ->execute(); + ->executeQuery(); - if ($statement->rowCount() > 0) { - $checkPublish = $statement->fetch(FetchMode::STANDARD_OBJECT); + if ($statement->rowCount()) { + $checkPublish = $statement->fetchAssociative(); $item = $metaModel->findById($intItemId); - if (null === $item || !$item->get($checkPublish->colname)) { + if (null === $item || !$item->get($checkPublish['colname'])) { return false; } } diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php index 286c3097e..9d8a5c13a 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php @@ -121,7 +121,7 @@ public function getTypeOfAttribute($value) $result = $statement->fetchFirstColumn(); if(count($result) > 0){ - self::$attributeTypes[$value] = $result[0]; + self::$attributeTypes[$value] = \current($result); }else { self::$attributeTypes[$value] = null; } diff --git a/src/FrontendIntegration/MetaModelHybrid.php b/src/FrontendIntegration/MetaModelHybrid.php index 44ca23733..11f0c87fb 100644 --- a/src/FrontendIntegration/MetaModelHybrid.php +++ b/src/FrontendIntegration/MetaModelHybrid.php @@ -198,7 +198,7 @@ public function generate() $infoTemplate, $GLOBALS['TL_LANG']['MSC']['mm_be_info_filter'][1], $GLOBALS['TL_LANG']['MSC']['mm_be_info_filter'][0], - $infoFi[0] + \current($infoFi) ); } } @@ -220,7 +220,7 @@ public function generate() $infoTemplate, $GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting'][1], $GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting'][0], - $infoRs[0] + \current($infoRs) ); } } From 993a68d2d60d71e961b83fbccdc6426be0701dff Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 11 Jul 2022 00:08:33 +0200 Subject: [PATCH 060/224] Fix tags widget --- src/Widgets/TagsWidget.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Widgets/TagsWidget.php b/src/Widgets/TagsWidget.php index 7f830ec1c..e7f47e147 100644 --- a/src/Widgets/TagsWidget.php +++ b/src/Widgets/TagsWidget.php @@ -92,8 +92,8 @@ protected function getClassForOption($index) { // If true we need another offset. $intSub = ($this->arrConfiguration['includeBlankOption'] ? 1 : 0); - $intSub += ($this->arrConfiguration['showSelectAll'] - || null === $this->arrConfiguration['showSelectAll'] ? 1 : 0); + $intSub += ((isset($this->arrConfiguration['showSelectAll']) + && null !== $this->arrConfiguration['showSelectAll']) ? 0 : 1); $strClass = $this->strName; if ($index == 0) { @@ -170,7 +170,8 @@ public function generate() } // Show select all checkbox - check null as BC-Layer. - if ($this->arrConfiguration['showSelectAll'] || null === $this->arrConfiguration['showSelectAll']) { + if (isset($this->arrConfiguration['showSelectAll']) + && ($this->arrConfiguration['showSelectAll'] || null === $this->arrConfiguration['showSelectAll'])) { $return .= $this->generateOption( [ 'value' => '--all--', From 1888a03b01d7ad4757687dd56d4ea50edf627e9b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 11 Jul 2022 16:03:37 +0200 Subject: [PATCH 061/224] Fix PHP 8 warnings --- src/Filter/Setting/SimpleLookup.php | 2 +- src/Widgets/MultiTextWidget.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Filter/Setting/SimpleLookup.php b/src/Filter/Setting/SimpleLookup.php index 3c25c130a..cdfa786b8 100644 --- a/src/Filter/Setting/SimpleLookup.php +++ b/src/Filter/Setting/SimpleLookup.php @@ -350,6 +350,6 @@ private function determineFilterValue($filterValues, $valueName) return $this->get('defaultid'); } - return $filterValues[$valueName]; + return $filterValues[$valueName] ?? null; } } diff --git a/src/Widgets/MultiTextWidget.php b/src/Widgets/MultiTextWidget.php index 915b8035e..b61f2de9b 100644 --- a/src/Widgets/MultiTextWidget.php +++ b/src/Widgets/MultiTextWidget.php @@ -119,7 +119,7 @@ public function generate() $i, '', (strlen($this->strClass) ? ' ' . $this->strClass : ''), - StringUtil::specialchars(isset($this->varValue) ? $this->varValue[$i] : ''), + StringUtil::specialchars($this->varValue[$i] ?? ''), $this->getAttributes(), $this->strTagEnding ); From 40d7358b6c505af9f5fb60881e5bcfc50695c656 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 12 Jul 2022 18:09:23 +0200 Subject: [PATCH 062/224] Fix PHP 8 warnings --- src/Dca/Helper.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Dca/Helper.php b/src/Dca/Helper.php index 9f9070005..2a732cc5b 100644 --- a/src/Dca/Helper.php +++ b/src/Dca/Helper.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 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 Cliff Parnitzky * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -41,7 +41,6 @@ class Helper * Decode a language array. * * @param array|string $varValue The value to decode. - * * @param IMetaModel $objMetaModel The MetaModel holding the languages. * * @return string @@ -63,7 +62,7 @@ public static function decodeLangArray($varValue, IMetaModel $objMetaModel) if ($arrLanguages) { foreach ($arrLanguages as $strLangCode) { if (is_array($arrLangValues)) { - $varSubValue = $arrLangValues[$strLangCode]; + $varSubValue = $arrLangValues[$strLangCode] ?? ''; } else { $varSubValue = $arrLangValues; } From 4defb0bf47ee79392eae94568b66681f65f7d3fb Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 12 Jul 2022 18:27:21 +0200 Subject: [PATCH 063/224] Fix code --- src/Dca/Helper.php | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/Dca/Helper.php b/src/Dca/Helper.php index 2a732cc5b..e91285db5 100644 --- a/src/Dca/Helper.php +++ b/src/Dca/Helper.php @@ -31,6 +31,7 @@ use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\Translator\TranslatorInterface; use MetaModels\IMetaModel; +use MetaModels\ITranslatedMetaModel; /** * This class is used as base class from dca handler classes for various callbacks. @@ -40,15 +41,15 @@ class Helper /** * Decode a language array. * - * @param array|string $varValue The value to decode. - * @param IMetaModel $objMetaModel The MetaModel holding the languages. + * @param array|string $varValue The value to decode. + * @param IMetaModel $metaModel The MetaModel holding the languages. * * @return string */ - public static function decodeLangArray($varValue, IMetaModel $objMetaModel) + public static function decodeLangArray($varValue, IMetaModel $metaModel) { $arrLangValues = StringUtil::deserialize($varValue); - if (!$objMetaModel->isTranslated()) { + if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { // If we have an array, return the first value and exit, if not an array, return the value itself. return is_array($arrLangValues) ? serialize($arrLangValues[key($arrLangValues)]) @@ -56,7 +57,7 @@ public static function decodeLangArray($varValue, IMetaModel $objMetaModel) } // Sort like in MetaModel definition. - $arrLanguages = $objMetaModel->getAvailableLanguages(); + $arrLanguages = $metaModel->getAvailableLanguages(); $arrOutput = []; if ($arrLanguages) { @@ -80,16 +81,15 @@ public static function decodeLangArray($varValue, IMetaModel $objMetaModel) /** * Decode a language array. * - * @param array|string $varValue The value to decode. - * - * @param IMetaModel $objMetaModel The MetaModel holding the languages. + * @param array|string $varValue The value to decode. + * @param IMetaModel $metaModel The MetaModel holding the languages. * * @return string */ - public static function encodeLangArray($varValue, IMetaModel $objMetaModel) + public static function encodeLangArray($varValue, IMetaModel $metaModel) { // Not translated, make it a plain string. - if (!$objMetaModel->isTranslated()) { + if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { return $varValue; } $arrLangValues = StringUtil::deserialize($varValue); @@ -130,17 +130,11 @@ private static function buildLanguageArray(IMetaModel $metaModel, TranslatorInte * Create a widget for naming contexts. Use the language and translation information from the MetaModel. * * @param EnvironmentInterface $environment The environment. - * * @param PropertyInterface $property The property. - * * @param IMetaModel $metaModel The MetaModel. - * * @param string $languageLabel The label to use for the language indicator. - * * @param string $valueLabel The label to use for the input field. - * * @param bool $isTextArea If true, the widget will become a textarea, false otherwise. - * * @param array $arrValues The values for the widget, needed to highlight the fallback language. * * @return void @@ -154,7 +148,7 @@ public static function prepareLanguageAwareWidget( $isTextArea, $arrValues ) { - if (!$metaModel->isTranslated()) { + if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { $extra = $property->getExtra(); $extra['tl_class'] .= empty($extra['tl_class']) ? 'w50' : ' w50'; From 5d2186b706b83121c9e36af380c483fcf02aa707 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 12 Jul 2022 19:04:12 +0200 Subject: [PATCH 064/224] Fix PHP 8 warnings --- src/Attribute/TranslatedReference.php | 13 ++++++------- src/DcGeneral/Data/Driver.php | 6 +++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Attribute/TranslatedReference.php b/src/Attribute/TranslatedReference.php index 6019bc02a..6159542c5 100644 --- a/src/Attribute/TranslatedReference.php +++ b/src/Attribute/TranslatedReference.php @@ -161,10 +161,10 @@ protected function getSetValues($arrValue, $intId, $strLangCode) */ protected function getOptionizer() { - return array( - 'key' => 'value', + return [ + 'key' => 'value', 'value' => 'value' - ); + ]; } @@ -173,7 +173,7 @@ protected function getOptionizer() */ public function valueToWidget($varValue) { - return $varValue['value']; + return $varValue['value'] ?? null; } /** @@ -183,12 +183,11 @@ public function valueToWidget($varValue) */ public function widgetToValue($varValue, $itemId) { - return array - ( + return [ 'tstamp' => time(), 'value' => $varValue, 'att_id' => $this->get('id'), - ); + ]; } /** diff --git a/src/DcGeneral/Data/Driver.php b/src/DcGeneral/Data/Driver.php index 0f102b1a2..2cc121bb4 100644 --- a/src/DcGeneral/Data/Driver.php +++ b/src/DcGeneral/Data/Driver.php @@ -749,8 +749,8 @@ public function getLanguages($mixID) if ($metaModel instanceof ITranslatedMetaModel) { $collection = new DefaultLanguageInformationCollection(); foreach ($metaModel->getLanguages() as $langCode) { - [$langCode, $country] = explode('_', $langCode, 2); - $collection->add(new DefaultLanguageInformation($langCode, $country ?: null)); + [$langCode, $locale] = explode('_', $langCode, 2) + [null, null]; + $collection->add(new DefaultLanguageInformation($langCode, $locale)); } if (count($collection) > 0) { return $collection; @@ -759,7 +759,7 @@ public function getLanguages($mixID) return null; } - if (!$metaModel->isTranslated(false)) { + if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { return null; } From e09b8146690d48a1735eb02ceb179865eb9b3ae7 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 12 Jul 2022 20:06:37 +0200 Subject: [PATCH 065/224] Fic PHP 8 warnings --- src/Attribute/TranslatedReference.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Attribute/TranslatedReference.php b/src/Attribute/TranslatedReference.php index 6159542c5..58591e82f 100644 --- a/src/Attribute/TranslatedReference.php +++ b/src/Attribute/TranslatedReference.php @@ -92,7 +92,7 @@ abstract protected function getValueTable(); private function buildWhere(QueryBuilder $queryBuilder, $mixIds, $mixLangCode = '') { $alias = ''; - if (null !== $firstFromAlias = $queryBuilder->getQueryPart('from')[0]['alias']) { + if (null !== $firstFromAlias = $queryBuilder->getQueryPart('from')[0]['alias'] ?? null) { $alias = $firstFromAlias . '.'; } From 54e5748cf0a47e84f4954551f9a5ad594f90a94e Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 12 Jul 2022 21:00:46 +0200 Subject: [PATCH 066/224] Fix PHP 8 warnings --- src/Attribute/TranslatedReference.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Attribute/TranslatedReference.php b/src/Attribute/TranslatedReference.php index 58591e82f..61745e58c 100644 --- a/src/Attribute/TranslatedReference.php +++ b/src/Attribute/TranslatedReference.php @@ -384,12 +384,12 @@ public function setTranslatedDataFor($arrValues, $strLangCode) $queryBuilder->delete($this->getValueTable()); } - $queryBuilder->execute(); + $queryBuilder->executeQuery(); } // Insert the new values. foreach ($arrNewIds as $intId) { - if ($arrValues[$intId]['value'] == '') { + if (!isset($arrValues[$intId]['value']) || $arrValues[$intId]['value'] == '') { continue; } @@ -450,7 +450,7 @@ public function unsetValueFor($arrIds, $strLangCode) $queryBuilder = $this->connection->createQueryBuilder()->delete($this->getValueTable()); $this->buildWhere($queryBuilder, $arrIds, $strLangCode); - $queryBuilder->execute(); + $queryBuilder->executeQuery(); } /** From 86d9df2e6797c3b17f31722242d6ed827eedc682 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 16 Jul 2022 19:16:07 +0200 Subject: [PATCH 067/224] Fix PHP 8 warning --- src/DcGeneral/Data/Driver.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/DcGeneral/Data/Driver.php b/src/DcGeneral/Data/Driver.php index 2cc121bb4..d2b37f295 100644 --- a/src/DcGeneral/Data/Driver.php +++ b/src/DcGeneral/Data/Driver.php @@ -777,10 +777,11 @@ public function getFallbackLanguage($mixID) { $metaModel = $this->getMetaModel(); if ($metaModel instanceof ITranslatedMetaModel) { - [$langCode, $country] = explode('_', $metaModel->getMainLanguage(), 2); - return new DefaultLanguageInformation($langCode, $country ?: null); + [$langCode, $locale] = explode('_', $metaModel->getMainLanguage(), 2) + [null, null]; + return new DefaultLanguageInformation($langCode, $locale); } - if (!$metaModel->isTranslated(false)) { + + if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { return null; } From d809f4837aa3c510d145d1903c600e22c6038a30 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 19 Jul 2022 13:27:48 +0200 Subject: [PATCH 068/224] Fix code --- src/Attribute/Base.php | 4 ++-- src/Dca/Helper.php | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 61032c098..85788a5a2 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -301,7 +301,7 @@ public function set($strKey, $varValue) */ public function handleMetaChange($strMetaName, $varNewValue) { - // By default we accept any change of meta information. + // By default, we accept any change of meta information. $this->set($strMetaName, $varNewValue); return $this; @@ -566,7 +566,7 @@ public function parseValue($arrRowData, $strOutputFormat = 'text', $objSettings // Text rendering is mandatory, try with the current setting, // upon exception, try again with the default settings, as the template name might have changed. - // if this fails again, we are definately out of luck and bail the exception. + // if this fails again, we are definitely out of luck and bail the exception. try { $arrResult['text'] = $objTemplate->parse('text', true); } catch (\Exception $e) { diff --git a/src/Dca/Helper.php b/src/Dca/Helper.php index e91285db5..6473610dc 100644 --- a/src/Dca/Helper.php +++ b/src/Dca/Helper.php @@ -51,9 +51,9 @@ public static function decodeLangArray($varValue, IMetaModel $metaModel) $arrLangValues = StringUtil::deserialize($varValue); if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { // If we have an array, return the first value and exit, if not an array, return the value itself. - return is_array($arrLangValues) - ? serialize($arrLangValues[key($arrLangValues)]) - : serialize($arrLangValues); + return \is_array($arrLangValues) + ? \serialize($arrLangValues[\key($arrLangValues)]) + : \serialize($arrLangValues); } // Sort like in MetaModel definition. @@ -62,20 +62,20 @@ public static function decodeLangArray($varValue, IMetaModel $metaModel) if ($arrLanguages) { foreach ($arrLanguages as $strLangCode) { - if (is_array($arrLangValues)) { + if (\is_array($arrLangValues)) { $varSubValue = $arrLangValues[$strLangCode] ?? ''; } else { $varSubValue = $arrLangValues; } - if (is_array($varSubValue)) { - $arrOutput[] = array_merge($varSubValue, array('langcode' => $strLangCode)); + if (\is_array($varSubValue)) { + $arrOutput[] = \array_merge($varSubValue, array('langcode' => $strLangCode)); } else { $arrOutput[] = array('langcode' => $strLangCode, 'value' => $varSubValue); } } } - return serialize($arrOutput); + return \serialize($arrOutput); } /** From 1e6f736995db19d1c5afa13e47e0d60be6a0371d Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 5 Aug 2022 09:11:36 +0200 Subject: [PATCH 069/224] Fix PHP 8 warnings --- src/CoreBundle/Contao/InsertTag/ReplaceParam.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CoreBundle/Contao/InsertTag/ReplaceParam.php b/src/CoreBundle/Contao/InsertTag/ReplaceParam.php index 4211a7987..f7a8db9af 100644 --- a/src/CoreBundle/Contao/InsertTag/ReplaceParam.php +++ b/src/CoreBundle/Contao/InsertTag/ReplaceParam.php @@ -117,7 +117,7 @@ private function replaceInputParameter(array $chunks, ?string $content, string $ } return \str_replace( '{{' . $tag . '}}', - \is_array($result) ? \serialize($result) : $result, + \is_array($result) ? \serialize($result) : ($result ?? ''), $content ); } @@ -125,7 +125,7 @@ private function replaceInputParameter(array $chunks, ?string $content, string $ $result = ($this->input->{$arguments[0]}($arguments[1]) ?: $arguments[2]); return \str_replace( '{{' . $tag . '}}', - \is_array($result) ? \serialize($result) : $result, + \is_array($result) ? \serialize($result) : ($result ?? ''), $content ); } @@ -152,7 +152,7 @@ private function replaceSessionParameter(array $chunks, ?string $content, string $result = $this->session->get($arguments[1]); return \str_replace( '{{' . $tag . '}}', - \is_array($result) ? \serialize($result) : $result, + \is_array($result) ? \serialize($result) : ($result ?? ''), $content ); } @@ -160,7 +160,7 @@ private function replaceSessionParameter(array $chunks, ?string $content, string $result = ($this->session->get($arguments[1]) ?: $arguments[2]); return \str_replace( '{{' . $tag . '}}', - \is_array($result) ? \serialize($result) : $result, + \is_array($result) ? \serialize($result) : ($result ?? ''), $content ); } From 67cdeb1fbed220669fbeae535bb4aa0e3034a2b4 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 7 Aug 2022 15:00:40 +0200 Subject: [PATCH 070/224] Update require MCW --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 84065d7a2..e4642e149 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ "discordier/justtextwidgets": "^1.2", "doctrine/cache": "^2.1", "doctrine/dbal": "^3.3.2", - "menatwork/contao-multicolumnwizard-bundle": "^3.4", + "menatwork/contao-multicolumnwizard-bundle": "^3.5.7", "symfony/asset": "^5.4", "symfony/cache": "^5.4", "symfony/config": "^5.4", From a8ae1f2b12825b4c66de0d94103e9a2e64e867d8 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 11 Aug 2022 23:01:49 +0200 Subject: [PATCH 071/224] Fic doctrine --- .../Hooks/AbstractContentElementAndModuleCallback.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php index ce84a354e..46e05c820 100644 --- a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php +++ b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author Marc Reimann - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -341,7 +341,7 @@ protected function buildFilterParamsFor(DC_Table $dataContainer, $elementName) ->executeQuery() ->fetchFirstColumn(); - if (!$filterId) { + if (!reset($filterId)) { unset($GLOBALS['TL_DCA'][static::$tableName]['fields']['metamodel_filterparams']); return; } From f587b2dd5baf20d6ba9a38394a5c15bd3c63f8b2 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 12 Aug 2022 13:01:49 +0200 Subject: [PATCH 072/224] Fix code --- src/Filter/Setting/FilterSettingFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Filter/Setting/FilterSettingFactory.php b/src/Filter/Setting/FilterSettingFactory.php index dee98d6c7..bb9007c17 100644 --- a/src/Filter/Setting/FilterSettingFactory.php +++ b/src/Filter/Setting/FilterSettingFactory.php @@ -262,7 +262,7 @@ public function createCollection($settingId) ->setMaxResults(1) ->setParameter('id', $settingId) ->executeQuery(); - if (!$query->rowCount()) { + if (!$query) { throw new \RuntimeException('Could not retrieve filter setting'); } From 49318ccf71c4dadab814a167a6064db6f19f575f Mon Sep 17 00:00:00 2001 From: zonky Date: Wed, 17 Aug 2022 19:10:37 +0200 Subject: [PATCH 073/224] Fix deprecated webutils to symfony filesystem --- src/CoreBundle/Assets/IconBuilder.php | 7 +++---- src/CoreBundle/DependencyInjection/Configuration.php | 2 +- .../DcGeneral/Table/RenderSettings/AddAssetListener.php | 7 ++++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/CoreBundle/Assets/IconBuilder.php b/src/CoreBundle/Assets/IconBuilder.php index 1b9dca040..0d36955c1 100644 --- a/src/CoreBundle/Assets/IconBuilder.php +++ b/src/CoreBundle/Assets/IconBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author David Molineus - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,8 +25,7 @@ use Contao\CoreBundle\Framework\Adapter; use Contao\CoreBundle\Image\ImageFactoryInterface; use Contao\Validator; -use Symfony\Component\Filesystem\Filesystem; -use Webmozart\PathUtil\Path; +use Symfony\Component\Filesystem\Path; /** * This class takes care of building icons for the backend. diff --git a/src/CoreBundle/DependencyInjection/Configuration.php b/src/CoreBundle/DependencyInjection/Configuration.php index 26a62eb21..2c5acaeab 100644 --- a/src/CoreBundle/DependencyInjection/Configuration.php +++ b/src/CoreBundle/DependencyInjection/Configuration.php @@ -23,7 +23,7 @@ use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; -use Webmozart\PathUtil\Path; +use Symfony\Component\Filesystem\Path; /** * Adds the Contao configuration structure. diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AddAssetListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AddAssetListener.php index afe973631..427605082 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AddAssetListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AddAssetListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Andreas Fischer - * @copyright 2012-2021 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,8 +25,8 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use MenAtWork\MultiColumnWizardBundle\Event\GetOptionsEvent; +use Symfony\Component\Filesystem\Path; use Symfony\Component\Finder\Finder; -use Webmozart\PathUtil\Path; /** * This handles the rendering of models to labels. From c2fc936e522542432a0b09bf6930dae56da29ee3 Mon Sep 17 00:00:00 2001 From: zonky Date: Wed, 17 Aug 2022 19:21:22 +0200 Subject: [PATCH 074/224] Fix code --- src/CoreBundle/Assets/IconBuilder.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CoreBundle/Assets/IconBuilder.php b/src/CoreBundle/Assets/IconBuilder.php index 0d36955c1..552e14ea0 100644 --- a/src/CoreBundle/Assets/IconBuilder.php +++ b/src/CoreBundle/Assets/IconBuilder.php @@ -25,6 +25,7 @@ use Contao\CoreBundle\Framework\Adapter; use Contao\CoreBundle\Image\ImageFactoryInterface; use Contao\Validator; +use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Path; /** From 7a8cfbe61b45b50c97f4454eb253981d2c38330b Mon Sep 17 00:00:00 2001 From: zonky Date: Fri, 19 Aug 2022 11:45:36 +0200 Subject: [PATCH 075/224] Fix SubDCAWidget --- src/Widgets/SubDcaWidget.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Widgets/SubDcaWidget.php b/src/Widgets/SubDcaWidget.php index 2b68e02b6..189116a15 100644 --- a/src/Widgets/SubDcaWidget.php +++ b/src/Widgets/SubDcaWidget.php @@ -299,7 +299,7 @@ protected function initializeWidget(&$arrField, $strRow, $strKey, $varValue) $arrField['name'] = $this->strName . '[' . $strRow . '][' . $strKey . ']'; $arrField['id'] = $this->strId . '_' . $strRow . '_' . $strKey; - $arrField['value'] = ($varValue !== '') ? $varValue : $arrField['default']; + $arrField['value'] = ($varValue !== '') ? $varValue : ($arrField['default'] ?? ''); $arrField['eval']['tableless'] = true; $event = new GetAttributesFromDcaEvent( @@ -418,7 +418,7 @@ protected function handleSaveCallback($field, $widget, $value) */ protected function validateWidget(&$arrField, $strRow, $strKey, &$varInput) { - $varValue = $varInput[$strRow][$strKey]; + $varValue = $varInput[$strRow][$strKey] ?? ''; $objWidget = $this->initializeWidget($arrField, $strRow, $strKey, $varValue); if (!is_object($objWidget)) { return false; @@ -434,7 +434,7 @@ protected function validateWidget(&$arrField, $strRow, $strKey, &$varInput) $varValue = $objWidget->value; // Convert date formats into timestamps (check the eval setting first -> #3063). - $rgxp = $arrField['eval']['rgxp']; + $rgxp = $arrField['eval']['rgxp'] ?? null; if (($rgxp == 'date' || $rgxp == 'time' || $rgxp == 'datim') && $varValue != '') { $objDate = new Date($varValue, $GLOBALS['TL_CONFIG'][$rgxp . 'Format']); $varValue = $objDate->tstamp; From a1d6e990e7525f6c8afcf119966163d9b5dc1d9a Mon Sep 17 00:00:00 2001 From: e-spin Date: Thu, 25 Aug 2022 08:31:15 +0200 Subject: [PATCH 076/224] Fix PHP 8 warning --- src/TranslatedMetaModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TranslatedMetaModel.php b/src/TranslatedMetaModel.php index b201f67b6..690834c1d 100644 --- a/src/TranslatedMetaModel.php +++ b/src/TranslatedMetaModel.php @@ -74,7 +74,7 @@ public function __construct($arrData, EventDispatcherInterface $dispatcher, Conn // Mark fallback language as active language. $this->activeLanguage = $this->mainLanguage; - $this->hasTerritorySupport = (bool) $this->arrData['localeterritorysupport']; + $this->hasTerritorySupport = (bool) ($this->arrData['localeterritorysupport'] ?? false); } /** From 7132a7ed07ff1ab628962047b3857870bd0df377 Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 14 Sep 2022 15:15:16 +0200 Subject: [PATCH 077/224] Fix composer to PHP 8.1 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e4642e149..7f6e47054 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "source": "https://github.com/MetaModels/core" }, "require": { - "php": "^7.4 || ^8.0", + "php": "^8.1", "contao-community-alliance/dc-general": "^2.3@dev", "contao-community-alliance/events-contao-bindings": "^4.10@dev", "contao-community-alliance/meta-palettes": "~2.0", From 4b6ef0e2a172a9754f33df7d90c348b4a8c56b64 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 21 Oct 2022 20:43:08 +0200 Subject: [PATCH 078/224] Fic PHP 8 warnings --- src/Attribute/Base.php | 6 ++---- src/Item.php | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 85788a5a2..9fea776b8 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -230,9 +230,7 @@ public function hookAdditionalFormatters($arrBaseFormatted, $arrRowData, $strOut * When rendered via a template, this populates the template with values. * * @param Template $objTemplate The Template instance to populate. - * * @param array $arrRowData The row data for the current item. - * * @param ISimpleRenderSetting $objSettings The render settings to use for this attribute. * * @return void @@ -244,7 +242,7 @@ protected function prepareTemplate(Template $objTemplate, $arrRowData, $objSetti 'attribute' => $this, 'settings' => $objSettings, 'row' => $arrRowData, - 'raw' => $arrRowData[$this->getColName()], + 'raw' => ($arrRowData[$this->getColName()] ?? null), 'additional_class' => $objSettings->get('additional_class') ? ' ' . $objSettings->get('additional_class') : '' @@ -549,7 +547,7 @@ public function getDefaultRenderSettings() */ public function parseValue($arrRowData, $strOutputFormat = 'text', $objSettings = null) { - $arrResult = ['raw' => $arrRowData[$this->getColName()]]; + $arrResult = ['raw' => ($arrRowData[$this->getColName()] ?? null)]; /** @var ISimpleRenderSetting $objSettings */ if ($objSettings && $objSettings->get('template')) { diff --git a/src/Item.php b/src/Item.php index 998f2b25b..ed1af8372 100644 --- a/src/Item.php +++ b/src/Item.php @@ -156,6 +156,7 @@ public function internalParseAttribute($objAttribute, $strOutputFormat, $objSett } else { $objAttributeSettings = null; } + foreach ($objAttribute->parseValue( $this->arrData, $strOutputFormat, From 8e22a9e8ce9a2a9bbfec833a00a5ece1b9492555 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 21 Oct 2022 22:19:04 +0200 Subject: [PATCH 079/224] Update composer.json --- composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 7f6e47054..522590ff3 100644 --- a/composer.json +++ b/composer.json @@ -32,12 +32,12 @@ "require": { "php": "^8.1", "contao-community-alliance/dc-general": "^2.3@dev", - "contao-community-alliance/events-contao-bindings": "^4.10@dev", - "contao-community-alliance/meta-palettes": "~2.0", - "contao-community-alliance/translator": "^2.2", - "contao-community-alliance/url-builder": "~1.3", + "contao-community-alliance/events-contao-bindings": "^4.13", + "contao-community-alliance/meta-palettes": "^2.0.10", + "contao-community-alliance/translator": "^2.3", + "contao-community-alliance/url-builder": "^1.3.3", "contao/core-bundle": "^4.13.5, <5.0", - "discordier/justtextwidgets": "^1.2", + "discordier/justtextwidgets": "^1.3", "doctrine/cache": "^2.1", "doctrine/dbal": "^3.3.2", "menatwork/contao-multicolumnwizard-bundle": "^3.5.7", From 097fbcc15397daf1ed45e166ec1b70be9fd66d83 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 21 Oct 2022 22:35:45 +0200 Subject: [PATCH 080/224] Fix symfony --- .../Controller/Backend/InputScreenAddAllController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php b/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php index 57185a847..dd7250116 100644 --- a/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php +++ b/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php @@ -30,7 +30,7 @@ use MetaModels\IMetaModel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; use Twig\Environment as TwigEnvironment; /** From 9a79404ccddbbddf0b75104b832d647d891069d1 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 24 Oct 2022 18:17:55 +0200 Subject: [PATCH 081/224] Add keys with default value to fix PHP 8 warnings --- src/Helper/ToolboxFile.php | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Helper/ToolboxFile.php b/src/Helper/ToolboxFile.php index 22e800780..14ce77f89 100644 --- a/src/Helper/ToolboxFile.php +++ b/src/Helper/ToolboxFile.php @@ -1025,17 +1025,20 @@ private function processFile($fileName) } $information = [ - 'file' => $fileName, - 'mtime' => $file->mtime, - 'alt' => $altText, - 'caption' => (!empty($meta['caption']) ? $meta['caption'] : ''), - 'title' => $title, - 'metafile' => $meta, - 'icon' => 'assets/contao/images/' . $file->icon, - 'extension' => $file->extension, - 'size' => $file->filesize, - 'sizetext' => sprintf('(%s)', Controller::getReadableSize($file->filesize, 2)), - 'url' => StringUtil::specialchars($this->getDownloadLink($fileName)) + 'file' => $fileName, + 'mtime' => $file->mtime, + 'alt' => $altText, + 'caption' => (!empty($meta['caption']) ? $meta['caption'] : ''), + 'title' => $title, + 'metafile' => $meta, + 'icon' => 'assets/contao/images/' . $file->icon, + 'extension' => $file->extension, + 'size' => $file->filesize, + 'sizetext' => sprintf('(%s)', Controller::getReadableSize($file->filesize, 2)), + 'url' => StringUtil::specialchars($this->getDownloadLink($fileName)), + 'isGdImage' => false, + 'isSvgImage' => false, + 'isPicture' => false, ]; // Prepare GD images. From c4f09d639ac856cb1d89d9b05953066344c4b160 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 26 Oct 2022 09:10:21 +0200 Subject: [PATCH 082/224] Fix PHP 8 warning --- src/Attribute/Base.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 9fea776b8..94597f93c 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -107,16 +107,16 @@ protected function parameterMask($parameters) } /** - * Retrieve the human readable name (or title) from the attribute. + * Retrieve the human-readable name (or title) from the attribute. * * If the MetaModel is translated, the currently active language is used, * with properly falling back to the defined fallback language. * - * @return string the human readable name + * @return string the human-readable name */ public function getName() { - if (is_array($this->arrData['name'])) { + if (isset($this->arrData['name']) && is_array($this->arrData['name'])) { $metaModel = $this->getMetaModel(); return $this->getLangValue( $this->get('name'), @@ -124,7 +124,8 @@ public function getName() ? $metaModel->getLanguage() : $metaModel->getActiveLanguage() ) ?: $this->getColName(); } - return $this->arrData['name'] ?: $this->getColName(); + + return $this->arrData['name'] ?? $this->getColName(); } /** From a74532aea18fc5b401ec1b3baae45096e7c0c56e Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Wed, 26 Oct 2022 13:36:06 +0200 Subject: [PATCH 083/224] Fix array access --- src/Attribute/TranslatedReference.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Attribute/TranslatedReference.php b/src/Attribute/TranslatedReference.php index 61745e58c..eae894836 100644 --- a/src/Attribute/TranslatedReference.php +++ b/src/Attribute/TranslatedReference.php @@ -352,7 +352,7 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) $arrReturn = []; while ($objValue = $statement->fetchAssociative()) { - $arrReturn[$objValue->{$arrOptionizer['key']}] = $objValue->{$arrOptionizer['value']}; + $arrReturn[$objValue[$arrOptionizer['key']]] = $objValue[$arrOptionizer['value']]; } return $arrReturn; } From 0906a101ed065850af485993999d5370bb0d0650 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 1 Nov 2022 15:20:53 +0100 Subject: [PATCH 084/224] Fix total count --- src/MetaModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MetaModel.php b/src/MetaModel.php index 5fe2e74b9..92748c636 100644 --- a/src/MetaModel.php +++ b/src/MetaModel.php @@ -981,7 +981,7 @@ public function getCount($objFilter) ->where($builder->expr()->in('t.id', ':values')) ->setParameter('values', $arrFilteredIds, Connection::PARAM_STR_ARRAY) ->executeQuery() - ->fetchFirstColumn(); + ->fetchOne(); } /** From b2858df6d1172cdb5c35346f46b1571788ed93d3 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 2 Nov 2022 12:54:33 +0100 Subject: [PATCH 085/224] Fix PHP 8 warning --- .../DcGeneral/Table/Attribute/AttributeRendererListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php index 85bf19b24..55e3b4e9e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php @@ -73,7 +73,7 @@ public function modelToLabel(ModelToLabelEvent $event) $name = $attribute->getName(); $arrDescription = StringUtil::deserialize($attribute->get('description')); if (is_array($arrDescription)) { - $description = $arrDescription[$attribute->getMetaModel()->getActiveLanguage()]; + $description = $arrDescription[$attribute->getMetaModel()->getActiveLanguage()] ?? null; if (!$description) { $description = $arrDescription[$attribute->getMetaModel()->getFallbackLanguage()]; } From 9979ace476d2d2bc06f19243e8da4b5b94b237fe Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 29 Nov 2022 20:36:54 +0100 Subject: [PATCH 086/224] Fix warning toolbox --- src/Helper/ToolboxFile.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Helper/ToolboxFile.php b/src/Helper/ToolboxFile.php index 58c7df158..91df967f0 100644 --- a/src/Helper/ToolboxFile.php +++ b/src/Helper/ToolboxFile.php @@ -517,7 +517,7 @@ protected function collectFiles() } /** - * Generate an URL for downloading the given file. + * Generate a URL for downloading the given file. * * @param string $strFile The file that shall be downloaded. * @@ -533,7 +533,8 @@ protected function getDownloadLink($strFile) ->setQueryParameter('file', urlencode($strFile)) ->getUrl(); } - if (isset($_SESSION) && !is_array($_SESSION['metaModels_downloads'])) { + + if (isset($_SESSION['metaModels_downloads']) && !is_array($_SESSION['metaModels_downloads'])) { $_SESSION['metaModels_downloads'] = []; } From 9fe7e209dba8c5b1f5a9b787e3fe9d3f9a1b30d4 Mon Sep 17 00:00:00 2001 From: Oliver Willmes Date: Wed, 30 Nov 2022 22:02:31 +0000 Subject: [PATCH 087/224] Update src/CoreBundle/Resources/config/services.yml --- src/CoreBundle/Resources/config/services.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index b5aad8431..c772ac665 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -170,7 +170,7 @@ services: MetaModels\MetaModelsServiceContainer: deprecated: 'The service "%service_id%" is deprecated and to be removed in MetaModels 3 - inject needed services directly.' - configurator: 'MetaModels\CoreBundle\LegacyCompat\ServiceContainerInitializer:configure' + configurator: ['@MetaModels\CoreBundle\LegacyCompat\ServiceContainerInitializer', 'configure'] public: true MetaModels\CoreBundle\LegacyCompat\ServiceContainerInitializer: From 11bfe5b9d471ed379ac054742fd0eae294e1ed46 Mon Sep 17 00:00:00 2001 From: "A. Fischer" Date: Mon, 5 Dec 2022 10:09:43 +0100 Subject: [PATCH 088/224] Removed string replacement (_ to -) because in Contao 4.13, the array already has the correct locale string as array key. --- src/Filter/FilterUrlBuilder.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Filter/FilterUrlBuilder.php b/src/Filter/FilterUrlBuilder.php index bf28b8b00..9cb89b59c 100644 --- a/src/Filter/FilterUrlBuilder.php +++ b/src/Filter/FilterUrlBuilder.php @@ -365,10 +365,6 @@ private function getFolderUrlFragments(string $alias, string $host, string $loca $pages = []; - $locale = ($locale) - ? \str_replace('_', '-', $locale) - : $locale; - if (!$this->isLocalePrepended) { // Use the first result (see #4872) $pages = current($languages); From fb40d53081f547d2742ceb348cf2adcf02bef63d Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Mon, 12 Sep 2022 19:21:23 +0200 Subject: [PATCH 089/224] Fix deleteConfirm with own language key --- src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php index 131a5cbfe..c058f160d 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php @@ -84,5 +84,4 @@ $GLOBALS['TL_LANG']['tl_metamodel']['itemFormatCount']['0'] = '%s items'; $GLOBALS['TL_LANG']['tl_metamodel']['itemFormatCount']['1'] = '%s item'; $GLOBALS['TL_LANG']['tl_metamodel']['itemFormatCount']['2:'] = '%s items'; - -$GLOBALS['TL_LANG']['tl_metamodel']['deleteConfirm'] = 'Do you really want to delete MetaModel ID %s?'; +$GLOBALS['TL_LANG']['tl_metamodel']['deleteConfirm'] = 'Do you really want to delete MetaModel ID %s?'; From e6e54b8da83006cff5c9f198deefe38c9291eddc Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Mon, 24 Oct 2022 15:56:22 +0200 Subject: [PATCH 090/224] Initial draft of schema generator handling --- src/Attribute/Base.php | 49 ++++ src/Attribute/BaseSimple.php | 118 +++++++++ src/Attribute/IAttribute.php | 6 + src/Attribute/ISchemaManagedAttribute.php | 34 +++ src/Attribute/ISimple.php | 8 + .../CollectDoctrineSchemaGeneratorsPass.php | 48 ++++ .../CollectSchemaGeneratorsPass.php | 48 ++++ .../CollectSchemaManagersPass.php | 48 ++++ src/CoreBundle/MetaModelsCoreBundle.php | 6 + src/CoreBundle/Resources/config/services.yml | 40 +++ src/Information/AttributeInformation.php | 74 ++++++ .../AttributeInformationInterface.php | 69 ++++++ src/Information/ConfigurationTrait.php | 89 +++++++ src/Information/MetaModelCollection.php | 103 ++++++++ .../MetaModelCollectionInterface.php | 69 ++++++ src/Information/MetaModelInformation.php | 134 ++++++++++ .../MetaModelInformationInterface.php | 105 ++++++++ ...ontaoDatabaseBackedInformationProvider.php | 111 +++++++++ .../InformationProviderInterface.php | 48 ++++ .../MetaModelInformationCollector.php | 86 +++++++ .../AbstractAttributeTypeSchemaGenerator.php | 68 +++++ .../Doctrine/DoctrineSchemaGenerator.php | 65 +++++ .../DoctrineSchemaGeneratorHelperTrait.php | 77 ++++++ .../DoctrineSchemaGeneratorInterface.php | 40 +++ .../Doctrine/DoctrineSchemaInformation.php | 142 +++++++++++ src/Schema/Doctrine/DoctrineSchemaManager.php | 110 ++++++++ .../Doctrine/DoctrineSchemaManipulator.php | 67 +++++ .../Doctrine/SchemaProcessorInterface.php | 35 +++ .../Doctrine/SystemColumnSchemaGenerator.php | 92 +++++++ src/Schema/SchemaGenerator.php | 57 +++++ src/Schema/SchemaGeneratorInterface.php | 40 +++ src/Schema/SchemaInformation.php | 93 +++++++ src/Schema/SchemaInformationInterface.php | 35 +++ src/Schema/SchemaManager.php | 78 ++++++ src/Schema/SchemaManagerInterface.php | 55 ++++ .../CollectSchemaGeneratorsPassTest.php | 81 ++++++ .../CollectSchemaManagersPassTest.php | 81 ++++++ .../Information/AttributeInformationTest.php | 47 ++++ tests/Information/ConfigurationTraitTest.php | 68 +++++ tests/Information/MetaModelCollectionTest.php | 104 ++++++++ .../Information/MetaModelInformationTest.php | 134 ++++++++++ .../MetaModelInformationCollectorTest.php | 105 ++++++++ .../Doctrine/DoctrineSchemaGeneratorTest.php | 89 +++++++ .../DoctrineSchemaInformationTest.php | 115 +++++++++ .../Doctrine/DoctrineSchemaManagerTest.php | 234 ++++++++++++++++++ tests/Schema/SchemaGeneratorTest.php | 65 +++++ tests/Schema/SchemaInformationTest.php | 128 ++++++++++ tests/Schema/SchemaManagerTest.php | 101 ++++++++ 48 files changed, 3699 insertions(+) create mode 100644 src/Attribute/ISchemaManagedAttribute.php create mode 100644 src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php create mode 100644 src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php create mode 100644 src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php create mode 100644 src/Information/AttributeInformation.php create mode 100644 src/Information/AttributeInformationInterface.php create mode 100644 src/Information/ConfigurationTrait.php create mode 100644 src/Information/MetaModelCollection.php create mode 100644 src/Information/MetaModelCollectionInterface.php create mode 100644 src/Information/MetaModelInformation.php create mode 100644 src/Information/MetaModelInformationInterface.php create mode 100644 src/InformationProvider/ContaoDatabaseBackedInformationProvider.php create mode 100644 src/InformationProvider/InformationProviderInterface.php create mode 100644 src/InformationProvider/MetaModelInformationCollector.php create mode 100644 src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php create mode 100644 src/Schema/Doctrine/DoctrineSchemaGenerator.php create mode 100644 src/Schema/Doctrine/DoctrineSchemaGeneratorHelperTrait.php create mode 100644 src/Schema/Doctrine/DoctrineSchemaGeneratorInterface.php create mode 100644 src/Schema/Doctrine/DoctrineSchemaInformation.php create mode 100644 src/Schema/Doctrine/DoctrineSchemaManager.php create mode 100644 src/Schema/Doctrine/DoctrineSchemaManipulator.php create mode 100644 src/Schema/Doctrine/SchemaProcessorInterface.php create mode 100644 src/Schema/Doctrine/SystemColumnSchemaGenerator.php create mode 100644 src/Schema/SchemaGenerator.php create mode 100644 src/Schema/SchemaGeneratorInterface.php create mode 100644 src/Schema/SchemaInformation.php create mode 100644 src/Schema/SchemaInformationInterface.php create mode 100644 src/Schema/SchemaManager.php create mode 100644 src/Schema/SchemaManagerInterface.php create mode 100644 tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php create mode 100644 tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPassTest.php create mode 100644 tests/Information/AttributeInformationTest.php create mode 100644 tests/Information/ConfigurationTraitTest.php create mode 100644 tests/Information/MetaModelCollectionTest.php create mode 100644 tests/Information/MetaModelInformationTest.php create mode 100644 tests/InformationProvider/MetaModelInformationCollectorTest.php create mode 100644 tests/Schema/Doctrine/DoctrineSchemaGeneratorTest.php create mode 100644 tests/Schema/Doctrine/DoctrineSchemaInformationTest.php create mode 100644 tests/Schema/Doctrine/DoctrineSchemaManagerTest.php create mode 100644 tests/Schema/SchemaGeneratorTest.php create mode 100644 tests/Schema/SchemaInformationTest.php create mode 100644 tests/Schema/SchemaManagerTest.php diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 94597f93c..307b786f2 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -303,6 +303,23 @@ public function handleMetaChange($strMetaName, $varNewValue) // By default, we accept any change of meta information. $this->set($strMetaName, $varNewValue); + if ($this instanceof ISchemaManagedAttribute) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + return $this; + } + + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + return $this; } @@ -311,6 +328,22 @@ public function handleMetaChange($strMetaName, $varNewValue) */ public function destroyAUX() { + if ($this instanceof ISchemaManagedAttribute) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + return; + } + + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd // No-op. } @@ -319,6 +352,22 @@ public function destroyAUX() */ public function initializeAUX() { + if ($this instanceof ISchemaManagedAttribute) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + return; + } + + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd // No-op. } diff --git a/src/Attribute/BaseSimple.php b/src/Attribute/BaseSimple.php index a70d0037f..dd2ca1486 100644 --- a/src/Attribute/BaseSimple.php +++ b/src/Attribute/BaseSimple.php @@ -114,9 +114,21 @@ public function __construct( * @param mixed $varNewValue The new value for this meta information. * * @return \MetaModels\Attribute\IAttribute The instance of this attribute, to support chaining. + * + * @deprecated Implement schema generators instead. */ public function handleMetaChange($strMetaName, $varNewValue) { + if ($this instanceof ISchemaManagedAttribute) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + return $this; + } + // By default we accept any change of meta information. if ($strMetaName == 'colname') { if ($this->get($strMetaName) != $varNewValue) { @@ -240,9 +252,20 @@ public function searchFor($strPattern) * Deriving classes SHOULD override this function. * * @return string 'blob NULL' + * + * @deprecated Implement schema generators instead. */ public function getSQLDataType() { + if ($this instanceof ISchemaManagedAttribute) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + } + return 'blob NULL'; } @@ -250,9 +273,28 @@ public function getSQLDataType() * Create auxiliary data like a column in the MetaModel table or references in another table etc. * * @return void + * + * @deprecated Implement schema generators instead. */ public function destroyAUX() { + if ($this instanceof ISchemaManagedAttribute) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + return $this; + } + + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + parent::destroyAUX(); $this->deleteColumn(); } @@ -261,9 +303,28 @@ public function destroyAUX() * Delete all auxiliary data like a column in the MetaModel table or references in another table etc. * * @return void + * + * @deprecated Implement schema generators instead. */ public function initializeAUX() { + if ($this instanceof ISchemaManagedAttribute) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + return; + } + + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + parent::initializeAUX(); $this->createColumn(); } @@ -274,9 +335,28 @@ public function initializeAUX() * You have to override this function in field types, when you want to have multi column structure etc. * * @return void + * + * @deprecated Implement schema generators instead. */ public function createColumn() { + if ($this instanceof ISchemaManagedAttribute) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + return; + } + + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + if ($this->getColName()) { $this->tableManipulator->createColumn( $this->getMetaModel()->getTableName(), @@ -290,9 +370,28 @@ public function createColumn() * Removes the underlying database structure for this field. * * @return void + * + * @deprecated Implement schema generators instead. */ public function deleteColumn() { + if ($this instanceof ISchemaManagedAttribute) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + return; + } + + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + $schemaManager = $this->connection->getSchemaManager(); $columns = $schemaManager->listTableColumns($this->getMetaModel()->getTableName()); @@ -308,9 +407,28 @@ public function deleteColumn() * @param string $strNewColumnName The new column name. * * @return void + * + * @deprecated Implement schema generators instead. */ public function renameColumn($strNewColumnName) { + if ($this instanceof ISchemaManagedAttribute) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + return; + } + + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + $this->tableManipulator->checkColumnName($strNewColumnName); $schemaManager = $this->connection->getSchemaManager(); diff --git a/src/Attribute/IAttribute.php b/src/Attribute/IAttribute.php index 0ef30766d..6776f40bb 100644 --- a/src/Attribute/IAttribute.php +++ b/src/Attribute/IAttribute.php @@ -98,6 +98,8 @@ public function set($strKey, $varValue); * @param mixed $varNewValue The new value for this meta information. * * @return IAttribute The instance of this attribute, to support chaining. + * + * @deprecated Implement schema manipulators instead. */ public function handleMetaChange($strMetaName, $varNewValue); @@ -105,6 +107,8 @@ public function handleMetaChange($strMetaName, $varNewValue); * Delete all auxiliary data like a column in the MetaModel table or references in another table etc. * * @return void + * + * @deprecated Implement schema generators instead. */ public function destroyAUX(); @@ -112,6 +116,8 @@ public function destroyAUX(); * Create auxiliary data like a column in the MetaModel table or references in another table etc. * * @return void + * + * @deprecated Implement schema generators instead. */ public function initializeAUX(); diff --git a/src/Attribute/ISchemaManagedAttribute.php b/src/Attribute/ISchemaManagedAttribute.php new file mode 100644 index 000000000..d51e44841 --- /dev/null +++ b/src/Attribute/ISchemaManagedAttribute.php @@ -0,0 +1,34 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\Attribute; + +/** + * This interface denotes an attribute that has been migrated to the new schema manager and therefore the manipulation + * methods shall not be called anymore. + * + * It is part of the migration process to MetaModels 3.0 and will get removed then. + * + * In order to migrate to a ISchemaManagedAttribute, you should implement and register a doctrine schema generator. + * + * @see \MetaModels\Schema\Doctrine\AbstractAttributeTypeSchemaGenerator + */ +interface ISchemaManagedAttribute extends IAttribute +{ +} diff --git a/src/Attribute/ISimple.php b/src/Attribute/ISimple.php index 9724950fe..13c6c1e11 100644 --- a/src/Attribute/ISimple.php +++ b/src/Attribute/ISimple.php @@ -32,6 +32,8 @@ interface ISimple extends IAttribute * Returns the SQL primitive type declaration in MySQL notation. i.e. "text NULL". * * @return string + * + * @deprecated Implement schema generators instead. */ public function getSQLDataType(); @@ -39,6 +41,8 @@ public function getSQLDataType(); * Creates the underlying database structure for this attribute. * * @return void + * + * @deprecated Implement schema generators instead. */ public function createColumn(); @@ -46,6 +50,8 @@ public function createColumn(); * Removes the underlying database structure for this attribute. * * @return void + * + * @deprecated Implement schema generators instead. */ public function deleteColumn(); @@ -55,6 +61,8 @@ public function deleteColumn(); * @param string $strNewColumnName The new column name for the attribute. * * @return void + * + * @deprecated Implement schema generators instead. */ public function renameColumn($strNewColumnName); diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php new file mode 100644 index 000000000..724cbb681 --- /dev/null +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php @@ -0,0 +1,48 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\CoreBundle\DependencyInjection\CompilerPass; + +use MetaModels\Schema\Doctrine\DoctrineSchemaGenerator; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * This pass adds the tagged schema generators to the doctrine engine. + */ +class CollectDoctrineSchemaGeneratorsPass implements CompilerPassInterface +{ + public const TAG_NAME = 'metamodels.schema-generator.doctrine'; + + /** + * {@inheritDoc} + */ + public function process(ContainerBuilder $container): void + { + $generator = $container->getDefinition(DoctrineSchemaGenerator::class); + $argument = $generator->getArgument(0); + foreach (array_keys($container->findTaggedServiceIds(self::TAG_NAME)) as $child) { + $argument[] = new Reference($child); + } + $generator->setArgument(0, $argument); + } +} diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php new file mode 100644 index 000000000..37b8f752a --- /dev/null +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php @@ -0,0 +1,48 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\CoreBundle\DependencyInjection\CompilerPass; + +use MetaModels\Schema\SchemaGenerator; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * This pass adds the tagged schema generators. + */ +class CollectSchemaGeneratorsPass implements CompilerPassInterface +{ + public const TAG_NAME = 'metamodels.schema-generator'; + + /** + * {@inheritDoc} + */ + public function process(ContainerBuilder $container): void + { + $generator = $container->getDefinition(SchemaGenerator::class); + $argument = $generator->getArgument(0); + foreach (array_keys($container->findTaggedServiceIds(self::TAG_NAME)) as $child) { + $argument[] = new Reference($child); + } + $generator->setArgument(0, $argument); + } +} diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php new file mode 100644 index 000000000..8886e3d5a --- /dev/null +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php @@ -0,0 +1,48 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\CoreBundle\DependencyInjection\CompilerPass; + +use MetaModels\Schema\SchemaManager; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * This pass adds the tagged schema managers. + */ +class CollectSchemaManagersPass implements CompilerPassInterface +{ + public const TAG_NAME = 'metamodels.schema-manager'; + + /** + * {@inheritDoc} + */ + public function process(ContainerBuilder $container): void + { + $generator = $container->getDefinition(SchemaManager::class); + $argument = $generator->getArgument(0); + foreach (array_keys($container->findTaggedServiceIds(self::TAG_NAME)) as $child) { + $argument[] = new Reference($child); + } + $generator->setArgument(0, $argument); + } +} diff --git a/src/CoreBundle/MetaModelsCoreBundle.php b/src/CoreBundle/MetaModelsCoreBundle.php index 6fec03470..355b99c8f 100644 --- a/src/CoreBundle/MetaModelsCoreBundle.php +++ b/src/CoreBundle/MetaModelsCoreBundle.php @@ -20,7 +20,10 @@ namespace MetaModels\CoreBundle; +use MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectDoctrineSchemaGeneratorsPass; use MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectFactoriesPass; +use MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectSchemaGeneratorsPass; +use MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectSchemaManagersPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; @@ -37,5 +40,8 @@ public function build(ContainerBuilder $container) parent::build($container); $container->addCompilerPass(new CollectFactoriesPass()); + $container->addCompilerPass(new CollectSchemaGeneratorsPass()); + $container->addCompilerPass(new CollectSchemaManagersPass()); + $container->addCompilerPass(new CollectDoctrineSchemaGeneratorsPass()); } } diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index c772ac665..7f813b6da 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -182,6 +182,46 @@ services: arguments: - '@contao.framework' + MetaModels\InformationProvider\ContaoDatabaseBackedInformationProvider: + arguments: + - '@database_connection' + + MetaModels\InformationProvider\MetaModelInformationCollector: + arguments: + - ['@MetaModels\InformationProvider\ContaoDatabaseBackedInformationProvider'] + + MetaModels\Schema\SchemaGenerator: + arguments: + - [] + public: true + + MetaModels\Schema\SchemaManager: + arguments: + - [] + public: true + + MetaModels\Schema\Doctrine\DoctrineSchemaGenerator: + arguments: + - [] + tags: + - { name: 'metamodels.schema-generator' } + + MetaModels\Schema\Doctrine\DoctrineSchemaManager: + arguments: + - '@MetaModels\Schema\Doctrine\DoctrineSchemaManipulator' + tags: + - { name: 'metamodels.schema-manager' } + + MetaModels\Schema\Doctrine\DoctrineSchemaManipulator: + arguments: + - '@database_connection' + tags: + - { name: 'metamodels.schema-manipulator' } + + MetaModels\Schema\Doctrine\SystemColumnSchemaGenerator: + tags: + - { name: 'metamodels.schema-generator.doctrine' } + MetaModels\CoreBundle\Migration\TableCollationMigration: arguments: $connection: '@database_connection' diff --git a/src/Information/AttributeInformation.php b/src/Information/AttributeInformation.php new file mode 100644 index 000000000..0f47a9ecf --- /dev/null +++ b/src/Information/AttributeInformation.php @@ -0,0 +1,74 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Information; + +/** + * This is a generic attribute information. + */ +class AttributeInformation implements AttributeInformationInterface +{ + use ConfigurationTrait; + + /** + * The name of the attribute. + * + * @var string + */ + private $name; + + /** + * The type of the attribute. + * + * @var string + */ + private $type; + + /** + * Create a new instance. + * + * @param string $name The name of the attribute. + * @param string $type The type name. + * @param array $configuration The initial configuration. + */ + public function __construct(string $name, string $type, array $configuration = []) + { + $this->name = $name; + $this->type = $type; + $this->configuration = $configuration; + } + + /** + * {@inheritDoc} + */ + public function getName(): string + { + return $this->name; + } + + /** + * {@inheritDoc} + */ + public function getType(): string + { + return $this->type; + } +} diff --git a/src/Information/AttributeInformationInterface.php b/src/Information/AttributeInformationInterface.php new file mode 100644 index 000000000..7ece0b7e7 --- /dev/null +++ b/src/Information/AttributeInformationInterface.php @@ -0,0 +1,69 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Information; + +/** + * This interface describes MetaModel attributes. + */ +interface AttributeInformationInterface +{ + /** + * Obtain the internal name of the attribute. + * + * @return string + */ + public function getName(): string; + + /** + * Get the type name. + * + * @return string + */ + public function getType(): string; + + /** + * Obtain the configuration for the attribute. + * + * @return array + */ + public function getConfiguration(): array; + + /** + * Check if a configuration value exists. + * + * @param string $name The name of the configuration value to test. + * + * @return bool + */ + public function hasConfigurationValue(string $name): bool; + + /** + * Obtain a single configuration value. + * + * @param string $name The name of the configuration value to obtain. + * + * @return mixed + * + * @throws \RuntimeException When the configuration key does not exist. + */ + public function getConfigurationValue(string $name); +} diff --git a/src/Information/ConfigurationTrait.php b/src/Information/ConfigurationTrait.php new file mode 100644 index 000000000..c34bef48c --- /dev/null +++ b/src/Information/ConfigurationTrait.php @@ -0,0 +1,89 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Information; + +/** + * This helps writing key/value stores. + */ +trait ConfigurationTrait +{ + /** + * The configuration values. + * + * @var array + */ + private $configuration = []; + + /** + * Retrieve configuration. + * + * @return array + */ + public function getConfiguration(): array + { + return $this->configuration; + } + + /** + * Check if a configuration value exists. + * + * @param string $name The name of the configuration value to test. + * + * @return bool + */ + public function hasConfigurationValue(string $name): bool + { + return array_key_exists($name, $this->configuration); + } + + /** + * Obtain a single configuration value. + * + * @param string $name The name of the configuration value to obtain. + * + * @return mixed + * + * @throws \InvalidArgumentException When the configuration key does not exist. + */ + public function getConfigurationValue(string $name) + { + if (!$this->hasConfigurationValue($name)) { + throw new \InvalidArgumentException('Configuration key "' . $name . '" does not exist'); + } + + return $this->configuration[$name]; + } + + /** + * Add configuration values from the passed array. + * + * @param array $values The new values. + * + * @return void + */ + public function addConfiguration(array $values): void + { + foreach ($values as $key => $value) { + $this->configuration[$key] = $value; + } + } +} diff --git a/src/Information/MetaModelCollection.php b/src/Information/MetaModelCollection.php new file mode 100644 index 000000000..4f4c03fe6 --- /dev/null +++ b/src/Information/MetaModelCollection.php @@ -0,0 +1,103 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Information; + +/** + * This is a collection of MetaModels. + */ +class MetaModelCollection implements MetaModelCollectionInterface +{ + /** + * The list of configured MetaModels. + * + * @var MetaModelInformationInterface[] + */ + private $metaModels = []; + + /** + * {@inheritDoc} + */ + public function getNames(): array + { + return array_keys($this->metaModels); + } + + /** + * {@inheritDoc} + */ + public function all(): array + { + return array_values($this->metaModels); + } + + /** + * Add information for a MetaModel. + * + * @param MetaModelInformationInterface $information The MetaModel information. + * + * @return void + * + * @throws \InvalidArgumentException When the MetaModel is already registered. + */ + public function add(MetaModelInformationInterface $information): void + { + if ($this->has($name = $information->getName())) { + throw new \InvalidArgumentException('MetaModel "' . $name . '" already registered'); + } + + $this->metaModels[$name] = $information; + } + + /** + * {@inheritDoc} + */ + public function has(string $name): bool + { + return array_key_exists($name, $this->metaModels); + } + + /** + * {@inheritDoc} + * + * @throws \InvalidArgumentException When the MetaModel is not registered. + */ + public function get(string $name): MetaModelInformationInterface + { + if (!$this->has($name)) { + throw new \InvalidArgumentException('Unknown MetaModel "' . $name . '"'); + } + + return $this->metaModels[$name]; + } + + /** + * {@inheritDoc} + */ + public function getIterator() + { + // Cannot "yield from" here as we have the names as key. + /** @noinspection YieldFromCanBeUsedInspection */ + foreach ($this->metaModels as $metaModel) { + yield $metaModel; + } + } +} diff --git a/src/Information/MetaModelCollectionInterface.php b/src/Information/MetaModelCollectionInterface.php new file mode 100644 index 000000000..9149207ad --- /dev/null +++ b/src/Information/MetaModelCollectionInterface.php @@ -0,0 +1,69 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Information; + +/** + * This is a collection of MetaModels. + */ +interface MetaModelCollectionInterface extends \IteratorAggregate +{ + /** + * Obtain the names of the registered MetaModels. + * + * @return array + */ + public function getNames(): array; + + /** + * Obtain the list of configured MetaModels. + * + * @return array + */ + public function all(): array; + + /** + * Test if a MetaModel is registered. + * + * @param string $name The name of the MetaModel to test. + * + * @return bool + */ + public function has(string $name): bool; + + /** + * Get a MetaModel by name. + * + * @param string $name The name to search. + * + * @return MetaModelInformationInterface + * + * @throws \InvalidArgumentException When the MetaModel is not registered. + */ + public function get(string $name): MetaModelInformationInterface; + + /** + * {@inheritDoc} + * + * @return \Traversable|MetaModelInformationInterface[] + */ + public function getIterator(); +} diff --git a/src/Information/MetaModelInformation.php b/src/Information/MetaModelInformation.php new file mode 100644 index 000000000..31bf5afaf --- /dev/null +++ b/src/Information/MetaModelInformation.php @@ -0,0 +1,134 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Information; + +/** + * This holds the schema information for a MetaModel. + */ +class MetaModelInformation implements MetaModelInformationInterface +{ + use ConfigurationTrait; + + /** + * The name of the attribute. + * + * @var string + */ + private $name; + + /** + * The array of attribute information. + * + * @var AttributeInformationInterface[] + */ + private $attributes = []; + + /** + * Create a new instance. + * + * @param string $name The name of the metamodel. + * @param array $configuration The initial configuration. + */ + public function __construct(string $name, array $configuration = []) + { + $this->name = $name; + $this->configuration = $configuration; + } + + /** + * {@inheritDoc} + */ + public function getName(): string + { + return $this->name; + } + + /** + * {@inheritDoc} + */ + public function getAttributeNames(): array + { + return array_keys($this->attributes); + } + + /** + * Add schema information for an attribute. + * + * @param AttributeInformationInterface $attribute The attribute schema information. + * + * @return void + * + * @throws \InvalidArgumentException When the MetaModel has already been registered. + */ + public function addAttribute(AttributeInformationInterface $attribute): void + { + if ($this->hasAttribute($name = $attribute->getName())) { + throw new \InvalidArgumentException('Attribute "' . $name . '" already registered'); + } + + $this->attributes[$name] = $attribute; + } + + /** + * {@inheritDoc} + * + * @return AttributeInformation + * + * @throws \InvalidArgumentException When the attribute is not registered. + */ + public function getAttribute(string $name): AttributeInformationInterface + { + if (!$this->hasAttribute($name)) { + throw new \InvalidArgumentException('Unknown attribute "' . $name . '"'); + } + + return $this->attributes[$name]; + } + + /** + * {@inheritDoc} + */ + public function hasAttribute(string $name): bool + { + return isset($this->attributes[$name]); + } + + /** + * {@inheritDoc} + */ + public function getAttributes(): array + { + return array_values($this->attributes); + } + + /** + * {@inheritDoc} + */ + public function getAttributesOfType(string $typeName): \Traversable + { + foreach ($this->attributes as $attribute) { + if ($typeName === $attribute->getType()) { + yield $attribute; + } + } + } +} diff --git a/src/Information/MetaModelInformationInterface.php b/src/Information/MetaModelInformationInterface.php new file mode 100644 index 000000000..74de7be9e --- /dev/null +++ b/src/Information/MetaModelInformationInterface.php @@ -0,0 +1,105 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Information; + +/** + * This holds the schema information for a MetaModel. + */ +interface MetaModelInformationInterface +{ + /** + * Obtain the internal name of the attribute. + * + * @return string + */ + public function getName(): string; + + /** + * Obtain the configuration for the attribute. + * + * @return array + */ + public function getConfiguration(): array; + + /** + * Check if a configuration value exists. + * + * @param string $name The name of the configuration value to test. + * + * @return bool + */ + public function hasConfigurationValue(string $name): bool; + + /** + * Obtain a single configuration value. + * + * @param string $name The name of the configuration value to obtain. + * + * @return mixed + * + * @throws \RuntimeException When the configuration key does not exist. + */ + public function getConfigurationValue(string $name); + + /** + * Obtain the attribute names. + * + * @return string[] + */ + public function getAttributeNames(): array; + + /** + * Retrieve attributes. + * + * @param string $name The name of the attribute. + * + * @return AttributeInformationInterface + * + * @throws \InvalidArgumentException When the attribute is not registered. + */ + public function getAttribute(string $name): AttributeInformationInterface; + + /** + * Test if an attribute has been registered. + * + * @param string $name The name of the attribute to test. + * + * @return bool + */ + public function hasAttribute(string $name): bool; + + /** + * Retrieve attributes. + * + * @return AttributeInformation[] + */ + public function getAttributes(): array; + + /** + * Retrieve attributes. + * + * @param string $typeName Retrieve all attributes of a certain type. + * + * @return \Traversable|AttributeInformation[] + */ + public function getAttributesOfType(string $typeName): \Traversable; +} diff --git a/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php b/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php new file mode 100644 index 000000000..ac1082bb3 --- /dev/null +++ b/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php @@ -0,0 +1,111 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\InformationProvider; + +use Doctrine\DBAL\Connection; +use MetaModels\Information\AttributeInformation; +use MetaModels\Information\MetaModelInformation; + +/** + * This adds information from the tl_metamodel_* tables in Contao. + */ +class ContaoDatabaseBackedInformationProvider implements InformationProviderInterface +{ + /** + * The database connection. + * + * @var Connection + */ + private $connection; + + /** + * Create a new instance. + * + * @param Connection $connection + */ + public function __construct(Connection $connection) + { + $this->connection = $connection; + } + + /** + * {@inheritDoc} + */ + public function getNames(): array + { + return $this + ->connection + ->createQueryBuilder() + ->select('tableName') + ->from('tl_metamodel') + ->execute() + ->fetchAll(\PDO::FETCH_COLUMN); + } + + /** + * {@inheritDoc} + * + * @throws \RuntimeException On error. + */ + public function getInformationFor(MetaModelInformation $information): void + { + $configuration = $this + ->connection + ->createQueryBuilder() + ->select('*') + ->from('tl_metamodel') + ->where('tableName=:tableName') + ->setParameter('tableName', $information->getName()) + ->setMaxResults(1) + ->execute() + ->fetch(\PDO::FETCH_ASSOC); + // Not managed by us. + if (empty($configuration)) { + return; + } + + $information->addConfiguration($configuration); + + // Now add the attributes. + $attributeRows = $this + ->connection + ->createQueryBuilder() + ->select('*') + ->from('tl_metamodel_attribute') + ->where('pid=:pid') + ->setParameter('pid', $information->getConfigurationValue('id')) + ->orderBy('sorting') + ->execute() + ->fetchAll(\PDO::FETCH_ASSOC); + + foreach ($attributeRows as $attributeRow) { + $colName = $attributeRow['colname']; + if (!$information->hasAttribute($colName)) { + $information->addAttribute(new AttributeInformation($colName, $attributeRow['type'], $attributeRow)); + continue; + } + + $attribute = $information->getAttribute($colName); + $attribute->addConfiguration($attributeRow); + } + } +} diff --git a/src/InformationProvider/InformationProviderInterface.php b/src/InformationProvider/InformationProviderInterface.php new file mode 100644 index 000000000..473a96421 --- /dev/null +++ b/src/InformationProvider/InformationProviderInterface.php @@ -0,0 +1,48 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\InformationProvider; + +use MetaModels\Information\MetaModelInformation; + +/** + * This collects information for MetaModels. + */ +interface InformationProviderInterface +{ + /** + * Gets the names of known MetaModels. + * + * @return string[] + */ + public function getNames(): array; + + /** + * Obtain the schema for a single MetaModel. + * + * If the provider does not know the MetaModel, it must ignore it. + * + * @param MetaModelInformation $information The information to which to add. + * + * @return void + */ + public function getInformationFor(MetaModelInformation $information): void; +} diff --git a/src/InformationProvider/MetaModelInformationCollector.php b/src/InformationProvider/MetaModelInformationCollector.php new file mode 100644 index 000000000..3957ba99e --- /dev/null +++ b/src/InformationProvider/MetaModelInformationCollector.php @@ -0,0 +1,86 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\InformationProvider; + +use MetaModels\Information\MetaModelCollection; +use MetaModels\Information\MetaModelCollectionInterface; +use MetaModels\Information\MetaModelInformation; + +/** + * This collects information for MetaModels. + */ +class MetaModelInformationCollector implements InformationProviderInterface +{ + /** + * The schema collectors to use. + * + * @var InformationProviderInterface[] + */ + private $providers; + + /** + * Create a new instance. + * + * @param InformationProviderInterface[] $providers + */ + public function __construct(array $providers) + { + $this->providers = $providers; + } + + /** + * {@inheritDoc} + */ + public function getNames(): array + { + return array_values(array_unique(array_merge(...array_map(function (InformationProviderInterface $provider) { + return $provider->getNames(); + }, $this->providers)))); + } + + /** + * {@inheritDoc} + */ + public function getInformationFor(MetaModelInformation $information): void + { + foreach ($this->providers as $provider) { + $provider->getInformationFor($information); + } + } + + /** + * Obtain all MetaModel information. + * + * @return MetaModelCollectionInterface + */ + public function getCollection(): MetaModelCollectionInterface + { + $collection = new MetaModelCollection(); + + foreach ($this->getNames() as $name) { + $collection->add($metaModel = new MetaModelInformation($name)); + $this->getInformationFor($metaModel); + } + + return $collection; + } +} diff --git a/src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php b/src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php new file mode 100644 index 000000000..1d99dbe60 --- /dev/null +++ b/src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php @@ -0,0 +1,68 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema\Doctrine; + +use Doctrine\DBAL\Schema\Table; +use MetaModels\Information\AttributeInformation; +use MetaModels\Information\MetaModelCollectionInterface; + +/** + * This abstract class eases schema generators for single types. + */ +abstract class AbstractAttributeTypeSchemaGenerator implements DoctrineSchemaGeneratorInterface +{ + use DoctrineSchemaGeneratorHelperTrait; + + /** + * {@inheritDoc} + */ + public function generate(DoctrineSchemaInformation $schema, MetaModelCollectionInterface $collection): void + { + $typeName = $this->getTypeName(); + foreach ($collection as $metaModelInformation) { + if ([] !== $attributes = $metaModelInformation->getAttributesOfType($typeName)) { + $tableSchema = $this->getSchemaForMetaModel($schema, $metaModelInformation); + + foreach ($attributes as $attribute) { + $this->generateAttribute($tableSchema, $attribute); + } + } + } + } + + /** + * Generate an attribute. + * + * @param Table $tableSchema The table schema. + * @param AttributeInformation $attribute The attribute to generate. + * + * @return mixed + */ + abstract protected function generateAttribute(Table $tableSchema, AttributeInformation $attribute); + + /** + * Obtain the type name. + * + * @return string + */ + abstract protected function getTypeName(): string; +} diff --git a/src/Schema/Doctrine/DoctrineSchemaGenerator.php b/src/Schema/Doctrine/DoctrineSchemaGenerator.php new file mode 100644 index 000000000..df22020ae --- /dev/null +++ b/src/Schema/Doctrine/DoctrineSchemaGenerator.php @@ -0,0 +1,65 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema\Doctrine; + +use MetaModels\Information\MetaModelCollectionInterface; +use MetaModels\Schema\SchemaGeneratorInterface; +use MetaModels\Schema\SchemaInformation; + +/** + * This is the base for a schema generator working with doctrine schemas. + */ +class DoctrineSchemaGenerator implements SchemaGeneratorInterface +{ + /** + * The list of schema providers. + * + * @var DoctrineSchemaGeneratorInterface[] + */ + private $providers; + + /** + * Create a new instance. + * + * @param array $providers The schema providers. + */ + public function __construct(array $providers) + { + $this->providers = $providers; + } + + /** + * {@inheritDoc} + */ + public function generate(SchemaInformation $information, MetaModelCollectionInterface $collection): void + { + if (!$information->has(DoctrineSchemaInformation::class)) { + $information->add(new DoctrineSchemaInformation()); + } + /** @var DoctrineSchemaInformation $schema */ + $schema = $information->get(DoctrineSchemaInformation::class); + + foreach ($this->providers as $provider) { + $provider->generate($schema, $collection); + } + } +} diff --git a/src/Schema/Doctrine/DoctrineSchemaGeneratorHelperTrait.php b/src/Schema/Doctrine/DoctrineSchemaGeneratorHelperTrait.php new file mode 100644 index 000000000..6993c7284 --- /dev/null +++ b/src/Schema/Doctrine/DoctrineSchemaGeneratorHelperTrait.php @@ -0,0 +1,77 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema\Doctrine; + +use Doctrine\DBAL\Schema\Column; +use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Types\Type; +use MetaModels\Information\MetaModelInformationInterface; + +/** + * This trait provides common used table manipulation tasks. + */ +trait DoctrineSchemaGeneratorHelperTrait +{ + /** + * Obtain the raw table schema for a MetaModel. + * + * @param DoctrineSchemaInformation $schema The schema to populate. + * @param MetaModelInformationInterface $metaModelInformation The MetaModel information. + * + * @return Table + */ + protected function getSchemaForMetaModel( + DoctrineSchemaInformation $schema, + MetaModelInformationInterface $metaModelInformation + ): Table { + $rawSchema = $schema->getSchema(); + if (!$rawSchema->hasTable($metaModelInformation->getName())) { + return $rawSchema->createTable($metaModelInformation->getName()); + } + + return $rawSchema->getTable($metaModelInformation->getName()); + } + + /** + * Update the information for a single column. + * + * @param Table $tableSchema The table schema. + * @param string $name The table name. + * @param string $typeName The type name. + * @param array $options The options. + * + * @return Column + */ + protected function setColumnData(Table $tableSchema, string $name, string $typeName, array $options = []): Column + { + if (!$tableSchema->hasColumn($name)) { + return $tableSchema->addColumn($name, $typeName, $options); + } + + $column = $tableSchema->getColumn($name); + $column->setType(Type::getType($typeName)); + if ([] !== $options) { + $column->setOptions($options); + } + return $column; + } +} diff --git a/src/Schema/Doctrine/DoctrineSchemaGeneratorInterface.php b/src/Schema/Doctrine/DoctrineSchemaGeneratorInterface.php new file mode 100644 index 000000000..6615d6724 --- /dev/null +++ b/src/Schema/Doctrine/DoctrineSchemaGeneratorInterface.php @@ -0,0 +1,40 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema\Doctrine; + +use MetaModels\Information\MetaModelCollectionInterface; + +/** + * This interface describes a schema provider. + */ +interface DoctrineSchemaGeneratorInterface +{ + /** + * Generate a schema. + * + * @param DoctrineSchemaInformation $schema The doctrine schema to populate. + * @param MetaModelCollectionInterface $collection The collection of MetaModels. + * + * @return void + */ + public function generate(DoctrineSchemaInformation $schema, MetaModelCollectionInterface $collection): void; +} diff --git a/src/Schema/Doctrine/DoctrineSchemaInformation.php b/src/Schema/Doctrine/DoctrineSchemaInformation.php new file mode 100644 index 000000000..0aac9537e --- /dev/null +++ b/src/Schema/Doctrine/DoctrineSchemaInformation.php @@ -0,0 +1,142 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema\Doctrine; + +use Doctrine\DBAL\Schema\Schema; +use MetaModels\Schema\SchemaInformationInterface; + +/** + * This is the encapsulation of doctrine schema information. + */ +class DoctrineSchemaInformation implements SchemaInformationInterface +{ + /** + * The generated doctrine schema. + * + * @var Schema + */ + private $schema; + + /** + * A list of pre processors ordered by priority. + * + * @var SchemaProcessorInterface[][] + */ + private $preProcessors = []; + + /** + * A list of post processors by priority. + * + * @var SchemaProcessorInterface[][] + */ + private $postProcessors = []; + + /** + * Create a new instance. + * + * @param Schema|null $schema The contained doctrine schema. + */ + public function __construct(Schema $schema = null) + { + $this->schema = ($schema ?? new Schema()); + } + + /** + * {@inheritDoc} + */ + public function getName(): string + { + return static::class; + } + + /** + * Retrieve schema. + * + * @return Schema + */ + public function getSchema(): Schema + { + return $this->schema; + } + + /** + * Add a pre processor. + * + * @param SchemaProcessorInterface $processor The processor to add. + * @param int $priority The priority to use. + * + * @return void + */ + public function addPreProcessor(SchemaProcessorInterface $processor, $priority = 0): void + { + if (!isset($this->preProcessors[$priority])) { + $this->preProcessors[$priority] = []; + krsort($this->preProcessors); + } + $this->preProcessors[$priority][] = $processor; + } + + /** + * Retrieve preProcessors. + * + * @return SchemaProcessorInterface[] + */ + public function getPreProcessors(): array + { + if ([] === $this->preProcessors) { + return []; + } + + return array_merge(...$this->preProcessors); + } + + /** + * Add a post processor. + * + * @param SchemaProcessorInterface $processor The processor to add. + * @param int $priority The priority to use. + * + * @return void + */ + public function addPostProcessor(SchemaProcessorInterface $processor, $priority = 0): void + { + if (!isset($this->postProcessors[$priority])) { + $this->postProcessors[$priority] = []; + krsort($this->postProcessors); + } + $this->postProcessors[$priority][] = $processor; + } + + /** + * Retrieve postProcessors. + * + * @return SchemaProcessorInterface[] + */ + public function getPostProcessors(): array + { + if ([] === $this->postProcessors) { + return []; + } + + return array_merge(...$this->postProcessors); + } +} diff --git a/src/Schema/Doctrine/DoctrineSchemaManager.php b/src/Schema/Doctrine/DoctrineSchemaManager.php new file mode 100644 index 000000000..632322af6 --- /dev/null +++ b/src/Schema/Doctrine/DoctrineSchemaManager.php @@ -0,0 +1,110 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema\Doctrine; + +use MetaModels\Schema\SchemaInformation; +use MetaModels\Schema\SchemaManagerInterface; + +/** + * This is the base for a schema manager working with doctrine schemas. + */ +class DoctrineSchemaManager implements SchemaManagerInterface +{ + /** + * The schema manipulator. + * + * @var DoctrineSchemaManipulator + */ + private $manipulator; + + /** + * Create a new instance. + * + * @param DoctrineSchemaManipulator $manipulator The database connection. + */ + public function __construct(DoctrineSchemaManipulator $manipulator) + { + $this->manipulator = $manipulator; + } + + /** + * Pre-process the schema information. + * + * @param SchemaInformation $information The schema information. + * + * @return void + */ + public function preprocess(SchemaInformation $information): void + { + // If no information added, exit. + if (!$information->has(DoctrineSchemaInformation::class)) { + return; + } + /** @var DoctrineSchemaInformation $doctrine */ + $doctrine = $information->get(DoctrineSchemaInformation::class); + + foreach ($doctrine->getPreProcessors() as $preProcessor) { + $preProcessor->process(); + } + } + + /** + * Pre-process the schema information. + * + * @param SchemaInformation $information The schema information. + * + * @return void + */ + public function process(SchemaInformation $information): void + { + // If no information added, exit. + if (!$information->has(DoctrineSchemaInformation::class)) { + return; + } + + /** @var DoctrineSchemaInformation $doctrine */ + $doctrine = $information->get(DoctrineSchemaInformation::class); + $this->manipulator->updateDatabase($doctrine); + } + + /** + * Post-process the schema information. + * + * @param SchemaInformation $information The schema information. + * + * @return void + */ + public function postprocess(SchemaInformation $information): void + { + // If no information added, exit. + if (!$information->has(DoctrineSchemaInformation::class)) { + return; + } + + /** @var DoctrineSchemaInformation $doctrine */ + $doctrine = $information->get(DoctrineSchemaInformation::class); + + foreach ($doctrine->getPostProcessors() as $postProcessor) { + $postProcessor->process(); + } + } +} diff --git a/src/Schema/Doctrine/DoctrineSchemaManipulator.php b/src/Schema/Doctrine/DoctrineSchemaManipulator.php new file mode 100644 index 000000000..c050d871e --- /dev/null +++ b/src/Schema/Doctrine/DoctrineSchemaManipulator.php @@ -0,0 +1,67 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema\Doctrine; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Schema\Comparator; + +/** + * This updates the database to be in sync with the passed schema. + */ +class DoctrineSchemaManipulator +{ + /** + * The doctrine connection. + * + * @var Connection + */ + private $connection; + + /** + * Create a new instance. + * + * @param Connection $connection The database connection to use. + */ + public function __construct(Connection $connection) + { + $this->connection = $connection; + } + + /** + * Update the database to be in sync with the passed doctrine information. + * + * @param DoctrineSchemaInformation $schemaInformation The schema information. + * + * @return void + */ + public function updateDatabase(DoctrineSchemaInformation $schemaInformation): void + { + $manager = $this->connection->getSchemaManager(); + $current = $manager->createSchema(); + $diff = Comparator::compareSchemas($current, $schemaInformation->getSchema()); + $queries = $diff->toSaveSql($this->connection->getDatabasePlatform()); + + foreach ($queries as $query) { + $this->connection->exec($query); + } + } +} diff --git a/src/Schema/Doctrine/SchemaProcessorInterface.php b/src/Schema/Doctrine/SchemaProcessorInterface.php new file mode 100644 index 000000000..2c3ef8bbf --- /dev/null +++ b/src/Schema/Doctrine/SchemaProcessorInterface.php @@ -0,0 +1,35 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema\Doctrine; + +/** + * This interface describes a schema processor for pre/post processing. + */ +interface SchemaProcessorInterface +{ + /** + * Perform the action. + * + * @return void + */ + public function process(): void; +} diff --git a/src/Schema/Doctrine/SystemColumnSchemaGenerator.php b/src/Schema/Doctrine/SystemColumnSchemaGenerator.php new file mode 100644 index 000000000..6893a4210 --- /dev/null +++ b/src/Schema/Doctrine/SystemColumnSchemaGenerator.php @@ -0,0 +1,92 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema\Doctrine; + +use Doctrine\DBAL\Types\Type; +use MetaModels\Information\MetaModelCollectionInterface; +use MetaModels\Information\MetaModelInformationInterface; + +/** + * This interface describes a schema provider. + */ +class SystemColumnSchemaGenerator implements DoctrineSchemaGeneratorInterface +{ + use DoctrineSchemaGeneratorHelperTrait; + + /** + * {@inheritDoc} + */ + public function generate(DoctrineSchemaInformation $schema, MetaModelCollectionInterface $collection): void + { + foreach ($collection as $metaModelInformation) { + $this->generateMetaModelSchema($schema, $metaModelInformation); + } + } + + /** + * Generate the schema for a MetaModel. + * + * @param DoctrineSchemaInformation $schema The doctrine schema to populate. + * @param MetaModelInformationInterface $metaModelInformation The metamodel information to use. + * + * @return void + */ + private function generateMetaModelSchema( + DoctrineSchemaInformation $schema, + MetaModelInformationInterface $metaModelInformation + ): void { + $tableSchema = $this->getSchemaForMetaModel($schema, $metaModelInformation); + + $this->setColumnData($tableSchema, 'id', Type::INTEGER, [ + 'unsigned' => true, + 'notnull' => true, + 'autoincrement' => true, + ]); + $this->setColumnData($tableSchema, 'pid', Type::INTEGER, [ + 'unsigned' => true, + 'notnull' => false, + ]); + $this->setColumnData($tableSchema, 'sorting', Type::INTEGER, [ + 'unsigned' => true, + 'default' => 0, + ]); + $this->setColumnData($tableSchema, 'tstamp', Type::INTEGER, [ + 'unsigned' => true, + 'default' => 0, + ]); + + $tableSchema->setPrimaryKey(['id']); + + if ($metaModelInformation->hasConfigurationValue('varsupport') + && '1' === $metaModelInformation->getConfigurationValue('varsupport')) { + $this->setColumnData($tableSchema, 'varbase', Type::STRING, [ + 'length' => 1, + 'fixed' => true, + 'default' => '', + ]); + $this->setColumnData($tableSchema, 'vargroup', Type::INTEGER, [ + 'unsigned' => true, + 'default' => 0, + ]); + } + } +} diff --git a/src/Schema/SchemaGenerator.php b/src/Schema/SchemaGenerator.php new file mode 100644 index 000000000..e11174abf --- /dev/null +++ b/src/Schema/SchemaGenerator.php @@ -0,0 +1,57 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema; + +use MetaModels\Information\MetaModelCollectionInterface; + +/** + * This is the main MetaModels schema generator, it is a composite of other generators. + */ +class SchemaGenerator implements SchemaGeneratorInterface +{ + /** + * The list of registered schema managers. + * + * @var SchemaGeneratorInterface[] + */ + private $generators; + + /** + * Create a new instance. + * + * @param SchemaGeneratorInterface[] $generators The managers to use. + */ + public function __construct(array $generators) + { + $this->generators = $generators; + } + + /** + * {@inheritDoc} + */ + public function generate(SchemaInformation $information, MetaModelCollectionInterface $collection): void + { + foreach ($this->generators as $manager) { + $manager->generate($information, $collection); + } + } +} diff --git a/src/Schema/SchemaGeneratorInterface.php b/src/Schema/SchemaGeneratorInterface.php new file mode 100644 index 000000000..444148371 --- /dev/null +++ b/src/Schema/SchemaGeneratorInterface.php @@ -0,0 +1,40 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema; + +use MetaModels\Information\MetaModelCollectionInterface; + +/** + * This interface describes a generic schema generator. + */ +interface SchemaGeneratorInterface +{ + /** + * Generate the schema information. + * + * @param SchemaInformation $information The schema information. + * @param MetaModelCollectionInterface $collection The collection of MetaModels. + * + * @return void + */ + public function generate(SchemaInformation $information, MetaModelCollectionInterface $collection): void; +} diff --git a/src/Schema/SchemaInformation.php b/src/Schema/SchemaInformation.php new file mode 100644 index 000000000..a1cf83186 --- /dev/null +++ b/src/Schema/SchemaInformation.php @@ -0,0 +1,93 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema; + +/** + * This encapsulates the different schema engine information. + */ +class SchemaInformation +{ + /** + * The list of registered schema information. + * + * @var SchemaInformationInterface[] + */ + private $information; + + /** + * Retrieve schema information. + * + * @param string $name The information to retrieve the schema for. + * + * @return SchemaInformationInterface + * + * @throws \InvalidArgumentException When the information is not registered. + */ + public function get(string $name): SchemaInformationInterface + { + if (!$this->has($name)) { + throw new \InvalidArgumentException('Information with name "' . $name . '" not registered.'); + } + + return $this->information[$name]; + } + + /** + * Test if the information with the passed name is registered. + * + * @param string $name The name of the information to search. + * + * @return bool + */ + public function has(string $name): bool + { + return isset($this->information[$name]); + } + + /** + * Test if the information with the passed name is registered. + * + * @param SchemaInformationInterface $information The information to add. + * + * @return void + * + * @throws \InvalidArgumentException When the information is already registered. + */ + public function add(SchemaInformationInterface $information): void + { + if ($this->has($name = $information->getName())) { + throw new \InvalidArgumentException('Information with name "' . $name . '" already registered.'); + } + + $this->information[$information->getName()] = $information; + } + + /** + * Obtain the list of registered names. + * + * @return string[] + */ + public function getRegisteredNames(): array + { + return array_keys($this->information); + } +} diff --git a/src/Schema/SchemaInformationInterface.php b/src/Schema/SchemaInformationInterface.php new file mode 100644 index 000000000..3b44cf2f9 --- /dev/null +++ b/src/Schema/SchemaInformationInterface.php @@ -0,0 +1,35 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema; + +/** + * This interface describes a MetaModels schema information for a particular engine. + */ +interface SchemaInformationInterface +{ + /** + * Obtain the name of the schema information. + * + * @return string + */ + public function getName(): string; +} diff --git a/src/Schema/SchemaManager.php b/src/Schema/SchemaManager.php new file mode 100644 index 000000000..b5bd1601e --- /dev/null +++ b/src/Schema/SchemaManager.php @@ -0,0 +1,78 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema; + +/** + * This is the main MetaModels schema manager, it is a composite of other managers. + */ +class SchemaManager implements SchemaManagerInterface +{ + /** + * The list of registered schema managers. + * + * @var SchemaManagerInterface[] + */ + private $managers; + + /** + * Create a new instance. + * + * @param SchemaManagerInterface[] $managers The managers to use. + */ + public function __construct(array $managers) + { + $this->managers = $managers; + } + + /** + * {@inheritDoc} + */ + public function preprocess(SchemaInformation $information): void + { + // pre process - this may perform data migrations and the like. + foreach ($this->managers as $manager) { + $manager->preprocess($information); + } + } + + /** + * {@inheritDoc} + */ + public function process(SchemaInformation $information): void + { + // process - here the automatic adjustments to the db will be made. + foreach ($this->managers as $manager) { + $manager->process($information); + } + } + + /** + * {@inheritDoc} + */ + public function postprocess(SchemaInformation $information): void + { + // post process - perform any cleanup to be done. + foreach ($this->managers as $manager) { + $manager->postprocess($information); + } + } +} diff --git a/src/Schema/SchemaManagerInterface.php b/src/Schema/SchemaManagerInterface.php new file mode 100644 index 000000000..61363692c --- /dev/null +++ b/src/Schema/SchemaManagerInterface.php @@ -0,0 +1,55 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema; + +/** + * This interface describes a schema manager. + */ +interface SchemaManagerInterface +{ + /** + * Pre-process the schema information. + * + * @param SchemaInformation $information The schema information. + * + * @return void + */ + public function preprocess(SchemaInformation $information): void; + + /** + * Pre-process the schema information. + * + * @param SchemaInformation $information The schema information. + * + * @return void + */ + public function process(SchemaInformation $information): void; + + /** + * Pre-process the schema information. + * + * @param SchemaInformation $information The schema information. + * + * @return void + */ + public function postprocess(SchemaInformation $information): void; +} diff --git a/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php new file mode 100644 index 000000000..3b708eb90 --- /dev/null +++ b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php @@ -0,0 +1,81 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\CoreBundle\DependencyInjection\CompilerPass; + +use MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectSchemaGeneratorsPass; +use MetaModels\Schema\SchemaGenerator; +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * This tests the schema generator collecting. + * + * @covers \MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectSchemaGeneratorsPass + */ +class CollectSchemaGeneratorsPassTest extends TestCase +{ + /** + * Test that all collectors are found. + * + * @return void + */ + public function testProcess(): void + { + $container = new ContainerBuilder(); + + $generator = $this + ->getMockBuilder(Definition::class) + ->setMethods(['getArgument', 'setArgument']) + ->getMock(); + $generator + ->expects($this->once()) + ->method('getArgument') + ->with(0) + ->willReturn([new Reference('previous-argument')]); + $generator + ->expects($this->once()) + ->method('setArgument') + ->willReturnCallback(function ($index, $children) { + $this->assertSame(0, $index); + $this->assertCount(3, $children); + $this->assertSame('previous-argument', (string) $children[0]); + $this->assertSame('child1', (string) $children[1]); + $this->assertSame('child2', (string) $children[2]); + }); + + $container->setDefinition(SchemaGenerator::class, $generator); + + $child1 = new Definition(); + $child1->addTag(CollectSchemaGeneratorsPass::TAG_NAME); + $child2 = new Definition(); + $child2->addTag(CollectSchemaGeneratorsPass::TAG_NAME); + + $container->setDefinition('child1', $child1); + $container->setDefinition('child2', $child2); + + $pass = new CollectSchemaGeneratorsPass(); + + $pass->process($container); + } +} diff --git a/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPassTest.php b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPassTest.php new file mode 100644 index 000000000..324b35be5 --- /dev/null +++ b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPassTest.php @@ -0,0 +1,81 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\CoreBundle\DependencyInjection\CompilerPass; + +use MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectSchemaManagersPass; +use MetaModels\Schema\SchemaManager; +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * This tests the schema generator collecting. + * + * @covers \MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectSchemaManagersPass + */ +class CollectSchemaManagersPassTest extends TestCase +{ + /** + * Test that all collectors are found. + * + * @return void + */ + public function testProcess(): void + { + $container = new ContainerBuilder(); + + $manager = $this + ->getMockBuilder(Definition::class) + ->setMethods(['getArgument', 'setArgument']) + ->getMock(); + $manager + ->expects($this->once()) + ->method('getArgument') + ->with(0) + ->willReturn([new Reference('previous-argument')]); + $manager + ->expects($this->once()) + ->method('setArgument') + ->willReturnCallback(function ($index, $children) { + $this->assertSame(0, $index); + $this->assertCount(3, $children); + $this->assertSame('previous-argument', (string) $children[0]); + $this->assertSame('child1', (string) $children[1]); + $this->assertSame('child2', (string) $children[2]); + }); + + $container->setDefinition(SchemaManager::class, $manager); + + $child1 = new Definition(); + $child1->addTag(CollectSchemaManagersPass::TAG_NAME); + $child2 = new Definition(); + $child2->addTag(CollectSchemaManagersPass::TAG_NAME); + + $container->setDefinition('child1', $child1); + $container->setDefinition('child2', $child2); + + $pass = new CollectSchemaManagersPass(); + + $pass->process($container); + } +} diff --git a/tests/Information/AttributeInformationTest.php b/tests/Information/AttributeInformationTest.php new file mode 100644 index 000000000..e97d2c8f3 --- /dev/null +++ b/tests/Information/AttributeInformationTest.php @@ -0,0 +1,47 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Information; + +use MetaModels\Information\AttributeInformation; +use PHPUnit\Framework\TestCase; + +/** + * This tests the attribute information. + * + * @covers \MetaModels\Information\AttributeInformation + */ +class AttributeInformationTest extends TestCase +{ + /** + * Test that the various methods work as intended. + * + * @return void + */ + public function testFunctionality(): void + { + $information = new AttributeInformation('attribute', 'typename', ['key1' => 'value', 'key2' => 'another']); + + $this->assertSame('attribute', $information->getName()); + $this->assertSame('typename', $information->getType()); + $this->assertSame(['key1' => 'value', 'key2' => 'another'], $information->getConfiguration()); + } +} diff --git a/tests/Information/ConfigurationTraitTest.php b/tests/Information/ConfigurationTraitTest.php new file mode 100644 index 000000000..63c72fbac --- /dev/null +++ b/tests/Information/ConfigurationTraitTest.php @@ -0,0 +1,68 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Information; + +use MetaModels\Information\ConfigurationTrait; +use PHPUnit\Framework\TestCase; + +/** + * This tests the configuration trait. + * + * @covers \MetaModels\Information\ConfigurationTrait + */ +class ConfigurationTraitTest extends TestCase +{ + /** + * Test that the various methods work as intended. + * + * @return void + */ + public function testFunctionality(): void + { + $trait = $this->getMockForTrait(ConfigurationTrait::class); + + $this->assertSame([], $trait->getConfiguration()); + $trait->addConfiguration(['string' => 'string', 'int' => 1, 'null' => null]); + $this->assertSame(['string' => 'string', 'int' => 1, 'null' => null], $trait->getConfiguration()); + $this->assertTrue($trait->hasConfigurationValue('string')); + $this->assertTrue($trait->hasConfigurationValue('int')); + $this->assertTrue($trait->hasConfigurationValue('null')); + $this->assertSame('string', $trait->getConfigurationValue('string')); + $this->assertSame(1, $trait->getConfigurationValue('int')); + $this->assertNull($trait->getConfigurationValue('null')); + } + + /** + * Test. + * + * @return void + */ + public function testGetConfigurationValueThrowsForUnknown(): void + { + $trait = $this->getMockForTrait(ConfigurationTrait::class); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Configuration key "unknown" does not exist'); + + $trait->getConfigurationValue('unknown'); + } +} diff --git a/tests/Information/MetaModelCollectionTest.php b/tests/Information/MetaModelCollectionTest.php new file mode 100644 index 000000000..6ca04e511 --- /dev/null +++ b/tests/Information/MetaModelCollectionTest.php @@ -0,0 +1,104 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Information; + +use MetaModels\Information\MetaModelInformationInterface; +use MetaModels\Information\MetaModelCollection; +use PHPUnit\Framework\TestCase; + +/** + * This tests the attribute information. + * + * @covers \MetaModels\Information\MetaModelCollection + */ +class MetaModelCollectionTest extends TestCase +{ + /** + * Test that the various methods work as intended. + * + * @return void + */ + public function testInstantiation(): void + { + $information = new MetaModelCollection(); + $this->assertSame([], $information->getNames()); + $this->assertSame([], $information->all()); + $this->assertSame([], iterator_to_array($information)); + } + + /** + * Test adding of a MetaModel. + * + * @return void + */ + public function testAddMetaModel(): void + { + $information = new MetaModelCollection(); + + $metamodel = $this->getMockForAbstractClass(MetaModelInformationInterface::class); + $metamodel->expects($this->once())->method('getName')->willReturn('mm_test'); + + $information->add($metamodel); + + $this->assertTrue($information->has('mm_test')); + $this->assertSame($metamodel, $information->get('mm_test')); + $this->assertSame([$metamodel], $information->all()); + $this->assertSame([$metamodel], iterator_to_array($information)); + } + + /** + * Test adding twice. + * + * @return void + */ + public function testAddThrowsForRegisteredName(): void + { + $information = new MetaModelCollection(); + + $metamodel = $this->getMockForAbstractClass(MetaModelInformationInterface::class); + $metamodel->expects($this->once())->method('getName')->willReturn('mm_test'); + $information->add($metamodel); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('MetaModel "mm_test" already registered'); + + $second = $this->getMockForAbstractClass(MetaModelInformationInterface::class); + $second->expects($this->once())->method('getName')->willReturn('mm_test'); + + $information->add($second); + } + + /** + * Test fetching unknown attribute. + * + * @return void + */ + public function testGetThrowsForUnknown(): void + { + $information = new MetaModelCollection(); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Unknown MetaModel "unknown"'); + + $information->get('unknown'); + } +} diff --git a/tests/Information/MetaModelInformationTest.php b/tests/Information/MetaModelInformationTest.php new file mode 100644 index 000000000..da1026619 --- /dev/null +++ b/tests/Information/MetaModelInformationTest.php @@ -0,0 +1,134 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Information; + +use MetaModels\Information\AttributeInformationInterface; +use MetaModels\Information\MetaModelInformation; +use PHPUnit\Framework\TestCase; + +/** + * This tests the attribute information. + * + * @covers \MetaModels\Information\MetaModelInformation + */ +class MetaModelInformationTest extends TestCase +{ + /** + * Test that the various methods work as intended. + * + * @return void + */ + public function testFunctionality(): void + { + $information = new MetaModelInformation('mm_test', ['key1' => 'value', 'key2' => 'another']); + + $this->assertSame('mm_test', $information->getName()); + $this->assertSame(['key1' => 'value', 'key2' => 'another'], $information->getConfiguration()); + $this->assertSame([], $information->getAttributeNames()); + $this->assertSame([], $information->getAttributes()); + } + + /** + * Test adding of an attribute. + * + * @return void + */ + public function testAddAttribute(): void + { + $information = new MetaModelInformation('mm_test'); + + $attribute = $this->getMockForAbstractClass(AttributeInformationInterface::class); + $attribute->expects($this->once())->method('getName')->willReturn('test'); + + $information->addAttribute($attribute); + + $this->assertTrue($information->hasAttribute('test')); + $this->assertSame($attribute, $information->getAttribute('test')); + $this->assertSame([$attribute], $information->getAttributes()); + } + + /** + * Test adding twice. + * + * @return void + */ + public function testAddThrowsForRegisteredName(): void + { + $information = new MetaModelInformation('mm_test'); + + $attribute = $this->getMockForAbstractClass(AttributeInformationInterface::class); + $attribute->expects($this->once())->method('getName')->willReturn('test'); + $information->addAttribute($attribute); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Attribute "test" already registered'); + + $second = $this->getMockForAbstractClass(AttributeInformationInterface::class); + $second->expects($this->once())->method('getName')->willReturn('test'); + + $information->addAttribute($second); + } + + /** + * Test fetching unknown attribute. + * + * @return void + */ + public function testGetAttributeThrowsForUnknown(): void + { + $information = new MetaModelInformation('mm_test'); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Unknown attribute "unknown"'); + + $information->getAttribute('unknown'); + } + + /** + * Test retrieving attributes of a given type. + * + * @return void + */ + public function testGetAttributesOfType(): void + { + $information = new MetaModelInformation('mm_test'); + + $attribute1 = $this->getMockForAbstractClass(AttributeInformationInterface::class); + $attribute1->expects($this->once())->method('getName')->willReturn('test1'); + $attribute1->expects($this->once())->method('getType')->willReturn('searched'); + $information->addAttribute($attribute1); + $attribute2 = $this->getMockForAbstractClass(AttributeInformationInterface::class); + $attribute2->expects($this->once())->method('getName')->willReturn('test2'); + $attribute2->expects($this->once())->method('getType')->willReturn('other'); + $information->addAttribute($attribute2); + $attribute3 = $this->getMockForAbstractClass(AttributeInformationInterface::class); + $attribute3->expects($this->once())->method('getName')->willReturn('test3'); + $attribute3->expects($this->once())->method('getType')->willReturn('searched'); + + $information->addAttribute($attribute3); + + $this->assertSame( + [$attribute1, $attribute3], + iterator_to_array($information->getAttributesOfType('searched')) + ); + } +} diff --git a/tests/InformationProvider/MetaModelInformationCollectorTest.php b/tests/InformationProvider/MetaModelInformationCollectorTest.php new file mode 100644 index 000000000..f667bf6e8 --- /dev/null +++ b/tests/InformationProvider/MetaModelInformationCollectorTest.php @@ -0,0 +1,105 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\InformationProvider; + +use MetaModels\Information\MetaModelInformation; +use MetaModels\InformationProvider\MetaModelInformationCollector; +use MetaModels\InformationProvider\InformationProviderInterface; +use PHPUnit\Framework\TestCase; + +/** + * This tests the information collector. + * + * @covers \MetaModels\InformationProvider\MetaModelInformationCollector + */ +class MetaModelInformationCollectorTest extends TestCase +{ + /** + * Test the class can be instantiated. + * + * @return void + */ + public function testInstantiation(): void + { + $collector = new MetaModelInformationCollector([]); + $this->assertInstanceOf(MetaModelInformationCollector::class, $collector); + } + + /** + * Test that all providers are queried. + * + * @return void + */ + public function testCollectsNamesFromAllProviders(): void + { + $provider1 = $this->getMockForAbstractClass(InformationProviderInterface::class); + $provider2 = $this->getMockForAbstractClass(InformationProviderInterface::class); + + $provider1->expects($this->once())->method('getNames')->willReturn(['name1', 'name2']); + $provider2->expects($this->once())->method('getNames')->willReturn(['name2', 'name3']); + + $collector = new MetaModelInformationCollector([$provider1, $provider2]); + + $this->assertSame(['name1', 'name2', 'name3'], $collector->getNames()); + } + + /** + * Test that all providers are queried. + * + * @return void + */ + public function testCollectsInformationFromAllProviders(): void + { + $information = new MetaModelInformation('mm_test'); + + $provider1 = $this->getMockForAbstractClass(InformationProviderInterface::class); + $provider2 = $this->getMockForAbstractClass(InformationProviderInterface::class); + + $provider1->expects($this->once())->method('getInformationFor')->with($information); + $provider2->expects($this->once())->method('getInformationFor')->with($information); + + $collector = new MetaModelInformationCollector([$provider1, $provider2]); + + $collector->getInformationFor($information); + } + + /** + * Test obtaining of the collection. + * + * @return void + */ + public function testGetCollection(): void + { + $collector = $this + ->getMockBuilder(MetaModelInformationCollector::class) + ->setMethods(['getNames', 'getInformationFor']) + ->disableOriginalConstructor() + ->getMock(); + + $collector->expects($this->once())->method('getNames')->willReturn(['name1', 'name2', 'name3']); + $collector->expects($this->exactly(3))->method('getInformationFor'); + /** @var MetaModelInformationCollector $collector */ + $collection = $collector->getCollection(); + + $this->assertSame(['name1', 'name2', 'name3'], $collection->getNames()); + } +} diff --git a/tests/Schema/Doctrine/DoctrineSchemaGeneratorTest.php b/tests/Schema/Doctrine/DoctrineSchemaGeneratorTest.php new file mode 100644 index 000000000..ecd1ea0a7 --- /dev/null +++ b/tests/Schema/Doctrine/DoctrineSchemaGeneratorTest.php @@ -0,0 +1,89 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Schema\Doctrine; + +use MetaModels\Information\MetaModelCollectionInterface; +use MetaModels\Schema\Doctrine\DoctrineSchemaGenerator; +use MetaModels\Schema\Doctrine\DoctrineSchemaInformation; +use MetaModels\Schema\Doctrine\DoctrineSchemaGeneratorInterface; +use MetaModels\Schema\SchemaInformation; +use PHPUnit\Framework\TestCase; + +/** + * This tests the doctrine schema. + * + * @covers \MetaModels\Schema\Doctrine\DoctrineSchemaGenerator + */ +class DoctrineSchemaGeneratorTest extends TestCase +{ + /** + * Test the instantiation. + * + * @return void + */ + public function testInstantiation(): void + { + $instance = new DoctrineSchemaGenerator([]); + + $this->assertInstanceOf(DoctrineSchemaGenerator::class, $instance); + } + + /** + * Test the generate method. + * + * @return void + */ + public function testGenerateAddsSchemaInformationIfNotFound(): void + { + $instance = new DoctrineSchemaGenerator([]); + + $information = new SchemaInformation(); + + $collection = $this->getMockForAbstractClass(MetaModelCollectionInterface::class); + + $instance->generate($information, $collection); + + $this->assertTrue($information->has(DoctrineSchemaInformation::class)); + } + + /** + * Test the generate method. + * + * @return void + */ + public function testGenerate(): void + { + $doctrineSchema = new DoctrineSchemaInformation(); + $collection = $this->getMockForAbstractClass(MetaModelCollectionInterface::class); + $generator1 = $this->getMockForAbstractClass(DoctrineSchemaGeneratorInterface::class); + $generator2 = $this->getMockForAbstractClass(DoctrineSchemaGeneratorInterface::class); + $generator1->expects($this->once())->method('generate')->with($doctrineSchema, $collection); + $generator2->expects($this->once())->method('generate')->with($doctrineSchema, $collection); + + + $instance = new DoctrineSchemaGenerator([$generator1, $generator2]); + + $information = new SchemaInformation(); + + $instance->generate($information, $collection); + } +} diff --git a/tests/Schema/Doctrine/DoctrineSchemaInformationTest.php b/tests/Schema/Doctrine/DoctrineSchemaInformationTest.php new file mode 100644 index 000000000..7535283cb --- /dev/null +++ b/tests/Schema/Doctrine/DoctrineSchemaInformationTest.php @@ -0,0 +1,115 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Schema\Doctrine; + +use Doctrine\DBAL\Schema\Schema; +use MetaModels\Schema\Doctrine\DoctrineSchemaInformation; +use MetaModels\Schema\Doctrine\SchemaProcessorInterface; +use PHPUnit\Framework\TestCase; + +/** + * This tests the doctrine schema. + * + * @covers \MetaModels\Schema\Doctrine\DoctrineSchemaInformation + */ +class DoctrineSchemaInformationTest extends TestCase +{ + /** + * Test the instantiation. + * + * @return void + */ + public function testInstantiation(): void + { + $schema = new Schema(); + + $instance = new DoctrineSchemaInformation($schema); + + $this->assertInstanceOf(DoctrineSchemaInformation::class, $instance); + $this->assertSame(DoctrineSchemaInformation::class, $instance->getName()); + $this->assertSame($schema, $instance->getSchema()); + $this->assertSame([], $instance->getPreProcessors()); + $this->assertSame([], $instance->getPostProcessors()); + } + + /** + * Test the pre processor handling. + * + * @return void + */ + public function testAddPreProcessors(): void + { + $schema = new Schema(); + + $processorNormal = $this + ->getMockBuilder(SchemaProcessorInterface::class) + ->setMockClassName('TestAddPreProcessorsNormal') + ->getMockForAbstractClass(); + $processorHigh = $this + ->getMockBuilder(SchemaProcessorInterface::class) + ->setMockClassName('TestAddPreProcessorsHigh') + ->getMockForAbstractClass(); + $processorLow = $this + ->getMockBuilder(SchemaProcessorInterface::class) + ->setMockClassName('TestAddPreProcessorsLow') + ->getMockForAbstractClass(); + + $instance = new DoctrineSchemaInformation($schema); + + $instance->addPreProcessor($processorNormal); + $instance->addPreProcessor($processorHigh, 100); + $instance->addPreProcessor($processorLow, -100); + + $this->assertSame([$processorHigh, $processorNormal, $processorLow], $instance->getPreProcessors()); + } + + /** + * Test the post processor handling. + * + * @return void + */ + public function testAddPostProcessors(): void + { + $schema = new Schema(); + + $processorNormal = $this + ->getMockBuilder(SchemaProcessorInterface::class) + ->setMockClassName('TestAddPostProcessorsNormal') + ->getMockForAbstractClass(); + $processorHigh = $this + ->getMockBuilder(SchemaProcessorInterface::class) + ->setMockClassName('TestAddPostProcessorsHigh') + ->getMockForAbstractClass(); + $processorLow = $this + ->getMockBuilder(SchemaProcessorInterface::class) + ->setMockClassName('TestAddPostProcessorsLow') + ->getMockForAbstractClass(); + + $instance = new DoctrineSchemaInformation($schema); + + $instance->addPostProcessor($processorNormal); + $instance->addPostProcessor($processorHigh, 100); + $instance->addPostProcessor($processorLow, -100); + + $this->assertSame([$processorHigh, $processorNormal, $processorLow], $instance->getPostProcessors()); + } +} diff --git a/tests/Schema/Doctrine/DoctrineSchemaManagerTest.php b/tests/Schema/Doctrine/DoctrineSchemaManagerTest.php new file mode 100644 index 000000000..7aab5dcfd --- /dev/null +++ b/tests/Schema/Doctrine/DoctrineSchemaManagerTest.php @@ -0,0 +1,234 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Schema\Doctrine; + +use MetaModels\Schema\Doctrine\DoctrineSchemaInformation; +use MetaModels\Schema\Doctrine\DoctrineSchemaManager; +use MetaModels\Schema\Doctrine\DoctrineSchemaManipulator; +use MetaModels\Schema\Doctrine\SchemaProcessorInterface; +use MetaModels\Schema\SchemaInformation; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * This tests the doctrine schema. + * + * @covers \MetaModels\Schema\Doctrine\DoctrineSchemaManager + */ +class DoctrineSchemaManagerTest extends TestCase +{ + /** + * Test the instantiation. + * + * @return void + */ + public function testInstantiation(): void + { + /** @var MockObject|DoctrineSchemaManipulator $manipulator */ + $manipulator = $this->getMockBuilder(DoctrineSchemaManipulator::class)->disableOriginalConstructor()->getMock(); + $instance = new DoctrineSchemaManager($manipulator); + + $this->assertInstanceOf(DoctrineSchemaManager::class, $instance); + } + + /** + * Test the preprocess method. + * + * @return void + */ + public function testPreprocess(): void + { + $processor1 = $this->getMockForAbstractClass(SchemaProcessorInterface::class); + $processor2 = $this->getMockForAbstractClass(SchemaProcessorInterface::class); + + $processor1->expects($this->once())->method('process'); + $processor2->expects($this->once())->method('process'); + + /** @var MockObject|DoctrineSchemaInformation $information */ + $information = $this + ->getMockBuilder(DoctrineSchemaInformation::class) + ->disableOriginalConstructor() + ->getMock(); + $information + ->expects($this->once()) + ->method('getPreProcessors') + ->willReturn([$processor1, $processor2]); + + $schemaInformation = $this->mockSchemaInformation($information); + + $instance = $this->createSchemaManager(); + $instance->preprocess($schemaInformation); + } + + /** + * Test the preprocess method. + * + * @return void + */ + public function testPreprocessSkipsIfNothingToDo(): void + { + $schemaInformation = $this->mockSchemaInformation(); + + $instance = $this->createSchemaManager(); + $instance->preprocess($schemaInformation); + } + + /** + * Test the process method. + * + * @return void + */ + public function testProcess(): void + { + $manipulator = $this + ->getMockBuilder(DoctrineSchemaManipulator::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var MockObject|DoctrineSchemaInformation $information */ + $information = $this + ->getMockBuilder(DoctrineSchemaInformation::class) + ->disableOriginalConstructor() + ->getMock(); + + $manipulator->expects($this->once())->method('updateDatabase')->with($information); + + $instance = $this->createSchemaManager($manipulator); + + $schemaInformation = $this->mockSchemaInformation($information); + $instance->process($schemaInformation); + } + + /** + * Test the postprocess method. + * + * @return void + */ + public function testProcessSkipsIfNothingToDo(): void + { + $schemaInformation = $this->mockSchemaInformation(); + + $instance = $this->createSchemaManager(); + $instance->process($schemaInformation); + } + + /** + * Test the postprocess method. + * + * @return void + */ + public function testPostProcess(): void + { + $processor1 = $this->getMockForAbstractClass(SchemaProcessorInterface::class); + $processor2 = $this->getMockForAbstractClass(SchemaProcessorInterface::class); + + $processor1->expects($this->once())->method('process'); + $processor2->expects($this->once())->method('process'); + + /** @var MockObject|DoctrineSchemaInformation $information */ + $information = $this + ->getMockBuilder(DoctrineSchemaInformation::class) + ->disableOriginalConstructor() + ->getMock(); + $information + ->expects($this->once()) + ->method('getPostProcessors') + ->willReturn([$processor1, $processor2]); + + $schemaInformation = $this->mockSchemaInformation($information); + + $instance = $this->createSchemaManager(); + $instance->postprocess($schemaInformation); + } + + /** + * Test the postprocess method. + * + * @return void + */ + public function testPostprocessSkipsIfNothingToDo(): void + { + $schemaInformation = $this->mockSchemaInformation(); + + $instance = $this->createSchemaManager(); + $instance->postprocess($schemaInformation); + } + + /** + * Create a schema manager instance. + * + * @param MockObject|DoctrineSchemaManipulator|null $manipulator The manipulator. + * + * @return DoctrineSchemaManager + */ + private function createSchemaManager( + DoctrineSchemaManipulator $manipulator = null + ): DoctrineSchemaManager { + if (null === $manipulator) { + $manipulator = $this + ->getMockBuilder(DoctrineSchemaManipulator::class) + ->disableOriginalConstructor() + ->getMock(); + } + + return new DoctrineSchemaManager($manipulator); + } + + /** + * Mock a schema information for the passed doctrine schema information. + * + * @param DoctrineSchemaInformation|null $information The doctrine information if any. + * + * @return SchemaInformation + */ + private function mockSchemaInformation(DoctrineSchemaInformation $information = null): SchemaInformation + { + /** @var MockObject|SchemaInformation $schemaInformation */ + $schemaInformation = $this->getMockBuilder(SchemaInformation::class)->getMock(); + + if (null === $information) { + $schemaInformation + ->expects($this->once()) + ->method('has') + ->with(DoctrineSchemaInformation::class) + ->willReturn(false); + $schemaInformation + ->expects($this->never()) + ->method('get'); + + return $schemaInformation; + } + + $schemaInformation + ->expects($this->once()) + ->method('has') + ->with(DoctrineSchemaInformation::class) + ->willReturn(true); + $schemaInformation + ->expects($this->once()) + ->method('get') + ->with(DoctrineSchemaInformation::class) + ->willReturn($information); + + return $schemaInformation; + } +} diff --git a/tests/Schema/SchemaGeneratorTest.php b/tests/Schema/SchemaGeneratorTest.php new file mode 100644 index 000000000..922118904 --- /dev/null +++ b/tests/Schema/SchemaGeneratorTest.php @@ -0,0 +1,65 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Schema; + +use MetaModels\Information\MetaModelCollectionInterface; +use MetaModels\Schema\SchemaGenerator; +use MetaModels\Schema\SchemaGeneratorInterface; +use MetaModels\Schema\SchemaInformation; +use PHPUnit\Framework\TestCase; + +/** + * This tests the schema generator class. + * + * @covers \MetaModels\Schema\SchemaGenerator + */ +class SchemaGeneratorTest extends TestCase +{ + /** + * Test the instantiation. + * + * @return void + */ + public function testInstantiation(): void + { + $instance = new SchemaGenerator([]); + + $this->assertInstanceOf(SchemaGenerator::class, $instance); + } + + /** + * Test generating the schema. + * + * @return void + */ + public function testGenerateSchema(): void + { + $collection = $this->getMockForAbstractClass(MetaModelCollectionInterface::class); + $information = new SchemaInformation(); + $generator = $this->getMockForAbstractClass(SchemaGeneratorInterface::class); + $generator->expects($this->once())->method('generate')->with($information, $collection); + + $instance = new SchemaGenerator([$generator]); + + $instance->generate($information, $collection); + } +} diff --git a/tests/Schema/SchemaInformationTest.php b/tests/Schema/SchemaInformationTest.php new file mode 100644 index 000000000..e964efc2d --- /dev/null +++ b/tests/Schema/SchemaInformationTest.php @@ -0,0 +1,128 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Schema; + +use MetaModels\Schema\SchemaInformation; +use MetaModels\Schema\SchemaInformationInterface; +use PHPUnit\Framework\TestCase; + +/** + * This tests the schema information. + * + * @covers \MetaModels\Schema\SchemaInformation + */ +class SchemaInformationTest extends TestCase +{ + /** + * Test the instantiation. + * + * @return void + */ + public function testInstantiation(): void + { + $instance = new SchemaInformation(); + + $this->assertInstanceOf(SchemaInformation::class, $instance); + } + + /** + * Test adding. + * + * @return void + */ + public function testAdd(): void + { + $instance = new SchemaInformation(); + + $mock = $this->getMockForAbstractClass(SchemaInformationInterface::class); + $mock->method('getName')->willReturn('test'); + + $instance->add($mock); + + $this->assertTrue($instance->has('test')); + $this->assertSame($mock, $instance->get('test')); + } + + /** + * Test adding. + * + * @return void + */ + public function testAddThrowsForAlreadyRegistered(): void + { + $instance = new SchemaInformation(); + + $mock = $this->getMockForAbstractClass(SchemaInformationInterface::class); + $mock->method('getName')->willReturn('test'); + + $instance->add($mock); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Information with name "test" already registered.'); + + $instance->add($mock); + } + + /** + * Test adding. + * + * @return void + */ + public function testGetThrowsForUnregistered(): void + { + $instance = new SchemaInformation(); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Information with name "test" not registered.'); + + $instance->get('test'); + } + + /** + * Test the has method. + * + * @return void + */ + public function testHasForUnknown(): void + { + $instance = new SchemaInformation(); + + $this->assertFalse($instance->has('unknown')); + } + + /** + * Test obtaining the list of registered names. + * + * @return void + */ + public function testGetRegisteredNames(): void + { + $instance = new SchemaInformation(); + + $mock = $this->getMockForAbstractClass(SchemaInformationInterface::class); + $mock->method('getName')->willReturn('test'); + + $instance->add($mock); + + $this->assertSame(['test'], $instance->getRegisteredNames()); + } +} diff --git a/tests/Schema/SchemaManagerTest.php b/tests/Schema/SchemaManagerTest.php new file mode 100644 index 000000000..715740110 --- /dev/null +++ b/tests/Schema/SchemaManagerTest.php @@ -0,0 +1,101 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Schema; + +use MetaModels\Schema\SchemaInformation; +use MetaModels\Schema\SchemaManager; +use MetaModels\Schema\SchemaManagerInterface; +use PHPUnit\Framework\TestCase; + +/** + * This tests the schema manager class. + * + * @covers \MetaModels\Schema\SchemaManager + */ +class SchemaManagerTest extends TestCase +{ + /** + * Test the instantiation. + * + * @return void + */ + public function testInstantiation(): void + { + $instance = new SchemaManager([]); + + $this->assertInstanceOf(SchemaManager::class, $instance); + } + + /** + * Test processing. + * + * @return void + */ + public function testPreprocess(): void + { + $manager1 = $this->getMockForAbstractClass(SchemaManagerInterface::class); + $manager2 = $this->getMockForAbstractClass(SchemaManagerInterface::class); + $information = new SchemaInformation(); + $manager1->expects($this->once())->method('preprocess')->with($information); + $manager2->expects($this->once())->method('preprocess')->with($information); + + $instance = new SchemaManager([$manager1, $manager2]); + + $instance->preprocess($information); + } + + /** + * Test processing. + * + * @return void + */ + public function testProcess(): void + { + $manager1 = $this->getMockForAbstractClass(SchemaManagerInterface::class); + $manager2 = $this->getMockForAbstractClass(SchemaManagerInterface::class); + $information = new SchemaInformation(); + $manager1->expects($this->once())->method('process')->with($information); + $manager2->expects($this->once())->method('process')->with($information); + + $instance = new SchemaManager([$manager1, $manager2]); + + $instance->process($information); + } + + /** + * Test processing. + * + * @return void + */ + public function testPostcess(): void + { + $manager1 = $this->getMockForAbstractClass(SchemaManagerInterface::class); + $manager2 = $this->getMockForAbstractClass(SchemaManagerInterface::class); + $information = new SchemaInformation(); + $manager1->expects($this->once())->method('postprocess')->with($information); + $manager2->expects($this->once())->method('postprocess')->with($information); + + $instance = new SchemaManager([$manager1, $manager2]); + + $instance->postprocess($information); + } +} From a71099b9fdeba13cc11ac3d0681084ffb51c446c Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Sat, 26 Jan 2019 15:14:17 +0100 Subject: [PATCH 091/224] Correctly return void --- src/Attribute/BaseSimple.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Attribute/BaseSimple.php b/src/Attribute/BaseSimple.php index dd2ca1486..1e1e9214d 100644 --- a/src/Attribute/BaseSimple.php +++ b/src/Attribute/BaseSimple.php @@ -285,7 +285,7 @@ public function destroyAUX() E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - return $this; + return; } // @codingStandardsIgnoreStart From 128eb3ded1c4b44a7400de51916ce08cab7b4d75 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Tue, 29 Jan 2019 23:17:26 +0100 Subject: [PATCH 092/224] Add PR number in deprecation hint --- src/Attribute/Base.php | 6 ++++++ src/Attribute/BaseSimple.php | 12 ++++++------ src/Attribute/IAttribute.php | 6 +++--- src/Attribute/ISimple.php | 8 ++++---- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 307b786f2..63c96d92e 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -297,6 +297,8 @@ public function set($strKey, $varValue) /** * {@inheritdoc} + * + * @deprecated Implement schema generators instead - see #1267. */ public function handleMetaChange($strMetaName, $varNewValue) { @@ -325,6 +327,8 @@ public function handleMetaChange($strMetaName, $varNewValue) /** * {@inheritdoc} + * + * @deprecated Implement schema generators instead - see #1267. */ public function destroyAUX() { @@ -349,6 +353,8 @@ public function destroyAUX() /** * {@inheritdoc} + * + * @deprecated Implement schema generators instead - see #1267. */ public function initializeAUX() { diff --git a/src/Attribute/BaseSimple.php b/src/Attribute/BaseSimple.php index 1e1e9214d..c081a9623 100644 --- a/src/Attribute/BaseSimple.php +++ b/src/Attribute/BaseSimple.php @@ -253,7 +253,7 @@ public function searchFor($strPattern) * * @return string 'blob NULL' * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function getSQLDataType() { @@ -274,7 +274,7 @@ public function getSQLDataType() * * @return void * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function destroyAUX() { @@ -304,7 +304,7 @@ public function destroyAUX() * * @return void * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function initializeAUX() { @@ -336,7 +336,7 @@ public function initializeAUX() * * @return void * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function createColumn() { @@ -371,7 +371,7 @@ public function createColumn() * * @return void * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function deleteColumn() { @@ -408,7 +408,7 @@ public function deleteColumn() * * @return void * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function renameColumn($strNewColumnName) { diff --git a/src/Attribute/IAttribute.php b/src/Attribute/IAttribute.php index 6776f40bb..d9b1b5e51 100644 --- a/src/Attribute/IAttribute.php +++ b/src/Attribute/IAttribute.php @@ -99,7 +99,7 @@ public function set($strKey, $varValue); * * @return IAttribute The instance of this attribute, to support chaining. * - * @deprecated Implement schema manipulators instead. + * @deprecated Implement schema manipulators instead - see #1267. */ public function handleMetaChange($strMetaName, $varNewValue); @@ -108,7 +108,7 @@ public function handleMetaChange($strMetaName, $varNewValue); * * @return void * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function destroyAUX(); @@ -117,7 +117,7 @@ public function destroyAUX(); * * @return void * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function initializeAUX(); diff --git a/src/Attribute/ISimple.php b/src/Attribute/ISimple.php index 13c6c1e11..bb33d4f92 100644 --- a/src/Attribute/ISimple.php +++ b/src/Attribute/ISimple.php @@ -33,7 +33,7 @@ interface ISimple extends IAttribute * * @return string * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function getSQLDataType(); @@ -42,7 +42,7 @@ public function getSQLDataType(); * * @return void * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function createColumn(); @@ -51,7 +51,7 @@ public function createColumn(); * * @return void * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function deleteColumn(); @@ -62,7 +62,7 @@ public function deleteColumn(); * * @return void * - * @deprecated Implement schema generators instead. + * @deprecated Implement schema generators instead - see #1267. */ public function renameColumn($strNewColumnName); From cba7000912e570c80fafb54e7cc63b89038a1534 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Tue, 29 Jan 2019 23:17:38 +0100 Subject: [PATCH 093/224] Initialize array --- src/Schema/SchemaInformation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Schema/SchemaInformation.php b/src/Schema/SchemaInformation.php index a1cf83186..9bd445062 100644 --- a/src/Schema/SchemaInformation.php +++ b/src/Schema/SchemaInformation.php @@ -31,7 +31,7 @@ class SchemaInformation * * @var SchemaInformationInterface[] */ - private $information; + private $information = []; /** * Retrieve schema information. From bdb7d6e38655a241860e3eab8f754f26d69114a7 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Tue, 29 Jan 2019 23:52:03 +0100 Subject: [PATCH 094/224] Priorize tagged services --- .../CollectDoctrineSchemaGeneratorsPass.php | 13 +-- .../CollectSchemaGeneratorsPass.php | 13 +-- .../CollectSchemaManagersPass.php | 13 +-- ...ollectDoctrineSchemaGeneratorsPassTest.php | 82 +++++++++++++++++++ .../CollectSchemaGeneratorsPassTest.php | 4 +- 5 files changed, 105 insertions(+), 20 deletions(-) create mode 100644 tests/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPassTest.php diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php index 724cbb681..b3864ddf0 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php @@ -23,14 +23,16 @@ use MetaModels\Schema\Doctrine\DoctrineSchemaGenerator; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; /** * This pass adds the tagged schema generators to the doctrine engine. */ class CollectDoctrineSchemaGeneratorsPass implements CompilerPassInterface { + use PriorityTaggedServiceTrait; + public const TAG_NAME = 'metamodels.schema-generator.doctrine'; /** @@ -39,10 +41,9 @@ class CollectDoctrineSchemaGeneratorsPass implements CompilerPassInterface public function process(ContainerBuilder $container): void { $generator = $container->getDefinition(DoctrineSchemaGenerator::class); - $argument = $generator->getArgument(0); - foreach (array_keys($container->findTaggedServiceIds(self::TAG_NAME)) as $child) { - $argument[] = new Reference($child); - } - $generator->setArgument(0, $argument); + $generator->setArgument( + 0, + array_merge($generator->getArgument(0), $this->findAndSortTaggedServices(self::TAG_NAME, $container)) + ); } } diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php index 37b8f752a..7913a79fd 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php @@ -23,14 +23,16 @@ use MetaModels\Schema\SchemaGenerator; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; /** * This pass adds the tagged schema generators. */ class CollectSchemaGeneratorsPass implements CompilerPassInterface { + use PriorityTaggedServiceTrait; + public const TAG_NAME = 'metamodels.schema-generator'; /** @@ -39,10 +41,9 @@ class CollectSchemaGeneratorsPass implements CompilerPassInterface public function process(ContainerBuilder $container): void { $generator = $container->getDefinition(SchemaGenerator::class); - $argument = $generator->getArgument(0); - foreach (array_keys($container->findTaggedServiceIds(self::TAG_NAME)) as $child) { - $argument[] = new Reference($child); - } - $generator->setArgument(0, $argument); + $generator->setArgument( + 0, + array_merge($generator->getArgument(0), $this->findAndSortTaggedServices(self::TAG_NAME, $container)) + ); } } diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php index 8886e3d5a..6fef35b94 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php @@ -23,14 +23,16 @@ use MetaModels\Schema\SchemaManager; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; /** * This pass adds the tagged schema managers. */ class CollectSchemaManagersPass implements CompilerPassInterface { + use PriorityTaggedServiceTrait; + public const TAG_NAME = 'metamodels.schema-manager'; /** @@ -39,10 +41,9 @@ class CollectSchemaManagersPass implements CompilerPassInterface public function process(ContainerBuilder $container): void { $generator = $container->getDefinition(SchemaManager::class); - $argument = $generator->getArgument(0); - foreach (array_keys($container->findTaggedServiceIds(self::TAG_NAME)) as $child) { - $argument[] = new Reference($child); - } - $generator->setArgument(0, $argument); + $generator->setArgument( + 0, + array_merge($generator->getArgument(0), $this->findAndSortTaggedServices(self::TAG_NAME, $container)) + ); } } diff --git a/tests/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPassTest.php b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPassTest.php new file mode 100644 index 000000000..43861c3ba --- /dev/null +++ b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPassTest.php @@ -0,0 +1,82 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\CoreBundle\DependencyInjection\CompilerPass; + +use MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectDoctrineSchemaGeneratorsPass; +use MetaModels\Schema\Doctrine\DoctrineSchemaGenerator; +use MetaModels\Schema\SchemaGenerator; +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * This tests the schema generator collecting. + * + * @covers \MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectDoctrineSchemaGeneratorsPass + */ +class CollectDoctrineSchemaGeneratorsPassTest extends TestCase +{ + /** + * Test that all collectors are found. + * + * @return void + */ + public function testProcess(): void + { + $container = new ContainerBuilder(); + + $generator = $this + ->getMockBuilder(Definition::class) + ->setMethods(['getArgument', 'setArgument']) + ->getMock(); + $generator + ->expects($this->once()) + ->method('getArgument') + ->with(0) + ->willReturn([new Reference('previous-argument')]); + $generator + ->expects($this->once()) + ->method('setArgument') + ->willReturnCallback(function ($index, $children) { + $this->assertSame(0, $index); + $this->assertCount(3, $children); + $this->assertSame('previous-argument', (string) $children[0]); + $this->assertSame('child1', (string) $children[1]); + $this->assertSame('child2', (string) $children[2]); + }); + + $container->setDefinition(DoctrineSchemaGenerator::class, $generator); + + $child1 = new Definition(); + $child1->addTag(CollectDoctrineSchemaGeneratorsPass::TAG_NAME, ['priority' => 10]); + $child2 = new Definition(); + $child2->addTag(CollectDoctrineSchemaGeneratorsPass::TAG_NAME); + + $container->setDefinition('child2', $child2); + $container->setDefinition('child1', $child1); + + $pass = new CollectDoctrineSchemaGeneratorsPass(); + + $pass->process($container); + } +} diff --git a/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php index 3b708eb90..63b602ea0 100644 --- a/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php +++ b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php @@ -67,12 +67,12 @@ public function testProcess(): void $container->setDefinition(SchemaGenerator::class, $generator); $child1 = new Definition(); - $child1->addTag(CollectSchemaGeneratorsPass::TAG_NAME); + $child1->addTag(CollectSchemaGeneratorsPass::TAG_NAME, ['priority' => 10]); $child2 = new Definition(); $child2->addTag(CollectSchemaGeneratorsPass::TAG_NAME); - $container->setDefinition('child1', $child1); $container->setDefinition('child2', $child2); + $container->setDefinition('child1', $child1); $pass = new CollectSchemaGeneratorsPass(); From 82aee178dc2a76c78dc0014a57e74291ccd25e42 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Wed, 30 Jan 2019 00:14:05 +0100 Subject: [PATCH 095/224] Add legacy schema generator This will add the remaining attributes (all non `ISchemaManagedAttribute` or `IInternal`) to the legacy schema. --- src/CoreBundle/Resources/config/services.yml | 6 + src/Schema/LegacySchemaGenerator.php | 85 +++++++++++++ src/Schema/LegacySchemaInformation.php | 69 ++++++++++ tests/Schema/LegacySchemaGeneratorTest.php | 126 +++++++++++++++++++ tests/Schema/LegacySchemaInformationTest.php | 66 ++++++++++ 5 files changed, 352 insertions(+) create mode 100644 src/Schema/LegacySchemaGenerator.php create mode 100644 src/Schema/LegacySchemaInformation.php create mode 100644 tests/Schema/LegacySchemaGeneratorTest.php create mode 100644 tests/Schema/LegacySchemaInformationTest.php diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index 7f813b6da..c0351c6d0 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -200,6 +200,12 @@ services: - [] public: true + MetaModels\Schema\LegacySchemaGenerator: + arguments: + - '@metamodels.factory' + tags: + - { name: 'metamodels.schema-generator' } + MetaModels\Schema\Doctrine\DoctrineSchemaGenerator: arguments: - [] diff --git a/src/Schema/LegacySchemaGenerator.php b/src/Schema/LegacySchemaGenerator.php new file mode 100644 index 000000000..c0e68f041 --- /dev/null +++ b/src/Schema/LegacySchemaGenerator.php @@ -0,0 +1,85 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema; + +use MetaModels\Attribute\IInternal; +use MetaModels\Attribute\ISchemaManagedAttribute; +use MetaModels\IFactory; +use MetaModels\Information\MetaModelCollectionInterface; + +/** + * This is the legacy handler for creating the legacy schema. + * + * @deprecated Only used as bc layer for 2.0 - to be removed in 3.0. + */ +class LegacySchemaGenerator implements SchemaGeneratorInterface +{ + /** + * The MetaModels factory. + * + * @var IFactory + */ + private $factory; + + /** + * Create a new instance. + * + * @param IFactory $factory The factory. + */ + public function __construct(IFactory $factory) + { + $this->factory = $factory; + } + + /** + * {@inheritDoc} + */ + public function generate(SchemaInformation $information, MetaModelCollectionInterface $collection): void + { + if (!$information->has(LegacySchemaInformation::class)) { + $information->add(new LegacySchemaInformation()); + } + + /** @var LegacySchemaInformation $legacy */ + $legacy = $information->get(LegacySchemaInformation::class); + + foreach ($collection as $metaModelInformation) { + $metaModel = $this->factory->getMetaModel($metaModelInformation->getName()); + foreach ($metaModel->getAttributes() as $attribute) { + // Skip managed and internal attributes. + if ($attribute instanceof ISchemaManagedAttribute || $attribute instanceof IInternal) { + continue; + } + + // @codingStandardsIgnoreStart + @trigger_error( + 'Attribute type "' . $attribute->get('type') . + '" should implement "' . ISchemaManagedAttribute::class . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + + $legacy->addAttribute($attribute); + } + } + } +} diff --git a/src/Schema/LegacySchemaInformation.php b/src/Schema/LegacySchemaInformation.php new file mode 100644 index 000000000..1198eb587 --- /dev/null +++ b/src/Schema/LegacySchemaInformation.php @@ -0,0 +1,69 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema; + +use MetaModels\Attribute\IAttribute; + +/** + * This schema information is used for bc to MetaModels 2.0 interfaces. + * + * @deprecated Since 2.1 - to be removed in 3.0 + */ +class LegacySchemaInformation implements SchemaInformationInterface +{ + /** + * The attributes. + * + * @var IAttribute[] + */ + private $attributes = []; + + /** + * {@inheritDoc} + */ + public function getName(): string + { + return static::class; + } + + /** + * Add an attribute + * + * @param IAttribute $attribute The attribute to add. + * + * @return void + */ + public function addAttribute(IAttribute $attribute): void + { + $this->attributes[] = $attribute; + } + + /** + * Retrieve attributes. + * + * @return IAttribute[] + */ + public function getAttributes(): array + { + return $this->attributes; + } +} diff --git a/tests/Schema/LegacySchemaGeneratorTest.php b/tests/Schema/LegacySchemaGeneratorTest.php new file mode 100644 index 000000000..0f754052d --- /dev/null +++ b/tests/Schema/LegacySchemaGeneratorTest.php @@ -0,0 +1,126 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Schema\Doctrine; + +use MetaModels\Attribute\IAttribute; +use MetaModels\Attribute\IComplex; +use MetaModels\Attribute\IInternal; +use MetaModels\Attribute\ISchemaManagedAttribute; +use MetaModels\Attribute\ISimple; +use MetaModels\IFactory; +use MetaModels\IMetaModel; +use MetaModels\Information\AttributeInformation; +use MetaModels\Information\MetaModelCollectionInterface; +use MetaModels\Information\MetaModelInformation; +use MetaModels\Schema\LegacySchemaGenerator; +use MetaModels\Schema\LegacySchemaInformation; +use MetaModels\Schema\SchemaInformation; +use PHPUnit\Framework\TestCase; + +/** + * This tests the doctrine schema. + * + * @covers \MetaModels\Schema\LegacySchemaGenerator + */ +class LegacySchemaGeneratorTest extends TestCase +{ + /** + * Test the instantiation. + * + * @return void + */ + public function testInstantiation(): void + { + $instance = new LegacySchemaGenerator($this->getMockForAbstractClass(IFactory::class)); + + $this->assertInstanceOf(LegacySchemaGenerator::class, $instance); + } + + /** + * Test the generate method. + * + * @return void + */ + public function testGenerateAddsSchemaInformationIfNotFound(): void + { + $instance = new LegacySchemaGenerator($this->getMockForAbstractClass(IFactory::class)); + $information = new SchemaInformation(); + $collection = $this->getMockForAbstractClass(MetaModelCollectionInterface::class); + + $collection->expects($this->once())->method('getIterator')->willReturn(new \ArrayIterator([])); + + $instance->generate($information, $collection); + + $this->assertTrue($information->has(LegacySchemaInformation::class)); + } + + /** + * Test the generate method. + * + * @return void + */ + public function testGenerate(): void + { + $information = new SchemaInformation(); + $collection = $this->getMockForAbstractClass(MetaModelCollectionInterface::class); + + $attribute1 = $this->getMockForAbstractClass(ISimple::class); + $attribute2 = $this->getMockForAbstractClass(IComplex::class); + $attribute3 = $this->getMockForAbstractClass(ISchemaManagedAttribute::class); + $attribute4 = $this->getMockForAbstractClass(IInternal::class); + $metaModel = $this->mockMetaModel([$attribute1, $attribute2, $attribute3, $attribute4]); + + $factory = $this->getMockForAbstractClass(IFactory::class); + $factory->expects($this->once())->method('getMetaModel')->with('mm_test')->willReturn($metaModel); + + $collection->expects($this->once())->method('getIterator')->willReturn(new \ArrayIterator([ + $metaModelInformation = new MetaModelInformation('mm_test') + ])); + $metaModelInformation->addAttribute(new AttributeInformation('test', 'test_type')); + + $instance = new LegacySchemaGenerator($factory); + + $instance->generate($information, $collection); + + $this->assertTrue($information->has(LegacySchemaInformation::class)); + $this->assertSame( + [$attribute1, $attribute2], + $information->get(LegacySchemaInformation::class)->getAttributes() + ); + } + + /** + * Mock a MetaModel with the passed attributes. + * + * @param IAttribute[] $attributes The attributes. + * + * @return IMetaModel + */ + private function mockMetaModel(array $attributes) + { + $metaModel = $this->getMockForAbstractClass(IMetaModel::class); + + $metaModel->expects($this->once())->method('getAttributes')->willReturn($attributes); + + return $metaModel; + } +} diff --git a/tests/Schema/LegacySchemaInformationTest.php b/tests/Schema/LegacySchemaInformationTest.php new file mode 100644 index 000000000..942052be6 --- /dev/null +++ b/tests/Schema/LegacySchemaInformationTest.php @@ -0,0 +1,66 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Schema\Doctrine; + +use MetaModels\Attribute\IAttribute; +use MetaModels\Attribute\IComplex; +use MetaModels\Attribute\ISimple; +use MetaModels\Schema\LegacySchemaInformation; +use PHPUnit\Framework\TestCase; + +/** + * This tests the legacy schema. + * + * @covers \MetaModels\Schema\LegacySchemaInformation + */ +class LegacySchemaInformationTest extends TestCase +{ + /** + * Test the instantiation. + * + * @return void + */ + public function testInstantiation(): void + { + $instance = new LegacySchemaInformation(); + + $this->assertInstanceOf(LegacySchemaInformation::class, $instance); + $this->assertSame(LegacySchemaInformation::class, $instance->getName()); + $this->assertSame([], $instance->getAttributes()); + } + + /** + * Test adding of attributes. + * + * @return void + */ + public function testAddAttributes(): void + { + $instance = new LegacySchemaInformation(); + + $instance->addAttribute($attribute1 = $this->getMockForAbstractClass(ISimple::class)); + $instance->addAttribute($attribute2 = $this->getMockForAbstractClass(IComplex::class)); + $instance->addAttribute($attribute3 = $this->getMockForAbstractClass(IAttribute::class)); + + $this->assertSame([$attribute1, $attribute2, $attribute3], $instance->getAttributes()); + } +} From 369ba798ff0b7bcadf53cf48bc068cc20299da60 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Wed, 30 Jan 2019 03:54:21 +0100 Subject: [PATCH 096/224] Fix class name in deprecations --- src/Attribute/Base.php | 6 +++--- src/Attribute/BaseSimple.php | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 63c96d92e..f0a5ad84d 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -317,7 +317,7 @@ public function handleMetaChange($strMetaName, $varNewValue) // @codingStandardsIgnoreStart @trigger_error( - 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd @@ -344,7 +344,7 @@ public function destroyAUX() // @codingStandardsIgnoreStart @trigger_error( - 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd @@ -370,7 +370,7 @@ public function initializeAUX() // @codingStandardsIgnoreStart @trigger_error( - 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd diff --git a/src/Attribute/BaseSimple.php b/src/Attribute/BaseSimple.php index c081a9623..a4d6c3645 100644 --- a/src/Attribute/BaseSimple.php +++ b/src/Attribute/BaseSimple.php @@ -290,7 +290,7 @@ public function destroyAUX() // @codingStandardsIgnoreStart @trigger_error( - 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd @@ -320,7 +320,7 @@ public function initializeAUX() // @codingStandardsIgnoreStart @trigger_error( - 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd @@ -352,7 +352,7 @@ public function createColumn() // @codingStandardsIgnoreStart @trigger_error( - 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd @@ -387,7 +387,7 @@ public function deleteColumn() // @codingStandardsIgnoreStart @trigger_error( - 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd @@ -424,7 +424,7 @@ public function renameColumn($strNewColumnName) // @codingStandardsIgnoreStart @trigger_error( - 'Class "' . __CLASS__ . '" should be changed to "' . ISchemaManagedAttribute::class . '".', + 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd From 248e0620e2bc2267e74253714cee2e3f254f2a7d Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Wed, 30 Jan 2019 04:02:39 +0100 Subject: [PATCH 097/224] Add legacy schema manager --- src/CoreBundle/Resources/config/services.yml | 4 + src/Schema/LegacySchemaManager.php | 94 ++++++++++++++++++++ tests/Schema/LegacySchemaManagerTest.php | 89 ++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 src/Schema/LegacySchemaManager.php create mode 100644 tests/Schema/LegacySchemaManagerTest.php diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index c0351c6d0..a3cc54ef1 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -206,6 +206,10 @@ services: tags: - { name: 'metamodels.schema-generator' } + MetaModels\Schema\LegacySchemaManager: + tags: + - { name: 'metamodels.schema-manager', priority: -100 } + MetaModels\Schema\Doctrine\DoctrineSchemaGenerator: arguments: - [] diff --git a/src/Schema/LegacySchemaManager.php b/src/Schema/LegacySchemaManager.php new file mode 100644 index 000000000..1c127563b --- /dev/null +++ b/src/Schema/LegacySchemaManager.php @@ -0,0 +1,94 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Schema; + +use Doctrine\DBAL\Exception\NonUniqueFieldNameException; + +/** + * This is the legacy schema manager used for bc reasons. + * + * @deprecated Since 2.1 - to be removed in 3.0 + */ +class LegacySchemaManager implements SchemaManagerInterface +{ + /** + * {@inheritDoc} + */ + public function preprocess(SchemaInformation $information): void + { + // No-op. + } + + /** + * {@inheritDoc} + */ + public function process(SchemaInformation $information): void + { + if (!$information->has(LegacySchemaInformation::class)) { + return; + } + /** @var LegacySchemaInformation $legacySchema */ + $legacySchema = $information->get(LegacySchemaInformation::class); + + foreach ($legacySchema->getAttributes() as $attribute) { + try { + $attribute->initializeAUX(); + } catch (\Throwable $exception) { + // Transcribe known exceptions. + switch (true) { + case $exception instanceof NonUniqueFieldNameException: + if (preg_match( + '/SQLSTATE\[42S21\]: Column already exists: 1060 Duplicate column name \'(?P.+)\'/', + $exception->getMessage(), + $matches + )) { + // @codingStandardsIgnoreStart + @trigger_error('Column already exists: "' . $matches['name'] . '"'); + // @codingStandardsIgnoreEnd + continue 2; + } + default: + } + + // @codingStandardsIgnoreStart + @trigger_error( + sprintf( + 'Ignored exception "%1$s" for attribute "%2$s": %3$s', + get_class($exception), + $attribute->getColName(), + $exception->getMessage() + ), + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + } + } + } + + /** + * {@inheritDoc} + */ + public function postprocess(SchemaInformation $information): void + { + // No-op. + } +} diff --git a/tests/Schema/LegacySchemaManagerTest.php b/tests/Schema/LegacySchemaManagerTest.php new file mode 100644 index 000000000..818cf211e --- /dev/null +++ b/tests/Schema/LegacySchemaManagerTest.php @@ -0,0 +1,89 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types = 1); + +namespace MetaModels\Test\Schema\Doctrine; + +use MetaModels\Attribute\IAttribute; +use MetaModels\Attribute\IComplex; +use MetaModels\Attribute\ISimple; +use MetaModels\Schema\LegacySchemaInformation; +use MetaModels\Schema\LegacySchemaManager; +use MetaModels\Schema\SchemaInformation; +use PHPUnit\Framework\TestCase; + +/** + * This tests the doctrine schema. + * + * @covers \MetaModels\Schema\LegacySchemaManager + */ +class LegacySchemaManagerTest extends TestCase +{ + /** + * Test the instantiation. + * + * @return void + */ + public function testInstantiation(): void + { + $instance = new LegacySchemaManager(); + + $this->assertInstanceOf(LegacySchemaManager::class, $instance); + } + + /** + * Test the generate method. + * + * @return void + */ + public function testIgnoresIfNotFound(): void + { + $instance = new LegacySchemaManager(); + $information = $this->getMockBuilder(SchemaInformation::class)->getMock(); + $information->expects($this->once())->method('has')->with(LegacySchemaInformation::class)->willReturn(false); + $information->expects($this->never())->method('get'); + + $instance->process($information); + } + + /** + * Test the process method. + * + * @return void + */ + public function testProcess(): void + { + $information = new SchemaInformation(); + $legacy = new LegacySchemaInformation(); + $information->add($legacy); + + $legacy->addAttribute($attribute1 = $this->getMockForAbstractClass(ISimple::class)); + $legacy->addAttribute($attribute2 = $this->getMockForAbstractClass(IComplex::class)); + $legacy->addAttribute($attribute3 = $this->getMockForAbstractClass(IAttribute::class)); + + $attribute1->expects($this->once())->method('initializeAUX'); + $attribute2->expects($this->once())->method('initializeAUX'); + $attribute3->expects($this->once())->method('initializeAUX')->willThrowException(new \RuntimeException()); + + $instance = new LegacySchemaManager(); + + $instance->process($information); + } +} From 8c303c5e490c0f278e7c57df95118631f271c0e4 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Wed, 30 Jan 2019 04:24:50 +0100 Subject: [PATCH 098/224] Add SchemaManagerInterface::validate() --- src/Schema/Doctrine/DoctrineSchemaManager.php | 29 +++++++++++ .../Doctrine/DoctrineSchemaManipulator.php | 41 +++++++++++++-- .../Doctrine/SchemaProcessorInterface.php | 7 +++ src/Schema/LegacySchemaManager.php | 23 +++++++++ src/Schema/SchemaManager.php | 13 +++++ src/Schema/SchemaManagerInterface.php | 9 ++++ .../Doctrine/DoctrineSchemaManagerTest.php | 51 +++++++++++++++++++ tests/Schema/LegacySchemaManagerTest.php | 31 +++++++++++ tests/Schema/SchemaManagerTest.php | 18 +++++++ 9 files changed, 219 insertions(+), 3 deletions(-) diff --git a/src/Schema/Doctrine/DoctrineSchemaManager.php b/src/Schema/Doctrine/DoctrineSchemaManager.php index 632322af6..4c1528617 100644 --- a/src/Schema/Doctrine/DoctrineSchemaManager.php +++ b/src/Schema/Doctrine/DoctrineSchemaManager.php @@ -107,4 +107,33 @@ public function postprocess(SchemaInformation $information): void $postProcessor->process(); } } + + /** + * {@inheritDoc} + */ + public function validate(SchemaInformation $information): array + { + // If no information added, exit. + if (!$information->has(DoctrineSchemaInformation::class)) { + return []; + } + + $tasks = []; + /** @var DoctrineSchemaInformation $doctrine */ + $doctrine = $information->get(DoctrineSchemaInformation::class); + + $tasks[] = array_map(function ($preProcessor) { + return (string) $preProcessor; + }, $doctrine->getPreProcessors()); + + $tasks[1] = array_map(function (string $query) { + return 'Execute SQL: ' . $query; + }, $this->manipulator->getScript($doctrine)); + + $tasks[] = array_map(function ($postProcessor) { + return (string) $postProcessor; + }, $doctrine->getPostProcessors()); + + return array_merge(...$tasks); + } } diff --git a/src/Schema/Doctrine/DoctrineSchemaManipulator.php b/src/Schema/Doctrine/DoctrineSchemaManipulator.php index c050d871e..0b5782d1a 100644 --- a/src/Schema/Doctrine/DoctrineSchemaManipulator.php +++ b/src/Schema/Doctrine/DoctrineSchemaManipulator.php @@ -54,14 +54,49 @@ public function __construct(Connection $connection) * @return void */ public function updateDatabase(DoctrineSchemaInformation $schemaInformation): void + { + foreach ($this->buildChangeSet($schemaInformation) as $query) { + $this->connection->exec($query); + } + } + + /** + * Obtain the list of tasks being performed. + * + * @param DoctrineSchemaInformation $schemaInformation The schema information. + * + * @return string[] + */ + public function getScript(DoctrineSchemaInformation $schemaInformation): array + { + return $this->buildChangeSet($schemaInformation); + } + + /** + * Build the change set. + * + * @param DoctrineSchemaInformation $schemaInformation The schema information. + * + * @return string[] + */ + private function buildChangeSet(DoctrineSchemaInformation $schemaInformation): array { $manager = $this->connection->getSchemaManager(); $current = $manager->createSchema(); $diff = Comparator::compareSchemas($current, $schemaInformation->getSchema()); - $queries = $diff->toSaveSql($this->connection->getDatabasePlatform()); - foreach ($queries as $query) { - $this->connection->exec($query); + foreach ($diff->changedTables as $changedTable) { + foreach ($changedTable->removedColumns as $removedColumn) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Ignoring drop of column "' . $removedColumn->getName(), + E_USER_WARNING + ); + // @codingStandardsIgnoreEnd + } + $changedTable->removedColumns = []; } + + return $diff->toSaveSql($this->connection->getDatabasePlatform()); } } diff --git a/src/Schema/Doctrine/SchemaProcessorInterface.php b/src/Schema/Doctrine/SchemaProcessorInterface.php index 2c3ef8bbf..c695a95fd 100644 --- a/src/Schema/Doctrine/SchemaProcessorInterface.php +++ b/src/Schema/Doctrine/SchemaProcessorInterface.php @@ -32,4 +32,11 @@ interface SchemaProcessorInterface * @return void */ public function process(): void; + + /** + * Get a string representation of the task performed. + * + * @return string + */ + public function __toString(); } diff --git a/src/Schema/LegacySchemaManager.php b/src/Schema/LegacySchemaManager.php index 1c127563b..508f9cb7b 100644 --- a/src/Schema/LegacySchemaManager.php +++ b/src/Schema/LegacySchemaManager.php @@ -91,4 +91,27 @@ public function postprocess(SchemaInformation $information): void { // No-op. } + + /** + * {@inheritDoc} + */ + public function validate(SchemaInformation $information): array + { + if (!$information->has(LegacySchemaInformation::class)) { + return []; + } + /** @var LegacySchemaInformation $legacySchema */ + $legacySchema = $information->get(LegacySchemaInformation::class); + + $tasks = []; + foreach ($legacySchema->getAttributes() as $attribute) { + $tasks[] = sprintf( + '(Re-)Initialize attribute "%1$s" (type: "%2$s") via legacy method.', + $attribute->getColName(), + $attribute->get('type') + ); + } + + return $tasks; + } } diff --git a/src/Schema/SchemaManager.php b/src/Schema/SchemaManager.php index b5bd1601e..026cc3422 100644 --- a/src/Schema/SchemaManager.php +++ b/src/Schema/SchemaManager.php @@ -75,4 +75,17 @@ public function postprocess(SchemaInformation $information): void $manager->postprocess($information); } } + + /** + * {@inheritDoc} + */ + public function validate(SchemaInformation $information): array + { + $tasks = []; + foreach ($this->managers as $manager) { + $tasks[] = $manager->validate($information); + } + + return array_merge(...$tasks); + } } diff --git a/src/Schema/SchemaManagerInterface.php b/src/Schema/SchemaManagerInterface.php index 61363692c..f83d7dcb8 100644 --- a/src/Schema/SchemaManagerInterface.php +++ b/src/Schema/SchemaManagerInterface.php @@ -52,4 +52,13 @@ public function process(SchemaInformation $information): void; * @return void */ public function postprocess(SchemaInformation $information): void; + + /** + * List the tasks that will be performed for the passed information + * + * @param SchemaInformation $information The schema information. + * + * @return string[] + */ + public function validate(SchemaInformation $information): array; } diff --git a/tests/Schema/Doctrine/DoctrineSchemaManagerTest.php b/tests/Schema/Doctrine/DoctrineSchemaManagerTest.php index 7aab5dcfd..90a19c690 100644 --- a/tests/Schema/Doctrine/DoctrineSchemaManagerTest.php +++ b/tests/Schema/Doctrine/DoctrineSchemaManagerTest.php @@ -173,6 +173,57 @@ public function testPostprocessSkipsIfNothingToDo(): void $instance->postprocess($schemaInformation); } + /** + * Test the validation + * + * @return void + */ + public function testValidate(): void + { + $manipulator = $this + ->getMockBuilder(DoctrineSchemaManipulator::class) + ->disableOriginalConstructor() + ->getMock(); + + $manipulator->expects($this->once())->method('getScript')->willReturn(['query1', 'query2']); + + $processor1 = $this->getMockForAbstractClass(SchemaProcessorInterface::class); + $processor2 = $this->getMockForAbstractClass(SchemaProcessorInterface::class); + $processor1->expects($this->once())->method('__toString')->willReturn('pre1'); + $processor2->expects($this->once())->method('__toString')->willReturn('pre2'); + $processor3 = $this->getMockForAbstractClass(SchemaProcessorInterface::class); + $processor4 = $this->getMockForAbstractClass(SchemaProcessorInterface::class); + $processor3->expects($this->once())->method('__toString')->willReturn('post1'); + $processor4->expects($this->once())->method('__toString')->willReturn('post2'); + + /** @var MockObject|DoctrineSchemaInformation $information */ + $information = $this + ->getMockBuilder(DoctrineSchemaInformation::class) + ->disableOriginalConstructor() + ->getMock(); + $information + ->expects($this->once()) + ->method('getPreProcessors') + ->willReturn([$processor1, $processor2]); + $information + ->expects($this->once()) + ->method('getPostProcessors') + ->willReturn([$processor3, $processor4]); + + $schemaInformation = $this->mockSchemaInformation($information); + + $instance = $this->createSchemaManager($manipulator); + + $this->assertSame([ + 'pre1', + 'pre2', + 'Execute SQL: query1', + 'Execute SQL: query2', + 'post1', + 'post2', + ], $instance->validate($schemaInformation)); + } + /** * Create a schema manager instance. * diff --git a/tests/Schema/LegacySchemaManagerTest.php b/tests/Schema/LegacySchemaManagerTest.php index 818cf211e..4496a4dfc 100644 --- a/tests/Schema/LegacySchemaManagerTest.php +++ b/tests/Schema/LegacySchemaManagerTest.php @@ -86,4 +86,35 @@ public function testProcess(): void $instance->process($information); } + + /** + * Test the validate method. + * + * @return void + */ + public function testValidate(): void + { + $information = new SchemaInformation(); + $legacy = new LegacySchemaInformation(); + $information->add($legacy); + + $legacy->addAttribute($attribute1 = $this->getMockForAbstractClass(ISimple::class)); + $legacy->addAttribute($attribute2 = $this->getMockForAbstractClass(IComplex::class)); + $legacy->addAttribute($attribute3 = $this->getMockForAbstractClass(IAttribute::class)); + + $attribute1->expects($this->once())->method('getColName')->willReturn('attribute1'); + $attribute1->expects($this->once())->method('get')->with('type')->willReturn('type1'); + $attribute2->expects($this->once())->method('getColName')->willReturn('attribute2'); + $attribute2->expects($this->once())->method('get')->with('type')->willReturn('type2'); + $attribute3->expects($this->once())->method('getColName')->willReturn('attribute3'); + $attribute3->expects($this->once())->method('get')->with('type')->willReturn('type3'); + + $instance = new LegacySchemaManager(); + + $this->assertSame([ + '(Re-)Initialize attribute "attribute1" (type: "type1") via legacy method.', + '(Re-)Initialize attribute "attribute2" (type: "type2") via legacy method.', + '(Re-)Initialize attribute "attribute3" (type: "type3") via legacy method.', + ], $instance->validate($information)); + } } diff --git a/tests/Schema/SchemaManagerTest.php b/tests/Schema/SchemaManagerTest.php index 715740110..d4083049d 100644 --- a/tests/Schema/SchemaManagerTest.php +++ b/tests/Schema/SchemaManagerTest.php @@ -98,4 +98,22 @@ public function testPostcess(): void $instance->postprocess($information); } + + /** + * Test validation. + * + * @return void + */ + public function testValidate(): void + { + $manager1 = $this->getMockForAbstractClass(SchemaManagerInterface::class); + $manager2 = $this->getMockForAbstractClass(SchemaManagerInterface::class); + $information = new SchemaInformation(); + $manager1->expects($this->once())->method('validate')->with($information)->willReturn(['1', '2']); + $manager2->expects($this->once())->method('validate')->with($information)->willReturn(['3', '4']); + + $instance = new SchemaManager([$manager1, $manager2]); + + $this->assertSame(['1', '2', '3', '4'], $instance->validate($information)); + } } From 03b4f741f0ea421c17432c73fedcc01ac28d5704 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Wed, 30 Jan 2019 04:26:39 +0100 Subject: [PATCH 099/224] Add console command for updating the schema --- .../Command/SchemaValidatorCommand.php | 102 ++++++++++++++++++ src/CoreBundle/Resources/config/services.yml | 8 ++ 2 files changed, 110 insertions(+) create mode 100644 src/CoreBundle/Command/SchemaValidatorCommand.php diff --git a/src/CoreBundle/Command/SchemaValidatorCommand.php b/src/CoreBundle/Command/SchemaValidatorCommand.php new file mode 100644 index 000000000..6af0ecdcf --- /dev/null +++ b/src/CoreBundle/Command/SchemaValidatorCommand.php @@ -0,0 +1,102 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\Command; + +use MetaModels\InformationProvider\MetaModelInformationCollector; +use MetaModels\Schema\SchemaGenerator; +use MetaModels\Schema\SchemaInformation; +use MetaModels\Schema\SchemaManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * This validates the schema of the current installation. + */ +class SchemaValidatorCommand extends Command +{ + /** + * The information collector. + * + * @var MetaModelInformationCollector + */ + private $collector; + + /** + * The schema generator. + * + * @var SchemaGenerator + */ + private $generator; + + /** + * The schema manager. + * + * @var SchemaManager + */ + private $manager; + + /** + * Create a new instance. + * + * @param MetaModelInformationCollector $collector + * @param SchemaGenerator $generator + * @param SchemaManager $manager + */ + public function __construct( + MetaModelInformationCollector $collector, + SchemaGenerator $generator, + SchemaManager $manager + ) { + $this->collector = $collector; + $this->generator = $generator; + $this->manager = $manager; + parent::__construct('metamodels:schema-update'); + } + + /** + * {@inheritDoc} + */ + protected function configure() + { + parent::configure(); + $this->addOption('force', null, InputOption::VALUE_NONE, 'Perform the update'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->generator->generate($information = new SchemaInformation(), $this->collector->getCollection()); + + if ($input->getOption('force')) { + $this->manager->preprocess($information); + $this->manager->process($information); + $this->manager->postprocess($information); + return; + } + + foreach ($this->manager->validate($information) as $item) { + $output->writeln($item); + } + } +} diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index a3cc54ef1..d1f188e66 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -228,6 +228,14 @@ services: tags: - { name: 'metamodels.schema-manipulator' } + MetaModels\CoreBundle\Command\SchemaValidatorCommand: + arguments: + - '@MetaModels\InformationProvider\MetaModelInformationCollector' + - '@MetaModels\Schema\SchemaGenerator' + - '@MetaModels\Schema\SchemaManager' + tags: + - { name: 'console.command' } + MetaModels\Schema\Doctrine\SystemColumnSchemaGenerator: tags: - { name: 'metamodels.schema-generator.doctrine' } From f475dd72efceabd8f0e78b2e116665c478e2bb87 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Fri, 1 Feb 2019 17:31:26 +0100 Subject: [PATCH 100/224] Fix some return types --- src/Information/MetaModelCollection.php | 2 +- src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Information/MetaModelCollection.php b/src/Information/MetaModelCollection.php index 4f4c03fe6..f1227a2c7 100644 --- a/src/Information/MetaModelCollection.php +++ b/src/Information/MetaModelCollection.php @@ -92,7 +92,7 @@ public function get(string $name): MetaModelInformationInterface /** * {@inheritDoc} */ - public function getIterator() + public function getIterator(): \Traversable { // Cannot "yield from" here as we have the names as key. /** @noinspection YieldFromCanBeUsedInspection */ diff --git a/src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php b/src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php index 1d99dbe60..87428cbd1 100644 --- a/src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php +++ b/src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php @@ -55,9 +55,9 @@ public function generate(DoctrineSchemaInformation $schema, MetaModelCollectionI * @param Table $tableSchema The table schema. * @param AttributeInformation $attribute The attribute to generate. * - * @return mixed + * @return void */ - abstract protected function generateAttribute(Table $tableSchema, AttributeInformation $attribute); + abstract protected function generateAttribute(Table $tableSchema, AttributeInformation $attribute): void; /** * Obtain the type name. From 87c4991e4511953e93d1b5a04f0195c2db127943 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Sat, 26 Jan 2019 15:01:18 +0100 Subject: [PATCH 101/224] Initial draft of schema generator handling --- .../CompilerPass/CollectDoctrineSchemaGeneratorsPass.php | 2 ++ .../CompilerPass/CollectSchemaGeneratorsPass.php | 2 ++ .../CompilerPass/CollectSchemaManagersPass.php | 1 + 3 files changed, 5 insertions(+) diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php index b3864ddf0..8584f401f 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php @@ -25,6 +25,8 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; /** * This pass adds the tagged schema generators to the doctrine engine. diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php index 7913a79fd..defff9101 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php @@ -25,6 +25,8 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; /** * This pass adds the tagged schema generators. diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php index 6fef35b94..e1c72912b 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php @@ -25,6 +25,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; /** * This pass adds the tagged schema managers. From a4fe9bae72933a6013f1b25cc688ee15c5cb1c38 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Tue, 29 Jan 2019 23:52:03 +0100 Subject: [PATCH 102/224] Priorize tagged services --- .../CompilerPass/CollectDoctrineSchemaGeneratorsPass.php | 2 -- .../CompilerPass/CollectSchemaGeneratorsPass.php | 2 -- .../CompilerPass/CollectSchemaManagersPass.php | 1 - 3 files changed, 5 deletions(-) diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php index 8584f401f..b3864ddf0 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php @@ -25,8 +25,6 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; /** * This pass adds the tagged schema generators to the doctrine engine. diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php index defff9101..7913a79fd 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php @@ -25,8 +25,6 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; /** * This pass adds the tagged schema generators. diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php index e1c72912b..6fef35b94 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php @@ -25,7 +25,6 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; /** * This pass adds the tagged schema managers. From fcea520c80667fa905a60a46c76bc5b9e5daee64 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 11 Jul 2022 17:42:41 +0200 Subject: [PATCH 103/224] Fix deprecated method --- src/Schema/Doctrine/DoctrineSchemaManipulator.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Schema/Doctrine/DoctrineSchemaManipulator.php b/src/Schema/Doctrine/DoctrineSchemaManipulator.php index 0b5782d1a..6d0b2224a 100644 --- a/src/Schema/Doctrine/DoctrineSchemaManipulator.php +++ b/src/Schema/Doctrine/DoctrineSchemaManipulator.php @@ -56,7 +56,7 @@ public function __construct(Connection $connection) public function updateDatabase(DoctrineSchemaInformation $schemaInformation): void { foreach ($this->buildChangeSet($schemaInformation) as $query) { - $this->connection->exec($query); + $this->connection->executeStatement($query); } } @@ -78,10 +78,11 @@ public function getScript(DoctrineSchemaInformation $schemaInformation): array * @param DoctrineSchemaInformation $schemaInformation The schema information. * * @return string[] + * @throws \Doctrine\DBAL\Exception */ private function buildChangeSet(DoctrineSchemaInformation $schemaInformation): array { - $manager = $this->connection->getSchemaManager(); + $manager = $this->connection->createSchemaManager(); $current = $manager->createSchema(); $diff = Comparator::compareSchemas($current, $schemaInformation->getSchema()); From f4585d2e300dbb16ccb123b6515c112bb324071b Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Wed, 14 Sep 2022 09:14:31 +0200 Subject: [PATCH 104/224] Add schema listener for Doctrine schema generating We now support the stock doctrine schema generating as used by doctrine/orm etc. --- .../EventListener/DoctrineSchemaListener.php | 186 ++++++++++++++++++ src/CoreBundle/Resources/config/listeners.yml | 6 + 2 files changed, 192 insertions(+) create mode 100644 src/CoreBundle/EventListener/DoctrineSchemaListener.php diff --git a/src/CoreBundle/EventListener/DoctrineSchemaListener.php b/src/CoreBundle/EventListener/DoctrineSchemaListener.php new file mode 100644 index 000000000..f6c04a720 --- /dev/null +++ b/src/CoreBundle/EventListener/DoctrineSchemaListener.php @@ -0,0 +1,186 @@ + + * @copyright 2012-2022 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\EventListener; + +use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Schema\Table; +use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs; +use LogicException; +use MetaModels\InformationProvider\MetaModelInformationCollector; +use MetaModels\Schema\Doctrine\DoctrineSchemaInformation; +use MetaModels\Schema\SchemaGenerator; +use MetaModels\Schema\SchemaInformation; + +final class DoctrineSchemaListener +{ + private SchemaGenerator $generator; + + private MetaModelInformationCollector $collector; + + public function __construct( + SchemaGenerator $generator, + MetaModelInformationCollector $collector + ) { + $this->generator = $generator; + $this->collector = $collector; + } + + /** + * Adds the MetaModels database schema information to the Doctrine schema. + */ + public function postGenerateSchema(GenerateSchemaEventArgs $event): void + { + $this->generator->generate($information = new SchemaInformation(), $this->collector->getCollection()); + + $contaoSchema = $event->getSchema(); + if ($schema = $information->get(DoctrineSchemaInformation::class)) { + if (!$schema instanceof DoctrineSchemaInformation) { + throw new LogicException('Invalid schema information obtained.'); + } + $this->mergeSchema($schema, $contaoSchema); + } + } + + private function mergeSchema(DoctrineSchemaInformation $source, Schema $target): void + { + foreach ($source->getSchema()->getTables() as $sourceTable) { + $tableName = $sourceTable->getName(); + if (!$target->hasTable($tableName)) { + $target->createTable($tableName); + } + $targetTable = $target->getTable($tableName); + $this->mergeTable($sourceTable, $targetTable); + } + } + + private function mergeTable(Table $sourceTable, Table $targetTable): void + { + $this->mergeColumns($sourceTable, $targetTable); + $this->mergeIndexes($sourceTable, $targetTable); + $this->mergeUniqueConstraints($sourceTable, $targetTable); + $this->mergeForeignKeyConstraints($sourceTable, $targetTable); + foreach ($sourceTable->getOptions() as $optionName => $optionValue) { + $targetTable->addOption($optionName, $optionValue); + } + + // NOTE: We are explicitely not copying the property: SchemaConfig|null Table::$_schemaConfig + } + + private function mergeColumns(Table $sourceTable, Table $targetTable): void + { + foreach ($sourceTable->getColumns() as $sourceColumn) { + $name = $sourceColumn->getName(); + $options = [ + 'default' => $sourceColumn->getDefault(), + 'notnull' => $sourceColumn->getNotnull(), + 'length' => $sourceColumn->getLength(), + 'precision' => $sourceColumn->getPrecision(), + 'scale' => $sourceColumn->getScale(), + 'fixed' => $sourceColumn->getFixed(), + 'unsigned' => $sourceColumn->getUnsigned(), + 'autoincrement' => $sourceColumn->getAutoincrement(), + 'columnDefinition' => $sourceColumn->getColumnDefinition(), + 'comment' => $sourceColumn->getComment(), + ]; + $platformOptions = $sourceColumn->getPlatformOptions(); + $customSchemaOptions = $sourceColumn->getCustomSchemaOptions(); + + if ($targetTable->hasColumn($name)) { + $tmpColumn = $targetTable->getColumn($name); + $platformOptions = array_merge($tmpColumn->getPlatformOptions(), $platformOptions); + $customSchemaOptions = array_merge($tmpColumn->getCustomSchemaOptions(), $customSchemaOptions); + } + + $targetTable + ->addColumn($name, $sourceColumn->getType()->getName(), $options) + ->setPlatformOptions($platformOptions) + ->setCustomSchemaOptions($customSchemaOptions); + + } + } + + private function mergeIndexes(Table $sourceTable, Table $targetTable): void + { + foreach ($sourceTable->getIndexes() as $source) { + $name = $source->getName(); + $columns = $source->getColumns(); + $flags = $source->getFlags(); + $options = $source->getOptions(); + $unique = $source->isUnique(); + $primary = $source->isPrimary(); + if ($targetTable->hasIndex($name)) { + $tmpIndex = $targetTable->getIndex($name); + $targetTable->dropIndex($name); + $columns = array_merge($tmpIndex->getColumns(), $columns); + $flags = array_merge($tmpIndex->getFlags(), $flags); + $options = array_merge($tmpIndex->getOptions(), $options); + $unique = $unique || $source->isUnique(); + $primary = $primary || $source->isPrimary(); + } + if ($primary) { + $targetTable->setPrimaryKey($columns, $name); + continue; + } + if ($unique) { + $targetTable->addUniqueIndex($columns, $name, $options); + continue; + } + $targetTable->addIndex($columns, $name, $flags, $options); + } + } + + private function mergeUniqueConstraints(Table $sourceTable, Table $targetTable): void + { + foreach ($sourceTable->getUniqueConstraints() as $uniqueConstraint) { + $name = $uniqueConstraint->getName(); + $columns = $uniqueConstraint->getColumns(); + $flags = $uniqueConstraint->getFlags(); + $options = $uniqueConstraint->getOptions(); + if ($targetTable->hasUniqueConstraint($name)) { + $tmpUniqueConstraint = $targetTable->getUniqueConstraint($name); + $targetTable->removeUniqueConstraint($name); + $columns = array_merge($tmpUniqueConstraint->getColumns(), $columns); + $flags = array_merge($tmpUniqueConstraint->getFlags(), $flags); + $options = array_merge($tmpUniqueConstraint->getOptions(), $options); + } + + $targetTable->addUniqueConstraint($columns, $name, $flags, $options); + } + } + + private function mergeForeignKeyConstraints(Table $sourceTable, Table $targetTable): void + { + foreach ($sourceTable->getForeignKeys() as $foreignKey) { + $name = $foreignKey->getName(); + $foreignTable = $foreignKey->getForeignTableName(); + $localColumns = $foreignKey->getLocalColumns(); + $foreignColumns = $foreignKey->getForeignColumns(); + $options = $foreignKey->getOptions(); + if ($targetTable->hasForeignKey($name)) { + $tmpUniqueConstraint = $targetTable->getForeignKey($name); + $targetTable->removeUniqueConstraint($name); + $localColumns = array_merge($tmpUniqueConstraint->getLocalColumns(), $localColumns); + $foreignColumns = array_merge($tmpUniqueConstraint->getForeignColumns(), $foreignColumns); + $options = array_merge($tmpUniqueConstraint->getOptions(), $options); + } + $targetTable->addForeignKeyConstraint($foreignTable, $localColumns, $foreignColumns, $options, $name); + } + } +} diff --git a/src/CoreBundle/Resources/config/listeners.yml b/src/CoreBundle/Resources/config/listeners.yml index 1c9322314..fe7851234 100644 --- a/src/CoreBundle/Resources/config/listeners.yml +++ b/src/CoreBundle/Resources/config/listeners.yml @@ -99,6 +99,12 @@ services: + MetaModels\CoreBundle\EventListener\DoctrineSchemaListener: + arguments: + $generator: '@MetaModels\Schema\SchemaGenerator' + $collector: '@MetaModels\InformationProvider\MetaModelInformationCollector' + tags: + - { name: doctrine.event_listener, event: postGenerateSchema } metamodels.backend.auth.listener: class: MetaModels\CoreBundle\EventListener\UserListener From 97acaeb99c87368762dbbd09a197a64c8a51404b Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Mon, 24 Oct 2022 16:17:31 +0200 Subject: [PATCH 105/224] Fix depecation in validator command --- .../Command/SchemaValidatorCommand.php | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/src/CoreBundle/Command/SchemaValidatorCommand.php b/src/CoreBundle/Command/SchemaValidatorCommand.php index 6af0ecdcf..8eccf17fe 100644 --- a/src/CoreBundle/Command/SchemaValidatorCommand.php +++ b/src/CoreBundle/Command/SchemaValidatorCommand.php @@ -35,32 +35,19 @@ class SchemaValidatorCommand extends Command { /** * The information collector. - * - * @var MetaModelInformationCollector */ - private $collector; + private MetaModelInformationCollector $collector; /** * The schema generator. - * - * @var SchemaGenerator */ - private $generator; + private SchemaGenerator $generator; /** * The schema manager. - * - * @var SchemaManager */ - private $manager; + private SchemaManager $manager; - /** - * Create a new instance. - * - * @param MetaModelInformationCollector $collector - * @param SchemaGenerator $generator - * @param SchemaManager $manager - */ public function __construct( MetaModelInformationCollector $collector, SchemaGenerator $generator, @@ -72,19 +59,13 @@ public function __construct( parent::__construct('metamodels:schema-update'); } - /** - * {@inheritDoc} - */ protected function configure() { parent::configure(); $this->addOption('force', null, InputOption::VALUE_NONE, 'Perform the update'); } - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $this->generator->generate($information = new SchemaInformation(), $this->collector->getCollection()); @@ -92,11 +73,13 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->manager->preprocess($information); $this->manager->process($information); $this->manager->postprocess($information); - return; + return 0; } foreach ($this->manager->validate($information) as $item) { $output->writeln($item); } + + return 0; } } From af898dfbc57c00f3d59381463191565d183a4e5e Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Mon, 24 Oct 2022 19:23:50 +0200 Subject: [PATCH 106/224] Rework managed attribute detection to use a param --- src/Attribute/Base.php | 51 ++-------- src/Attribute/BaseSimple.php | 100 ++++--------------- src/Attribute/ISchemaManagedAttribute.php | 34 ------- src/Attribute/ManagedAttributeTrait.php | 58 +++++++++++ src/CoreBundle/Resources/config/services.yml | 3 + src/Schema/LegacySchemaGenerator.php | 22 ++-- tests/Schema/LegacySchemaGeneratorTest.php | 32 ++++-- 7 files changed, 133 insertions(+), 167 deletions(-) delete mode 100644 src/Attribute/ISchemaManagedAttribute.php create mode 100644 src/Attribute/ManagedAttributeTrait.php diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index f0a5ad84d..0e308c564 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -41,6 +41,8 @@ */ abstract class Base implements IAttribute { + use ManagedAttributeTrait; + /** * The MetaModel instance this object belongs to. * @@ -305,22 +307,11 @@ public function handleMetaChange($strMetaName, $varNewValue) // By default, we accept any change of meta information. $this->set($strMetaName, $varNewValue); - if ($this instanceof ISchemaManagedAttribute) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + if ($this->isManagedAttribute($this->get('type'))) { + $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); return $this; } - - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); return $this; } @@ -332,22 +323,12 @@ public function handleMetaChange($strMetaName, $varNewValue) */ public function destroyAUX() { - if ($this instanceof ISchemaManagedAttribute) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + if ($this->isManagedAttribute($this->get('type'))) { + $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); return; } - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); // No-op. } @@ -358,22 +339,12 @@ public function destroyAUX() */ public function initializeAUX() { - if ($this instanceof ISchemaManagedAttribute) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + if ($this->isManagedAttribute($this->get('type'))) { + $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); return; } - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); // No-op. } diff --git a/src/Attribute/BaseSimple.php b/src/Attribute/BaseSimple.php index a4d6c3645..492e3c48d 100644 --- a/src/Attribute/BaseSimple.php +++ b/src/Attribute/BaseSimple.php @@ -39,6 +39,8 @@ */ class BaseSimple extends Base implements ISimple { + use ManagedAttributeTrait; + /** * Database connection. * @@ -119,13 +121,8 @@ public function __construct( */ public function handleMetaChange($strMetaName, $varNewValue) { - if ($this instanceof ISchemaManagedAttribute) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + if ($this->isManagedAttribute($this->get('type'))) { + $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); return $this; } @@ -257,13 +254,8 @@ public function searchFor($strPattern) */ public function getSQLDataType() { - if ($this instanceof ISchemaManagedAttribute) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + if ($this->isManagedAttribute($this->get('type'))) { + $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); } return 'blob NULL'; @@ -278,22 +270,12 @@ public function getSQLDataType() */ public function destroyAUX() { - if ($this instanceof ISchemaManagedAttribute) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + if ($this->isManagedAttribute($this->get('type'))) { + $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); return; } - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); parent::destroyAUX(); $this->deleteColumn(); @@ -308,22 +290,12 @@ public function destroyAUX() */ public function initializeAUX() { - if ($this instanceof ISchemaManagedAttribute) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + if ($this->isManagedAttribute($this->get('type'))) { + $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); return; } - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); parent::initializeAUX(); $this->createColumn(); @@ -340,22 +312,12 @@ public function initializeAUX() */ public function createColumn() { - if ($this instanceof ISchemaManagedAttribute) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + if ($this->isManagedAttribute($this->get('type'))) { + $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); return; } - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); if ($this->getColName()) { $this->tableManipulator->createColumn( @@ -375,22 +337,12 @@ public function createColumn() */ public function deleteColumn() { - if ($this instanceof ISchemaManagedAttribute) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + if ($this->isManagedAttribute($this->get('type'))) { + $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); return; } - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); $schemaManager = $this->connection->getSchemaManager(); $columns = $schemaManager->listTableColumns($this->getMetaModel()->getTableName()); @@ -412,22 +364,12 @@ public function deleteColumn() */ public function renameColumn($strNewColumnName) { - if ($this instanceof ISchemaManagedAttribute) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" is a managed attribute you should not call "' . __METHOD__ . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + if ($this->isManagedAttribute($this->get('type'))) { + $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); return; } - // @codingStandardsIgnoreStart - @trigger_error( - 'Class "' . static::class . '" should be changed to "' . ISchemaManagedAttribute::class . '".', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd + $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); $this->tableManipulator->checkColumnName($strNewColumnName); diff --git a/src/Attribute/ISchemaManagedAttribute.php b/src/Attribute/ISchemaManagedAttribute.php deleted file mode 100644 index d51e44841..000000000 --- a/src/Attribute/ISchemaManagedAttribute.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -namespace MetaModels\Attribute; - -/** - * This interface denotes an attribute that has been migrated to the new schema manager and therefore the manipulation - * methods shall not be called anymore. - * - * It is part of the migration process to MetaModels 3.0 and will get removed then. - * - * In order to migrate to a ISchemaManagedAttribute, you should implement and register a doctrine schema generator. - * - * @see \MetaModels\Schema\Doctrine\AbstractAttributeTypeSchemaGenerator - */ -interface ISchemaManagedAttribute extends IAttribute -{ -} diff --git a/src/Attribute/ManagedAttributeTrait.php b/src/Attribute/ManagedAttributeTrait.php new file mode 100644 index 000000000..32237fd49 --- /dev/null +++ b/src/Attribute/ManagedAttributeTrait.php @@ -0,0 +1,58 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\Attribute; + +use Contao\System; + +trait ManagedAttributeTrait +{ + private function isManagedAttribute(string $type): bool + { + $container = System::getContainer(); + return in_array( + $type, + $container->hasParameter('metamodels.managed-schema-type-names') + ? ($container->getParameter('metamodels.managed-schema-type-names') ?? []) + : [], + true + ); + } + + private function triggerDeprecationIsUnmanagedAttribute(string $class, string $method): void + { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . $class . '" should be changed to a managed attribute and skip calling method "' . $method . + '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + } + + private function triggerDeprecationShouldNotCallManaged(string $class, string $method): void + { + // @codingStandardsIgnoreStart + @trigger_error( + 'Class "' . $class . '" is a managed attribute you should not call "' . $method . '".', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + } +} diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index d1f188e66..8b49e510f 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -1,3 +1,5 @@ +parameters: + metamodels.managed-schema-type-names: [] services: MetaModels\IFactory: '@metamodels.factory' MetaModels\Filter\Setting\IFilterSettingFactory: '@metamodels.filter_setting_factory' @@ -203,6 +205,7 @@ services: MetaModels\Schema\LegacySchemaGenerator: arguments: - '@metamodels.factory' + - '%metamodels.managed-schema-type-names%' tags: - { name: 'metamodels.schema-generator' } diff --git a/src/Schema/LegacySchemaGenerator.php b/src/Schema/LegacySchemaGenerator.php index c0e68f041..70e573903 100644 --- a/src/Schema/LegacySchemaGenerator.php +++ b/src/Schema/LegacySchemaGenerator.php @@ -22,10 +22,11 @@ namespace MetaModels\Schema; use MetaModels\Attribute\IInternal; -use MetaModels\Attribute\ISchemaManagedAttribute; use MetaModels\IFactory; use MetaModels\Information\MetaModelCollectionInterface; +use function in_array; + /** * This is the legacy handler for creating the legacy schema. * @@ -33,21 +34,26 @@ */ class LegacySchemaGenerator implements SchemaGeneratorInterface { + /** @var list */ + private array $ignoredTypeNames; + /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Create a new instance. * - * @param IFactory $factory The factory. + * @param IFactory $factory The factory. + * @param list $ignoredTypeNames */ - public function __construct(IFactory $factory) + public function __construct(IFactory $factory, array $ignoredTypeNames) { $this->factory = $factory; + $this->ignoredTypeNames = $ignoredTypeNames; } /** @@ -66,14 +72,16 @@ public function generate(SchemaInformation $information, MetaModelCollectionInte $metaModel = $this->factory->getMetaModel($metaModelInformation->getName()); foreach ($metaModel->getAttributes() as $attribute) { // Skip managed and internal attributes. - if ($attribute instanceof ISchemaManagedAttribute || $attribute instanceof IInternal) { + if ( + $attribute instanceof IInternal + || in_array($attribute->get('type'), $this->ignoredTypeNames, true) + ) { continue; } // @codingStandardsIgnoreStart @trigger_error( - 'Attribute type "' . $attribute->get('type') . - '" should implement "' . ISchemaManagedAttribute::class . '".', + 'Attribute type "' . $attribute->get('type') . '" should be changed to a managed attribute.', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd diff --git a/tests/Schema/LegacySchemaGeneratorTest.php b/tests/Schema/LegacySchemaGeneratorTest.php index 0f754052d..047e3cbb3 100644 --- a/tests/Schema/LegacySchemaGeneratorTest.php +++ b/tests/Schema/LegacySchemaGeneratorTest.php @@ -24,7 +24,6 @@ use MetaModels\Attribute\IAttribute; use MetaModels\Attribute\IComplex; use MetaModels\Attribute\IInternal; -use MetaModels\Attribute\ISchemaManagedAttribute; use MetaModels\Attribute\ISimple; use MetaModels\IFactory; use MetaModels\IMetaModel; @@ -50,7 +49,7 @@ class LegacySchemaGeneratorTest extends TestCase */ public function testInstantiation(): void { - $instance = new LegacySchemaGenerator($this->getMockForAbstractClass(IFactory::class)); + $instance = new LegacySchemaGenerator($this->getMockForAbstractClass(IFactory::class), []); $this->assertInstanceOf(LegacySchemaGenerator::class, $instance); } @@ -62,7 +61,7 @@ public function testInstantiation(): void */ public function testGenerateAddsSchemaInformationIfNotFound(): void { - $instance = new LegacySchemaGenerator($this->getMockForAbstractClass(IFactory::class)); + $instance = new LegacySchemaGenerator($this->getMockForAbstractClass(IFactory::class), []); $information = new SchemaInformation(); $collection = $this->getMockForAbstractClass(MetaModelCollectionInterface::class); @@ -83,9 +82,9 @@ public function testGenerate(): void $information = new SchemaInformation(); $collection = $this->getMockForAbstractClass(MetaModelCollectionInterface::class); - $attribute1 = $this->getMockForAbstractClass(ISimple::class); - $attribute2 = $this->getMockForAbstractClass(IComplex::class); - $attribute3 = $this->getMockForAbstractClass(ISchemaManagedAttribute::class); + $attribute1 = $this->mockAttribute(ISimple::class, 'attribute1'); + $attribute2 = $this->mockAttribute(IComplex::class, 'attribute2'); + $attribute3 = $this->mockAttribute(ISimple::class, 'managed-type'); $attribute4 = $this->getMockForAbstractClass(IInternal::class); $metaModel = $this->mockMetaModel([$attribute1, $attribute2, $attribute3, $attribute4]); @@ -97,7 +96,7 @@ public function testGenerate(): void ])); $metaModelInformation->addAttribute(new AttributeInformation('test', 'test_type')); - $instance = new LegacySchemaGenerator($factory); + $instance = new LegacySchemaGenerator($factory, ['managed-type']); $instance->generate($information, $collection); @@ -123,4 +122,23 @@ private function mockMetaModel(array $attributes) return $metaModel; } + + /** @param class-string $interface */ + private function mockAttribute(string $interface, string $typeName): IAttribute + { + $attribute = $this->getMockForAbstractClass($interface); + + $attribute + ->expects(self::atLeastOnce()) + ->method('get') + ->willReturnCallback(function (string $key) use ($typeName) { + switch ($key) { + case 'type': + return $typeName; + } + throw new \LogicException('Unexpected get call'); + }); + + return $attribute; + } } From 8680080b9c2d8ebf5c17c735c2cc87eae60ba4e1 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Wed, 28 Dec 2022 15:05:03 +0100 Subject: [PATCH 107/224] Fix strict type issues and deprecations --- .../Doctrine/DoctrineSchemaInformation.php | 30 +++++++------------ .../Doctrine/SystemColumnSchemaGenerator.php | 19 ++++++------ src/Schema/SchemaInformation.php | 20 ++++++------- src/Schema/SchemaManager.php | 4 +-- 4 files changed, 31 insertions(+), 42 deletions(-) diff --git a/src/Schema/Doctrine/DoctrineSchemaInformation.php b/src/Schema/Doctrine/DoctrineSchemaInformation.php index 0aac9537e..3a1526b15 100644 --- a/src/Schema/Doctrine/DoctrineSchemaInformation.php +++ b/src/Schema/Doctrine/DoctrineSchemaInformation.php @@ -31,31 +31,29 @@ class DoctrineSchemaInformation implements SchemaInformationInterface { /** * The generated doctrine schema. - * - * @var Schema */ - private $schema; + private Schema $schema; /** - * A list of pre processors ordered by priority. + * A list of pre-processors ordered by priority. * - * @var SchemaProcessorInterface[][] + * @var array> */ - private $preProcessors = []; + private array $preProcessors = []; /** * A list of post processors by priority. * - * @var SchemaProcessorInterface[][] + * @var array> */ - private $postProcessors = []; + private array $postProcessors = []; /** * Create a new instance. * * @param Schema|null $schema The contained doctrine schema. */ - public function __construct(Schema $schema = null) + public function __construct(?Schema $schema = null) { $this->schema = ($schema ?? new Schema()); } @@ -70,8 +68,6 @@ public function getName(): string /** * Retrieve schema. - * - * @return Schema */ public function getSchema(): Schema { @@ -83,10 +79,8 @@ public function getSchema(): Schema * * @param SchemaProcessorInterface $processor The processor to add. * @param int $priority The priority to use. - * - * @return void */ - public function addPreProcessor(SchemaProcessorInterface $processor, $priority = 0): void + public function addPreProcessor(SchemaProcessorInterface $processor, int $priority = 0): void { if (!isset($this->preProcessors[$priority])) { $this->preProcessors[$priority] = []; @@ -98,7 +92,7 @@ public function addPreProcessor(SchemaProcessorInterface $processor, $priority = /** * Retrieve preProcessors. * - * @return SchemaProcessorInterface[] + * @return list */ public function getPreProcessors(): array { @@ -114,10 +108,8 @@ public function getPreProcessors(): array * * @param SchemaProcessorInterface $processor The processor to add. * @param int $priority The priority to use. - * - * @return void */ - public function addPostProcessor(SchemaProcessorInterface $processor, $priority = 0): void + public function addPostProcessor(SchemaProcessorInterface $processor, int $priority = 0): void { if (!isset($this->postProcessors[$priority])) { $this->postProcessors[$priority] = []; @@ -129,7 +121,7 @@ public function addPostProcessor(SchemaProcessorInterface $processor, $priority /** * Retrieve postProcessors. * - * @return SchemaProcessorInterface[] + * @return list */ public function getPostProcessors(): array { diff --git a/src/Schema/Doctrine/SystemColumnSchemaGenerator.php b/src/Schema/Doctrine/SystemColumnSchemaGenerator.php index 6893a4210..9a1def6e9 100644 --- a/src/Schema/Doctrine/SystemColumnSchemaGenerator.php +++ b/src/Schema/Doctrine/SystemColumnSchemaGenerator.php @@ -21,7 +21,7 @@ namespace MetaModels\Schema\Doctrine; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use MetaModels\Information\MetaModelCollectionInterface; use MetaModels\Information\MetaModelInformationInterface; @@ -47,8 +47,6 @@ public function generate(DoctrineSchemaInformation $schema, MetaModelCollectionI * * @param DoctrineSchemaInformation $schema The doctrine schema to populate. * @param MetaModelInformationInterface $metaModelInformation The metamodel information to use. - * - * @return void */ private function generateMetaModelSchema( DoctrineSchemaInformation $schema, @@ -56,20 +54,21 @@ private function generateMetaModelSchema( ): void { $tableSchema = $this->getSchemaForMetaModel($schema, $metaModelInformation); - $this->setColumnData($tableSchema, 'id', Type::INTEGER, [ + $this->setColumnData($tableSchema, 'id', Types::INTEGER, [ 'unsigned' => true, 'notnull' => true, 'autoincrement' => true, ]); - $this->setColumnData($tableSchema, 'pid', Type::INTEGER, [ + $this->setColumnData($tableSchema, 'pid', Types::INTEGER, [ 'unsigned' => true, - 'notnull' => false, + 'notnull' => true, + 'default' => 0, ]); - $this->setColumnData($tableSchema, 'sorting', Type::INTEGER, [ + $this->setColumnData($tableSchema, 'sorting', Types::INTEGER, [ 'unsigned' => true, 'default' => 0, ]); - $this->setColumnData($tableSchema, 'tstamp', Type::INTEGER, [ + $this->setColumnData($tableSchema, 'tstamp', Types::INTEGER, [ 'unsigned' => true, 'default' => 0, ]); @@ -78,12 +77,12 @@ private function generateMetaModelSchema( if ($metaModelInformation->hasConfigurationValue('varsupport') && '1' === $metaModelInformation->getConfigurationValue('varsupport')) { - $this->setColumnData($tableSchema, 'varbase', Type::STRING, [ + $this->setColumnData($tableSchema, 'varbase', Types::STRING, [ 'length' => 1, 'fixed' => true, 'default' => '', ]); - $this->setColumnData($tableSchema, 'vargroup', Type::INTEGER, [ + $this->setColumnData($tableSchema, 'vargroup', Types::INTEGER, [ 'unsigned' => true, 'default' => 0, ]); diff --git a/src/Schema/SchemaInformation.php b/src/Schema/SchemaInformation.php index 9bd445062..e0e73b7f6 100644 --- a/src/Schema/SchemaInformation.php +++ b/src/Schema/SchemaInformation.php @@ -21,6 +21,8 @@ namespace MetaModels\Schema; +use InvalidArgumentException; + /** * This encapsulates the different schema engine information. */ @@ -29,9 +31,9 @@ class SchemaInformation /** * The list of registered schema information. * - * @var SchemaInformationInterface[] + * @var list */ - private $information = []; + private array $information = []; /** * Retrieve schema information. @@ -40,12 +42,12 @@ class SchemaInformation * * @return SchemaInformationInterface * - * @throws \InvalidArgumentException When the information is not registered. + * @throws InvalidArgumentException When the information is not registered. */ public function get(string $name): SchemaInformationInterface { if (!$this->has($name)) { - throw new \InvalidArgumentException('Information with name "' . $name . '" not registered.'); + throw new InvalidArgumentException('Information with name "' . $name . '" not registered.'); } return $this->information[$name]; @@ -55,8 +57,6 @@ public function get(string $name): SchemaInformationInterface * Test if the information with the passed name is registered. * * @param string $name The name of the information to search. - * - * @return bool */ public function has(string $name): bool { @@ -68,14 +68,12 @@ public function has(string $name): bool * * @param SchemaInformationInterface $information The information to add. * - * @return void - * - * @throws \InvalidArgumentException When the information is already registered. + * @throws InvalidArgumentException When the information is already registered. */ public function add(SchemaInformationInterface $information): void { if ($this->has($name = $information->getName())) { - throw new \InvalidArgumentException('Information with name "' . $name . '" already registered.'); + throw new InvalidArgumentException('Information with name "' . $name . '" already registered.'); } $this->information[$information->getName()] = $information; @@ -84,7 +82,7 @@ public function add(SchemaInformationInterface $information): void /** * Obtain the list of registered names. * - * @return string[] + * @return list */ public function getRegisteredNames(): array { diff --git a/src/Schema/SchemaManager.php b/src/Schema/SchemaManager.php index 026cc3422..55bd85079 100644 --- a/src/Schema/SchemaManager.php +++ b/src/Schema/SchemaManager.php @@ -29,9 +29,9 @@ class SchemaManager implements SchemaManagerInterface /** * The list of registered schema managers. * - * @var SchemaManagerInterface[] + * @var list */ - private $managers; + private array $managers; /** * Create a new instance. From 344399eb256a970cd7f9a22409fb7ca861acb11a Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 1 Jan 2023 14:39:17 +0100 Subject: [PATCH 108/224] Fix schema manager --- ...ontaoDatabaseBackedInformationProvider.php | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php b/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php index ac1082bb3..eb3e4fbe2 100644 --- a/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php +++ b/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,8 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -52,13 +53,17 @@ public function __construct(Connection $connection) */ public function getNames(): array { - return $this - ->connection - ->createQueryBuilder() - ->select('tableName') - ->from('tl_metamodel') - ->execute() - ->fetchAll(\PDO::FETCH_COLUMN); + if ($this->connection->createSchemaManager()->tablesExist('tl_metamodel')) { + return $this + ->connection + ->createQueryBuilder() + ->select('tableName') + ->from('tl_metamodel') + ->executeQuery() + ->fetchAllAssociative(); + } + + return []; } /** @@ -76,8 +81,9 @@ public function getInformationFor(MetaModelInformation $information): void ->where('tableName=:tableName') ->setParameter('tableName', $information->getName()) ->setMaxResults(1) - ->execute() - ->fetch(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); + // Not managed by us. if (empty($configuration)) { return; @@ -94,8 +100,8 @@ public function getInformationFor(MetaModelInformation $information): void ->where('pid=:pid') ->setParameter('pid', $information->getConfigurationValue('id')) ->orderBy('sorting') - ->execute() - ->fetchAll(\PDO::FETCH_ASSOC); + ->executeQuery() + ->fetchAllAssociative(); foreach ($attributeRows as $attributeRow) { $colName = $attributeRow['colname']; From cf1d22d4f40e885658dc08c54b1d6aab3382e975 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 1 Jan 2023 15:33:21 +0100 Subject: [PATCH 109/224] Fix PHP 8 warning --- .../DcGeneral/Table/RenderSettings/JumpToListener.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php index c50f058e5..144fd5d1f 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -95,7 +95,7 @@ public function decodeValue(DecodePropertyValueForWidgetEvent $event) $extra = $propInfo->getExtra(); $newValues = []; - $languages = $extra['columnFields']['langcode']['options']; + $languages = $extra['columnFields']['langcode']['options'] ?? []; foreach (array_keys($languages) as $key) { $newValue = ''; $filter = 0; From ab21da6e677b5da4c16d10f5ba2b42cd66e34c31 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 2 Jan 2023 20:51:16 +0100 Subject: [PATCH 110/224] Fix Associatives --- .../ContaoDatabaseBackedInformationProvider.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php b/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php index eb3e4fbe2..e51092497 100644 --- a/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php +++ b/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php @@ -60,7 +60,7 @@ public function getNames(): array ->select('tableName') ->from('tl_metamodel') ->executeQuery() - ->fetchAllAssociative(); + ->fetchFirstColumn(); } return []; @@ -82,7 +82,7 @@ public function getInformationFor(MetaModelInformation $information): void ->setParameter('tableName', $information->getName()) ->setMaxResults(1) ->executeQuery() - ->fetchAllAssociative(); + ->fetchAssociative(); // Not managed by us. if (empty($configuration)) { From 14a83c21254820ee7b3c942a86a451c22372477b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 6 Jan 2023 10:35:23 +0100 Subject: [PATCH 111/224] Add attribute sorter --- .../DcaSortGroup/AttributeOptionsListener.php | 28 ++++++-- .../dc-general/table/tl_dca_sortgroup.yml | 1 + src/CoreBundle/Resources/config/services.yml | 3 + src/CoreBundle/Sorter/AttributeSorter.php | 70 +++++++++++++++++++ 4 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 src/CoreBundle/Sorter/AttributeSorter.php diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AttributeOptionsListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AttributeOptionsListener.php index 31ff18227..bc534f9d8 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AttributeOptionsListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AttributeOptionsListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2020 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +27,7 @@ use Doctrine\DBAL\Connection; use MetaModels\Attribute\IInternal; use MetaModels\CoreBundle\Formatter\SelectAttributeOptionLabelFormatter; +use MetaModels\CoreBundle\Sorter\AttributeSorter; use MetaModels\IFactory; /** @@ -38,21 +40,31 @@ class AttributeOptionsListener extends AbstractListener * * @var SelectAttributeOptionLabelFormatter */ - private $attributeLabelFormatter; + private SelectAttributeOptionLabelFormatter $attributeLabelFormatter; + + /** + * The attribute sorter. + * + * @var AttributeSorter + */ + private AttributeSorter $attributeSorter; /** * {@inheritDoc} * * @param SelectAttributeOptionLabelFormatter $attributeLabelFormatter The attribute select option label formatter. + * @param AttributeSorter $attributeSorter The attribute sorter. */ public function __construct( RequestScopeDeterminator $scopeDeterminator, IFactory $factory, Connection $connection, - SelectAttributeOptionLabelFormatter $attributeLabelFormatter + SelectAttributeOptionLabelFormatter $attributeLabelFormatter, + AttributeSorter $attributeSorter ) { parent::__construct($scopeDeterminator, $factory, $connection); $this->attributeLabelFormatter = $attributeLabelFormatter; + $this->attributeSorter = $attributeSorter; } /** @@ -68,10 +80,12 @@ public function handle(GetPropertyOptionsEvent $event) return; } - $result = []; - $metaModel = $this->getMetaModelFromModel($event->getModel()); + $result = []; + $metaModel = $this->getMetaModelFromModel($event->getModel()); + $attributes = $metaModel->getAttributes(); + $attributes = $this->attributeSorter->sortByName($attributes); - foreach ($metaModel->getAttributes() as $attribute) { + foreach ($attributes as $attribute) { if ($attribute instanceof IInternal) { continue; } diff --git a/src/CoreBundle/Resources/config/dc-general/table/tl_dca_sortgroup.yml b/src/CoreBundle/Resources/config/dc-general/table/tl_dca_sortgroup.yml index a5f236416..a429c99ab 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_dca_sortgroup.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_dca_sortgroup.yml @@ -6,6 +6,7 @@ services: - '@MetaModels\IFactory' - '@database_connection' - '@MetaModels\CoreBundle\Formatter\SelectAttributeOptionLabelFormatter' + - '@MetaModels\CoreBundle\Sorter\AttributeSorter' tags: - name: kernel.event_listener event: dc-general.view.contao2backend.get-property-options diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index 8b49e510f..1cd0c2fd3 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -272,6 +272,9 @@ services: MetaModels\CoreBundle\Formatter\SelectAttributeOptionLabelFormatter: public: false + MetaModels\CoreBundle\Sorter\AttributeSorter: + public: false + MetaModels\Helper\ToolboxFile: public: false arguments: diff --git a/src/CoreBundle/Sorter/AttributeSorter.php b/src/CoreBundle/Sorter/AttributeSorter.php new file mode 100644 index 000000000..d385769c7 --- /dev/null +++ b/src/CoreBundle/Sorter/AttributeSorter.php @@ -0,0 +1,70 @@ + + * @copyright 2012-2023 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\Sorter; + +use MetaModels\Attribute\IAttribute; + +/** + * This sort attributes. + */ +final class AttributeSorter +{ + /** + * Sort by name. + * + * @param array $attributes The attributes. + * @param string $dir The sort direction. + * + * @return array + */ + public function sortByName(array $attributes, string $dir = 'ASC'): array + { + if ('ASC' === \strtoupper($dir)) { + \usort($attributes, fn($a, $b) => $a->getName() <=> $b->getName()); + } + + if ('DESC' === \strtoupper($dir)) { + \usort($attributes, fn($a, $b) => $b->getName() <=> $a->getName()); + } + + return $attributes; + } + + /** + * Sort by column name. + * + * @param array $attributes The attributes. + * @param string $dir The sort direction. + * + * @return array + */ + public function sortByColumnName(array $attributes, string $dir = 'ASC'): array + { + if ('ASC' === \strtoupper($dir)) { + \usort($attributes, fn($a, $b) => $a->getColName() <=> $b->getColName()); + } + + if ('DESC' === \strtoupper($dir)) { + \usort($attributes, fn($a, $b) => $b->getColName() <=> $a->getColName()); + } + + return $attributes; + } +} From a0b6829f039a42de5b2311abb12cbb5bc1de79c6 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 6 Jan 2023 10:46:51 +0100 Subject: [PATCH 112/224] Add chosen at attribute select sort-group --- .../Resources/contao/dca/tl_metamodel_dca_sortgroup.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php index f19e6eb05..d235de669 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Cliff Parnitzky - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -234,6 +234,7 @@ 'inputType' => 'select', 'eval' => [ 'tl_class' => 'w50 clr', + 'chosen' => true ], 'sql' => "int(10) unsigned NOT NULL default '0'" ], @@ -256,7 +257,7 @@ 'inputType' => 'select', 'eval' => [ 'tl_class' => 'w50', - 'submitOnChange' => true + 'chosen' => true ], 'sql' => "int(10) unsigned NOT NULL default '0'" ], From 28a249a39e009a2de37d76c38a573fd6192e005e Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 6 Jan 2023 14:42:44 +0100 Subject: [PATCH 113/224] Add filter rule type in FE filter list see https://github.com/MetaModels/core/issues/1473 --- src/Filter/Setting/Collection.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Filter/Setting/Collection.php b/src/Filter/Setting/Collection.php index 60434a1f2..9280ff160 100644 --- a/src/Filter/Setting/Collection.php +++ b/src/Filter/Setting/Collection.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -181,7 +181,11 @@ public function getParameterFilterNames() { $parameters = []; foreach ($this->arrSettings as $objSetting) { - $parameters[] = $objSetting->getParameterFilterNames(); + $filterNames = $objSetting->getParameterFilterNames(); + $filterType = $objSetting->get('type'); + $parameters[] = \array_map(function ($name) use ($filterType) { + return $name . ' [' . $filterType . ']'; + }, $filterNames); } return [] === $parameters ? [] : array_merge(...$parameters); From 46d2a402bd27317d3eeec2d4b70eebbfbedeefc6 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 6 Jan 2023 14:44:14 +0100 Subject: [PATCH 114/224] Revert "Add filter rule type in FE filter list" This reverts commit 28a249a39e009a2de37d76c38a573fd6192e005e. --- src/Filter/Setting/Collection.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Filter/Setting/Collection.php b/src/Filter/Setting/Collection.php index 9280ff160..60434a1f2 100644 --- a/src/Filter/Setting/Collection.php +++ b/src/Filter/Setting/Collection.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2020 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2020 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -181,11 +181,7 @@ public function getParameterFilterNames() { $parameters = []; foreach ($this->arrSettings as $objSetting) { - $filterNames = $objSetting->getParameterFilterNames(); - $filterType = $objSetting->get('type'); - $parameters[] = \array_map(function ($name) use ($filterType) { - return $name . ' [' . $filterType . ']'; - }, $filterNames); + $parameters[] = $objSetting->getParameterFilterNames(); } return [] === $parameters ? [] : array_merge(...$parameters); From be55d2be36cc2d357a284cfd1a2364c8fcdf5c19 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 6 Jan 2023 14:46:08 +0100 Subject: [PATCH 115/224] Add filter type at filterlist --- src/Filter/Setting/Collection.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Filter/Setting/Collection.php b/src/Filter/Setting/Collection.php index 60434a1f2..9280ff160 100644 --- a/src/Filter/Setting/Collection.php +++ b/src/Filter/Setting/Collection.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -181,7 +181,11 @@ public function getParameterFilterNames() { $parameters = []; foreach ($this->arrSettings as $objSetting) { - $parameters[] = $objSetting->getParameterFilterNames(); + $filterNames = $objSetting->getParameterFilterNames(); + $filterType = $objSetting->get('type'); + $parameters[] = \array_map(function ($name) use ($filterType) { + return $name . ' [' . $filterType . ']'; + }, $filterNames); } return [] === $parameters ? [] : array_merge(...$parameters); From 72a0cb499ad65cd4e796cd3c7301e0c9922cf021 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 6 Jan 2023 17:19:27 +0100 Subject: [PATCH 116/224] Set isdefault at first sortgroup --- .../DcaSortGroup/SortGroupCreateListener.php | 90 +++++++++++++++++++ .../dc-general/table/tl_dca_sortgroup.yml | 8 ++ 2 files changed, 98 insertions(+) create mode 100644 src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/SortGroupCreateListener.php diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/SortGroupCreateListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/SortGroupCreateListener.php new file mode 100644 index 000000000..12d12819b --- /dev/null +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/SortGroupCreateListener.php @@ -0,0 +1,90 @@ + + * @copyright 2012-2023 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSortGroup; + +use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\Event\PreEditModelEvent; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; + +/** + * This provides the attribute at generate. + */ +class SortGroupCreateListener +{ + /** + * Database connection. + * + * @var Connection + */ + private Connection $connection; + + /** + * SortGroupCreateListener constructor. + * + * @param Connection $connection Database connection. + */ + public function __construct( + Connection $connection + ) { + $this->connection = $connection; + } + + /** + * Set as default if first item. + * + * @param PreEditModelEvent $event The event. + * + * @return void + * + * @throws Exception + */ + public function handle(PreEditModelEvent $event): void + { + if ('tl_metamodel_dca_sortgroup' !== $event->getEnvironment()->getDataDefinition()->getName()) { + return; + } + + if ('paste' !== $event->getEnvironment()->getInputProvider()->getParameter('act') + || !($pid = $event->getEnvironment()->getInputProvider()->getParameter('pid'))) { + return; + } + + if (!($pid = ModelId::fromSerialized($pid)->getId())) { + return; + } + + // Retrieve if first item. + $statement = $this->connection->createQueryBuilder() + ->select('t.*') + ->from('tl_metamodel_dca_sortgroup', 't') + ->where('t.pid=:pid') + ->setParameter('pid', $pid) + ->executeQuery(); + + if ($statement->rowCount()) { + return; + } + + // Set 'isdefault' as checked is first item. + $model = $event->getModel(); + $model->setProperty('isdefault', 1); + } +} diff --git a/src/CoreBundle/Resources/config/dc-general/table/tl_dca_sortgroup.yml b/src/CoreBundle/Resources/config/dc-general/table/tl_dca_sortgroup.yml index a5f236416..3a3b7fe42 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_dca_sortgroup.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_dca_sortgroup.yml @@ -29,3 +29,11 @@ services: - name: kernel.event_listener event: dc-general.factory.build-data-definition method: handle + + MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSortGroup\SortGroupCreateListener: + arguments: + - '@database_connection' + tags: + - name: kernel.event_listener + event: dc-general.model.pre-edit-model + method: handle From adb2dbc267535403fc1bb667c79c94f94bd48411 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 6 Jan 2023 18:56:08 +0100 Subject: [PATCH 117/224] Add hint to set manual sorting if render type hierachical --- .../Table/Dca/RenderModeHintListener.php | 81 +++++++++++++++++++ .../config/dc-general/table/tl_dca.yml | 8 ++ .../contao/languages/en/tl_metamodel_dca.php | 3 + 3 files changed, 92 insertions(+) create mode 100644 src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php new file mode 100644 index 000000000..c3191be5a --- /dev/null +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php @@ -0,0 +1,81 @@ + + * @copyright 2012-2023 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\Dca; + +use Contao\Message; +use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\BuildWidgetEvent; +use Doctrine\DBAL\Connection; +use MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting\AbstractListener; +use MetaModels\IFactory; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * This adds a hint if render mode hierarchical. + */ +class RenderModeHintListener +{ + /** + * The translator. + * + * @var TranslatorInterface + */ + private $translator; + + /** + * Create a new instance. + * + * @param TranslatorInterface $translator The translator. + */ + public function __construct( + TranslatorInterface $translator + ) { + $this->translator = $translator; + } + + /** + * Adds a hint if render mode hierarchical. + * + * @param BuildWidgetEvent $event The event. + * + * @return void + */ + public function handle(BuildWidgetEvent $event) + { + $environment = $event->getEnvironment(); + if (($environment->getDataDefinition()->getName() !== 'tl_metamodel_dca') + || ($event->getProperty()->getName() !== 'rendermode') + || (null === $event->getModel()->getId())) { + return; + } + + $model = $event->getModel(); + + if ('hierarchical' === $model->getProperty('rendermode')) { + Message::addInfo( + $this->translator->trans( + 'tl_metamodel_dca.hint_rendermode_hierarchical', + [], + 'contao_tl_metamodel_dca' + ) + ); + } + } +} diff --git a/src/CoreBundle/Resources/config/dc-general/table/tl_dca.yml b/src/CoreBundle/Resources/config/dc-general/table/tl_dca.yml index dc148e225..3f40d2fec 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_dca.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_dca.yml @@ -36,3 +36,11 @@ services: - name: kernel.event_listener event: dc-general.view.contao2backend.get-property-options method: handle + + MetaModels\CoreBundle\EventListener\DcGeneral\Table\Dca\RenderModeHintListener: + arguments: + - "@translator" + tags: + - name: kernel.event_listener + event: dc-general.view.contao2backend.build-widget + method: handle diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php index d43962439..b360e225e 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php @@ -96,4 +96,7 @@ $GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermodes']['parented'] = 'Parented'; $GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermodes']['hierarchical'] = 'Hierarchical'; +$GLOBALS['TL_LANG']['tl_metamodel_dca']['hint_rendermode_hierarchical'] = + 'When using the "Hierarchical" render mode, the current sort must be enable to "Manual sorting" as default.'; + $GLOBALS['TL_LANG']['tl_metamodel_dca']['deleteConfirm'] = 'Do you really want to delete input screen ID %s?'; From c360391d54cab9857e3c289e84e6ef6f62469afd Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 7 Jan 2023 14:07:24 +0100 Subject: [PATCH 118/224] Add published at sortgroup --- .../Contao2BackendViewDefinitionBuilder.php | 10 ++++++++-- .../contao/dca/tl_metamodel_dca_sortgroup.php | 9 +++++++++ .../contao/languages/en/tl_metamodel_dca_sortgroup.php | 7 +++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php index 6e3a9d963..125610241 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -202,8 +203,13 @@ private function parseListSorting(ListingConfigInterface $listing) if (null === $this->inputScreen) { return; } + $definitions = $listing->getGroupAndSortingDefinition(); foreach ($this->inputScreen['groupSort'] as $information) { + if (!$information['published']) { + continue; + } + $definition = $definitions->add(); $definition->setName($information['name']); if ($information['isdefault'] && !$definitions->hasDefault()) { diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php index d235de669..741f05d95 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php @@ -136,6 +136,11 @@ 'href' => 'act=show', 'icon' => 'show.svg' ], + 'toggle' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['toggle'], + 'icon' => 'visible.svg', + 'toggleProperty' => 'published' + ] ] ], 'metapalettes' => [ @@ -270,6 +275,10 @@ 'rgxp' => 'digit' ], 'sql' => "int(10) unsigned NOT NULL default '1'" + ], + 'published' => [ + 'default' => 1, + 'sql' => "char(1) NOT NULL default '1'" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php index e522b76e7..876a98c5d 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -70,6 +70,9 @@ $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'][1] = 'Delete the definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][0] = 'Definition details'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][1] = 'Show details of definition ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][0] = 'Toggle'; +$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][1] = + 'Toggle the state of definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][0] = 'Definition settings'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][1] = 'Edit the settings of definition ID %s'; From b25ad6b267fb4544f69e84ecf575e744d9395cf5 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 7 Jan 2023 14:08:56 +0100 Subject: [PATCH 119/224] Revert "Add published at sortgroup" This reverts commit c360391d54cab9857e3c289e84e6ef6f62469afd. --- .../Contao2BackendViewDefinitionBuilder.php | 10 ++-------- .../contao/dca/tl_metamodel_dca_sortgroup.php | 9 --------- .../contao/languages/en/tl_metamodel_dca_sortgroup.php | 7 ++----- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php index 125610241..6e3a9d963 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2019 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,8 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2019 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -203,13 +202,8 @@ private function parseListSorting(ListingConfigInterface $listing) if (null === $this->inputScreen) { return; } - $definitions = $listing->getGroupAndSortingDefinition(); foreach ($this->inputScreen['groupSort'] as $information) { - if (!$information['published']) { - continue; - } - $definition = $definitions->add(); $definition->setName($information['name']); if ($information['isdefault'] && !$definitions->hasDefault()) { diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php index 741f05d95..d235de669 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php @@ -136,11 +136,6 @@ 'href' => 'act=show', 'icon' => 'show.svg' ], - 'toggle' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['toggle'], - 'icon' => 'visible.svg', - 'toggleProperty' => 'published' - ] ] ], 'metapalettes' => [ @@ -275,10 +270,6 @@ 'rgxp' => 'digit' ], 'sql' => "int(10) unsigned NOT NULL default '1'" - ], - 'published' => [ - 'default' => 1, - 'sql' => "char(1) NOT NULL default '1'" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php index 876a98c5d..e522b76e7 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -70,9 +70,6 @@ $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'][1] = 'Delete the definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][0] = 'Definition details'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][1] = 'Show details of definition ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][0] = 'Toggle'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][1] = - 'Toggle the state of definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][0] = 'Definition settings'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][1] = 'Edit the settings of definition ID %s'; From bf3c0117de4cf13d048ea1fe61fabc04badf72a4 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 7 Jan 2023 14:09:15 +0100 Subject: [PATCH 120/224] Revert "Add published at sortgroup" This reverts commit c360391d54cab9857e3c289e84e6ef6f62469afd. --- .../Contao2BackendViewDefinitionBuilder.php | 10 ++-------- .../contao/dca/tl_metamodel_dca_sortgroup.php | 9 --------- .../contao/languages/en/tl_metamodel_dca_sortgroup.php | 7 ++----- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php index 125610241..6e3a9d963 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2019 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,8 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2019 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -203,13 +202,8 @@ private function parseListSorting(ListingConfigInterface $listing) if (null === $this->inputScreen) { return; } - $definitions = $listing->getGroupAndSortingDefinition(); foreach ($this->inputScreen['groupSort'] as $information) { - if (!$information['published']) { - continue; - } - $definition = $definitions->add(); $definition->setName($information['name']); if ($information['isdefault'] && !$definitions->hasDefault()) { diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php index 741f05d95..d235de669 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php @@ -136,11 +136,6 @@ 'href' => 'act=show', 'icon' => 'show.svg' ], - 'toggle' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['toggle'], - 'icon' => 'visible.svg', - 'toggleProperty' => 'published' - ] ] ], 'metapalettes' => [ @@ -275,10 +270,6 @@ 'rgxp' => 'digit' ], 'sql' => "int(10) unsigned NOT NULL default '1'" - ], - 'published' => [ - 'default' => 1, - 'sql' => "char(1) NOT NULL default '1'" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php index 876a98c5d..e522b76e7 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2022 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2022 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -70,9 +70,6 @@ $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'][1] = 'Delete the definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][0] = 'Definition details'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][1] = 'Show details of definition ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][0] = 'Toggle'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][1] = - 'Toggle the state of definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][0] = 'Definition settings'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][1] = 'Edit the settings of definition ID %s'; From dc18c1872e3920b6afbbfccd38c8af2d9ec9ce95 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 7 Jan 2023 14:10:08 +0100 Subject: [PATCH 121/224] Add published sortgroup --- .../Contao2BackendViewDefinitionBuilder.php | 4 ++++ .../Resources/contao/dca/tl_metamodel_dca_sortgroup.php | 9 +++++++++ .../contao/languages/en/tl_metamodel_dca_sortgroup.php | 7 +++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php index 6e3a9d963..8b4b0b9cf 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php @@ -204,6 +204,10 @@ private function parseListSorting(ListingConfigInterface $listing) } $definitions = $listing->getGroupAndSortingDefinition(); foreach ($this->inputScreen['groupSort'] as $information) { + if (!$information['published']) { + continue; + } + $definition = $definitions->add(); $definition->setName($information['name']); if ($information['isdefault'] && !$definitions->hasDefault()) { diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php index d235de669..741f05d95 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php @@ -136,6 +136,11 @@ 'href' => 'act=show', 'icon' => 'show.svg' ], + 'toggle' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['toggle'], + 'icon' => 'visible.svg', + 'toggleProperty' => 'published' + ] ] ], 'metapalettes' => [ @@ -270,6 +275,10 @@ 'rgxp' => 'digit' ], 'sql' => "int(10) unsigned NOT NULL default '1'" + ], + 'published' => [ + 'default' => 1, + 'sql' => "char(1) NOT NULL default '1'" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php index e522b76e7..876a98c5d 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -70,6 +70,9 @@ $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'][1] = 'Delete the definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][0] = 'Definition details'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][1] = 'Show details of definition ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][0] = 'Toggle'; +$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][1] = + 'Toggle the state of definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][0] = 'Definition settings'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][1] = 'Edit the settings of definition ID %s'; From a0edaddabdcdceca297d06aa898d36a2c4818924 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 7 Jan 2023 14:10:08 +0100 Subject: [PATCH 122/224] Add published sortgroup --- .../Contao2BackendViewDefinitionBuilder.php | 5 +++++ .../Resources/contao/dca/tl_metamodel_dca_sortgroup.php | 9 +++++++++ .../contao/languages/en/tl_metamodel_dca_sortgroup.php | 7 +++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php index 6e3a9d963..05de7320c 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php @@ -202,8 +202,13 @@ private function parseListSorting(ListingConfigInterface $listing) if (null === $this->inputScreen) { return; } + $definitions = $listing->getGroupAndSortingDefinition(); foreach ($this->inputScreen['groupSort'] as $information) { + if (!$information['published']) { + continue; + } + $definition = $definitions->add(); $definition->setName($information['name']); if ($information['isdefault'] && !$definitions->hasDefault()) { diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php index d235de669..741f05d95 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php @@ -136,6 +136,11 @@ 'href' => 'act=show', 'icon' => 'show.svg' ], + 'toggle' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['toggle'], + 'icon' => 'visible.svg', + 'toggleProperty' => 'published' + ] ] ], 'metapalettes' => [ @@ -270,6 +275,10 @@ 'rgxp' => 'digit' ], 'sql' => "int(10) unsigned NOT NULL default '1'" + ], + 'published' => [ + 'default' => 1, + 'sql' => "char(1) NOT NULL default '1'" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php index e522b76e7..876a98c5d 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -70,6 +70,9 @@ $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'][1] = 'Delete the definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][0] = 'Definition details'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][1] = 'Show details of definition ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][0] = 'Toggle'; +$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][1] = + 'Toggle the state of definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][0] = 'Definition settings'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][1] = 'Edit the settings of definition ID %s'; From 8803d7fcc7ac723eedf33ecbaaa4f7462be4585f Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 8 Jan 2023 19:19:35 +0100 Subject: [PATCH 123/224] Set checkbox disabled if model not variant --- .../Table/Attribute/GetVariantListener.php | 70 +++++++++++++++++++ .../config/dc-general/table/tl_attribute.yml | 7 ++ .../contao/dca/tl_metamodel_attribute.php | 15 ++-- 3 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 src/CoreBundle/EventListener/DcGeneral/Table/Attribute/GetVariantListener.php diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/GetVariantListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/GetVariantListener.php new file mode 100644 index 000000000..e23581afd --- /dev/null +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/GetVariantListener.php @@ -0,0 +1,70 @@ + + * @copyright 2012-2023 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\Attribute; + +use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\BuildWidgetEvent; +use MetaModels\Attribute\IAttributeFactory; +use MetaModels\IFactory; + +/** + * This class provides the attribute variant activation. + */ +class GetVariantListener extends BaseListener +{ + /** + * Create a new instance. + * + * @param RequestScopeDeterminator $scopeDeterminator The scope determinator. + * @param IAttributeFactory $attributeFactory The attribute factory. + * @param IFactory $factory The MetaModel factory. + */ + public function __construct( + RequestScopeDeterminator $scopeDeterminator, + IAttributeFactory $attributeFactory, + IFactory $factory + ) { + parent::__construct($scopeDeterminator, $attributeFactory, $factory); + } + + /** + * Set widget disabled/readonly if model not variant. + * + * @param BuildWidgetEvent $event The event. + * + * @return void + */ + public function buildWidget(BuildWidgetEvent $event) + { + if (!($this->wantToHandle($event) && 'isvariant' === $event->getProperty()->getName())) { + return; + } + + $model = $event->getModel(); + $metaModel = $this->getMetaModelByModelPid($model); + + if (!$metaModel->hasVariants()) { + $extra = $event->getProperty()->getExtra(); + $extra['disabled'] = true; + $event->getProperty()->setExtra($extra); + $model->setProperty('readonly', true); + } + } +} diff --git a/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml b/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml index 7cfc0909e..055f75fef 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml @@ -80,3 +80,10 @@ services: - name: kernel.event_listener event: dc-general.view.contao2backend.encode-property-value-from-widget method: encodeValue + + MetaModels\CoreBundle\EventListener\DcGeneral\Table\Attribute\GetVariantListener: + parent: metamodels.listener.table.tl_metamodel_attribute.listener_base + tags: + - name: kernel.event_listener + event: dc-general.view.contao2backend.build-widget + method: buildWidget diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php index 6a2513a5b..04d7b9e5d 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -39,13 +39,13 @@ ], 'dca_config' => [ 'data_provider' => [ - 'default' => [ + 'default' => [ 'source' => 'tl_metamodel_attribute' ], - 'parent' => [ + 'parent' => [ 'source' => 'tl_metamodel' ], - 'tl_metamodel_rendersetting' => [ + 'tl_metamodel_rendersetting' => [ 'source' => 'tl_metamodel_rendersetting' ], 'tl_metamodel_dcasetting' => [ @@ -54,7 +54,7 @@ 'tl_metamodel_dcasetting_condition' => [ 'source' => 'tl_metamodel_dcasetting_condition' ], - 'tl_metamodel_dca_sortgroup' => [ + 'tl_metamodel_dca_sortgroup' => [ 'source' => 'tl_metamodel_dca_sortgroup' ] ], @@ -315,8 +315,7 @@ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['isvariant'], 'inputType' => 'checkbox', 'eval' => [ - 'submitOnChange' => true, - 'tl_class' => 'w50 cbx m12' + 'tl_class' => 'w50 cbx m12' ], 'filter' => true, 'sql' => "char(1) NOT NULL default ''" From 7ffca9f91ca332317a8ed78bfc98511722839b55 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 12 Jan 2023 09:56:48 +0100 Subject: [PATCH 124/224] Fix language file sortgroup --- .../contao/languages/en/tl_metamodel_dca_sortgroup.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php index 876a98c5d..83f33b642 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php @@ -70,8 +70,8 @@ $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'][1] = 'Delete the definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][0] = 'Definition details'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][1] = 'Show details of definition ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][0] = 'Toggle'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][1] = +$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['toggle'][0] = 'Toggle'; +$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['toggle'][1] = 'Toggle the state of definition ID %s'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][0] = 'Definition settings'; $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][1] = From f3dd180375edef5c142d8c5096f5ed6fb36e9894 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 14 Jan 2023 13:59:19 +0100 Subject: [PATCH 125/224] Change 'dataContainer' to '\ContaoCommunityAlliance\DcGeneral\DC\General::class' --- .../dca/tl_metamodel_dcasetting_condition.php | 30 +- .../contao/dca/tl_metamodel_filter.php | 322 ++++++++---------- .../contao/dca/tl_metamodel_filtersetting.php | 76 ++--- .../dca/tl_metamodel_rendersettings.php | 24 +- .../dca/tl_metamodel_searchable_pages.php | 12 +- 5 files changed, 210 insertions(+), 254 deletions(-) diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php index 8bc11dcf3..882e9390d 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,18 +17,16 @@ * @author Ingolf Steinhardt * @author Richard Henkenjohann * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -/** - * Table tl_metamodel_dcasetting_condition - */ +use ContaoCommunityAlliance\DcGeneral\DC\General; $GLOBALS['TL_DCA']['tl_metamodel_dcasetting_condition'] = [ 'config' => [ - 'dataContainer' => 'General', + 'dataContainer' => General::class, 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['list_label'], 'switchToEdit' => false, 'enableVersioning' => false, @@ -41,10 +39,10 @@ ], 'dca_config' => [ 'data_provider' => [ - 'root' => [ + 'root' => [ 'source' => 'tl_metamodel_dcasetting_condition' ], - 'parent' => [ + 'parent' => [ 'source' => 'tl_metamodel_dcasetting', ], 'tl_metamodel_dcasetting' => [ @@ -53,15 +51,15 @@ ], 'childCondition' => [ [ - 'from' => 'tl_metamodel_dcasetting', - 'to' => 'tl_metamodel_dcasetting_condition', - 'setOn' => [ + 'from' => 'tl_metamodel_dcasetting', + 'to' => 'tl_metamodel_dcasetting_condition', + 'setOn' => [ [ 'to_field' => 'settingId', 'from_field' => 'id', ] ], - 'filter' => [ + 'filter' => [ [ 'local' => 'settingId', 'remote' => 'id', @@ -77,9 +75,9 @@ ] ], [ - 'from' => 'tl_metamodel_dcasetting_condition', - 'to' => 'tl_metamodel_dcasetting_condition', - 'setOn' => [ + 'from' => 'tl_metamodel_dcasetting_condition', + 'to' => 'tl_metamodel_dcasetting_condition', + 'setOn' => [ [ 'to_field' => 'pid', 'from_field' => 'id', @@ -89,7 +87,7 @@ 'from_field' => 'settingId', ], ], - 'filter' => [ + 'filter' => [ [ 'local' => 'pid', 'remote' => 'id', diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php index 188022c74..87f612452 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,216 +18,172 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Cliff Parnitzky - * @copyright 2012-2022 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -/** - * Table tl_metamodel_attribute - */ +use ContaoCommunityAlliance\DcGeneral\DC\General; -$GLOBALS['TL_DCA']['tl_metamodel_filter'] = array -( - 'config' => array - ( - 'dataContainer' => 'General', - 'switchToEdit' => false, - 'enableVersioning' => false, - 'sql' => array - ( - 'keys' => array - ( - 'id' => 'primary', - 'pid' => 'index' - ), - ), - ), +$GLOBALS['TL_DCA']['tl_metamodel_filter'] = [ + 'config' => [ + 'dataContainer' => General::class, + 'switchToEdit' => false, + 'enableVersioning' => false, + 'sql' => [ + 'keys' => [ + 'id' => 'primary', + 'pid' => 'index' + ], + ], + ], - 'dca_config' => array - ( - 'data_provider' => array - ( - 'default' => array - ( - 'source' => 'tl_metamodel_filter' - ), - 'parent' => array - ( - 'source' => 'tl_metamodel' - ), + 'dca_config' => [ + 'data_provider' => [ + 'default' => [ + 'source' => 'tl_metamodel_filter' + ], + 'parent' => [ + 'source' => 'tl_metamodel' + ], - 'tl_metamodel_filtersetting' => array - ( - 'source' => 'tl_metamodel_filtersetting' - ), - ), - 'childCondition' => array - ( - array - ( - 'from' => 'tl_metamodel', - 'to' => 'tl_metamodel_filter', - 'setOn' => array - ( - array - ( - 'to_field' => 'pid', - 'from_field' => 'id', - ), - ), - 'filter' => array - ( - array - ( - 'local' => 'pid', - 'remote' => 'id', - 'operation' => '=', - ), - ), - 'inverse' => array - ( - array - ( - 'local' => 'pid', - 'remote' => 'id', - 'operation' => '=', - ), - ) - ), + 'tl_metamodel_filtersetting' => [ + 'source' => 'tl_metamodel_filtersetting' + ], + ], + 'childCondition' => [ + [ + 'from' => 'tl_metamodel', + 'to' => 'tl_metamodel_filter', + 'setOn' => [ + [ + 'to_field' => 'pid', + 'from_field' => 'id', + ], + ], + 'filter' => [ + [ + 'local' => 'pid', + 'remote' => 'id', + 'operation' => '=', + ], + ], + 'inverse' => [ + [ + 'local' => 'pid', + 'remote' => 'id', + 'operation' => '=', + ], + ] + ], - array( + [ 'from' => 'tl_metamodel_filter', 'to' => 'tl_metamodel_filtersetting', - 'setOn' => array - ( - array - ( + 'setOn' => [ + [ 'to_field' => 'fid', 'from_field' => 'id', - ) - ), - 'filter' => array - ( - array - ( + ] + ], + 'filter' => [ + [ 'local' => 'fid', 'remote' => 'id', 'operation' => '=', - ), - ) - ), - ), - ), + ], + ] + ], + ], + ], - 'list' => array - ( - 'sorting' => array - ( - 'mode' => 4, - 'fields' => array - ( + 'list' => [ + 'sorting' => [ + 'mode' => 4, + 'fields' => [ 'name' - ), - 'panelLayout' => 'filter,sort,limit', - 'headerFields' => array - ( + ], + 'panelLayout' => 'filter,sort,limit', + 'headerFields' => [ 'name' - ), - 'flag' => 1, - ), + ], + 'flag' => 1, + ], - 'label' => array - ( - 'fields' => array - ( + 'label' => [ + 'fields' => [ 'name' - ), - 'format' => '%s' - ), + ], + 'format' => '%s' + ], - 'global_operations' => array - ( - 'all' => array - ( - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' - ) - ), + 'global_operations' => [ + 'all' => [ + 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' + ] + ], - 'operations' => array - ( - 'edit' => array - ( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['edit'], - 'href' => 'act=edit', - 'icon' => 'edit.svg' - ), - 'delete' => array - ( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( + 'operations' => [ + 'edit' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['edit'], + 'href' => 'act=edit', + 'icon' => 'edit.svg' + ], + 'delete' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['delete'], + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => sprintf( 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', $GLOBALS['TL_LANG']['tl_metamodel_filter']['deleteConfirm'] ?? '' ) - ), - 'show' => array - ( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' - ), - 'settings' => array - ( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['settings'], - 'href' => 'table=tl_metamodel_filtersetting', - 'idparam' => 'pid', - 'icon' => 'bundles/metamodelscore/images/icons/filter_setting.png', - ), - ) - ), + ], + 'show' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['show'], + 'href' => 'act=show', + 'icon' => 'show.svg' + ], + 'settings' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['settings'], + 'href' => 'table=tl_metamodel_filtersetting', + 'idparam' => 'pid', + 'icon' => 'bundles/metamodelscore/images/icons/filter_setting.png', + ], + ] + ], - 'metapalettes' => array - ( - 'default' => array - ( - 'title' => array - ( + 'metapalettes' => [ + 'default' => [ + 'title' => [ 'name' - ) - ), - ), + ] + ], + ], - 'fields' => array - ( - 'id' => array - ( + 'fields' => [ + 'id' => [ 'sql' => 'int(10) unsigned NOT NULL auto_increment' - ), - 'pid' => array - ( + ], + 'pid' => [ 'sql' => "int(10) unsigned NOT NULL default '0'" - ), - 'tstamp' => array - ( + ], + 'tstamp' => [ 'sql' => "int(10) unsigned NOT NULL default '0'" - ), - 'name' => array - ( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['name'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => array - ( - 'mandatory' => true, - 'maxlength' => 255, - 'tl_class' => 'w50' - ), - 'sql' => "varchar(255) NOT NULL default ''" - ), - ) -); + ], + 'name' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['name'], + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ + 'mandatory' => true, + 'maxlength' => 255, + 'tl_class' => 'w50' + ], + 'sql' => "varchar(255) NOT NULL default ''" + ], + ] +]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php index 17436edfb..96b10f26c 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -20,18 +20,16 @@ * @author Ingolf Steinhardt * @author Richard Henkenjohann * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -/** - * Table tl_metamodel_attribute - */ +use ContaoCommunityAlliance\DcGeneral\DC\General; $GLOBALS['TL_DCA']['tl_metamodel_filtersetting'] = [ 'config' => [ - 'dataContainer' => 'General', + 'dataContainer' => General::class, 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['list_label'], 'switchToEdit' => false, 'enableVersioning' => false, @@ -53,15 +51,15 @@ ], 'childCondition' => [ [ - 'from' => 'tl_metamodel_filter', - 'to' => 'tl_metamodel_filtersetting', - 'setOn' => [ + 'from' => 'tl_metamodel_filter', + 'to' => 'tl_metamodel_filtersetting', + 'setOn' => [ [ 'to_field' => 'fid', 'from_field' => 'id', ] ], - 'filter' => [ + 'filter' => [ [ 'local' => 'fid', 'remote' => 'id', @@ -256,26 +254,26 @@ ] ], 'fields' => [ - 'id' => [ + 'id' => [ 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], - 'pid' => [ + 'pid' => [ 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'sorting' => [ + 'sorting' => [ 'sorting' => true, 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'tstamp' => [ + 'tstamp' => [ 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'fid' => [ + 'fid' => [ // Keep this empty but keep it here! // needed for act=copy in DC_Table, as otherwise the fid value will not be copied. 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['fid'], 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'type' => [ + 'type' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['type'], 'exclude' => true, 'inputType' => 'select', @@ -290,7 +288,7 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'enabled' => [ + 'enabled' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['enabled'], 'exclude' => true, 'inputType' => 'checkbox', @@ -301,14 +299,14 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'comment' => [ + 'comment' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['comment'], 'exclude' => true, 'inputType' => 'text', 'eval' => ['tl_class' => 'clr long'], 'sql' => "varchar(255) NOT NULL default ''" ], - 'attr_id' => [ + 'attr_id' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['attr_id'], 'exclude' => true, 'inputType' => 'select', @@ -323,7 +321,7 @@ ], 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'all_langs' => [ + 'all_langs' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['all_langs'], 'exclude' => true, 'inputType' => 'checkbox', @@ -333,7 +331,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'items' => [ + 'items' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['items'], 'exclude' => true, 'inputType' => 'textarea', @@ -344,7 +342,7 @@ ], 'sql' => 'text NULL' ], - 'urlparam' => [ + 'urlparam' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['urlparam'], 'exclude' => true, 'inputType' => 'text', @@ -353,7 +351,7 @@ ], 'sql' => "varchar(255) NOT NULL default ''" ], - 'predef_param' => [ + 'predef_param' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['predef_param'], 'exclude' => true, 'inputType' => 'checkbox', @@ -363,7 +361,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'fe_widget' => [ + 'fe_widget' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['fe_widget'], 'exclude' => true, 'inputType' => 'checkbox', @@ -373,7 +371,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'customsql' => [ + 'customsql' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['customsql'], 'exclude' => true, 'inputType' => 'textarea', @@ -390,7 +388,7 @@ 'explanation' => 'customsql', 'sql' => 'text NULL' ], - 'allow_empty' => [ + 'allow_empty' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['allow_empty'], 'exclude' => true, 'inputType' => 'checkbox', @@ -400,7 +398,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'stop_after_match' => [ + 'stop_after_match' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['stop_after_match'], 'exclude' => true, 'inputType' => 'checkbox', @@ -410,7 +408,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'label' => [ + 'label' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['label'], 'exclude' => true, 'inputType' => 'text', @@ -419,7 +417,7 @@ ], 'sql' => 'blob NULL' ], - 'template' => [ + 'template' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['template'], 'default' => 'mm_filteritem_default', 'exclude' => true, @@ -430,7 +428,7 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'blankoption' => [ + 'blankoption' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['blankoption'], 'exclude' => true, 'default' => true, @@ -440,7 +438,7 @@ ], 'sql' => "char(1) NOT NULL default '1'" ], - 'onlyused' => [ + 'onlyused' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['onlyused'], 'exclude' => true, 'default' => true, @@ -451,7 +449,7 @@ ], 'sql' => "char(1) NOT NULL default '0'" ], - 'onlypossible' => [ + 'onlypossible' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['onlypossible'], 'exclude' => true, 'default' => true, @@ -461,7 +459,7 @@ ], 'sql' => "char(1) NOT NULL default '0'" ], - 'skipfilteroptions' => [ + 'skipfilteroptions' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['skipfilteroptions'], 'exclude' => true, 'default' => false, @@ -471,7 +469,7 @@ ], 'sql' => "char(1) NOT NULL default '0'" ], - 'defaultid' => [ + 'defaultid' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['defaultid'], 'exclude' => true, 'inputType' => 'select', @@ -481,7 +479,7 @@ ], 'sql' => "varchar(255) NOT NULL default ''" ], - 'hide_label' => [ + 'hide_label' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['hide_label'], 'exclude' => true, 'default' => false, @@ -501,7 +499,7 @@ ], 'sql' => "char(1) NOT NULL default '0'" ], - 'apply_sorting' => [ + 'apply_sorting' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['apply_sorting'], 'exclude' => true, 'inputType' => 'select', @@ -511,9 +509,9 @@ 'tl_class' => 'w50', 'includeBlankOption' => true ], - 'sql' => ['type' => 'string', 'length' => '24', 'notnull' => false, 'default' => ''] + 'sql' => ['type' => 'string', 'length' => '24', 'notnull' => false, 'default' => ''] ], - 'cssID' => [ + 'cssID' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['cssID'], 'exclude' => true, 'inputType' => 'text', @@ -524,7 +522,7 @@ ], 'sql' => "varchar(255) NOT NULL default ''" ], - 'placeholder' => [ + 'placeholder' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['placeholder'], 'exclude' => true, 'inputType' => 'text', diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php index 7508e8aa8..19efc4225 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,14 +21,16 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Cliff Parnitzky - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ +use ContaoCommunityAlliance\DcGeneral\DC\General; + $GLOBALS['TL_DCA']['tl_metamodel_rendersettings'] = [ 'config' => [ - 'dataContainer' => 'General', + 'dataContainer' => General::class, 'ptable' => 'tl_metamodel', 'switchToEdit' => false, 'enableVersioning' => false, @@ -41,13 +43,13 @@ ], 'dca_config' => [ 'data_provider' => [ - 'default' => [ + 'default' => [ 'source' => 'tl_metamodel_rendersettings' ], - 'parent' => [ + 'parent' => [ 'source' => 'tl_metamodel' ], - 'tl_metamodel_rendersetting' => [ + 'tl_metamodel_rendersetting' => [ 'source' => 'tl_metamodel_rendersetting' ], ], @@ -164,21 +166,21 @@ ], 'metapalettes' => [ 'default' => [ - 'title' => [ + 'title' => [ 'name' ], - 'general' => [ + 'general' => [ 'template', 'format' ], - 'expert' => [ + 'expert' => [ 'hideEmptyValues', 'hideLabels', ], - 'jumpto' => [ + 'jumpto' => [ 'jumpTo' ], - 'additional' => [ + 'additional' => [ ':hide', 'additionalCss', 'additionalJs' diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php index 0be4560e6..ca176d2ed 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,14 +17,16 @@ * @author Richard Henkenjohann * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ +use ContaoCommunityAlliance\DcGeneral\DC\General; + $GLOBALS['TL_DCA']['tl_metamodel_searchable_pages'] = [ 'config' => [ - 'dataContainer' => 'General', + 'dataContainer' => General::class, 'ptable' => 'tl_metamodel', 'switchToEdit' => false, 'enableVersioning' => false, @@ -40,7 +42,7 @@ 'default' => [ 'source' => 'tl_metamodel_searchable_pages' ], - 'parent' => [ + 'parent' => [ 'source' => 'tl_metamodel' ] ], @@ -197,7 +199,7 @@ ], 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'published' => [ + 'published' => [ 'default' => 1, 'sql' => "char(1) NOT NULL default '1'" ] From 111ad7c3124fe1a234dfd854fff94f8b2b20f8aa Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 15 Jan 2023 16:13:55 +0100 Subject: [PATCH 126/224] Fix "PHP Deprecated: strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated" --- src/MetaModel.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/MetaModel.php b/src/MetaModel.php index 9fc539dac..c3a59aac0 100644 --- a/src/MetaModel.php +++ b/src/MetaModel.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,7 +21,7 @@ * @author David Molineus * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -212,11 +212,12 @@ protected function getDatabase() * * @return mixed */ - protected function tryUnserialize($value) + protected function tryUnserialize(mixed $value): mixed { - if (!is_array($value) - && 0 === strpos($value, 'a:') - && is_array($unSerialized = unserialize($value, ['allowed_classes' => false]))) { + if (\is_string($value) + && 0 === \strpos($value, 'a:') + && \is_array($unSerialized = \unserialize($value, ['allowed_classes' => false]))) { + return $unSerialized; } From a3291fd1d4684073acc36ac2abf874b087df3493 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 16 Jan 2023 16:29:33 +0100 Subject: [PATCH 127/224] Fix empty values --- .../Contao2BackendViewDefinitionBuilder.php | 9 +++++---- .../DcGeneral/DefinitionBuilder/PanelBuilder.php | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php index 05de7320c..f1ffab41e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -181,13 +182,13 @@ private function parseListing() } if (null === $listing->getRootIcon()) { - $listing->setRootIcon($this->iconBuilder->getBackendIcon($this->inputScreen['meta']['backendicon'])); + $listing->setRootIcon($this->iconBuilder->getBackendIcon(($this->inputScreen['meta']['backendicon'] ?? ''))); } $this->parseListSorting($listing); $this->parseListLabel($listing); - $listing->setShowColumns((bool) $this->inputScreen['meta']['showColumns']); + $listing->setShowColumns((bool) ($this->inputScreen['meta']['showColumns'] ?? false)); } /** diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PanelBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PanelBuilder.php index ddeca449b..493bc64f9 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PanelBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PanelBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -85,7 +86,7 @@ protected function build(IMetaModelDataDefinition $container) } // Get the panel layout. - $panelLayout = $this->inputScreen['meta']['panelLayout']; + $panelLayout = $this->inputScreen['meta']['panelLayout'] ?? null; // Check if we have a layout. if (empty($panelLayout)) { From d882f989f986799cadd38c16dcd90319838aa685 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 16 Jan 2023 20:52:34 +0100 Subject: [PATCH 128/224] Fix subscribe service --- src/Filter/Setting/CustomSql.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Filter/Setting/CustomSql.php b/src/Filter/Setting/CustomSql.php index 94a9078ae..64c03c414 100644 --- a/src/Filter/Setting/CustomSql.php +++ b/src/Filter/Setting/CustomSql.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,16 +17,14 @@ * @author Oliver Hoff * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\Filter\Setting; -use Contao\Input; use Contao\InsertTags; -use Contao\Session; use Doctrine\DBAL\Connection; use MetaModels\CoreBundle\Contao\InsertTag\ReplaceParam; use MetaModels\CoreBundle\Contao\InsertTag\ReplaceTableName; @@ -123,10 +121,9 @@ public function __construct($collection, $data, ContainerInterface $container) public static function getSubscribedServices() { return [ - Connection::class => Connection::class, - Input::class => Input::class, - InsertTags::class => InsertTags::class, - Session::class => Session::class, + Connection::class => Connection::class, + InsertTags::class => InsertTags::class, + ReplaceParam::class => ReplaceParam::class, // This one is deprecated. IMetaModelsServiceContainer::class => IMetaModelsServiceContainer::class ]; From 3b64a119a69b3f1ff6ca03c1346945c91756a1bc Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 18 Jan 2023 14:34:51 +0100 Subject: [PATCH 129/224] Disconnect TableUpdatungListener - we use the schema manager to manipulate the mm_* tables --- .../Table/MetaModel/TableUpdatingListener.php | 104 ------------------ .../config/dc-general/table/tl_metamodel.yml | 12 -- 2 files changed, 116 deletions(-) delete mode 100644 src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableUpdatingListener.php diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableUpdatingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableUpdatingListener.php deleted file mode 100644 index c8bf4fb6e..000000000 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableUpdatingListener.php +++ /dev/null @@ -1,104 +0,0 @@ - - * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\MetaModel; - -use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; -use ContaoCommunityAlliance\DcGeneral\Event\PostPersistModelEvent; -use ContaoCommunityAlliance\DcGeneral\Event\PreDeleteModelEvent; -use MetaModels\Helper\TableManipulator; - -/** - * This handles table renaming and table deleting. - */ -class TableUpdatingListener extends AbstractAbstainingListener -{ - /** - * The table manipulator. - * - * @var TableManipulator - */ - private $tableManipulator; - - /** - * Create a new instance. - * - * @param RequestScopeDeterminator $scopeDeterminator The scope determinator. - * @param TableManipulator $tableManipulator The table manipulator. - */ - public function __construct(RequestScopeDeterminator $scopeDeterminator, TableManipulator $tableManipulator) - { - parent::__construct($scopeDeterminator); - $this->tableManipulator = $tableManipulator; - } - - /** - * Handle the deletion of a MetaModel and all attached data. - * - * @param PreDeleteModelEvent $event The event. - * - * @return void - */ - public function handleDelete(PreDeleteModelEvent $event) - { - if (!$this->wantToHandle($event)) { - return; - } - - try { - $this->tableManipulator->checkTableExists($tableName = $event->getModel()->getProperty('tableName')); - } catch (\Exception $exception) { - // Exit if table does not exist. - return; - } - - $this->tableManipulator->deleteTable($tableName); - } - - /** - * Handle the update of a MetaModel and all attached data. - * - * @param PostPersistModelEvent $event The event. - * - * @return void - */ - public function handleUpdate(PostPersistModelEvent $event) - { - if (!$this->wantToHandle($event)) { - return; - } - - $old = $event->getOriginalModel(); - $new = $event->getModel(); - $oldTable = $old ? $old->getProperty('tableName') : null; - $newTable = $new->getProperty('tableName'); - - // Table name changed? - if ($oldTable !== $newTable) { - if (!empty($oldTable)) { - $this->tableManipulator->renameTable($oldTable, $newTable); - } else { - $this->tableManipulator->createTable($newTable); - } - } - - $this->tableManipulator->setVariantSupport($newTable, $new->getProperty('varsupport')); - } -} diff --git a/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml b/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml index 862099589..3eafea1de 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml @@ -45,15 +45,3 @@ services: - name: kernel.event_listener event: dc-general.view.contao2backend.encode-property-value-from-widget method: handle - metamodels.listener.table.tl_metamodel.table_updater: - class: MetaModels\CoreBundle\EventListener\DcGeneral\Table\MetaModel\TableUpdatingListener - arguments: - - "@cca.dc-general.scope-matcher" - - "@metamodels.table_manipulator" - tags: - - name: kernel.event_listener - event: dc-general.model.pre-delete - method: handleDelete - - name: kernel.event_listener - event: dc-general.model.post-persist - method: handleUpdate From b2c6c0ada6969f564e2b1b730d96b37ef91c90fe Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 19 Jan 2023 16:58:18 +0100 Subject: [PATCH 130/224] Fix getTemplate call if routing from sitemap.xml --- src/Render/Template.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Render/Template.php b/src/Render/Template.php index 7aeaf08ea..bed56313f 100644 --- a/src/Render/Template.php +++ b/src/Render/Template.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Sven Baumann * @author David Molineus * @author Ingolf Steinhardt - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -310,8 +310,9 @@ protected function getTemplate($strTemplate, $strFormat = 'html5', $blnFailIfNot { $strTemplate = basename($strTemplate); $strCustom = 'templates'; - // Check for a theme folder. - if ($this->scopeDeterminator->currentScopeIsFrontend()) { + + // Check for a theme folder if scope frontend and a normal page. + if (isset($GLOBALS['objPage']) && $this->scopeDeterminator->currentScopeIsFrontend()) { $tmpDir = str_replace('../', '', $GLOBALS['objPage']->templateGroup); if (!empty($tmpDir)) { $strCustom = $tmpDir; From e50c79a360dc981ee17b4a9f64a526a4b1a38f72 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 19 Jan 2023 21:49:21 +0100 Subject: [PATCH 131/224] Rewrite getSearchablePages to sitemap event --- .../GetSearchablePagesListener.php | 205 +++++++++--------- 1 file changed, 105 insertions(+), 100 deletions(-) diff --git a/src/CoreBundle/EventListener/GetSearchablePagesListener.php b/src/CoreBundle/EventListener/GetSearchablePagesListener.php index 16ad9c44a..510c48e0f 100644 --- a/src/CoreBundle/EventListener/GetSearchablePagesListener.php +++ b/src/CoreBundle/EventListener/GetSearchablePagesListener.php @@ -24,79 +24,81 @@ namespace MetaModels\CoreBundle\EventListener; -use Contao\CoreBundle\ServiceAnnotation\Hook; -use Contao\StringUtil; +use Contao\PageModel; use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; use ContaoCommunityAlliance\Contao\Bindings\Events\Controller\GenerateFrontendUrlEvent; use ContaoCommunityAlliance\Contao\Bindings\Events\Controller\GetPageDetailsEvent; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; +use Contao\CoreBundle\Event\ContaoCoreEvents; +use Contao\CoreBundle\Event\SitemapEvent; +use Contao\StringUtil; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\FetchMode; +use Doctrine\DBAL\Exception; use MetaModels\Filter\IFilter; use MetaModels\Filter\Setting\ICollection as IFilterSettingCollection; use MetaModels\Filter\Setting\IFilterSettingFactory; use MetaModels\IFactory; use MetaModels\IMetaModel; -use MetaModels\Item; use MetaModels\ITranslatedMetaModel; +use MetaModels\Item; use MetaModels\Render\Setting\ICollection as IRenderSettingCollection; use MetaModels\Render\Setting\IRenderSettingFactory; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Terminal42\ServiceAnnotationBundle\ServiceAnnotationInterface; +use Terminal42\ServiceAnnotationBundle\Annotation\ServiceTag; /** * Class SearchablePages. */ -class GetSearchablePagesListener implements ServiceAnnotationInterface +class GetSearchablePagesListener { /** * A list with all pages found by Contao. * * @var array */ - protected $foundPages = []; + protected array $foundPages = []; /** * A list with all settings from the database. * * @var array */ - private $configs = []; + private array $configs = []; /** * Database connection. * * @var Connection */ - private $connection; + private Connection $connection; /** * Factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Event dispatcher. * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * Filter setting factory. * * @var IFilterSettingFactory */ - private $filterSettingFactory; + private IFilterSettingFactory $filterSettingFactory; /** * Render setting factory. * * @var IRenderSettingFactory */ - private $renderSettingFactory; + private IRenderSettingFactory $renderSettingFactory; /** * Construct. @@ -122,43 +124,47 @@ public function __construct( } /** - * Start point for the hook getSearchablePages. + * Start point for the contao sitemap event. * - * @param array $pages List with all pages. - * @param int|null $rootPage ID of the root page. - * @param bool|null $fromSiteMap True when called from sitemap generator, null otherwise. - * @param string|null $language The current language. - * - * @return array - * - * @throws \Doctrine\DBAL\DBALException When an database error occur. - * - * @see \RebuildIndex::run() - * @see \Automator::generateSitemap() - * - * @Hook("getSearchablePages") + * @ServiceTag("kernel.event_listener", event=ContaoCoreEvents::SITEMAP) * * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * + * @throws \DOMException|Exception */ - public function __invoke($pages, $rootPage = null, $fromSiteMap = false, $language = null) + public function __invoke(SitemapEvent $event): void { - // Save the pages. - $this->foundPages = $pages; + $this->foundPages = []; + $rootPageIds = $event->getRootPageIds(); + // Run each entry in the published config array. foreach ($this->getConfigs() as $config) { if (!$config['published']) { continue; } - $this->getMetaModelsPages( - $config, - $rootPage, - $language - ); + + foreach ($rootPageIds as $rootPageId) { + $rootPageLanguage = PageModel::findById($rootPageId)->language; + + $this->getMetaModelsPages( + $config, + $rootPageId, + $rootPageLanguage + ); + } } - asort($this->foundPages); + $sitemap = $event->getDocument(); + $urlSet = $sitemap->childNodes[0]; - return $this->foundPages; + foreach ($this->foundPages as $foundPages) { + foreach ((array) $foundPages as $page) { + $loc = $sitemap->createElement('loc', $page); + $urlEl = $sitemap->createElement('url'); + $urlEl->appendChild($loc); + $urlSet->appendChild($urlEl); + } + } } /** @@ -166,7 +172,7 @@ public function __invoke($pages, $rootPage = null, $fromSiteMap = false, $langua * * @return array * - * @throws \Doctrine\DBAL\DBALException When a database error occur. + * @throws Exception When a database error occur. */ protected function getConfigs(): array { @@ -176,9 +182,9 @@ protected function getConfigs(): array ->createQueryBuilder() ->select('t.*') ->from('tl_metamodel_searchable_pages', 't') - ->execute(); + ->executeQuery(); - $this->configs = $statement->fetchAll(FetchMode::ASSOCIATIVE); + $this->configs = $statement->fetchAllAssociative(); } return $this->configs; @@ -188,14 +194,13 @@ protected function getConfigs(): array * Get a MetaModels by name or id. * * @param string|int $identifier The Name or ID of a MetaModels. - * - * @param boolean $ignoreError If true ignore errors like the MetaModels was not found. + * @param bool $ignoreError If true ignore errors like the MetaModels was not found. * * @return IMetaModel|null * * @throws \RuntimeException When the MetaModels is missing. */ - protected function getMetaModel($identifier, $ignoreError): ?IMetaModel + protected function getMetaModel($identifier, bool $ignoreError): ?IMetaModel { // Id to name. if (is_numeric($identifier)) { @@ -205,7 +210,7 @@ protected function getMetaModel($identifier, $ignoreError): ?IMetaModel // Create mm, if yowl is true check if we have really a mm . $metaModels = $this->factory->getMetaModel($identifier); - // If $ignoreError is off and we have no mm throw a new exception. + // If $ignoreError is off, and we have no mm throw a new exception. if (!$ignoreError && null === $metaModels) { throw new \RuntimeException('Could not find the MetaModels with the name ' . $identifier); } @@ -233,7 +238,7 @@ protected function getFilterSettings($identifier): IFilterSettingCollection * * @return IRenderSettingCollection */ - protected function getView($identifier, $view): ?IRenderSettingCollection + protected function getView($identifier, int $view): ?IRenderSettingCollection { $metaModel = $this->getMetaModel($identifier, false); if (null === $metaModel) { @@ -257,21 +262,22 @@ protected function getView($identifier, $view): ?IRenderSettingCollection * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - protected function getLanguage($singleLanguage, $metaModels): array + protected function getLanguage(string $singleLanguage, IMetaModel $metaModels): array { if (!empty($singleLanguage)) { - return array($singleLanguage); + return [$singleLanguage]; } if ($metaModels instanceof ITranslatedMetaModel) { return $metaModels->getLanguages(); } + // Legacy fallback. if ($metaModels->isTranslated() && $metaModels->getAvailableLanguages()) { return $metaModels->getAvailableLanguages(); } - return array(\str_replace('-', '_', $GLOBALS['TL_LANGUAGE'])); + return [\str_replace('-', '_', $GLOBALS['TL_LANGUAGE'])]; } /** @@ -289,24 +295,28 @@ protected function getLanguage($singleLanguage, $metaModels): array * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ - protected function getJumpTosFor($metaModels, $filter, $view, $rootPage = null): array - { + protected function getJumpTosFor( + IMetaModel $metaModels, + IFilter $filter, + IRenderSettingCollection $view, + string $rootPage = null + ): array { $entries = []; $filterAttributes = []; $translated = ($metaModels instanceof ITranslatedMetaModel) || $metaModels->isTranslated(false); $desired = \str_replace('-', '_', $GLOBALS['TL_LANGUAGE']); $fallback = $translated ? (($metaModels instanceof ITranslatedMetaModel) ? $metaModels->getMainLanguage() - : $metaModels->getFallbackLanguage()) : null; + : $metaModels->getFallbackLanguage()) : null; - foreach ((array) $view->get('jumpTo') as $jumpTo) { + foreach ((array)$view->get('jumpTo') as $jumpTo) { $langCode = $jumpTo['langcode']; // If either desired language or fallback, keep the result. if (!$translated || ($langCode === $desired) || ($langCode === $fallback)) { $jumpToFilterSetting = $this->filterSettingFactory->createCollection($jumpTo['filter']); $filterAttributes = $jumpToFilterSetting->getReferencedAttributes(); // If the desired language, break. - // Otherwise try to get the desired one until all have been evaluated. + // Otherwise, try to get the desired one until all have been evaluated. if (!$translated || ($desired === $jumpTo['langcode'])) { break; } @@ -315,16 +325,18 @@ protected function getJumpTosFor($metaModels, $filter, $view, $rootPage = null): // Get the object. /** @var Item $item */ - foreach ($metaModels->findByFilter( - $filter, - '', - 0, - 0, - 'ASC', - array_merge($view->getSettingNames(), $filterAttributes) - ) as $item) { + foreach ( + $metaModels->findByFilter( + $filter, + '', + 0, + 0, + 'ASC', + array_merge($view->getSettingNames(), $filterAttributes) + ) as $item + ) { $jumpTo = $item->buildJumpToLink($view); - $event = new GetPageDetailsEvent((int) $jumpTo['page']); + $event = new GetPageDetailsEvent((int)$jumpTo['page']); $this->dispatcher->dispatch($event, ContaoEvents::CONTROLLER_GET_PAGE_DETAILS); $pageDetails = $event->getPageDetails(); @@ -349,12 +361,12 @@ protected function getJumpTosFor($metaModels, $filter, $view, $rootPage = null): * Get the base URL. * * @param string[] $pageDetails The page details. - * @param null|string $path Additional path settings. + * @param string|null $path Additional path settings. * @param bool $ignoreSSL If active the system will ignore the 'rootUseSSL' flag. * * @return UrlBuilder */ - private function getBaseUrl($pageDetails, $path = null, $ignoreSSL = false): UrlBuilder + private function getBaseUrl(array $pageDetails, string $path = null, bool $ignoreSSL = false): UrlBuilder { $url = new UrlBuilder(); @@ -396,12 +408,12 @@ private function getBaseUrl($pageDetails, $path = null, $ignoreSSL = false): Url * * @return void */ - protected function removeEmptyDetailPages($jumpTos): void + protected function removeEmptyDetailPages(array $jumpTos): void { // Remove the detail pages. foreach ($jumpTos as $jumpTo) { // Get the page from the url. - $event = new GetPageDetailsEvent((int) $jumpTo['value']); + $event = new GetPageDetailsEvent((int)$jumpTo['value']); $this->dispatcher->dispatch($event, ContaoEvents::CONTROLLER_GET_PAGE_DETAILS); $pageDetails = $event->getPageDetails(); @@ -414,14 +426,14 @@ protected function removeEmptyDetailPages($jumpTos): void // Make a full url from it. $baseUrl = $this->getBaseUrl($pageDetails); - if (($strKey = array_search($baseUrl->getUrl(), $this->foundPages)) !== false) { + if (($strKey = \array_search($baseUrl->getUrl(), $this->foundPages)) !== false) { unset($this->foundPages[$strKey]); } // Make a full url from it without the https. $baseUrl = $this->getBaseUrl($pageDetails, null, true); - if (($strKey = array_search($baseUrl->getUrl(), $this->foundPages)) !== false) { + if (($strKey = \array_search($baseUrl->getUrl(), $this->foundPages)) !== false) { unset($this->foundPages[$strKey]); } } @@ -436,7 +448,7 @@ protected function removeEmptyDetailPages($jumpTos): void * * @return array */ - public function setFilterParameters($filterId, $presets, $values) + public function setFilterParameters(string $filterId, array $presets, array $values): array { $filterSettings = $this->getFilterSettings($filterId); $presetNames = $filterSettings->getParameters(); @@ -455,11 +467,11 @@ public function setFilterParameters($filterId, $presets, $values) // * or are overridable. foreach ($feFilterParams as $strParameter) { // Unknown parameter? - next please. - if (!array_key_exists($strParameter, $values)) { + if (!\array_key_exists($strParameter, $values)) { continue; } // Not a preset or allowed to override? - use value. - if ((!array_key_exists($strParameter, $presets)) || $presets[$strParameter]['use_get']) { + if ((!\array_key_exists($strParameter, $presets)) || $presets[$strParameter]['use_get']) { $processed[$strParameter] = $values[$strParameter]; } } @@ -477,34 +489,27 @@ public function setFilterParameters($filterId, $presets, $values) * * @return array * - * @throws \Doctrine\DBAL\DBALException When an database error occur. + * @see \RebuildIndex::run() + * @see \Automator::generateSitemap() * - * @see \RebuildIndex::run() - * @see \Automator::generateSitemap() + * @deprecated Method is deprecated and will get removed. * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function addPages($pages, $rootPage = null, $fromSiteMap = false, $language = null) - { - // Save the pages. - $this->foundPages = $pages; - unset($pages); - - // Run each entry in the published config array. - foreach ($this->getConfigs() as $config) { - if (!$config['published']) { - continue; - } - $this->getMetaModelsPages( - $config, - $rootPage, - $language - ); - } - - asort($this->foundPages); - - return $this->foundPages; + public function addPages( + array $pages, + int $rootPage = null, + ?bool $fromSiteMap = false, + string $language = null + ): array { + // @codingStandardsIgnoreStart + @trigger_error( + '"' . __METHOD__ . '" is deprecated and will get removed.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + + return $pages; } /** @@ -520,9 +525,9 @@ public function addPages($pages, $rootPage = null, $fromSiteMap = false, $langua * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ private function getMetaModelsPages( - $config, - $rootPage = null, - $language = null + array $config, + string $rootPage = null, + string $language = null ): void { $metaModelsIdentifier = $config['pid']; $filterIdentifier = $config['filter']; @@ -534,7 +539,7 @@ private function getMetaModelsPages( $availableLanguages = $this->getLanguage($language, $metaModels); $currentLanguage = $GLOBALS['TL_LANGUAGE']; - $foundPages = [$this->foundPages]; + $foundPages = []; foreach ($availableLanguages as $newLanguage) { // Change language. @@ -571,7 +576,7 @@ private function getMetaModelsPages( $foundPages[] = $newEntries; } - $this->foundPages = array_merge(...$foundPages); + $this->foundPages = \array_merge($this->foundPages, $foundPages); // Reset the language. $GLOBALS['TL_LANGUAGE'] = $currentLanguage; From 6b6264def729d9b0d2804e4f158ea1f71307dd7a Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 20 Jan 2023 08:30:43 +0100 Subject: [PATCH 132/224] Fix code --- .../EventListener/GetSearchablePagesListener.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/CoreBundle/EventListener/GetSearchablePagesListener.php b/src/CoreBundle/EventListener/GetSearchablePagesListener.php index 510c48e0f..52df98ff3 100644 --- a/src/CoreBundle/EventListener/GetSearchablePagesListener.php +++ b/src/CoreBundle/EventListener/GetSearchablePagesListener.php @@ -137,7 +137,7 @@ public function __invoke(SitemapEvent $event): void $this->foundPages = []; $rootPageIds = $event->getRootPageIds(); - // Run each entry in the published config array. + // Run each entry in the published config array and search detail pages. foreach ($this->getConfigs() as $config) { if (!$config['published']) { continue; @@ -154,9 +154,11 @@ public function __invoke(SitemapEvent $event): void } } + // Get sitemap. $sitemap = $event->getDocument(); $urlSet = $sitemap->childNodes[0]; + // Add detail pages. foreach ($this->foundPages as $foundPages) { foreach ((array) $foundPages as $page) { $loc = $sitemap->createElement('loc', $page); @@ -336,7 +338,7 @@ protected function getJumpTosFor( ) as $item ) { $jumpTo = $item->buildJumpToLink($view); - $event = new GetPageDetailsEvent((int)$jumpTo['page']); + $event = new GetPageDetailsEvent((int) $jumpTo['page']); $this->dispatcher->dispatch($event, ContaoEvents::CONTROLLER_GET_PAGE_DETAILS); $pageDetails = $event->getPageDetails(); @@ -413,7 +415,7 @@ protected function removeEmptyDetailPages(array $jumpTos): void // Remove the detail pages. foreach ($jumpTos as $jumpTo) { // Get the page from the url. - $event = new GetPageDetailsEvent((int)$jumpTo['value']); + $event = new GetPageDetailsEvent((int) $jumpTo['value']); $this->dispatcher->dispatch($event, ContaoEvents::CONTROLLER_GET_PAGE_DETAILS); $pageDetails = $event->getPageDetails(); @@ -489,8 +491,8 @@ public function setFilterParameters(string $filterId, array $presets, array $val * * @return array * - * @see \RebuildIndex::run() - * @see \Automator::generateSitemap() + * @see \RebuildIndex::run() + * @see \Automator::generateSitemap() * * @deprecated Method is deprecated and will get removed. * @@ -504,7 +506,7 @@ public function addPages( ): array { // @codingStandardsIgnoreStart @trigger_error( - '"' . __METHOD__ . '" is deprecated and will get removed.', + '"' . __METHOD__ . '" is deprecated and will get removed in 3.0.', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd From 0e02d0c898bb7951f47d63488ef3e06919ee4dec Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 21 Jan 2023 11:15:40 +0100 Subject: [PATCH 133/224] Completly rewrite --- composer.json | 1 + .../GetSearchablePagesListener.php | 566 ++++++------------ src/CoreBundle/Resources/config/hooks.yml | 2 + 3 files changed, 195 insertions(+), 374 deletions(-) diff --git a/composer.json b/composer.json index 269f0fb75..831435130 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,7 @@ }, "require": { "php": "^8.1", + "ext-dom": "*", "contao-community-alliance/dc-general": "^2.3@dev", "contao-community-alliance/events-contao-bindings": "^4.13", "contao-community-alliance/meta-palettes": "^2.0.10", diff --git a/src/CoreBundle/EventListener/GetSearchablePagesListener.php b/src/CoreBundle/EventListener/GetSearchablePagesListener.php index 52df98ff3..68318087e 100644 --- a/src/CoreBundle/EventListener/GetSearchablePagesListener.php +++ b/src/CoreBundle/EventListener/GetSearchablePagesListener.php @@ -24,47 +24,49 @@ namespace MetaModels\CoreBundle\EventListener; -use Contao\PageModel; use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; use ContaoCommunityAlliance\Contao\Bindings\Events\Controller\GenerateFrontendUrlEvent; use ContaoCommunityAlliance\Contao\Bindings\Events\Controller\GetPageDetailsEvent; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; -use Contao\CoreBundle\Event\ContaoCoreEvents; use Contao\CoreBundle\Event\SitemapEvent; use Contao\StringUtil; +use DOMElement; +use DOMException; +use DOMNode; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Exception; +use Environment; +use Generator; use MetaModels\Filter\IFilter; -use MetaModels\Filter\Setting\ICollection as IFilterSettingCollection; use MetaModels\Filter\Setting\IFilterSettingFactory; use MetaModels\IFactory; +use MetaModels\IItem; +use MetaModels\IItems; use MetaModels\IMetaModel; use MetaModels\ITranslatedMetaModel; -use MetaModels\Item; use MetaModels\Render\Setting\ICollection as IRenderSettingCollection; use MetaModels\Render\Setting\IRenderSettingFactory; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Terminal42\ServiceAnnotationBundle\Annotation\ServiceTag; +use RuntimeException; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; + +use function in_array; /** * Class SearchablePages. + * + * @psalm-type TSearchablePageConfig=array{ + * id: int, + * pid: int, + * tstamp: int, + * name: string, + * filter: int, + * filterparams: string, + * rendersetting: int, + * published: string + * } */ class GetSearchablePagesListener { - /** - * A list with all pages found by Contao. - * - * @var array - */ - protected array $foundPages = []; - - /** - * A list with all settings from the database. - * - * @var array - */ - private array $configs = []; - /** * Database connection. * @@ -126,237 +128,211 @@ public function __construct( /** * Start point for the contao sitemap event. * - * @ServiceTag("kernel.event_listener", event=ContaoCoreEvents::SITEMAP) - * - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - * - * @throws \DOMException|Exception + * @throws DOMException|Exception */ public function __invoke(SitemapEvent $event): void { - $this->foundPages = []; $rootPageIds = $event->getRootPageIds(); + $sitemap = $event->getDocument(); + $urlSet = $sitemap->childNodes[0]; // Run each entry in the published config array and search detail pages. - foreach ($this->getConfigs() as $config) { - if (!$config['published']) { - continue; - } + foreach ($this->getPublishedConfigs() as $config) { + $metaModelId = $config['pid']; + $metaModel = $this->getMetaModel($metaModelId); + $filterParams = StringUtil::deserialize($config['filterparams'], true); + $listFilter = $this->getListFilter($metaModel, (string)$config['filter'], $filterParams); + $renderSetting = $this->renderSettingFactory->createCollection($metaModel, $config['rendersetting']); + + // Now loop over all detail pages... + foreach ((array) $renderSetting->get('jumpTo') as $jumpTo) { + if (empty($jumpTo['langcode']) || empty($jumpTo['value']) || empty($jumpTo['filter'])) { + continue; + } - foreach ($rootPageIds as $rootPageId) { - $rootPageLanguage = PageModel::findById($rootPageId)->language; + $event = new GetPageDetailsEvent((int) $jumpTo['value']); + $this->dispatcher->dispatch($event, ContaoEvents::CONTROLLER_GET_PAGE_DETAILS); + $pageDetails = $event->getPageDetails(); - $this->getMetaModelsPages( - $config, - $rootPageId, - $rootPageLanguage - ); - } - } + // If details page not found or root page is not within passed list, continue. + if (empty($pageDetails) || !in_array($pageDetails['rootId'], $rootPageIds, true)) { + continue; + } - // Get sitemap. - $sitemap = $event->getDocument(); - $urlSet = $sitemap->childNodes[0]; - - // Add detail pages. - foreach ($this->foundPages as $foundPages) { - foreach ((array) $foundPages as $page) { - $loc = $sitemap->createElement('loc', $page); - $urlEl = $sitemap->createElement('url'); - $urlEl->appendChild($loc); - $urlSet->appendChild($urlEl); + $this->removePlainDetailsUrl($pageDetails, $urlSet); + + $langCode = $jumpTo['langcode']; + $filterSetting = $this->filterSettingFactory->createCollection($jumpTo['filter']); + $filterAttributes = $filterSetting->getReferencedAttributes(); + + foreach ( + $this->generateUrlsFor( + $metaModel, + $langCode, + $renderSetting, + $pageDetails, + $filterAttributes, + $listFilter + ) as $url + ) { + $loc = $sitemap->createElement('loc', $url); + $urlEl = $sitemap->createElement('url'); + $urlEl->appendChild($loc); + $urlSet->appendChild($urlEl); + } } } } /** - * Get all configs. - * - * @return array - * - * @throws Exception When a database error occur. - */ - protected function getConfigs(): array - { - if (!count($this->configs)) { - // Init the config from database. - $statement = $this->connection - ->createQueryBuilder() - ->select('t.*') - ->from('tl_metamodel_searchable_pages', 't') - ->executeQuery(); - - $this->configs = $statement->fetchAllAssociative(); - } - - return $this->configs; - } - - /** - * Get a MetaModels by name or id. + * Generate URLs for detail page. * - * @param string|int $identifier The Name or ID of a MetaModels. - * @param bool $ignoreError If true ignore errors like the MetaModels was not found. + * @param IMetaModel $metaModel The MetaModel. + * @param string $language The language. + * @param IRenderSettingCollection $renderSetting The render settings for the detail page. + * @param array $pageDetails The page information for the detail page. + * @param array $filterAttributes The filter attributes. + * @param IFilter $listFilter The list filter. * - * @return IMetaModel|null - * - * @throws \RuntimeException When the MetaModels is missing. + * @return Generator */ - protected function getMetaModel($identifier, bool $ignoreError): ?IMetaModel - { - // Id to name. - if (is_numeric($identifier)) { - $identifier = $this->factory->translateIdToMetaModelName($identifier); - } + private function generateUrlsFor( + IMetaModel $metaModel, + string $language, + IRenderSettingCollection $renderSetting, + array $pageDetails, + array $filterAttributes, + IFilter $listFilter + ): Generator { + // Save language. + $currentLanguage = $GLOBALS['TL_LANGUAGE']; + + // Try to generate URLs. + try { + if ($metaModel instanceof ITranslatedMetaModel) { + $prevLanguage = $metaModel->selectLanguage($language); + } + $GLOBALS['TL_LANGUAGE'] = $language; - // Create mm, if yowl is true check if we have really a mm . - $metaModels = $this->factory->getMetaModel($identifier); + $items = $metaModel->findByFilter( + $listFilter, + '', + 0, + 0, + 'ASC', + array_merge($renderSetting->getSettingNames(), $filterAttributes) + ); - // If $ignoreError is off, and we have no mm throw a new exception. - if (!$ignoreError && null === $metaModels) { - throw new \RuntimeException('Could not find the MetaModels with the name ' . $identifier); + foreach ($this->buildUrlsForItems($items, $renderSetting, $pageDetails) as $url) { + yield $url; + } + } finally { + // Reset language. + $GLOBALS['TL_LANGUAGE'] = $currentLanguage; + if (isset($prevLanguage) && $metaModel instanceof ITranslatedMetaModel) { + $metaModel->selectLanguage($prevLanguage); + } } - - return $metaModels; } /** - * Get a filter based on the id. + * Get all published index configs. * - * @param mixed $identifier Id of the filter. + * @return Generator * - * @return IFilterSettingCollection The filter + * @throws Exception When a database error occur. */ - protected function getFilterSettings($identifier): IFilterSettingCollection + private function getPublishedConfigs(): Generator { - return $this->filterSettingFactory->createCollection($identifier); + $statement = $this->connection + ->createQueryBuilder() + ->select('t.*') + ->from('tl_metamodel_searchable_pages', 't') + ->where('t.published=1') + ->executeQuery(); + + foreach ($statement->fetchAllAssociative() as $config) { + yield $config; + } } /** - * Get the view for a MetaModels. + * Calculate list filter. * - * @param string|int $identifier ID/Name of the MetaModels. - * @param int $view ID of the view. + * @param IMetaModel $metaModel The MetaModel. + * @param string $filterId The id of the filter. + * @param array $presets The parameter preset values to use. * - * @return IRenderSettingCollection + * @return IFilter */ - protected function getView($identifier, int $view): ?IRenderSettingCollection + private function getListFilter(IMetaModel $metaModel, string $filterId, array $presets): IFilter { - $metaModel = $this->getMetaModel($identifier, false); - if (null === $metaModel) { - return null; + $filterSettings = $this->filterSettingFactory->createCollection($filterId); + $presetNames = $filterSettings->getParameters(); + $processed = []; + + // We have to use all the preset values we want first. + foreach ($presets as $presetName => $arrPreset) { + if (in_array($presetName, $presetNames, true)) { + $processed[$presetName] = $arrPreset['value']; + } } - return $this->renderSettingFactory->createCollection($metaModel, $view); + // Create a new filter for the search. + $filter = $metaModel->getEmptyFilter(); + $filterSettings->addRules($filter, $processed); + + return $filter; } /** - * Get the language. - * - * First check the overwrite language. Then check if the MetaModels is translated and get all languages from it. - * Use the current language as fallback. + * Get a MetaModels by name or id. * - * @param string $singleLanguage The language with the overwrite. - * @param IMetaModel $metaModels The MetaModels for the check. + * @param string $identifier The Name or ID of a MetaModels. * - * @return string[] A list with all languages or null. + * @return IMetaModel * - * @SuppressWarnings(PHPMD.Superglobals) - * @SuppressWarnings(PHPMD.CamelCaseVariableName) + * @throws RuntimeException When the MetaModels is missing. */ - protected function getLanguage(string $singleLanguage, IMetaModel $metaModels): array + private function getMetaModel(string $identifier): IMetaModel { - if (!empty($singleLanguage)) { - return [$singleLanguage]; - } - - if ($metaModels instanceof ITranslatedMetaModel) { - return $metaModels->getLanguages(); - } + // Translate id to name. + $identifier = $this->factory->translateIdToMetaModelName($identifier); + $metaModel = $this->factory->getMetaModel($identifier); - // Legacy fallback. - if ($metaModels->isTranslated() && $metaModels->getAvailableLanguages()) { - return $metaModels->getAvailableLanguages(); + // If we have no mm throw a new exception. + if (null === $metaModel) { + throw new RuntimeException('Could not find the MetaModels with the name ' . $identifier); } - return [\str_replace('-', '_', $GLOBALS['TL_LANGUAGE'])]; + return $metaModel; } /** - * Get the list of jumpTos based on the items. + * Build URL for every item to detail page. * - * @param IMetaModel $metaModels The MetaModels to be used. - * @param IFilter $filter The filter to be used. - * @param IRenderSettingCollection $view The view to be used. - * @param string|null $rootPage The root page id or null if there is no root page. + * @param IItems $items The items to process. + * @param IRenderSettingCollection $renderSetting The render settings for the detail page. + * @param array $pageDetails The page information for the detail page. * - * @return array A list of urls for the jumpTos - * - * @SuppressWarnings(PHPMD.Superglobals) - * @SuppressWarnings(PHPMD.CamelCaseVariableName) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) + * @return Generator */ - protected function getJumpTosFor( - IMetaModel $metaModels, - IFilter $filter, - IRenderSettingCollection $view, - string $rootPage = null - ): array { - $entries = []; - $filterAttributes = []; - $translated = ($metaModels instanceof ITranslatedMetaModel) || $metaModels->isTranslated(false); - $desired = \str_replace('-', '_', $GLOBALS['TL_LANGUAGE']); - $fallback = $translated - ? (($metaModels instanceof ITranslatedMetaModel) ? $metaModels->getMainLanguage() - : $metaModels->getFallbackLanguage()) : null; - - foreach ((array)$view->get('jumpTo') as $jumpTo) { - $langCode = $jumpTo['langcode']; - // If either desired language or fallback, keep the result. - if (!$translated || ($langCode === $desired) || ($langCode === $fallback)) { - $jumpToFilterSetting = $this->filterSettingFactory->createCollection($jumpTo['filter']); - $filterAttributes = $jumpToFilterSetting->getReferencedAttributes(); - // If the desired language, break. - // Otherwise, try to get the desired one until all have been evaluated. - if (!$translated || ($desired === $jumpTo['langcode'])) { - break; - } - } - } - - // Get the object. - /** @var Item $item */ - foreach ( - $metaModels->findByFilter( - $filter, - '', - 0, - 0, - 'ASC', - array_merge($view->getSettingNames(), $filterAttributes) - ) as $item - ) { - $jumpTo = $item->buildJumpToLink($view); - $event = new GetPageDetailsEvent((int) $jumpTo['page']); - $this->dispatcher->dispatch($event, ContaoEvents::CONTROLLER_GET_PAGE_DETAILS); - $pageDetails = $event->getPageDetails(); - - // If there is a root page check the context or if we have no page continue. - if (empty($pageDetails) || ($rootPage !== null && $pageDetails['rootId'] != $rootPage)) { - continue; - } - - $url = UrlBuilder::fromUrl($jumpTo['url']); + private function buildUrlsForItems( + IItems $items, + IRenderSettingCollection $renderSetting, + array $pageDetails + ): Generator { + foreach ($items as $item) { + assert($item instanceof IItem); + $jumpTo = $item->buildJumpToLink($renderSetting); + $url = UrlBuilder::fromUrl($jumpTo['url']); if (null === $url->getScheme()) { // Build the absolute url. $url = $this->getBaseUrl($pageDetails, $jumpTo['url']); } - $entries[] = $url->getUrl(); + yield $url->getUrl(); } - - return $entries; } /** @@ -364,223 +340,65 @@ protected function getJumpTosFor( * * @param string[] $pageDetails The page details. * @param string|null $path Additional path settings. - * @param bool $ignoreSSL If active the system will ignore the 'rootUseSSL' flag. * * @return UrlBuilder */ - private function getBaseUrl(array $pageDetails, string $path = null, bool $ignoreSSL = false): UrlBuilder + private function getBaseUrl(array $pageDetails, string $path = null): UrlBuilder { $url = new UrlBuilder(); - // Set the domain (see contao/core#6421) - if ($pageDetails['domain']) { - $url->setHost($pageDetails['domain']); - } else { - $url->setHost(\Environment::get('host')); - } - - if ($pageDetails['rootUseSSL'] && !$ignoreSSL) { - $url->setScheme('https'); - } else { - $url->setScheme('http'); - } - - // Make an array for the parts. - $fullPath = []; - $fullPath[] = TL_PATH; + $url->setHost($pageDetails['domain'] ?: Environment::get('host')); + $url->setScheme($pageDetails['rootUseSSL'] ? 'https' : 'http'); // Get the path. if ($path === null) { $event = new GenerateFrontendUrlEvent($pageDetails, null, $pageDetails['language'], true); $this->dispatcher->dispatch($event, ContaoEvents::CONTROLLER_GENERATE_FRONTEND_URL); - $fullPath[] = $event->getUrl(); + $url->setPath($event->getUrl()); } else { - $fullPath[] = $path; + $url->setPath($path); } - $url->setPath(implode('/', $fullPath)); - return $url; } /** - * Remove all empty detail pages. + * Remove the plain details URL from the sitemap to omit 404 without filter url. * - * @param array $jumpTos A list with the jumpTo pages. + * @param array $pageDetails The page details information. + * @param DOMElement $urlSet The list of URLs. * * @return void */ - protected function removeEmptyDetailPages(array $jumpTos): void + public function removePlainDetailsUrl(array $pageDetails, DOMElement $urlSet): void { - // Remove the detail pages. - foreach ($jumpTos as $jumpTo) { - // Get the page from the url. - $event = new GetPageDetailsEvent((int) $jumpTo['value']); - $this->dispatcher->dispatch($event, ContaoEvents::CONTROLLER_GET_PAGE_DETAILS); - - $pageDetails = $event->getPageDetails(); - - // Check if we have a page - if not go to the next one. - if (empty($pageDetails)) { + $removeUrl = $this->getBaseUrl($pageDetails)->getUrl(); + foreach ($urlSet->childNodes as $childNode) { + if (!$this->isDomElement($childNode, 'url')) { continue; } - // Make a full url from it. - $baseUrl = $this->getBaseUrl($pageDetails); - - if (($strKey = \array_search($baseUrl->getUrl(), $this->foundPages)) !== false) { - unset($this->foundPages[$strKey]); - } - - // Make a full url from it without the https. - $baseUrl = $this->getBaseUrl($pageDetails, null, true); + foreach ($childNode->childNodes as $childNode2) { + if (!$this->isDomElement($childNode2, 'loc') || trim($childNode2->nodeValue) !== $removeUrl) { + continue; + } + $childNode->parentNode->removeChild($childNode); - if (($strKey = \array_search($baseUrl->getUrl(), $this->foundPages)) !== false) { - unset($this->foundPages[$strKey]); + return; } } } /** - * Set parameters. + * Check if right DOM element. * - * @param string $filterId The id of the filter. - * @param string[] $presets The parameter preset values to use. - * @param string[] $values The dynamic parameter values that may be used. + * @param DOMNode $node The node. + * @param string $nodeName The node name. * - * @return array + * @return bool */ - public function setFilterParameters(string $filterId, array $presets, array $values): array + private function isDomElement(DOMNode $node, string $nodeName): bool { - $filterSettings = $this->getFilterSettings($filterId); - $presetNames = $filterSettings->getParameters(); - $feFilterParams = array_keys($filterSettings->getParameterFilterNames()); - $processed = []; - - // We have to use all the preset values we want first. - foreach ($presets as $strPresetName => $arrPreset) { - if (in_array($strPresetName, $presetNames, true)) { - $processed[$strPresetName] = $arrPreset['value']; - } - } - - // Now we have to use all FE filter params, that are either: - // * not contained within the presets - // * or are overridable. - foreach ($feFilterParams as $strParameter) { - // Unknown parameter? - next please. - if (!\array_key_exists($strParameter, $values)) { - continue; - } - // Not a preset or allowed to override? - use value. - if ((!\array_key_exists($strParameter, $presets)) || $presets[$strParameter]['use_get']) { - $processed[$strParameter] = $values[$strParameter]; - } - } - - return $processed; - } - - /** - * Start point for the hook getSearchablePages. - * - * @param array $pages List with all pages. - * @param int|null $rootPage ID of the root page. - * @param bool|null $fromSiteMap True when called from sitemap generator, null otherwise. - * @param string|null $language The current language. - * - * @return array - * - * @see \RebuildIndex::run() - * @see \Automator::generateSitemap() - * - * @deprecated Method is deprecated and will get removed. - * - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function addPages( - array $pages, - int $rootPage = null, - ?bool $fromSiteMap = false, - string $language = null - ): array { - // @codingStandardsIgnoreStart - @trigger_error( - '"' . __METHOD__ . '" is deprecated and will get removed in 3.0.', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd - - return $pages; - } - - /** - * Get a MetaModels, a filter and a renderSetting. Get all items based on the filter and build the jumpTo urls. - * - * @param array $config ID of the MetaModels. - * @param string|null $rootPage The root page id or null if there is no root page. - * @param string|null $language The current language. - * - * @return void - * - * @SuppressWarnings(PHPMD.Superglobals) - * @SuppressWarnings(PHPMD.CamelCaseVariableName) - */ - private function getMetaModelsPages( - array $config, - string $rootPage = null, - string $language = null - ): void { - $metaModelsIdentifier = $config['pid']; - $filterIdentifier = $config['filter']; - $presetParams = StringUtil::deserialize($config['filterparams'], true); - $renderSettingId = $config['rendersetting']; - - // Get the MetaModels. - $metaModels = $this->getMetaModel($metaModelsIdentifier, false); - $availableLanguages = $this->getLanguage($language, $metaModels); - $currentLanguage = $GLOBALS['TL_LANGUAGE']; - - $foundPages = []; - - foreach ($availableLanguages as $newLanguage) { - // Change language. - $GLOBALS['TL_LANGUAGE'] = \str_replace('_', '-', $newLanguage); - if ($metaModels instanceof ITranslatedMetaModel) { - $prevLanguage = $metaModels->selectLanguage($newLanguage); - } - - // Get the view. - $view = $this->getView($metaModelsIdentifier, $renderSettingId); - $jumpTos = $view->get('jumpTo'); - - // Set the filter. - $processed = $this->setFilterParameters($filterIdentifier, $presetParams, []); - - // Create a new filter for the search. - $filter = $metaModels->getEmptyFilter(); - $filterSetting = $this->getFilterSettings($filterIdentifier); - $filterSetting->addRules($filter, $processed); - - // Get all jumpTos. - $newEntries = $this->getJumpTosFor($metaModels, $filter, $view, $rootPage); - - // Remove all empty page details. - $this->removeEmptyDetailPages($jumpTos); - - // Reset language. - $GLOBALS['TL_LANGUAGE'] = $currentLanguage; - if ($metaModels instanceof ITranslatedMetaModel) { - $metaModels->selectLanguage($prevLanguage); - } - - // Merge all results. - $foundPages[] = $newEntries; - } - - $this->foundPages = \array_merge($this->foundPages, $foundPages); - - // Reset the language. - $GLOBALS['TL_LANGUAGE'] = $currentLanguage; + return ($node instanceof DOMElement) && $node->nodeName === $nodeName; } } diff --git a/src/CoreBundle/Resources/config/hooks.yml b/src/CoreBundle/Resources/config/hooks.yml index e0364f3ab..78412536d 100644 --- a/src/CoreBundle/Resources/config/hooks.yml +++ b/src/CoreBundle/Resources/config/hooks.yml @@ -39,6 +39,8 @@ services: - '@event_dispatcher' - '@metamodels.filter_setting_factory' - '@metamodels.render_setting_factory' + tags: + - { name: 'kernel.event_listener', event: 'contao.sitemap' } MetaModels\CoreBundle\EventListener\InsertTagsListener: arguments: From 5bd7aaab93dae3333fa2d3d0eb2a49e523f65c15 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sat, 21 Jan 2023 22:19:46 +0100 Subject: [PATCH 134/224] Add hints to masks of model and attribute to use a migration --- .../AttributeSchemaManagerHintListener.php | 81 +++++++++++++++++++ .../ModelSchemaManagerHintListener.php | 72 +++++++++++++++++ .../config/dc-general/table/tl_attribute.yml | 9 +++ .../config/dc-general/table/tl_metamodel.yml | 9 +++ .../contao/languages/en/tl_metamodel.php | 8 +- .../languages/en/tl_metamodel_attribute.php | 8 +- 6 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSchemaManagerHintListener.php create mode 100644 src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelSchemaManagerHintListener.php diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSchemaManagerHintListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSchemaManagerHintListener.php new file mode 100644 index 000000000..fc2921b34 --- /dev/null +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSchemaManagerHintListener.php @@ -0,0 +1,81 @@ + + * @copyright 2012-2023 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\Attribute; + +use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\Event\PreEditModelEvent; +use Contao\Message; +use MetaModels\Attribute\IAttributeFactory; +use MetaModels\IFactory; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * This class takes care of updating all data when an attribute has been saved. + */ +class AttributeSchemaManagerHintListener extends BaseListener +{ + /** + * The translator. + * + * @var TranslatorInterface + */ + private $translator; + + + /** + * Create a new instance. + * + * @param RequestScopeDeterminator $scopeDeterminator The scope determinator. + * @param IAttributeFactory $attributeFactory The attribute factory. + * @param IFactory $factory The MetaModel factory. + * @param TranslatorInterface $translator The translator. + */ + public function __construct( + RequestScopeDeterminator $scopeDeterminator, + IAttributeFactory $attributeFactory, + IFactory $factory, + TranslatorInterface $translator + ) { + parent::__construct($scopeDeterminator, $attributeFactory, $factory); + $this->translator = $translator; + } + + /** + * Add hint at attribute. + * + * @param PreEditModelEvent $event The event. + * + * @return void + */ + public function handle(PreEditModelEvent $event): void + { + if (!$this->wantToHandle($event)) { + return; + } + + Message::addInfo( + $this->translator->trans( + 'tl_metamodel_attribute.hint_schema_manager', + [], + 'contao_tl_metamodel_attribute' + ) + ); + } +} diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelSchemaManagerHintListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelSchemaManagerHintListener.php new file mode 100644 index 000000000..4131e8f3c --- /dev/null +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelSchemaManagerHintListener.php @@ -0,0 +1,72 @@ + + * @copyright 2012-2023 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\MetaModel; + +use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\Event\PreEditModelEvent; +use Contao\Message; +use Symfony\Contracts\Translation\TranslatorInterface; + +class ModelSchemaManagerHintListener extends AbstractAbstainingListener +{ + /** + * The translator. + * + * @var TranslatorInterface + */ + private $translator; + + + /** + * Create a new instance. + * + * @param RequestScopeDeterminator $scopeDeterminator The scope determinator. + * @param TranslatorInterface $translator The translator. + */ + public function __construct( + RequestScopeDeterminator $scopeDeterminator, + TranslatorInterface $translator + ) { + parent::__construct($scopeDeterminator); + $this->translator = $translator; + } + + /** + * Add hint at attribute. + * + * @param PreEditModelEvent $event The event. + * + * @return void + */ + public function handle(PreEditModelEvent $event): void + { + if (!$this->wantToHandle($event)) { + return; + } + + Message::addInfo( + $this->translator->trans( + 'tl_metamodel.hint_schema_manager', + [], + 'contao_tl_metamodel' + ) + ); + } +} diff --git a/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml b/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml index 055f75fef..ddf34f008 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml @@ -87,3 +87,12 @@ services: - name: kernel.event_listener event: dc-general.view.contao2backend.build-widget method: buildWidget + + MetaModels\CoreBundle\EventListener\DcGeneral\Table\Attribute\AttributeSchemaManagerHintListener: + parent: metamodels.listener.table.tl_metamodel_attribute.listener_base + arguments: + - "@translator" + tags: + - name: kernel.event_listener + event: dc-general.model.pre-edit-model + method: handle diff --git a/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml b/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml index 3eafea1de..9e7cb23e7 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml @@ -45,3 +45,12 @@ services: - name: kernel.event_listener event: dc-general.view.contao2backend.encode-property-value-from-widget method: handle + + MetaModels\CoreBundle\EventListener\DcGeneral\Table\MetaModel\ModelSchemaManagerHintListener: + arguments: + - "@cca.dc-general.scope-matcher" + - "@translator" + tags: + - name: kernel.event_listener + event: dc-general.model.pre-edit-model + method: handle diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php index c058f160d..6d0e29ba4 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Christian de la Haye * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -85,3 +85,7 @@ $GLOBALS['TL_LANG']['tl_metamodel']['itemFormatCount']['1'] = '%s item'; $GLOBALS['TL_LANG']['tl_metamodel']['itemFormatCount']['2:'] = '%s items'; $GLOBALS['TL_LANG']['tl_metamodel']['deleteConfirm'] = 'Do you really want to delete MetaModel ID %s?'; + +$GLOBALS['TL_LANG']['tl_metamodel']['hint_schema_manager'] = + 'After creating a model, the database must be migrated (console, Contao Manager) -' . + ' even if the table name is changed. When changing the table name, the user data itself must be transferred.'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php index fc69c261c..aa01a4596 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -67,3 +67,7 @@ 'Extension missing? The attribute type "%s" is not installed.'; $GLOBALS['TL_LANG']['tl_metamodel_attribute']['deleteConfirm'] = 'Do you really want to delete attribute ID %s?'; + +$GLOBALS['TL_LANG']['tl_metamodel_attribute']['hint_schema_manager'] = + 'After creating a attribute, the database must be migrated (console, Contao Manager) -' . + ' even if the column name is changed. When changing the column name, the user data itself must be transferred.'; From 7907cdfbe2d16982d45a082bc5078216127d42a8 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 25 Jan 2023 16:31:39 +0100 Subject: [PATCH 135/224] Rework MM inserttags --- .../EventListener/InsertTagsListener.php | 201 +++++++++++------- src/CoreBundle/Resources/config/hooks.yml | 3 + 2 files changed, 131 insertions(+), 73 deletions(-) diff --git a/src/CoreBundle/EventListener/InsertTagsListener.php b/src/CoreBundle/EventListener/InsertTagsListener.php index e5fad250d..bd6839f7a 100644 --- a/src/CoreBundle/EventListener/InsertTagsListener.php +++ b/src/CoreBundle/EventListener/InsertTagsListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,26 +17,24 @@ * @author David Molineus * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener; -use Contao\CoreBundle\ServiceAnnotation\Hook; use Contao\StringUtil; use Contao\Input; -use Contao\System; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\FetchMode; +use Doctrine\DBAL\Exception; use MetaModels\Filter\Rules\StaticIdList; use MetaModels\Filter\Setting\IFilterSettingFactory; use MetaModels\IFactory; use MetaModels\IMetaModel; use MetaModels\ItemList; use MetaModels\Render\Setting\IRenderSettingFactory; -use Terminal42\ServiceAnnotationBundle\ServiceAnnotationInterface; +use Psr\Log\LoggerInterface; /** * This class handles the replacement of all MetaModels insert tags. @@ -50,45 +48,52 @@ * mm::total::mm::[MM Name|ID](::[ID filter]) * * -- Item -- - * mm::item::[MM Name|ID]::[Item ID|ID,ID,ID]::[ID render setting](::[Output raw|text|html|..]) + * mm::item::[MM Name|ID]::[Item ID|ID,ID,ID]::[ID render setting](::[Output raw|text|html5]) * * -- Attribute -- - * mm::attribute::[MM Name|ID]::[Item ID]::[Attribute Name|ID](::[Output raw|text|html|..]) + * mm::attribute::[MM Name|ID]::[Item ID]::[Attribute Name|ID](::[Output (Default:text)|raw|html5]) * * -- JumpTo -- * mm::jumpTo::[MM Name|ID]::[Item ID]::[ID render setting](::[Parameter (Default:url)|label|page|params.attname]) * * @codingStandardsIgnoreEnd */ -class InsertTagsListener implements ServiceAnnotationInterface +final class InsertTagsListener { /** * Database connection. * * @var Connection */ - private $connection; + private Connection $connection; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The render setting factory. * * @var IRenderSettingFactory */ - private $renderSettingFactory; + private IRenderSettingFactory $renderSettingFactory; /** * The filter setting factory. * * @var IFilterSettingFactory */ - private $filterSettingFactory; + private IFilterSettingFactory $filterSettingFactory; + + /** + * The logger interface. + * + * @var LoggerInterface|null + */ + private ?LoggerInterface $logger; /** * InsertTagsListener constructor. @@ -97,17 +102,20 @@ class InsertTagsListener implements ServiceAnnotationInterface * @param IFactory $factory The MetaModels factory. * @param IRenderSettingFactory $renderSettingFactory The render setting factory. * @param IFilterSettingFactory $filterSettingFactory The filter setting factory. + * @param LoggerInterface|null $logger The logger interface. */ public function __construct( Connection $connection, IFactory $factory, IRenderSettingFactory $renderSettingFactory, - IFilterSettingFactory $filterSettingFactory + IFilterSettingFactory $filterSettingFactory, + LoggerInterface $logger = null ) { $this->connection = $connection; $this->factory = $factory; $this->renderSettingFactory = $renderSettingFactory; $this->filterSettingFactory = $filterSettingFactory; + $this->logger = $logger; } /** @@ -115,13 +123,11 @@ public function __construct( * * @param string $insertTag The tag to evaluate. * - * @return bool|string - * - * @Hook("replaceInsertTags") + * @return bool|int|string */ - public function __invoke($insertTag) + public function __invoke(string $insertTag): bool|int|string { - $elements = explode('::', $insertTag); + $elements = \explode('::', $insertTag); // Check if we have the mm tags. if ('mm' !== $elements[0]) { @@ -133,23 +139,26 @@ public function __invoke($insertTag) switch ($elements[1]) { // Count for mod or ce elements. case 'total': - return $this->getCount($elements[2], $elements[3], $elements[4]); + return $this->getCount($elements[2], $elements[3], ($elements[4] ?? null)); // Get value from an attribute. case 'attribute': - return $this->getAttribute($elements[2], $elements[3], $elements[4], $elements[5]); + return $this->getAttribute($elements[2], $elements[3], $elements[4], ($elements[5] ?? null)); // Get item. case 'item': - return $this->getItem($elements[2], $elements[3], $elements[4], $elements[5]); + return $this->getItem($elements[2], $elements[3], $elements[4], ($elements[5] ?? null)); + // Get jump-to detail page. case 'jumpTo': - return $this->jumpTo($elements[2], $elements[3], $elements[4], $elements[5]); + return $this->jumpTo($elements[2], $elements[3], $elements[4], ($elements[5] ?? null)); default: } } catch (\Exception $exc) { - System::log('Error by replace tags: ' . $exc->getMessage(), __CLASS__ . ' | ' . __FUNCTION__, TL_ERROR); + $this->logger?->error( + 'Error by replace tags: ' . $exc->getMessage() . ' | ' . __CLASS__ . ' | ' . __FUNCTION__ + ); } return false; @@ -158,17 +167,19 @@ public function __invoke($insertTag) /** * Get the jumpTo for a chosen value. * - * @param string|int $mixMetaModel ID or name of MetaModels. - * + * @param int|string $mixMetaModel ID or name of MetaModels. * @param int $mixDataId ID of the data row. - * * @param int $viewId ID of render setting. - * * @param string $strParam Name of parameter - Default:url|label|page|params.[attrname]. * - * @return boolean|string Return false when nothing was found for the requested value. + * @return bool|string Return false when nothing was found for the requested value. */ - protected function jumpTo($mixMetaModel, $mixDataId, $viewId, $strParam = 'url') + private function jumpTo( + int|string $mixMetaModel, + int $mixDataId, + int $viewId, + string $strParam = 'url' + ): bool|string { // Set the param to url if empty. if (empty($strParam)) { @@ -201,7 +212,7 @@ protected function jumpTo($mixMetaModel, $mixDataId, $viewId, $strParam = 'url') // Check if someone want the sub params. if (stripos($strParam, 'params.') !== false) { $mixAttName = StringUtil::trimsplit('.', $strParam); - $mixAttName = array_pop($mixAttName); + $mixAttName = \array_pop($mixAttName); if (isset($arrRenderedItem['jumpTo']['params'][$mixAttName])) { return $arrRenderedItem['jumpTo']['params'][$mixAttName]; @@ -218,14 +229,19 @@ protected function jumpTo($mixMetaModel, $mixDataId, $viewId, $strParam = 'url') /** * Get an item. * - * @param string|int $metaModelIdOrName ID or name of MetaModels. - * @param string|int $mixDataId ID of the data row. - * @param int $viewId ID of render setting. - * @param string $strOutput Name of output. Default:null (fallback to html5)|text|html5|... + * @param int|string $metaModelIdOrName ID or name of MetaModels. + * @param int|string $mixDataId ID of the data row. + * @param int|string $viewId ID of render setting. + * @param string|null $strOutput Name of output. Default:null (fallback to html5)|text|html5|... * - * @return boolean|string Return false when nothing was found or return the value. + * @return bool|string Return false when nothing was found or return the value. */ - protected function getItem($metaModelIdOrName, $mixDataId, $viewId, $strOutput = null) + private function getItem( + int|string $metaModelIdOrName, + int|string $mixDataId, + int|string $viewId, + string $strOutput = null + ): bool|string { // Get the MetaModel. Return if we can not find one. $metaModel = $this->loadMetaModel($metaModelIdOrName); @@ -240,7 +256,7 @@ protected function getItem($metaModelIdOrName, $mixDataId, $viewId, $strOutput = $objMetaModelList = new ItemList(); $objMetaModelList - ->setMetaModel($metaModel->get('id'), $viewId) + ->setMetaModel((int) $metaModel->get('id'), (int) $viewId) ->overrideOutputFormat($strOutput); // Handle a set of ids. @@ -253,75 +269,84 @@ protected function getItem($metaModelIdOrName, $mixDataId, $viewId, $strOutput = } $objMetaModelList->addFilterRule(new StaticIdList($arrIds)); + return $objMetaModelList->render(false, $this); } /** * Get from MM X the item with the id Y and parse the attribute Z and return it. * - * @param string|int $metaModelIdOrName ID or name of MetaModel. - * @param int $intDataId ID of the data row. - * @param string $strAttributeName Name of the attribute. - * @param string $strOutput Name of output. Default:raw|text|html5|... + * @param int|string $metaModelIdOrName ID or name of MetaModel. + * @param int $intDataId ID of the data row. + * @param string $attributeIdentifier Name of the attribute. + * @param string|null $outputFormat Type of output format - default: text. * - * @return boolean|string Return false when nothing was found or return the value. + * @return bool|string Return false when nothing was found or return the value. * * @throws \RuntimeException If $intDataId does not provide an existingMetaModel ID. */ - protected function getAttribute($metaModelIdOrName, $intDataId, $strAttributeName, $strOutput = 'raw') + private function getAttribute( + int|string $metaModelIdOrName, + int $intDataId, + int|string $attributeIdentifier, + ?string $outputFormat + ): bool|string { // Get the MM. - $objMM = $this->loadMetaModel($metaModelIdOrName); - if (null === $objMM) { + $metaModel = $this->loadMetaModel($metaModelIdOrName); + if (null === $metaModel) { return false; } - // Set output to default if not set. - if (empty($strOutput)) { - $strOutput = 'raw'; - } - // Get item. - $objMetaModelItem = $objMM->findById($intDataId); - if (null === $objMetaModelItem) { + $item = $metaModel->findById($intDataId); + if (null === $item) { throw new \RuntimeException('MetaModel item not found: ' . $intDataId); } + if (\is_int($attributeIdentifier)) { + $attributeIdentifier = $metaModel->getAttributeById($attributeIdentifier)->getName(); + } + // Parse attribute. - $arrAttr = $objMetaModelItem->parseAttribute($strAttributeName); + $arrAttr = $item->parseAttribute($attributeIdentifier, $outputFormat); - return $arrAttr[$strOutput]; + return $arrAttr[$outputFormat]; } /** * Get count from a module or content element of a mm or from mm with filter direct. * - * @param string $type Type of element like mod or ce. - * @param string|int $identifier ID of content element or module or ID or name of MetaModel. + * @param string $type Type of element like mod, ce or mm. + * @param int|string $identifier ID of content element or module or ID or name of MetaModel. * @param int|null $filterId ID of the filter. * * @return int Return the count value. + * @throws Exception */ - protected function getCount(string $type, $identifier, int $filterId = null): int + private function getCount(string $type, int|string $identifier, int $filterId = null): int { switch ($type) { // From module, can be a MetaModel list or filter. case 'mod': - if (null !== ($result = $this->getMetaModelDataFrom('tl_module', $identifier))) { + if (($result = $this->getMetaModelDataFrom('tl_module', $identifier))) { return $this->getCountFor($result['metamodel'], $result['metamodel_filtering']); } break; // From content element, can be a MetaModel list or filter. case 'ce': - if (null !== ($result = $this->getMetaModelDataFrom('tl_content', $identifier))) { + if (($result = $this->getMetaModelDataFrom('tl_content', $identifier))) { return $this->getCountFor($result['metamodel'], $result['metamodel_filtering']); } break; // From MetaModel with filter. case 'mm': - return $this->getCountFor($identifier, $filterId); + if (($result = $this->translateMetaModelNameToId($identifier))) { + return $this->getCountFor((int)$result, $filterId); + } + break; // Unknown element type. default: @@ -331,6 +356,35 @@ protected function getCount(string $type, $identifier, int $filterId = null): in return 0; } + /** + * Translate MetaModel name to id if found. + * + * @param $identifier int|string The MetaModel identifier. + * + * @return false|int + * @throws Exception + */ + private function translateMetaModelNameToId(int|string $identifier): bool|int + { + if (\is_numeric($identifier)) { + return $identifier; + } + + $statement = $this->connection->createQueryBuilder() + ->select('t.id') + ->from('tl_metamodel', 't') + ->where('t.tableName=:tableName') + ->setParameter('tableName', $identifier) + ->executeQuery(); + + // Check if we have some data. + if ($statement->rowCount() < 1) { + return false; + } + + return (int) $statement->fetchFirstColumn(); + } + /** * Try to load the MetaModel by id or name. * @@ -338,7 +392,7 @@ protected function getCount(string $type, $identifier, int $filterId = null): in * * @return IMetaModel|null */ - protected function loadMetaModel($nameOrId): ?IMetaModel + private function loadMetaModel($nameOrId): ?IMetaModel { if (is_numeric($nameOrId)) { // ID. @@ -362,15 +416,16 @@ protected function loadMetaModel($nameOrId): ?IMetaModel * @param string $strTable Name of table. * @param int $intID ID of the filter. * - * @return null|\stdClass Returns null when nothing was found or a \Database\Result with the chosen information. + * @return false|array Returns null when nothing was found or a \Database\Result with the chosen information. * * @throws \Doctrine\DBAL\DBALException When an database error occur. + * @throws Exception */ - protected function getMetaModelDataFrom($strTable, $intID) + private function getMetaModelDataFrom(string $strTable, int $intID): bool|array { // Check if we know the table. - if (!$this->connection->getSchemaManager()->tablesExist([$strTable])) { - return null; + if (!$this->connection->createSchemaManager()->tablesExist([$strTable])) { + return false; } // Get all information form table or return null if we have no data. @@ -384,7 +439,7 @@ protected function getMetaModelDataFrom($strTable, $intID) // Check if we have some data. if ($statement->rowCount() < 1) { - return null; + return false; } return $statement->fetchAssociative(); @@ -398,7 +453,7 @@ protected function getMetaModelDataFrom($strTable, $intID) * * @return int The count result. */ - protected function getCountFor(int $intMetaModelId, int $intFilterId = null): int + private function getCountFor(int $intMetaModelId, int $intFilterId = null): int { $metaModel = $this->loadMetaModel($intMetaModelId); if (null === $metaModel) { @@ -423,18 +478,18 @@ protected function getCountFor(int $intMetaModelId, int $intFilterId = null): in /** * Check if the item is published. * - * @param IMetaModel $metaModel Current metamodels. + * @param IMetaModel $metaModel Current MetaModel. * @param int $intItemId Id of the item. * - * @return boolean True => Published | False => Not published - * - * @deprecated + * @return bool True => Published | False => Not published * * @throws \Doctrine\DBAL\DBALException When a database error occur. * * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @deprecated + * */ - protected function isPublishedItem($metaModel, $intItemId): bool + protected function isPublishedItem(IMetaModel $metaModel, int $intItemId): bool { // @codingStandardsIgnoreStart @trigger_error( diff --git a/src/CoreBundle/Resources/config/hooks.yml b/src/CoreBundle/Resources/config/hooks.yml index 78412536d..3f92b9c1a 100644 --- a/src/CoreBundle/Resources/config/hooks.yml +++ b/src/CoreBundle/Resources/config/hooks.yml @@ -48,6 +48,9 @@ services: - '@metamodels.factory' - '@metamodels.render_setting_factory' - '@metamodels.filter_setting_factory' + - '@?logger' + tags: + - { name: contao.hook, hook: replaceInsertTags } MetaModels\CoreBundle\Contao\Hooks\FixupUserGroupModules: arguments: From 941cafcb437fa7da8032a5f9aa5fed188e298432 Mon Sep 17 00:00:00 2001 From: Oliver Willmes Date: Thu, 8 Jul 2021 16:00:10 +0200 Subject: [PATCH 136/224] change to symfony session Changing session handling --- .../Contao/InsertTag/ReplaceParam.php | 8 ++++--- .../Resources/config/insert-tags.yml | 2 +- src/Helper/ToolboxFile.php | 21 ++++++++++++++++--- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/CoreBundle/Contao/InsertTag/ReplaceParam.php b/src/CoreBundle/Contao/InsertTag/ReplaceParam.php index f7a8db9af..82b04cd88 100644 --- a/src/CoreBundle/Contao/InsertTag/ReplaceParam.php +++ b/src/CoreBundle/Contao/InsertTag/ReplaceParam.php @@ -28,7 +28,7 @@ use Contao\CoreBundle\Framework\Adapter; use Contao\Input; -use Contao\Session; +use Symfony\Component\HttpFoundation\Session\Session; /** * This replaces the insert tag param. @@ -147,9 +147,11 @@ private function replaceSessionParameter(array $chunks, ?string $content, string ) { return $content; } + // FIXME: only frontend now, is this ok? :/ + $sessionBag = $this->session->getBag('contao_frontend'); if ((false === \strpos($tag, '&default='))) { - $result = $this->session->get($arguments[1]); + $result = $sessionBag->get($arguments[1]); return \str_replace( '{{' . $tag . '}}', \is_array($result) ? \serialize($result) : ($result ?? ''), @@ -157,7 +159,7 @@ private function replaceSessionParameter(array $chunks, ?string $content, string ); } - $result = ($this->session->get($arguments[1]) ?: $arguments[2]); + $result = ($sessionBag->get($arguments[1]) ?: $arguments[2]); return \str_replace( '{{' . $tag . '}}', \is_array($result) ? \serialize($result) : ($result ?? ''), diff --git a/src/CoreBundle/Resources/config/insert-tags.yml b/src/CoreBundle/Resources/config/insert-tags.yml index 51a999734..bab9fea5e 100644 --- a/src/CoreBundle/Resources/config/insert-tags.yml +++ b/src/CoreBundle/Resources/config/insert-tags.yml @@ -6,4 +6,4 @@ services: public: false arguments: - '@metamodels.contao_input' - - '@metamodels.contao_session' + - '@session' diff --git a/src/Helper/ToolboxFile.php b/src/Helper/ToolboxFile.php index df4efe1bc..620275048 100644 --- a/src/Helper/ToolboxFile.php +++ b/src/Helper/ToolboxFile.php @@ -30,6 +30,7 @@ use Contao\Controller; use Contao\CoreBundle\Image\ImageFactoryInterface; use Contao\CoreBundle\Image\PictureFactoryInterface; +use Contao\CoreBundle\Session\LazySessionAccess; use Contao\Dbafs; use Contao\Environment; use Contao\File; @@ -47,6 +48,7 @@ use InvalidArgumentException; use Symfony\Component\Asset\Context\ContextInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Session\Session; /** * This class provides various methods for handling file collection within Contao. @@ -191,6 +193,13 @@ class ToolboxFile */ protected $modifiedTime; + /** + * Symfony session object + * + * @var Session + */ + private $session; + /** * Create a new instance. * @@ -270,6 +279,7 @@ public function __construct( // @codingStandardsIgnoreEnd $this->pictureFactory = System::getContainer()->get('contao.image.picture_factory'); } + $this->session = System::getContainer()->get('session'); } /** @@ -538,13 +548,17 @@ protected function getDownloadLink($strFile) $_SESSION['metaModels_downloads'] = []; } - if (!isset($_SESSION['metaModels_downloads'][$strFile])) { - $_SESSION['metaModels_downloads'][$strFile] = md5(uniqid()); + $bag = $this->session->getBag('attributes'); + + $links = $bag->has('metaModels_downloads') ? $bag->get('metaModels_downloads') : []; + if (!isset($links[$strFile])) { + $links[$strFile] = md5(uniqid()); + $bag->set('metaModels_downloads', $links); } return UrlBuilder::fromUrl(Environment::get('request')) ->setQueryParameter('file', urlencode($strFile)) - ->setQueryParameter('fileKey', $_SESSION['metaModels_downloads'][$strFile]) + ->setQueryParameter('fileKey', $links[$strFile]) ->getUrl(); } @@ -804,6 +818,7 @@ private function checkDownloads() if ($this->getShowImages()) { return; } + if (($file = Input::get('file'))) { if ($this->withDownloadKeys) { // Check key and return 403 if mismatch From d60cb6883949d0c8b9275a861ba5c2c068bc3dff Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Sun, 15 Jan 2023 16:09:13 +0100 Subject: [PATCH 137/224] Revision of the code --- .../Contao/InsertTag/ReplaceParam.php | 2 +- src/CoreBundle/Resources/config/services.yml | 1 + src/Helper/ToolboxFile.php | 169 ++++++++++-------- 3 files changed, 94 insertions(+), 78 deletions(-) diff --git a/src/CoreBundle/Contao/InsertTag/ReplaceParam.php b/src/CoreBundle/Contao/InsertTag/ReplaceParam.php index 82b04cd88..851b65e58 100644 --- a/src/CoreBundle/Contao/InsertTag/ReplaceParam.php +++ b/src/CoreBundle/Contao/InsertTag/ReplaceParam.php @@ -147,7 +147,7 @@ private function replaceSessionParameter(array $chunks, ?string $content, string ) { return $content; } - // FIXME: only frontend now, is this ok? :/ + $sessionBag = $this->session->getBag('contao_frontend'); if ((false === \strpos($tag, '&default='))) { diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index 8b49e510f..4d1266fd8 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -279,3 +279,4 @@ services: - "%kernel.project_dir%" - "@contao.assets.files_context" - "@contao.image.picture_factory" + - "@session" diff --git a/src/Helper/ToolboxFile.php b/src/Helper/ToolboxFile.php index 620275048..438e29284 100644 --- a/src/Helper/ToolboxFile.php +++ b/src/Helper/ToolboxFile.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -20,17 +20,19 @@ * @author Ingolf Steinhardt * @author Sven Baumann * @author Andreas Fischer - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\Helper; +use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; +use ContaoCommunityAlliance\Contao\Bindings\Events\Image\ResizeImageEvent; +use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; use Contao\Controller; use Contao\CoreBundle\Image\ImageFactoryInterface; use Contao\CoreBundle\Image\PictureFactoryInterface; -use Contao\CoreBundle\Session\LazySessionAccess; use Contao\Dbafs; use Contao\Environment; use Contao\File; @@ -38,13 +40,9 @@ use Contao\Input; use Contao\LayoutModel; use Contao\PageError403; -use Contao\Picture; use Contao\StringUtil; use Contao\System; use Contao\Validator; -use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; -use ContaoCommunityAlliance\Contao\Bindings\Events\Image\ResizeImageEvent; -use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; use InvalidArgumentException; use Symfony\Component\Asset\Context\ContextInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -65,98 +63,105 @@ class ToolboxFile * * @deprecated The event dispatcher will get removed in 3.0 as we now use the image factory. */ - private $dispatcher; + private EventDispatcherInterface|null $dispatcher; /** * The project root dir. * - * @var string + * @var string|null */ - private $rootDir; + private string|null $rootDir; /** * The image factory for resizing. * - * @var ImageFactoryInterface + * @var ImageFactoryInterface|null */ - private $imageFactory; + private ImageFactoryInterface|null $imageFactory; /** - * The assets files context. + * The assets file context. * - * @var ContextInterface + * @var ContextInterface|null */ - private $filesContext; + private ContextInterface|null $filesContext; /** * The picture factory. * - * @var PictureFactoryInterface + * @var PictureFactoryInterface|null */ - private $pictureFactory; + private PictureFactoryInterface|null $pictureFactory; + + /** + * Symfony session object + * + * @var Session + */ + private Session $session; /** * Allowed file extensions. * * @var array */ - protected $acceptedExtensions; + protected array $acceptedExtensions = []; /** * Base language, used for retrieving meta.txt information. * * @var string */ - protected $baseLanguage; + protected string $baseLanguage = ''; /** * The fallback language, used for retrieving meta.txt information. * * @var string */ - protected $fallbackLanguage; + protected string $fallbackLanguage = ''; /** * Determines if we want to generate images or not. * - * @var boolean + * @var bool */ - protected $blnShowImages; + protected bool $blnShowImages = false; /** * Image resize information. * * @var array */ - protected $resizeImages; + protected array $resizeImages = []; /** * The id to use in lightboxes. * * @var string */ - protected $strLightboxId; + protected string $strLightboxId = ''; /** * The files to process in this instance. * * @var array */ - protected $foundFiles = []; + protected array $foundFiles = []; /** * The pending paths to collect from DB. * * @var string[] */ - protected $pendingPaths = []; + protected array $pendingPaths = []; /** * The pending uuids to collect from DB. * * @var array */ - protected $pendingIds = []; + protected array $pendingIds = []; /** * Flag if download keys shall be generated. @@ -170,43 +175,37 @@ class ToolboxFile * * @var array */ - protected $metaInformation; + protected array $metaInformation = []; /** * File id mapping for files. * * @var string[] */ - protected $uuidMap = []; + protected array $uuidMap = []; /** * Buffered file information. * * @var array */ - protected $outputBuffer; + protected array $outputBuffer = []; /** * Buffered modification timestamps. * * @var array */ - protected $modifiedTime; - - /** - * Symfony session object - * - * @var Session - */ - private $session; + protected array $modifiedTime = []; /** * Create a new instance. * * @param ImageFactoryInterface|EventDispatcherInterface|null $imageFactory The image factory to use. * @param string|null $rootDir The root path of the installation. - * @param ContextInterface|null $filesContext The assets files context. + * @param ContextInterface|null $filesContext The assets file context. * @param PictureFactoryInterface|null $pictureFactory The picture factory. + * @param Session|null $session The session. * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) @@ -214,10 +213,11 @@ class ToolboxFile * @SuppressWarnings(PHPMD.NPathComplexity) */ public function __construct( - $imageFactory = null, + ImageFactoryInterface|EventDispatcherInterface $imageFactory = null, string $rootDir = null, ContextInterface $filesContext = null, - PictureFactoryInterface $pictureFactory = null + PictureFactoryInterface $pictureFactory = null, + Session $session = null ) { switch (true) { case ($imageFactory instanceof ImageFactoryInterface) && !empty($rootDir): @@ -275,11 +275,22 @@ public function __construct( 'Not passing an "PictureFactoryInterface" is deprecated.', E_USER_DEPRECATED ); - // @codingStandardsIgnoreEnd $this->pictureFactory = System::getContainer()->get('contao.image.picture_factory'); } - $this->session = System::getContainer()->get('session'); + + if (null === $session) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Not passing a "Session" is deprecated.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + $session = System::getContainer()->get('session'); + assert($session instanceof Session); + } + + $this->session = $session; } /** @@ -297,11 +308,11 @@ public function setAcceptedExtensions($acceptedExtensions) // We must not allow file extensions that are globally disabled. $allowedDownload = StringUtil::trimsplit(',', $GLOBALS['TL_CONFIG']['allowedDownload']); - if (!is_array($acceptedExtensions)) { + if (!\is_array($acceptedExtensions)) { $acceptedExtensions = StringUtil::trimsplit(',', $acceptedExtensions); } - $this->acceptedExtensions = array_map('strtolower', array_intersect($allowedDownload, $acceptedExtensions)); + $this->acceptedExtensions = \array_map('strtolower', \array_intersect($allowedDownload, $acceptedExtensions)); } /** @@ -496,14 +507,14 @@ protected function collectFiles() $conditions = []; $parameters = []; - if (count($this->pendingIds)) { + if (\count($this->pendingIds)) { $conditions[] = $table . '.uuid IN(' . - implode(',', array_fill(0, count($this->pendingIds), 'UNHEX(?)')) . ')'; - $parameters = array_map('bin2hex', $this->pendingIds); + \implode(',', \array_fill(0, count($this->pendingIds), 'UNHEX(?)')) . ')'; + $parameters = \array_map('bin2hex', $this->pendingIds); $this->pendingIds = []; } - if (count($this->pendingPaths)) { + if (\count($this->pendingPaths)) { $slug = $table . '.path LIKE ?'; foreach ($this->pendingPaths as $pendingPath) { $conditions[] = $slug; @@ -512,11 +523,11 @@ protected function collectFiles() $this->pendingPaths = []; } - if (!count($conditions)) { + if (!\count($conditions)) { return; } - if ($files = FilesModel::findBy([implode(' OR ', $conditions)], $parameters)) { + if ($files = FilesModel::findBy([\implode(' OR ', $conditions)], $parameters)) { $this->addFileModels($files); } @@ -540,19 +551,18 @@ protected function getDownloadLink($strFile) { if (!$this->withDownloadKeys) { return UrlBuilder::fromUrl(Environment::get('request')) - ->setQueryParameter('file', urlencode($strFile)) + ->setQueryParameter('file', \urlencode($strFile)) ->getUrl(); } - if (isset($_SESSION['metaModels_downloads']) && !is_array($_SESSION['metaModels_downloads'])) { - $_SESSION['metaModels_downloads'] = []; - } - $bag = $this->session->getBag('attributes'); $links = $bag->has('metaModels_downloads') ? $bag->get('metaModels_downloads') : []; + if (!\is_array($links)) { + $links = []; + } if (!isset($links[$strFile])) { - $links[$strFile] = md5(uniqid()); + $links[$strFile] = \md5(\uniqid('', true)); $bag->set('metaModels_downloads', $links); } @@ -604,7 +614,7 @@ protected function remapSorting($arrFiles, $arrSource) $files = []; $source = []; - foreach (array_keys($arrFiles) as $k) { + foreach (\array_keys($arrFiles) as $k) { $files[] = $arrFiles[$k]; $source[] = $arrSource[$k]; } @@ -667,8 +677,8 @@ public function sortFiles($sortType, $sortIds = []) */ protected function addClasses(&$arrSource) { - $countFiles = count($arrSource); - foreach (array_keys($arrSource) as $k) { + $countFiles = \count($arrSource); + foreach (\array_keys($arrSource) as $k) { $arrSource[$k]['class'] = (($k == 0) ? ' first' : '') . (($k == ($countFiles - 1)) ? ' last' : '') . ((($k % 2) == 0) ? ' even' : ' odd'); @@ -712,9 +722,9 @@ protected function sortByDate($blnAscending = true) } if ($blnAscending) { - array_multisort($arrFiles, SORT_NUMERIC, $arrDates, SORT_ASC); + \array_multisort($arrFiles, SORT_NUMERIC, $arrDates, SORT_ASC); } else { - array_multisort($arrFiles, SORT_NUMERIC, $arrDates, SORT_DESC); + \array_multisort($arrFiles, SORT_NUMERIC, $arrDates, SORT_DESC); } return $this->remapSorting($arrFiles, $this->outputBuffer); @@ -733,7 +743,7 @@ protected function sortByIdList($sortIds) if (!$fileMap) { return ['files' => [], 'source' => []]; } - $fileKeys = array_flip(array_keys($this->uuidMap)); + $fileKeys = \array_flip(\array_keys($this->uuidMap)); $sorted = []; foreach ($sortIds as $sortStringId) { $key = $fileKeys[$sortStringId]; @@ -760,9 +770,9 @@ protected function sortByRandom() return ['files' => [], 'source' => []]; } - $keys = array_keys($arrFiles); + $keys = \array_keys($arrFiles); $files = []; - shuffle($keys); + \shuffle($keys); foreach ($keys as $key) { $files[$key] = $arrFiles[$key]; } @@ -821,9 +831,14 @@ private function checkDownloads() if (($file = Input::get('file'))) { if ($this->withDownloadKeys) { + $bag = $this->session->getBag('attributes'); + $links = $bag->has('metaModels_downloads') ? $bag->get('metaModels_downloads') : []; + if (!\is_array($links)) { + $links = []; + } // Check key and return 403 if mismatch // keep both null-coalescing values different to account for missing values. - if (($_SESSION['metaModels_downloads'][$file] ?? null) !== (Input::get('fileKey') ?? false)) { + if (($links[$file] ?? null) !== (Input::get('fileKey') ?? false)) { $objHandler = new $GLOBALS['TL_PTY']['error_403'](); /** @var PageError403 $objHandler */ $objHandler->generate($file); @@ -910,8 +925,8 @@ public static function convertValuesToMetaModels($values) } // Convert UUIDs to binary and clean empty values out. - $values = array_filter( - array_map(function ($fileId) { + $values = \array_filter( + \array_map(function ($fileId) { return Validator::isStringUuid($fileId) ? StringUtil::uuidToBin($fileId) : $fileId; }, $values) ); @@ -961,7 +976,7 @@ public static function convertValuesToMetaModels($values) */ public static function convertUuidsOrPathsToMetaModels($values) { - $values = array_filter((array) $values); + $values = \array_filter((array) $values); if (empty($values)) { return [ 'bin' => [], @@ -1005,13 +1020,13 @@ private function addFileModels($files, $skipPaths = []) $baseLanguage = $this->getBaseLanguage(); $fallbackLanguage = $this->getFallbackLanguage(); foreach ($files as $file) { - if ('folder' === $file->type && !in_array($file->path, $skipPaths)) { + if ('folder' === $file->type && !\in_array($file->path, $skipPaths)) { $this->pendingPaths[] = $file->path . '/'; continue; } if (is_file(TL_ROOT . DIRECTORY_SEPARATOR . $file->path) - && in_array( - strtolower(pathinfo($file->path, PATHINFO_EXTENSION)), + && \in_array( + \strtolower(pathinfo($file->path, PATHINFO_EXTENSION)), $this->acceptedExtensions ) ) { @@ -1043,13 +1058,13 @@ private function processFile($fileName) { $file = new File($fileName); $meta = $this->metaInformation[dirname($fileName)][$file->basename] ?? []; - $title = isset($meta['title']) && strlen($meta['title']) + $title = isset($meta['title']) && \strlen($meta['title']) ? $meta['title'] : StringUtil::specialchars($file->basename); - if (isset($meta['caption']) && strlen($meta['caption'])) { + if (isset($meta['caption']) && \strlen($meta['caption'])) { $altText = $meta['caption']; } else { - $altText = ucfirst(str_replace('_', ' ', preg_replace('/^[0-9]+_/', '', $file->filename))); + $altText = \ucfirst(\str_replace('_', ' ', \preg_replace('/^[0-9]+_/', '', $file->filename))); } $information = [ @@ -1062,7 +1077,7 @@ private function processFile($fileName) 'icon' => 'assets/contao/images/' . $file->icon, 'extension' => $file->extension, 'size' => $file->filesize, - 'sizetext' => sprintf('(%s)', Controller::getReadableSize($file->filesize, 2)), + 'sizetext' => \sprintf('(%s)', Controller::getReadableSize($file->filesize, 2)), 'url' => StringUtil::specialchars($this->getDownloadLink($fileName)), 'isGdImage' => false, 'isSvgImage' => false, @@ -1071,7 +1086,7 @@ private function processFile($fileName) // Prepare GD images. if ($information['isGdImage'] = $file->isGdImage) { - $information['src'] = urldecode($this->resizeImage($fileName)); + $information['src'] = \urldecode($this->resizeImage($fileName)); $information['lb'] = 'lb_' . $this->getLightboxId(); if (file_exists(TL_ROOT . '/' . $information['src'])) { $size = getimagesize(TL_ROOT . '/' . $information['src']); From 1a73c18cd8636e8bf57165dbfb01ea82e01d89ee Mon Sep 17 00:00:00 2001 From: e-spin Date: Fri, 27 Jan 2023 08:37:41 +0100 Subject: [PATCH 138/224] Fix PHP8 --- src/Helper/ToolboxFile.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Helper/ToolboxFile.php b/src/Helper/ToolboxFile.php index 438e29284..5065c0cb5 100644 --- a/src/Helper/ToolboxFile.php +++ b/src/Helper/ToolboxFile.php @@ -117,16 +117,16 @@ class ToolboxFile /** * The fallback language, used for retrieving meta.txt information. * - * @var string + * @var string|null */ - protected string $fallbackLanguage = ''; + protected string|null $fallbackLanguage = ''; /** * Determines if we want to generate images or not. * - * @var bool + * @var bool|null */ - protected bool $blnShowImages = false; + protected bool|null $blnShowImages = false; /** * Image resize information. @@ -352,11 +352,11 @@ public function getBaseLanguage() /** * Set the fallback language. * - * @param string $fallbackLanguage The fallback language to use. + * @param string|null $fallbackLanguage The fallback language to use. * * @return ToolboxFile */ - public function setFallbackLanguage($fallbackLanguage) + public function setFallbackLanguage(?string $fallbackLanguage): static { $this->fallbackLanguage = $fallbackLanguage; @@ -366,9 +366,9 @@ public function setFallbackLanguage($fallbackLanguage) /** * Retrieve the fallback language. * - * @return string + * @return string|null */ - public function getFallbackLanguage() + public function getFallbackLanguage(): ?string { return $this->fallbackLanguage; } @@ -376,11 +376,11 @@ public function getFallbackLanguage() /** * Set to show/prepare images or not. * - * @param boolean $blnShowImages True to show images, false otherwise. + * @param boolean|null $blnShowImages True to show images, false otherwise. * * @return ToolboxFile */ - public function setShowImages($blnShowImages) + public function setShowImages(?bool $blnShowImages): static { $this->blnShowImages = $blnShowImages; @@ -1143,7 +1143,7 @@ private function processFile($fileName) */ private function resizeImage($fileName) { - [$width, $height, $mode] = $this->getResizeImages(); + [$width, $height, $mode] = $this->getResizeImages() + [null, null, null]; if ($this->getShowImages() && ($width || $height || $mode)) { if ($this->imageFactory) { $image = $this->imageFactory->create( From 72589a7af1096f63a9dc823cbb12105d42f0b679 Mon Sep 17 00:00:00 2001 From: e-spin Date: Fri, 27 Jan 2023 21:36:18 +0100 Subject: [PATCH 139/224] Add sub-headline config at input mask --- .../EditMaskSubHeadlineListener.php | 128 ++++++++++++++++++ .../config/dc-general/table/tl_dcasetting.yml | 9 ++ .../Resources/contao/dca/tl_metamodel_dca.php | 16 ++- .../contao/languages/en/tl_metamodel_dca.php | 8 +- 4 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php new file mode 100644 index 000000000..50e88984a --- /dev/null +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php @@ -0,0 +1,128 @@ + + * @copyright 2012-2023 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\Contao\View\Contao2BackendView\Event\GetEditMaskSubHeadlineEvent; +use Contao\CoreBundle\String\SimpleTokenParser; +use MetaModels\DcGeneral\DataDefinition\Definition\IMetaModelDefinition; +use MetaModels\ViewCombination\InputScreenInformationBuilder; + +/** + * This handles the additional part of sub-headline in input mask. + */ +final class EditMaskSubHeadlineListener +{ + /** + * The input screen information builder. + * + * @var InputScreenInformationBuilder + */ + private InputScreenInformationBuilder $inputScreens; + + /** + * The token parser. + * + * @var SimpleTokenParser + */ + private SimpleTokenParser $tokenParser; + + /** + * EditMaskSubHeadlineListener constructor. + * + * @param InputScreenInformationBuilder $inputScreens The input screen information builder. + * @param SimpleTokenParser $tokenParser The token parser. + */ + public function __construct(InputScreenInformationBuilder $inputScreens, SimpleTokenParser $tokenParser) + { + $this->inputScreens = $inputScreens; + $this->tokenParser = $tokenParser; + } + + /** + * Set sub-headline. + * + * @param GetEditMaskSubHeadlineEvent $event The sub-headline event. + */ + public function __invoke(GetEditMaskSubHeadlineEvent $event): void + { + if (!\str_starts_with($event->getEnvironment()->getDataDefinition()->getName(), 'mm_')) { + return; + } + + // Retrieve the settings of the input mask for member attribute. + $status = 'editRecord'; + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + $definitionName = $environment->getDataDefinition()->getName(); + $translator = $environment->getTranslator(); + /** @var IMetaModelDefinition $metaModels */ + $metaModel = $dataDefinition->getDefinition(IMetaModelDefinition::NAME); + $metaModelName = $dataDefinition->getName(); + $screen = $this->inputScreens->fetchInputScreens([$metaModelName => $metaModel->getActiveInputScreen()]); + $screenMeta = $screen[$metaModelName]['meta']; + + if (empty($headline = $screenMeta['subheadline'])) { + return; + } + + $tokenData = []; + // Get model properties. + foreach ($event->getModel()->getPropertiesAsArray() as $keyData => $valueData) { + $tokenData['model_' . $keyData] = $valueData; + } + + // Replace simple tokens. + $headlineAdd = $this->replaceSimpleTokensAtHeadline($headline, $tokenData); + + // Translate language key and add headline part. + $headline = $translator->translate($status, $definitionName, [$headlineAdd]); + + if ($status !== $headline) { + $subHeadline = $headline; + } else { + $subHeadline = $translator->translate('MSC.' . $status, null, [$headlineAdd]); + } + + $event->setHeadline($subHeadline); + } + + /** + * Replace simple tokens at headline parameter. + * + * @param string $headline The headline string. + * @param array $tokenData The token data. + * + * @return string + */ + private function replaceSimpleTokensAtHeadline(string $headline, array $tokenData): string + { + if (\str_contains($headline, '##') + || \str_contains($headline, '##')) { + $headline = + $this->tokenParser->parse( + \str_replace('#', '#', $headline), + $tokenData, + false + ); + } + + return $headline; + } +} 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 1bb8062c6..278568844 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_dcasetting.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_dcasetting.yml @@ -115,3 +115,12 @@ services: event: dc-general.view.contao2backend.get-operation-button method: handle priority: 2048 + + MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting\EditMaskSubHeadlineListener: + arguments: + - '@metamodels.view_combination' + - "@metamodels.view_combination.input_screen_information_builder" + - "@contao.string.simple_token_parser" + tags: + - name: kernel.event_listener + event: dc-general.view.contao2backend.get-edit-mask-subheadline diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php index 37085b7a9..9b0e940e2 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,7 +21,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Cliff Parnitzky - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -190,7 +190,8 @@ 'backendcaption', ], 'display' => [ - 'rendermode' + 'rendermode', + 'subheadline' ], 'permissions' => [ 'iseditable', @@ -390,6 +391,15 @@ 'tl_class' => 'clr w50 cbx', ], 'sql' => "char(1) NOT NULL default ''" + ], + 'subheadline' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['subheadline'], + 'inputType' => 'text', + 'eval' => [ + 'maxlength' => 255, + 'tl_class' => 'w50' + ], + 'sql' => "varchar(255) NOT NULL default ''" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php index b360e225e..3f9a4d42f 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -90,6 +90,10 @@ $GLOBALS['TL_LANG']['tl_metamodel_dca']['groupsort_settings'][0] = 'Grouping and sorting'; $GLOBALS['TL_LANG']['tl_metamodel_dca']['groupsort_settings'][1] = 'Edit the grouping and sorting settings of input screen ID %s'; +$GLOBALS['TL_LANG']['tl_metamodel_dca']['subheadline'][0] = 'Additions to the mask-heading'; +$GLOBALS['TL_LANG']['tl_metamodel_dca']['subheadline'][1] = + 'The field can be used to adapt the heading of the mask at edit and replaces the output of the ID.' . + 'You can use simple tokens e.g. ##model_name##, ##model_firstname## [##model_id##]'; $GLOBALS['TL_LANG']['tl_metamodel_dca']['rendertypes']['standalone'] = 'Standalone'; $GLOBALS['TL_LANG']['tl_metamodel_dca']['rendertypes']['ctable'] = 'As child table'; $GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermodes']['flat'] = 'Flat'; From da4bc0d0dcedfe2d02f1e786a7ebf844b441e491 Mon Sep 17 00:00:00 2001 From: e-spin Date: Sat, 28 Jan 2023 17:07:44 +0100 Subject: [PATCH 140/224] Fix typo --- src/MetaModelsEvents.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/MetaModelsEvents.php b/src/MetaModelsEvents.php index a620c7650..cff4065b1 100644 --- a/src/MetaModelsEvents.php +++ b/src/MetaModelsEvents.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -69,9 +70,9 @@ class MetaModelsEvents const FILTER_SETTING_FACTORY_CREATE = 'metamodels.filter-setting.factory.create'; /** - * Event when a filter setting factory is created. + * Event when a render setting factory is created. * - * @see \MetaModels\Filter\Setting\Events\CreateRenderSettingFactoryEvent + * @see \MetaModels\Render\Setting\Events\CreateRenderSettingFactoryEvent */ const RENDER_SETTING_FACTORY_CREATE = 'metamodels.render-setting.factory.create'; From 26665e986caaae25b9b07754e1cfe2fbb1e9fbb1 Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 30 Jan 2023 20:47:28 +0100 Subject: [PATCH 141/224] Rewrite MM inserttags listener --- .../EventListener/InsertTagsListener.php | 82 +++++++++++-------- 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/src/CoreBundle/EventListener/InsertTagsListener.php b/src/CoreBundle/EventListener/InsertTagsListener.php index bd6839f7a..40601d822 100644 --- a/src/CoreBundle/EventListener/InsertTagsListener.php +++ b/src/CoreBundle/EventListener/InsertTagsListener.php @@ -40,21 +40,22 @@ * This class handles the replacement of all MetaModels insert tags. * * @codingStandardsIgnoreStart + * * Available insert tags: * * -- Total Count -- * mm::total::mod::[ID] * mm::total::ce::[ID] - * mm::total::mm::[MM Name|ID](::[ID filter]) + * mm::total::mm::[MM Col-Name|ID](::[ID filter]) * * -- Item -- - * mm::item::[MM Name|ID]::[Item ID|ID,ID,ID]::[ID render setting](::[Output raw|text|html5]) + * mm::item::[MM Col-Name|ID]::[Item ID|ID,ID,ID]::[ID render setting](::[Output (Default:text)|html5]) * * -- Attribute -- - * mm::attribute::[MM Name|ID]::[Item ID]::[Attribute Name|ID](::[Output (Default:text)|raw|html5]) + * mm::attribute::[MM Col-Name|ID]::[Item ID]::[ID render setting]::[Attribute Col-Name|ID](::[Output (Default:text)|html5|raw]) * * -- JumpTo -- - * mm::jumpTo::[MM Name|ID]::[Item ID]::[ID render setting](::[Parameter (Default:url)|label|page|params.attname]) + * mm::jumpTo::[MM Col-Name|ID]::[Item ID]::[ID render setting](::[Parameter (Default:url)|label|page|params.attname]) * * @codingStandardsIgnoreEnd */ @@ -143,7 +144,7 @@ public function __invoke(string $insertTag): bool|int|string // Get value from an attribute. case 'attribute': - return $this->getAttribute($elements[2], $elements[3], $elements[4], ($elements[5] ?? null)); + return $this->getAttribute($elements[2], $elements[3], $elements[4], $elements[5], ($elements[6] ?? null)); // Get item. case 'item': @@ -167,10 +168,10 @@ public function __invoke(string $insertTag): bool|int|string /** * Get the jumpTo for a chosen value. * - * @param int|string $mixMetaModel ID or name of MetaModels. - * @param int $mixDataId ID of the data row. - * @param int $viewId ID of render setting. - * @param string $strParam Name of parameter - Default:url|label|page|params.[attrname]. + * @param int|string $mixMetaModel ID or column name of MetaModels. + * @param int $mixDataId ID of the data row. + * @param int $viewId ID of render setting. + * @param string|null $strParam Name of parameter - (Default:url)|label|page|params.[attrname]. * * @return bool|string Return false when nothing was found for the requested value. */ @@ -178,7 +179,7 @@ private function jumpTo( int|string $mixMetaModel, int $mixDataId, int $viewId, - string $strParam = 'url' + ?string $strParam ): bool|string { // Set the param to url if empty. @@ -193,7 +194,7 @@ private function jumpTo( } // Get the render setting. - if (null === $renderSettings = $this->renderSettingFactory->createCollection($metaModel, $viewId)) { + if (null === $renderSetting = $this->renderSettingFactory->createCollection($metaModel, (int) $viewId)) { return false; } @@ -204,7 +205,7 @@ private function jumpTo( } // Render the item and check if we have a jump to. - $arrRenderedItem = $item->parseValue('text', $renderSettings); + $arrRenderedItem = $item->parseValue('text', $renderSetting); if (!isset($arrRenderedItem['jumpTo'])) { return false; } @@ -229,10 +230,10 @@ private function jumpTo( /** * Get an item. * - * @param int|string $metaModelIdOrName ID or name of MetaModels. + * @param int|string $metaModelIdOrName ID or column name of MetaModels. * @param int|string $mixDataId ID of the data row. * @param int|string $viewId ID of render setting. - * @param string|null $strOutput Name of output. Default:null (fallback to html5)|text|html5|... + * @param string|null $outputFormat Name of output format- (Default:text)|html5. * * @return bool|string Return false when nothing was found or return the value. */ @@ -240,7 +241,7 @@ private function getItem( int|string $metaModelIdOrName, int|string $mixDataId, int|string $viewId, - string $strOutput = null + ?string $outputFormat ): bool|string { // Get the MetaModel. Return if we can not find one. @@ -249,21 +250,21 @@ private function getItem( return false; } - // Set output to default if not set. - if (empty($strOutput)) { - $strOutput = 'html5'; + // Set output format to default if not set. + if (empty($outputFormat)) { + $outputFormat = 'text'; } $objMetaModelList = new ItemList(); $objMetaModelList ->setMetaModel((int) $metaModel->get('id'), (int) $viewId) - ->overrideOutputFormat($strOutput); + ->overrideOutputFormat($outputFormat); // Handle a set of ids. $arrIds = StringUtil::trimsplit(',', $mixDataId); - // Render an empty insert tag rather than displaying a list with an empty. - // result information. do not return false here because the insert tag itself is correct. + // Render an empty insert tag rather than displaying a list with an empty + // result information - do not return false here because the insert tag itself is correct. if (count($arrIds) < 1) { return ''; } @@ -276,18 +277,19 @@ private function getItem( /** * Get from MM X the item with the id Y and parse the attribute Z and return it. * - * @param int|string $metaModelIdOrName ID or name of MetaModel. + * @param int|string $metaModelIdOrName ID or column name of MetaModel. * @param int $intDataId ID of the data row. - * @param string $attributeIdentifier Name of the attribute. - * @param string|null $outputFormat Type of output format - default: text. + * @param int|string $viewId ID of render setting. + * @param int|string $attributeIdentifier ID or column name of the attribute. + * @param string|null $outputFormat Type of output format - (Default:text)|html5|raw. * * @return bool|string Return false when nothing was found or return the value. * - * @throws \RuntimeException If $intDataId does not provide an existingMetaModel ID. */ private function getAttribute( int|string $metaModelIdOrName, int $intDataId, + int|string $viewId, int|string $attributeIdentifier, ?string $outputFormat ): bool|string @@ -301,15 +303,31 @@ private function getAttribute( // Get item. $item = $metaModel->findById($intDataId); if (null === $item) { - throw new \RuntimeException('MetaModel item not found: ' . $intDataId); + return false; + } + + if (\is_numeric($attributeIdentifier)) { + $attributeIdentifier = $metaModel->getAttributeById((int) $attributeIdentifier)->getColName(); + } + + $originalOutputFormat = $outputFormat; + // Set output format to default if not set or raw. + if (empty($outputFormat) || 'raw' === $outputFormat) { + $outputFormat = 'text'; } - if (\is_int($attributeIdentifier)) { - $attributeIdentifier = $metaModel->getAttributeById($attributeIdentifier)->getName(); + // Get render setting. + if (null === ($renderSetting = $this->renderSettingFactory->createCollection($metaModel, (int) $viewId))) { + $outputFormat = 'text'; } // Parse attribute. - $arrAttr = $item->parseAttribute($attributeIdentifier, $outputFormat); + $arrAttr = $item->parseAttribute($attributeIdentifier, $outputFormat, $renderSetting); + + // Reset format to raw if is it. + if ('raw' === $originalOutputFormat) { + $outputFormat = 'raw'; + } return $arrAttr[$outputFormat]; } @@ -344,7 +362,7 @@ private function getCount(string $type, int|string $identifier, int $filterId = // From MetaModel with filter. case 'mm': if (($result = $this->translateMetaModelNameToId($identifier))) { - return $this->getCountFor((int)$result, $filterId); + return $this->getCountFor((int) $result, $filterId); } break; @@ -394,10 +412,10 @@ private function translateMetaModelNameToId(int|string $identifier): bool|int */ private function loadMetaModel($nameOrId): ?IMetaModel { - if (is_numeric($nameOrId)) { + if (\is_numeric($nameOrId)) { // ID. $tableName = $this->factory->translateIdToMetaModelName($nameOrId); - } elseif (is_string($nameOrId)) { + } elseif (\is_string($nameOrId)) { // Name. $tableName = $nameOrId; } From 9a6615a3b9d4c1b71ac90d5f6bf951c7b50af0d7 Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 30 Jan 2023 21:42:45 +0100 Subject: [PATCH 142/224] Some fixes --- .../EditMaskSubHeadlineListener.php | 32 +++++++++++-------- .../config/dc-general/table/tl_dcasetting.yml | 2 +- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php index 50e88984a..b22790215 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php @@ -23,6 +23,7 @@ use Contao\CoreBundle\String\SimpleTokenParser; use MetaModels\DcGeneral\DataDefinition\Definition\IMetaModelDefinition; use MetaModels\ViewCombination\InputScreenInformationBuilder; +use Symfony\Contracts\Translation\TranslatorInterface; /** * This handles the additional part of sub-headline in input mask. @@ -43,16 +44,28 @@ final class EditMaskSubHeadlineListener */ private SimpleTokenParser $tokenParser; + /** + * The translator. + * + * @var TranslatorInterface + */ + private TranslatorInterface $translator; + /** * EditMaskSubHeadlineListener constructor. * * @param InputScreenInformationBuilder $inputScreens The input screen information builder. * @param SimpleTokenParser $tokenParser The token parser. + * @param TranslatorInterface $translator The translator. */ - public function __construct(InputScreenInformationBuilder $inputScreens, SimpleTokenParser $tokenParser) - { + public function __construct( + InputScreenInformationBuilder $inputScreens, + SimpleTokenParser $tokenParser, + TranslatorInterface $translator + ) { $this->inputScreens = $inputScreens; $this->tokenParser = $tokenParser; + $this->translator = $translator; } /** @@ -70,15 +83,13 @@ public function __invoke(GetEditMaskSubHeadlineEvent $event): void $status = 'editRecord'; $environment = $event->getEnvironment(); $dataDefinition = $environment->getDataDefinition(); - $definitionName = $environment->getDataDefinition()->getName(); - $translator = $environment->getTranslator(); /** @var IMetaModelDefinition $metaModels */ $metaModel = $dataDefinition->getDefinition(IMetaModelDefinition::NAME); $metaModelName = $dataDefinition->getName(); $screen = $this->inputScreens->fetchInputScreens([$metaModelName => $metaModel->getActiveInputScreen()]); - $screenMeta = $screen[$metaModelName]['meta']; + $screenMeta = $screen[$metaModelName]['meta'] ?? null; - if (empty($headline = $screenMeta['subheadline'])) { + if (empty($screenMeta) || empty($headline = ($screenMeta['subheadline'] ?? null))) { return; } @@ -92,13 +103,8 @@ public function __invoke(GetEditMaskSubHeadlineEvent $event): void $headlineAdd = $this->replaceSimpleTokensAtHeadline($headline, $tokenData); // Translate language key and add headline part. - $headline = $translator->translate($status, $definitionName, [$headlineAdd]); - - if ($status !== $headline) { - $subHeadline = $headline; - } else { - $subHeadline = $translator->translate('MSC.' . $status, null, [$headlineAdd]); - } + $subHeadline = + $this->translator->trans('tl_metamodel_item.' . $status, [0 => $headlineAdd], 'contao_tl_metamodel_item'); $event->setHeadline($subHeadline); } 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 278568844..c66485de8 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_dcasetting.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_dcasetting.yml @@ -118,9 +118,9 @@ services: MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting\EditMaskSubHeadlineListener: arguments: - - '@metamodels.view_combination' - "@metamodels.view_combination.input_screen_information_builder" - "@contao.string.simple_token_parser" + - "@translator" tags: - name: kernel.event_listener event: dc-general.view.contao2backend.get-edit-mask-subheadline From 3f0a7c2a71645d5901e34494f1910ab97e5e2d9a Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 1 Feb 2023 15:18:52 +0100 Subject: [PATCH 143/224] Add element check --- .../EventListener/InsertTagsListener.php | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/CoreBundle/EventListener/InsertTagsListener.php b/src/CoreBundle/EventListener/InsertTagsListener.php index 40601d822..67dadfdce 100644 --- a/src/CoreBundle/EventListener/InsertTagsListener.php +++ b/src/CoreBundle/EventListener/InsertTagsListener.php @@ -46,16 +46,16 @@ * -- Total Count -- * mm::total::mod::[ID] * mm::total::ce::[ID] - * mm::total::mm::[MM Col-Name|ID](::[ID filter]) + * mm::total::mm::[MM Table-Name|ID](::[ID filter]) * * -- Item -- - * mm::item::[MM Col-Name|ID]::[Item ID|ID,ID,ID]::[ID render setting](::[Output (Default:text)|html5]) + * mm::item::[MM Table-Name|ID]::[Item ID|ID,ID,ID]::[ID render setting](::[Output (Default:text)|html5]) * * -- Attribute -- - * mm::attribute::[MM Col-Name|ID]::[Item ID]::[ID render setting]::[Attribute Col-Name|ID](::[Output (Default:text)|html5|raw]) + * mm::attribute::[MM Table-Name|ID]::[Item ID]::[ID render setting]::[Attribute Col-Name|ID](::[Output (Default:text)|html5|raw]) * * -- JumpTo -- - * mm::jumpTo::[MM Col-Name|ID]::[Item ID]::[ID render setting](::[Parameter (Default:url)|label|page|params.attname]) + * mm::jumpTo::[MM Table-Name|ID]::[Item ID]::[ID render setting](::[Parameter (Default:url)|label|page|params.attname]) * * @codingStandardsIgnoreEnd */ @@ -140,19 +140,27 @@ public function __invoke(string $insertTag): bool|int|string switch ($elements[1]) { // Count for mod or ce elements. case 'total': - return $this->getCount($elements[2], $elements[3], ($elements[4] ?? null)); + return $this->checkMinExpectElements(4, $elements) + ? $this->getCount($elements[2], $elements[3], ($elements[4] ?? null)) + : false; // Get value from an attribute. case 'attribute': - return $this->getAttribute($elements[2], $elements[3], $elements[4], $elements[5], ($elements[6] ?? null)); + return $this->checkMinExpectElements(6, $elements) + ? $this->getAttribute($elements[2], $elements[3], $elements[4], $elements[5], ($elements[6] ?? null)) + : false; // Get item. case 'item': - return $this->getItem($elements[2], $elements[3], $elements[4], ($elements[5] ?? null)); + return $this->checkMinExpectElements(6, $elements) + ? $this->getItem($elements[2], $elements[3], $elements[4], ($elements[5] ?? null)) + : false; // Get jump-to detail page. case 'jumpTo': - return $this->jumpTo($elements[2], $elements[3], $elements[4], ($elements[5] ?? null)); + return $this->checkMinExpectElements(5, $elements) + ? $this->jumpTo($elements[2], $elements[3], $elements[4], ($elements[5] ?? null)) + : false; default: } @@ -493,11 +501,22 @@ private function getCountFor(int $intMetaModelId, int $intFilterId = null): int return $metaModel->getCount($objFilter); } + /** + * @param int $expectCount The expected number of elements. + * @param array $elements The elements. + * + * @return bool + */ + private function checkMinExpectElements(int $expectCount, array $elements): bool + { + return \count($elements) >= $expectCount; + } + /** * Check if the item is published. * * @param IMetaModel $metaModel Current MetaModel. - * @param int $intItemId Id of the item. + * @param int $intItemId ID of the item. * * @return bool True => Published | False => Not published * From bf28ad457eaa9fb357cacd3e19eb573b6793ed21 Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 1 Feb 2023 15:48:10 +0100 Subject: [PATCH 144/224] delete superfluous method --- .../EventListener/InsertTagsListener.php | 45 +++---------------- 1 file changed, 7 insertions(+), 38 deletions(-) diff --git a/src/CoreBundle/EventListener/InsertTagsListener.php b/src/CoreBundle/EventListener/InsertTagsListener.php index 67dadfdce..297bfd21c 100644 --- a/src/CoreBundle/EventListener/InsertTagsListener.php +++ b/src/CoreBundle/EventListener/InsertTagsListener.php @@ -369,9 +369,7 @@ private function getCount(string $type, int|string $identifier, int $filterId = // From MetaModel with filter. case 'mm': - if (($result = $this->translateMetaModelNameToId($identifier))) { - return $this->getCountFor((int) $result, $filterId); - } + return $this->getCountFor($identifier, $filterId); break; // Unknown element type. @@ -382,43 +380,14 @@ private function getCount(string $type, int|string $identifier, int $filterId = return 0; } - /** - * Translate MetaModel name to id if found. - * - * @param $identifier int|string The MetaModel identifier. - * - * @return false|int - * @throws Exception - */ - private function translateMetaModelNameToId(int|string $identifier): bool|int - { - if (\is_numeric($identifier)) { - return $identifier; - } - - $statement = $this->connection->createQueryBuilder() - ->select('t.id') - ->from('tl_metamodel', 't') - ->where('t.tableName=:tableName') - ->setParameter('tableName', $identifier) - ->executeQuery(); - - // Check if we have some data. - if ($statement->rowCount() < 1) { - return false; - } - - return (int) $statement->fetchFirstColumn(); - } - /** * Try to load the MetaModel by id or name. * - * @param mixed $nameOrId Name or id of the MetaModel. + * @param int|string $nameOrId Name or id of the MetaModel. * * @return IMetaModel|null */ - private function loadMetaModel($nameOrId): ?IMetaModel + private function loadMetaModel(int|string $nameOrId): ?IMetaModel { if (\is_numeric($nameOrId)) { // ID. @@ -474,14 +443,14 @@ private function getMetaModelDataFrom(string $strTable, int $intID): bool|array /** * Get count form one MM for chosen filter. * - * @param int $intMetaModelId ID of the metamodels. - * @param int|null $intFilterId ID of the filter. + * @param string $metaModelNameOrId Name or id of the MetaModel. + * @param int|null $intFilterId ID of the filter. * * @return int The count result. */ - private function getCountFor(int $intMetaModelId, int $intFilterId = null): int + private function getCountFor(string $metaModelNameOrId, int $intFilterId = null): int { - $metaModel = $this->loadMetaModel($intMetaModelId); + $metaModel = $this->loadMetaModel($metaModelNameOrId); if (null === $metaModel) { return 0; } From f4d064c5acfcb2684be8ca4ad8f6bcb3d1feb770 Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 1 Feb 2023 16:00:53 +0100 Subject: [PATCH 145/224] Fix check --- src/CoreBundle/EventListener/InsertTagsListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/EventListener/InsertTagsListener.php b/src/CoreBundle/EventListener/InsertTagsListener.php index 297bfd21c..715d77184 100644 --- a/src/CoreBundle/EventListener/InsertTagsListener.php +++ b/src/CoreBundle/EventListener/InsertTagsListener.php @@ -152,7 +152,7 @@ public function __invoke(string $insertTag): bool|int|string // Get item. case 'item': - return $this->checkMinExpectElements(6, $elements) + return $this->checkMinExpectElements(5, $elements) ? $this->getItem($elements[2], $elements[3], $elements[4], ($elements[5] ?? null)) : false; From 4d4dc1dda187588499b68ebf7927133787a25ae7 Mon Sep 17 00:00:00 2001 From: e-spin Date: Tue, 7 Feb 2023 08:44:30 +0100 Subject: [PATCH 146/224] Add deprecation notice at hookAdditionalFormatters --- src/Attribute/Base.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 0e308c564..7d8ba8d9c 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -192,20 +192,26 @@ protected function getLangValue($arrValues, $strLangCode = null) * * @param array $arrBaseFormatted The current result array. The keys "raw" and "text" are always * populated. - * * @param array $arrRowData The Raw values from the database. - * * @param string $strOutputFormat The output format to use. - * * @param ISimpleRenderSetting $objSettings The output format settings. * * @return mixed * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) + * + * @deprecated This will get removed in 3.0. */ public function hookAdditionalFormatters($arrBaseFormatted, $arrRowData, $strOutputFormat, $objSettings) { + // @codingStandardsIgnoreStart + @trigger_error( + '"' .__METHOD__ . '" is deprecated and will get removed.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + $arrResult = $arrBaseFormatted; if (isset($GLOBALS['METAMODEL_HOOKS']['parseValue']) && is_array($GLOBALS['METAMODEL_HOOKS']['parseValue'])) { From 020bd8845dc349a3b2f7b2acbf4351b960d82e25 Mon Sep 17 00:00:00 2001 From: e-spin Date: Tue, 7 Feb 2023 08:45:55 +0100 Subject: [PATCH 147/224] Fix deprecation --- src/MetaModel.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/MetaModel.php b/src/MetaModel.php index c3a59aac0..9d4a4b3a8 100644 --- a/src/MetaModel.php +++ b/src/MetaModel.php @@ -799,6 +799,7 @@ public function getActiveLanguage() '"\MetaModels\ITranslatedMetaModel::selectLanguage" instead.', __METHOD__), E_USER_DEPRECATED ); + // @codingStandardsIgnoreEnd } else { // @codingStandardsIgnoreStart @\trigger_error( From 63ea1870b57b4c6414e7cd04243dd2e37eb8f5f8 Mon Sep 17 00:00:00 2001 From: e-spin Date: Tue, 7 Feb 2023 21:53:25 +0100 Subject: [PATCH 148/224] Move notice --- src/Attribute/Base.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 7d8ba8d9c..aeb66b0ed 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -205,20 +205,20 @@ protected function getLangValue($arrValues, $strLangCode = null) */ public function hookAdditionalFormatters($arrBaseFormatted, $arrRowData, $strOutputFormat, $objSettings) { - // @codingStandardsIgnoreStart - @trigger_error( - '"' .__METHOD__ . '" is deprecated and will get removed.', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd - $arrResult = $arrBaseFormatted; - if (isset($GLOBALS['METAMODEL_HOOKS']['parseValue']) && is_array($GLOBALS['METAMODEL_HOOKS']['parseValue'])) { + if (isset($GLOBALS['METAMODEL_HOOKS']['parseValue']) && \is_array($GLOBALS['METAMODEL_HOOKS']['parseValue'])) { + // @codingStandardsIgnoreStart + @trigger_error( + '"' .__METHOD__ . '" is deprecated and will get removed.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + foreach ($GLOBALS['METAMODEL_HOOKS']['parseValue'] as $callback) { list($strClass, $strMethod) = $callback; - $objCallback = (in_array('getInstance', get_class_methods($strClass))) + $objCallback = (\in_array('getInstance', get_class_methods($strClass))) ? call_user_func(array($strClass, 'getInstance')) : new $strClass(); From 329866deb4019cbfe2a2bffb867c57a55642ff98 Mon Sep 17 00:00:00 2001 From: e-spin Date: Thu, 9 Feb 2023 14:00:44 +0100 Subject: [PATCH 149/224] Fix translation --- .../DcGeneral/Table/Attribute/ColNameValidationListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php index 0d97c32ae..9936274a9 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php @@ -82,7 +82,7 @@ public function handle(EncodePropertyValueFromWidgetEvent $event) if (in_array($columnName, $colNames)) { throw new \RuntimeException( sprintf( - $event->getEnvironment()->getTranslator()->translate('columnExists', 'ERR'), + $event->getEnvironment()->getTranslator()->translate('ERR.columnExists'), $columnName, $metaModel->getTableName() ) From e337ca365ca2106829f592a5f7257609e456b5a2 Mon Sep 17 00:00:00 2001 From: e-spin Date: Thu, 9 Feb 2023 14:04:52 +0100 Subject: [PATCH 150/224] Fix typo --- .../Table/Attribute/ColNameValidationListener.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php index 9936274a9..445f05666 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -36,7 +37,7 @@ class ColNameValidationListener extends BaseListener * * @var TableManipulator */ - private $tableManipulator; + private TableManipulator $tableManipulator; /** * Create a new instance. @@ -65,7 +66,7 @@ public function __construct( * * @throws \RuntimeException When the column name is illegal or duplicate. */ - public function handle(EncodePropertyValueFromWidgetEvent $event) + public function handle(EncodePropertyValueFromWidgetEvent $event): void { if (!parent::wantToHandle($event) || ($event->getProperty() !== 'colname')) { return; @@ -78,10 +79,10 @@ public function handle(EncodePropertyValueFromWidgetEvent $event) if ((!$columnName) || $oldColumnName !== $columnName) { $this->tableManipulator->checkColumnDoesNotExist($metaModel->getTableName(), $columnName); - $colNames = array_keys($metaModel->getAttributes()); - if (in_array($columnName, $colNames)) { + $colNames = \array_keys($metaModel->getAttributes()); + if (\in_array($columnName, $colNames)) { throw new \RuntimeException( - sprintf( + \sprintf( $event->getEnvironment()->getTranslator()->translate('ERR.columnExists'), $columnName, $metaModel->getTableName() From 47cbec78e5cb1f690f8ea1069a45281949475691 Mon Sep 17 00:00:00 2001 From: e-spin Date: Sat, 11 Feb 2023 19:13:48 +0100 Subject: [PATCH 151/224] Add key jumpTo as deprecated --- src/Item.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Item.php b/src/Item.php index ed1af8372..f3ba8c997 100644 --- a/src/Item.php +++ b/src/Item.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Richard Henkenjohann * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -474,6 +474,7 @@ public function parseValue($strOutputFormat = 'text', $objSettings = null) } // Just here for backwards compatibility with templates. See #1087 + // @deprecated usage of array key 'jumpTo' - remove in MM 3.0. $arrResult['jumpTo'] = $jumpTo; // First, parse the values in the same order as they are in the render settings. From 136d3b01537acf265c04b225f10bec939ea627db Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 25 Jan 2023 21:45:20 +0100 Subject: [PATCH 152/224] Add MM locale util --- src/CoreBundle/Resources/config/services.yml | 3 ++ src/Helper/LocaleUtil.php | 51 ++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/Helper/LocaleUtil.php diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index 560d51335..dc01b93d1 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -283,3 +283,6 @@ services: - "@contao.assets.files_context" - "@contao.image.picture_factory" - "@session" + + MetaModels\Helper\LocaleUtil: + public: false diff --git a/src/Helper/LocaleUtil.php b/src/Helper/LocaleUtil.php new file mode 100644 index 000000000..8b1c1ddef --- /dev/null +++ b/src/Helper/LocaleUtil.php @@ -0,0 +1,51 @@ + + * @copyright 2012-2023 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\Helper; + +use Contao\CoreBundle\Util\LocaleUtil as ContaoLocaleUtil; + +final class LocaleUtil +{ + /** + * Converts a Locale ID (_) to a Language Tag (-) and strips keywords + * after the @ sign. + * + * @param string $localeId The locale id. + * + * @return string + */ + public static function formatAsLanguageTag(string $localeId): string + { + return \str_replace('_', '-', ContaoLocaleUtil::formatAsLocale($localeId)); + } + + /** + * Converts a Language Tag (-) to a Locale ID (_) and strips keywords + * after the @ sign. + * + * @param string $languageTag The language tag. + * + * @return string + */ + public static function formatAsLocale(string $languageTag): string + { + return ContaoLocaleUtil::formatAsLocale($languageTag); + } +} From 0a589989c677bce87d4b7bc101c761dce4c7d28b Mon Sep 17 00:00:00 2001 From: e-spin Date: Fri, 27 Jan 2023 22:01:30 +0100 Subject: [PATCH 153/224] Fix code --- src/CoreBundle/Resources/config/services.yml | 3 --- src/Helper/LocaleUtil.php | 13 ++++++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index dc01b93d1..560d51335 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -283,6 +283,3 @@ services: - "@contao.assets.files_context" - "@contao.image.picture_factory" - "@session" - - MetaModels\Helper\LocaleUtil: - public: false diff --git a/src/Helper/LocaleUtil.php b/src/Helper/LocaleUtil.php index 8b1c1ddef..2b21f49b7 100644 --- a/src/Helper/LocaleUtil.php +++ b/src/Helper/LocaleUtil.php @@ -20,12 +20,15 @@ namespace MetaModels\Helper; use Contao\CoreBundle\Util\LocaleUtil as ContaoLocaleUtil; +use Contao\System; final class LocaleUtil { /** - * Converts a Locale ID (_) to a Language Tag (-) and strips keywords + * Converts a Locale ID to a Language Tag and strips keywords * after the @ sign. + * As legacy part we convert a Locale ID (_) to a Language Tag (-) + * and strips keywords after the @ sign. * * @param string $localeId The locale id. * @@ -33,6 +36,14 @@ final class LocaleUtil */ public static function formatAsLanguageTag(string $localeId): string { + $packages = System::getContainer()->getParameter('kernel.packages'); + $coreVersion = $packages['contao/core-bundle']; + + if (\version_compare($coreVersion, '4.13', '>=')) { + return self::formatAsLocale($localeId); + } + + // Legacy call. return \str_replace('_', '-', ContaoLocaleUtil::formatAsLocale($localeId)); } From 70ebdddd44f3462320c5be7305996a28c9a2418d Mon Sep 17 00:00:00 2001 From: e-spin Date: Tue, 7 Feb 2023 18:10:31 +0100 Subject: [PATCH 154/224] Fix language option listener --- .../Table/MetaModel/LanguageOptionsListener.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/LanguageOptionsListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/LanguageOptionsListener.php index 4e8943df8..2a2a6d021 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/LanguageOptionsListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/LanguageOptionsListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,7 +35,7 @@ class LanguageOptionsListener * * @var RequestScopeDeterminator */ - private $scopeDeterminator; + private RequestScopeDeterminator $scopeDeterminator; /** * Create a new instance. @@ -54,7 +54,7 @@ public function __construct(RequestScopeDeterminator $scopeDeterminator) * * @return void */ - public function handle(GetOptionsEvent $event) + public function handle(GetOptionsEvent $event): void { if (!$this->wantToHandle($event)) { return; @@ -73,7 +73,7 @@ public function handle(GetOptionsEvent $event) $languageOptions[$langKey] = \sprintf( '%s [%s]', $langValue, - $hasTerritory ? \substr_replace($langKey, '-', 2, 1) : $langKey + $langKey ); } @@ -87,7 +87,7 @@ public function handle(GetOptionsEvent $event) * * @return bool */ - protected function wantToHandle(GetOptionsEvent $event) + protected function wantToHandle(GetOptionsEvent $event): bool { if ($event->getOptions() !== null) { return false; From 498f5dc81a1b5b3d91569a8ac82fe116cf0c4388 Mon Sep 17 00:00:00 2001 From: e-spin Date: Tue, 7 Feb 2023 21:06:35 +0100 Subject: [PATCH 155/224] Change str_replace to LocaleUtil --- src/Attribute/Base.php | 26 +++++++++++-------- .../InputScreen/InputScreen.php | 8 +++--- .../Contao/Hooks/LoadDataContainer.php | 8 +++--- .../BreadcrumbDcaSettingConditionListener.php | 10 ++++--- .../DefinitionBuilder/CommandBuilder.php | 8 +++--- .../TranslatorPopulator.php | 8 +++--- src/DcGeneral/Data/Driver.php | 11 +++++--- src/Events/DatabaseBackedListener.php | 8 +++--- src/ItemList.php | 8 +++--- src/MetaModel.php | 4 ++- src/TranslatedMetaModel.php | 9 ++++--- 11 files changed, 67 insertions(+), 41 deletions(-) diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index aeb66b0ed..07ce099f6 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -26,6 +26,7 @@ namespace MetaModels\Attribute; +use MetaModels\Helper\LocaleUtil; use MetaModels\IMetaModel; use MetaModels\ITranslatedMetaModel; use MetaModels\Render\Setting\ISimple as ISimpleRenderSetting; @@ -136,20 +137,19 @@ public function getName() * If the language is not contained within the value array, the fallback language from the parenting * {@link IMetaModel} instance is tried as well. * - * @param array $arrValues The array holding all language values in the form array('langcode' => $varValue). - * - * @param string $strLangCode The language code of the language to fetch. + * @param array $arrValues The array holding all language values in the form array('langcode' => $varValue). + * @param string|null $strLangCode The language code of the language to fetch. * * @return mixed|null the value for the given language or the fallback language, NULL if neither is present. * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - protected function getLangValue($arrValues, $strLangCode = null) + protected function getLangValue($arrValues, $strLangCode = null): mixed { $metaModel = $this->getMetaModel(); // Not a valid lookup array, exit. - if (!is_array($arrValues)) { + if (!\is_array($arrValues)) { return $arrValues; } @@ -163,7 +163,9 @@ protected function getLangValue($arrValues, $strLangCode = null) E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - $strLangCode = \str_replace('-', '_', $GLOBALS['TL_LANGUAGE']); + + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + $strLangCode = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); } // Not translated, exit. @@ -171,16 +173,18 @@ protected function getLangValue($arrValues, $strLangCode = null) return $arrValues; } - if (array_key_exists($strLangCode, $arrValues)) { + if (\array_key_exists($strLangCode, $arrValues)) { return $arrValues[$strLangCode]; } + // Language code not set, use fallback. if ($metaModel instanceof ITranslatedMetaModel) { $strLangCode = $metaModel->getMainLanguage(); } else { $strLangCode = $metaModel->getFallbackLanguage(); } - if (array_key_exists($strLangCode, $arrValues)) { + + if (\array_key_exists($strLangCode, $arrValues)) { return $arrValues[$strLangCode]; } @@ -216,7 +220,7 @@ public function hookAdditionalFormatters($arrBaseFormatted, $arrRowData, $strOut // @codingStandardsIgnoreEnd foreach ($GLOBALS['METAMODEL_HOOKS']['parseValue'] as $callback) { - list($strClass, $strMethod) = $callback; + [$strClass, $strMethod] = $callback; $objCallback = (\in_array('getInstance', get_class_methods($strClass))) ? call_user_func(array($strClass, 'getInstance')) @@ -389,8 +393,8 @@ private function setLanguageStrings() if (empty($GLOBALS['TL_LANG'][$this->getMetaModel()->getTableName()][$this->getColName()])) { $GLOBALS['TL_LANG'][$this->getMetaModel()->getTableName()][$this->getColName()] = array ( - $this->getLangValue($this->get('name'), \str_replace('-', '_', $GLOBALS['TL_LANGUAGE'])), - $this->getLangValue($this->get('description'), \str_replace('-', '_', $GLOBALS['TL_LANGUAGE'])), + $this->getLangValue($this->get('name'), LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])), + $this->getLangValue($this->get('description'), LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])), ); } } diff --git a/src/BackendIntegration/InputScreen/InputScreen.php b/src/BackendIntegration/InputScreen/InputScreen.php index e5dcc451a..83a5e9402 100644 --- a/src/BackendIntegration/InputScreen/InputScreen.php +++ b/src/BackendIntegration/InputScreen/InputScreen.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Ingolf Steinhardt * @author Sven Baumann * @author Richard Henkenjohann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,6 +32,7 @@ use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Property\PropertyConditionChain; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Property\PropertyConditionInterface; use MetaModels\Events\CreatePropertyConditionEvent; +use MetaModels\Helper\LocaleUtil; use MetaModels\IMetaModel; use MetaModels\IMetaModelsServiceContainer; use MetaModels\ITranslatedMetaModel; @@ -170,7 +171,8 @@ protected function translateLegend($legend, $metaModel) private function extractLegendName(array $legend, IMetaModel $metaModel): string { // Current backend language. - $language = \str_replace('-', '_', $GLOBALS['TL_LANGUAGE']); + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + $language = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); if (null !== ($result = $legend[$language] ?? null)) { return $result; } diff --git a/src/CoreBundle/Contao/Hooks/LoadDataContainer.php b/src/CoreBundle/Contao/Hooks/LoadDataContainer.php index bb6512379..e8653c354 100644 --- a/src/CoreBundle/Contao/Hooks/LoadDataContainer.php +++ b/src/CoreBundle/Contao/Hooks/LoadDataContainer.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +25,7 @@ use Contao\CoreBundle\Framework\Adapter; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; use MetaModels\CoreBundle\Assets\IconBuilder; +use MetaModels\Helper\LocaleUtil; use MetaModels\IFactory; use MetaModels\IMetaModel; use MetaModels\ViewCombination\ViewCombination; @@ -251,7 +252,8 @@ private function buildCaption($metaModel, $inputScreen): array '' ]; - $currentLanguage = \str_replace('-', '_', $GLOBALS['TL_LANGUAGE']); + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + $currentLanguage = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); foreach ($inputScreen['label'] as $langCode => $label) { if ($label !== '' && $langCode === $currentLanguage) { $caption = [ diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php index e6798532c..aa7ed8e29 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +26,7 @@ use ContaoCommunityAlliance\DcGeneral\Data\ModelId; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; +use MetaModels\Helper\LocaleUtil; /** * Generate a breadcrumb for table tl_metamodel_dcasetting_condition. @@ -68,7 +69,7 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea ->unsetQueryParameter('id'); $elements->push( - ampersand($builder->getUrl()), + StringUtil::ampersand($builder->getUrl()), sprintf( $elements->getLabel('tl_metamodel_dcasetting_condition'), $this->getConditionAttribute($elements->getId('tl_metamodel_dcasetting')) @@ -100,7 +101,8 @@ private function getConditionAttribute($settingId) } } else { $title = StringUtil::deserialize($setting->legendtitle, true); - return ($title[\str_replace('-', '_', $GLOBALS['TL_LANGUAGE'])] ?? current($title)); + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + return ($title[LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])] ?? current($title)); } return 'unknown ' . $setting->dcatype; diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php index 3a1bbba7c..a7f49b27b 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -33,6 +33,7 @@ use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\DcGeneral\DataDefinition\IMetaModelDataDefinition; use MetaModels\DcGeneral\Events\MetaModel\BuildMetaModelOperationsEvent; +use MetaModels\Helper\LocaleUtil; use MetaModels\IFactory; use MetaModels\IMetaModel; use MetaModels\ViewCombination\ViewCombination; @@ -361,7 +362,8 @@ private function getChildModelCaption($metaModel, $screen) ]; foreach ($screen['label'] as $langCode => $label) { - if (!empty($label) && $langCode === \str_replace('-', '_', $GLOBALS['TL_LANGUAGE'])) { + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + if (!empty($label) && $langCode === LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])) { $caption = [ $screen['description'][$langCode], $label diff --git a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php index 7ff13bdbf..2bb795429 100644 --- a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php +++ b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +26,7 @@ use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\Translator\StaticTranslator; use ContaoCommunityAlliance\Translator\TranslatorChain; +use MetaModels\Helper\LocaleUtil; use MetaModels\ViewCombination\ViewCombination; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -144,7 +145,8 @@ private function mapTranslations($array, $domain, StaticTranslator $translator, private function addInputScreenTranslations(StaticTranslator $translator, $inputScreen, $containerName) { // Either 2 or 5 char long language code. - $currentLocale = \str_replace('-', '_', $GLOBALS['TL_LANGUAGE']); + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + $currentLocale = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); // Either 2 char language code or null. $shortLocale = (false !== strpos($currentLocale, '_')) ? explode('_', $currentLocale, 2)[0] diff --git a/src/DcGeneral/Data/Driver.php b/src/DcGeneral/Data/Driver.php index d2b37f295..cc7043825 100644 --- a/src/DcGeneral/Data/Driver.php +++ b/src/DcGeneral/Data/Driver.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -42,6 +42,7 @@ use MetaModels\Attribute\IComplex; use MetaModels\Attribute\ITranslated; use MetaModels\Filter\IFilter; +use MetaModels\Helper\LocaleUtil; use MetaModels\IItem; use MetaModels\IItems; use MetaModels\IMetaModel; @@ -227,14 +228,16 @@ public function getActiveVersion($mixID) */ protected function setLanguage($language = '') { - $previousLanguage = \str_replace('-', '_', $GLOBALS['TL_LANGUAGE']); + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + $previousLanguage = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); if (!empty($language)) { $metaModel = $this->getMetaModel(); if ($metaModel instanceof ITranslatedMetaModel) { $metaModel->selectLanguage($language); } - $language = \str_replace('_', '-', $language); + $language = LocaleUtil::formatAsLanguageTag($language); + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. if ($GLOBALS['TL_LANGUAGE'] !== $language) { $GLOBALS['TL_LANGUAGE'] = $language; } diff --git a/src/Events/DatabaseBackedListener.php b/src/Events/DatabaseBackedListener.php index 6b0e72aba..8d21f091f 100644 --- a/src/Events/DatabaseBackedListener.php +++ b/src/Events/DatabaseBackedListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author David Molineus * @author Cliff Parnitzky * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +26,7 @@ use Contao\System; use Doctrine\DBAL\Connection; use MetaModels\Attribute\Events\CollectMetaModelAttributeInformationEvent; +use MetaModels\Helper\LocaleUtil; use MetaModels\IMetaModel; use MetaModels\IMetaModelsServiceContainer; use MetaModels\ITranslatedMetaModel; @@ -212,7 +213,8 @@ protected function createInstance(CreateMetaModelEvent $event, $arrData) if (!$this->createInstanceViaLegacyFactory($event, $arrData)) { if ($arrData['translated']) { $metaModel = new TranslatedMetaModel($arrData, $this->dispatcher, $this->database); - $metaModel->selectLanguage(\str_replace('-', '_', $GLOBALS['TL_LANGUAGE'])); + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + $metaModel->selectLanguage(LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])); } else { $metaModel = new MetaModel($arrData, $this->dispatcher, $this->database); } diff --git a/src/ItemList.php b/src/ItemList.php index ef532607f..1b8e073f7 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -25,7 +25,7 @@ * @author David Molineus * @author Ingolf Steinhardt * @author Fritz Michael Gschwantner - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -44,6 +44,7 @@ use MetaModels\Filter\IFilterRule; use MetaModels\Filter\Setting\ICollection as IFilterSettingCollection; use MetaModels\Filter\Setting\IFilterSettingFactory; +use MetaModels\Helper\LocaleUtil; use MetaModels\Helper\PaginationLimitCalculator; use MetaModels\Render\Setting\ICollection as IRenderSettingCollection; use MetaModels\Render\Setting\IRenderSettingFactory; @@ -847,7 +848,8 @@ public function prepare(): self $this->objTemplate->total = $total; if ($this->objMetaModel instanceof TranslatedMetaModel) { - $previousLanguage = $this->objMetaModel->selectLanguage(\str_replace('-', '_', $GLOBALS['TL_LANGUAGE'])); + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + $previousLanguage = $this->objMetaModel->selectLanguage(LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])); } $this->objItems = $this->objMetaModel->findByFilter( diff --git a/src/MetaModel.php b/src/MetaModel.php index 9d4a4b3a8..0be3c625f 100644 --- a/src/MetaModel.php +++ b/src/MetaModel.php @@ -37,6 +37,7 @@ use MetaModels\Filter\Filter; use MetaModels\Filter\IFilter; use MetaModels\Filter\Rules\StaticIdList; +use MetaModels\Helper\LocaleUtil; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** @@ -810,7 +811,8 @@ public function getActiveLanguage() // @codingStandardsIgnoreEnd } - return \str_replace('-', '_', $GLOBALS['TL_LANGUAGE']); + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + return LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); } /** diff --git a/src/TranslatedMetaModel.php b/src/TranslatedMetaModel.php index 59ace966f..bc9dc14c1 100644 --- a/src/TranslatedMetaModel.php +++ b/src/TranslatedMetaModel.php @@ -22,6 +22,7 @@ use Doctrine\DBAL\Connection; use MetaModels\Attribute\ITranslated; +use MetaModels\Helper\LocaleUtil; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** @@ -132,8 +133,9 @@ public function selectLanguage(string $activeLanguage): string */ protected function fetchTranslatedAttributeValues(ITranslated $attribute, $ids) { - $originalLanguage = $GLOBALS['TL_LANGUAGE']; - $GLOBALS['TL_LANGUAGE'] = \str_replace('_', '-', $this->getLanguage()); + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + $originalLanguage = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); + $GLOBALS['TL_LANGUAGE'] = LocaleUtil::formatAsLanguageTag($this->getLanguage()); try { $attributeData = $attribute->getTranslatedDataFor($ids, $this->getLanguage()); @@ -144,7 +146,8 @@ protected function fetchTranslatedAttributeValues(ITranslated $attribute, $ids) return $attributeData; } finally { - $GLOBALS['TL_LANGUAGE'] = $originalLanguage; + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + $GLOBALS['TL_LANGUAGE'] = LocaleUtil::formatAsLanguageTag($originalLanguage); } } } From e75bead53d64ad04421bc230043dc967b8c22a10 Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 8 Feb 2023 19:09:34 +0100 Subject: [PATCH 156/224] Fix comment --- src/Attribute/Base.php | 1 + src/ItemList.php | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 07ce099f6..9e0a15dc5 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -165,6 +165,7 @@ protected function getLangValue($arrValues, $strLangCode = null): mixed // @codingStandardsIgnoreEnd // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + // In future versions we try to read from locale request, otherwise we raise an exception. $strLangCode = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); } diff --git a/src/ItemList.php b/src/ItemList.php index 1b8e073f7..0d1a1fcd3 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -849,7 +849,8 @@ public function prepare(): self if ($this->objMetaModel instanceof TranslatedMetaModel) { // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. - $previousLanguage = $this->objMetaModel->selectLanguage(LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])); + $previousLanguage = + $this->objMetaModel->selectLanguage(LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])); } $this->objItems = $this->objMetaModel->findByFilter( From 66cdedaa6b4e4db47d05fc5b32db4bb1e01feb02 Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 13 Feb 2023 19:56:53 +0100 Subject: [PATCH 157/224] Fix the review --- src/Attribute/Base.php | 35 ++++++++++++++++++++---------- src/DcGeneral/Data/Driver.php | 41 ++++++++++++++++++++--------------- src/ItemList.php | 41 +++++++++++++++++++++++++++++++---- src/MetaModel.php | 2 +- 4 files changed, 84 insertions(+), 35 deletions(-) diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 9e0a15dc5..b8081246b 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -147,12 +147,17 @@ public function getName() */ protected function getLangValue($arrValues, $strLangCode = null): mixed { - $metaModel = $this->getMetaModel(); // Not a valid lookup array, exit. if (!\is_array($arrValues)) { return $arrValues; } + $metaModel = $this->getMetaModel(); + // Not translated, exit. + if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { + return $arrValues; + } + if (null === $strLangCode) { // @codingStandardsIgnoreStart @\trigger_error( @@ -166,12 +171,12 @@ protected function getLangValue($arrValues, $strLangCode = null): mixed // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. // In future versions we try to read from locale request, otherwise we raise an exception. - $strLangCode = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); - } - - // Not translated, exit. - if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { - return $arrValues; + $strLangCode = LocaleUtil::formatAsLocale( + $GLOBALS['TL_LANGUAGE'] + ?? (($this->metaModel instanceof ITranslatedMetaModel) + ? $this->metaModel->getLanguage() + : $this->metaModel->getActiveLanguage()) + ); } if (\array_key_exists($strLangCode, $arrValues)) { @@ -388,15 +393,21 @@ public function getAttributeSettingNames() * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - private function setLanguageStrings() + private function setLanguageStrings(): void { // Only overwrite the language if not already set. if (empty($GLOBALS['TL_LANG'][$this->getMetaModel()->getTableName()][$this->getColName()])) { - $GLOBALS['TL_LANG'][$this->getMetaModel()->getTableName()][$this->getColName()] = array - ( - $this->getLangValue($this->get('name'), LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])), - $this->getLangValue($this->get('description'), LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])), + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + $language = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'] ?? ( + ($this->metaModel instanceof ITranslatedMetaModel) + ? $this->metaModel->getLanguage() + : $this->metaModel->getActiveLanguage()) ); + + $GLOBALS['TL_LANG'][$this->getMetaModel()->getTableName()][$this->getColName()] = [ + $this->getLangValue($this->get('name'), $language), + $this->getLangValue($this->get('description'), $language), + ]; } } diff --git a/src/DcGeneral/Data/Driver.php b/src/DcGeneral/Data/Driver.php index cc7043825..24e2ac923 100644 --- a/src/DcGeneral/Data/Driver.php +++ b/src/DcGeneral/Data/Driver.php @@ -62,37 +62,37 @@ class Driver implements MultiLanguageDataProviderInterface /** * Name of current table. * - * @var string + * @var null|string */ - protected $strTable = null; + protected ?string $strTable = null; /** * The MetaModel this DataContainer is working on. * - * @var IMetaModel + * @var null|IMetaModel */ - protected $metaModel = null; + protected ?IMetaModel $metaModel = null; /** * The event dispatcher to pass to items. * * @var null|EventDispatcherInterface */ - private $dispatcher = null; + private ?EventDispatcherInterface $dispatcher = null; /** * The current active language. * * @var string */ - protected $strCurrentLanguage; + protected string $strCurrentLanguage; /** * The database connection. * * @var Connection|null */ - private $connection; + private ?Connection $connection; /** * Set dispatcher. @@ -228,19 +228,24 @@ public function getActiveVersion($mixID) */ protected function setLanguage($language = '') { + $metaModel = $this->getMetaModel(); // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. - $previousLanguage = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); - if (!empty($language)) { - $metaModel = $this->getMetaModel(); - if ($metaModel instanceof ITranslatedMetaModel) { - $metaModel->selectLanguage($language); - } + $previousLanguage = ($metaModel instanceof ITranslatedMetaModel) + ? $metaModel->getLanguage() + : LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); - $language = LocaleUtil::formatAsLanguageTag($language); - // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. - if ($GLOBALS['TL_LANGUAGE'] !== $language) { - $GLOBALS['TL_LANGUAGE'] = $language; - } + if (empty($language)) { + return $previousLanguage; + } + + if ($metaModel instanceof ITranslatedMetaModel) { + $previousLanguage = $metaModel->selectLanguage($language); + } + + $language = LocaleUtil::formatAsLanguageTag($language); + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + if ($GLOBALS['TL_LANGUAGE'] !== $language) { + $GLOBALS['TL_LANGUAGE'] = $language; } return $previousLanguage; diff --git a/src/ItemList.php b/src/ItemList.php index 0d1a1fcd3..dd5d9535a 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -164,7 +164,14 @@ class ItemList * * @var EventDispatcherInterface|null */ - private $eventDispatcher; + private ?EventDispatcherInterface $eventDispatcher; + + /** + * The language. + * + * @var string|null + */ + private ?string $language = null; /** * Create a new instance. @@ -498,7 +505,6 @@ public function setMetaModel(int $intMetaModel, int $intView): self * Add the attribute names for meta title and description. * * @param string $titleAttribute Name of attribute for title. - * * @param string $descriptionAttribute Name of attribute for description. * * @return ItemList @@ -511,6 +517,20 @@ public function setMetaTags(string $titleAttribute, string $descriptionAttribute return $this; } + /** + * Set the language. + * + * @param string $language The language. + * + * @return $this + */ + public function setLanguage(string $language): self + { + $this->language = $language; + + return $this; + } + /** * The Metamodel to use. * @@ -848,9 +868,22 @@ public function prepare(): self $this->objTemplate->total = $total; if ($this->objMetaModel instanceof TranslatedMetaModel) { - // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + if (null === $this->language) { + // @codingStandardsIgnoreStart + @\trigger_error( + sprintf( + 'Not setting a language code in "%s" is deprecated since MetaModels 2.3 and will fail in 3.0', + __CLASS__ + ), + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + + // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + $this->language = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'] ?? 'en'); + } $previousLanguage = - $this->objMetaModel->selectLanguage(LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])); + $this->objMetaModel->selectLanguage($this->language); } $this->objItems = $this->objMetaModel->findByFilter( diff --git a/src/MetaModel.php b/src/MetaModel.php index 0be3c625f..1f7a7725c 100644 --- a/src/MetaModel.php +++ b/src/MetaModel.php @@ -812,7 +812,7 @@ public function getActiveLanguage() } // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. - return LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); + return LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'] ?? 'en'); } /** From 03a602f3cf09b05da1551e80143d013842fbaef2 Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 15 Feb 2023 11:45:45 +0100 Subject: [PATCH 158/224] Delete old proxy --- src/ItemList.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ItemList.php b/src/ItemList.php index dd5d9535a..0ac10bc8a 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -51,7 +51,6 @@ use MetaModels\Render\Template; use RuntimeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; /** * Implementation of a general purpose MetaModel listing. @@ -215,7 +214,7 @@ public function __construct( $this->factory = $factory; $this->filterFactory = $filterFactory; $this->renderSettingFactory = $renderSettingFactory; - $this->eventDispatcher = LegacyEventDispatcherProxy::decorate($eventDispatcher); + $this->eventDispatcher = $eventDispatcher; } /** From 95fd3eaca3436126194c5b89deda2a337a884bcc Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 15 Feb 2023 14:10:27 +0100 Subject: [PATCH 159/224] Fix table and column validation --- .../Attribute/ColNameValidationListener.php | 19 ++++++++- .../Table/MetaModel/ModelToLabelListener.php | 39 ++++++++++--------- .../contao/dca/tl_metamodel_attribute.php | 1 + 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php index 445f05666..b7e1e440b 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php @@ -24,6 +24,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\EncodePropertyValueFromWidgetEvent; use MetaModels\Attribute\IAttributeFactory; +use MetaModels\Exceptions\Database\InvalidColumnNameException; use MetaModels\Helper\TableManipulator; use MetaModels\IFactory; @@ -77,7 +78,23 @@ public function handle(EncodePropertyValueFromWidgetEvent $event): void $metaModel = $this->getMetaModelByModelPid($event->getModel()); if ((!$columnName) || $oldColumnName !== $columnName) { - $this->tableManipulator->checkColumnDoesNotExist($metaModel->getTableName(), $columnName); + try { + $this->tableManipulator->checkColumnName($columnName); + } catch (InvalidColumnNameException $exception) { + throw new \RuntimeException( + \sprintf( + $event->getEnvironment()->getTranslator()->translate( + 'ERR.' . ($this->tableManipulator->isSystemColumn($columnName) + ? 'systemColumn' + : 'invalidColumnName') + ), + $columnName, + $metaModel->getTableName() + ), + 0, + $exception + ); + } $colNames = \array_keys($metaModel->getAttributes()); if (\in_array($columnName, $colNames)) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php index 04bf72835..6cb705332 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php @@ -80,30 +80,31 @@ public function handle(ModelToLabelEvent $event) $model = $event->getModel(); $tableName = $model->getProperty('tableName'); - if (!($model && !empty($tableName) && $this->connection->getSchemaManager()->tablesExist([$tableName]))) { - return; + $count = '?'; + $transId = 'tl_metamodel.itemFormatCount.0'; + if ($model && !empty($tableName) && $this->connection->createSchemaManager()->tablesExist([$tableName])) { + $count = $this->connection + ->createQueryBuilder() + ->select('COUNT(t.id) AS itemCount') + ->from($tableName, 't') + ->executeQuery() + ->fetchOne(); + + switch ($count) { + case 0: + $transId = 'tl_metamodel.itemFormatCount.0'; + break; + case 1: + $transId = 'tl_metamodel.itemFormatCount.1'; + break; + default: + $transId = 'tl_metamodel.itemFormatCount.2:'; + } } // Keep the previous label. $label = vsprintf($event->getLabel(), $event->getArgs()); $image = ((bool) $model->getProperty('translated')) ? 'locale.png' : 'locale_1.png'; - $count = $this->connection - ->createQueryBuilder() - ->select('COUNT(t.id) AS itemCount') - ->from($tableName, 't') - ->executeQuery() - ->fetchOne(); - - switch ($count) { - case 0: - $transId = 'tl_metamodel.itemFormatCount.0'; - break; - case 1: - $transId = 'tl_metamodel.itemFormatCount.1'; - break; - default: - $transId = 'tl_metamodel.itemFormatCount.2:'; - } $event ->setLabel(' diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php index 04d7b9e5d..4542b7a9b 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php @@ -34,6 +34,7 @@ 'id' => 'primary', 'pid' => 'index', 'colname' => 'index' + // TODO: new unique index over pid + colname ], ], ], From af1f5705af31a9e25c4ba72f7ad1a45a51752deb Mon Sep 17 00:00:00 2001 From: e-spin Date: Thu, 16 Feb 2023 11:49:13 +0100 Subject: [PATCH 160/224] Fix in driver language not set --- src/DcGeneral/Data/Driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DcGeneral/Data/Driver.php b/src/DcGeneral/Data/Driver.php index 24e2ac923..da7978495 100644 --- a/src/DcGeneral/Data/Driver.php +++ b/src/DcGeneral/Data/Driver.php @@ -817,6 +817,6 @@ public function setCurrentLanguage($strLanguage) */ public function getCurrentLanguage() { - return $this->strCurrentLanguage; + return $this->strCurrentLanguage ?? 'en'; } } From eb5593a07bf1b546394939d97f5cc41db37eea01 Mon Sep 17 00:00:00 2001 From: e-spin Date: Sun, 19 Feb 2023 10:58:22 +0100 Subject: [PATCH 161/224] Fix code --- .../Table/MetaModel/ModelToLabelListener.php | 11 +- src/Helper/TableManipulator.php | 210 ++++++++++-------- 2 files changed, 118 insertions(+), 103 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php index 6cb705332..0cc914598 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -69,9 +69,10 @@ public function __construct( * @param ModelToLabelEvent $event The event. * * @return void + * * @throws \Doctrine\DBAL\Exception */ - public function handle(ModelToLabelEvent $event) + public function handle(ModelToLabelEvent $event): void { if (!$this->wantToHandle($event)) { return; @@ -80,7 +81,7 @@ public function handle(ModelToLabelEvent $event) $model = $event->getModel(); $tableName = $model->getProperty('tableName'); - $count = '?'; + $count = '?'; $transId = 'tl_metamodel.itemFormatCount.0'; if ($model && !empty($tableName) && $this->connection->createSchemaManager()->tablesExist([$tableName])) { $count = $this->connection @@ -103,7 +104,7 @@ public function handle(ModelToLabelEvent $event) } // Keep the previous label. - $label = vsprintf($event->getLabel(), $event->getArgs()); + $label = \vsprintf($event->getLabel(), $event->getArgs()); $image = ((bool) $model->getProperty('translated')) ? 'locale.png' : 'locale_1.png'; $event diff --git a/src/Helper/TableManipulator.php b/src/Helper/TableManipulator.php index 2bd12df8d..e8585e4a5 100644 --- a/src/Helper/TableManipulator.php +++ b/src/Helper/TableManipulator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Cliff Parnitzky * @author Ingolf Steinhardt * @author Richard Henkenjohann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -27,6 +27,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\InputProvider; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use MetaModels\Exceptions\Database\ColumnDoesNotExistException; use MetaModels\Exceptions\Database\ColumnExistsException; use MetaModels\Exceptions\Database\InvalidColumnNameException; @@ -34,6 +35,11 @@ use MetaModels\Exceptions\Database\TableDoesNotExistException; use MetaModels\Exceptions\Database\TableExistsException; +use function in_array; +use function preg_match; +use function sprintf; +use function strtolower; + /** * This is the class for table manipulations like creation/renaming/deleting of tables and columns. * @@ -45,7 +51,7 @@ class TableManipulator * SQL statement template to create a table. * First parameter is the table name. */ - const STATEMENT_CREATE_TABLE = ' + public const STATEMENT_CREATE_TABLE = ' CREATE TABLE `%s` ( `id` int(10) unsigned NOT NULL auto_increment, `pid` int(10) unsigned NOT NULL default \'0\', @@ -58,13 +64,13 @@ class TableManipulator * SQL statement template to rename a table. * First parameter is the old name, second parameter is the new name. */ - const STATEMENT_RENAME_TABLE = 'ALTER TABLE `%s` RENAME TO `%s`'; + public const STATEMENT_RENAME_TABLE = 'ALTER TABLE `%s` RENAME TO `%s`'; /** * SQL statement template to drop a table. * First parameter is the table name of the table to drop. */ - const STATEMENT_DROP_TABLE = 'DROP TABLE `%s`'; + public const STATEMENT_DROP_TABLE = 'DROP TABLE `%s`'; /** * SQL statement template to rename a column of a table. @@ -73,7 +79,7 @@ class TableManipulator * Third parameter is the new name of the column. * Fourth parameter is the new type of the column. */ - const STATEMENT_RENAME_COLUMN = 'ALTER TABLE `%s` CHANGE COLUMN `%s` `%s` %s'; + public const STATEMENT_RENAME_COLUMN = 'ALTER TABLE `%s` CHANGE COLUMN `%s` `%s` %s'; /** * SQL statement template to add a column to a table. @@ -81,13 +87,13 @@ class TableManipulator * Second parameter is the column name. * Third parameter is the type of the new column. */ - const STATEMENT_CREATE_COLUMN = 'ALTER TABLE `%s` ADD `%s` %s'; + public const STATEMENT_CREATE_COLUMN = 'ALTER TABLE `%s` ADD `%s` %s'; /** * SQL statement template to delete a column from a table. * First parameter is the name of the column. */ - const STATEMENT_DROP_COLUMN = 'ALTER TABLE `%s` DROP COLUMN `%s`'; + public const STATEMENT_DROP_COLUMN = 'ALTER TABLE `%s` DROP COLUMN `%s`'; /** * SQL statement template to add a index to a column of a table. @@ -95,7 +101,7 @@ class TableManipulator * second parameter is indextype * third parameter is name of the column. */ - const STATEMENT_ADD_INDEX_COLUMN = 'ALTER TABLE `%s` ADD %s(`%s`)'; + public const STATEMENT_ADD_INDEX_COLUMN = 'ALTER TABLE `%s` ADD %s(`%s`)'; /** * List of reserved MySQL identifiers. @@ -104,21 +110,21 @@ class TableManipulator * * @deprecated We work with backticks for table names and columns instead reserved words. */ - protected static $reservedWords = []; + protected static array $reservedWords = []; /** * List of reserved column post fix. * * @var string[] */ - protected static $reservedColumnPostFix = array('__sort'); + protected static array $reservedColumnPostFix = ['__sort']; /** * Database connection. * * @var Connection */ - private $connection; + private Connection $connection; /** * All system columns that always are defined in a MetaModel table. @@ -127,7 +133,7 @@ class TableManipulator * * @var string[] */ - private $systemColumns; + private array $systemColumns; /** * TableManipulator constructor. @@ -151,7 +157,7 @@ public function __construct(Connection $connection, array $systemColumns) * * @deprecated We work with backticks for table names and columns instead reserved words. */ - public function isReservedWord($word) + public function isReservedWord($word): bool { return in_array(strtoupper($word), self::$reservedWords); } @@ -163,7 +169,7 @@ public function isReservedWord($word) * * @return bool */ - public function isReserveColumnPostFix($strColName) + public function isReserveColumnPostFix($strColName): bool { $inputProvider = new InputProvider(); @@ -191,7 +197,7 @@ public function isReserveColumnPostFix($strColName) * * @return bool */ - public function isValidMySQLIdentifier($strName) + public function isValidMySQLIdentifier(string $strName): bool { // Match for valid table/column name, according to MySQL, a table name must start // with a letter and must be combined of letters, decimals and underscore. @@ -205,7 +211,7 @@ public function isValidMySQLIdentifier($strName) * * @return bool true if the table name is valid, false otherwise. */ - public function isValidTablename($strTableName) + public function isValidTablename(string $strTableName): bool { return $this->isValidMySQLIdentifier($strTableName) && !$this->isReservedWord($strTableName); } @@ -217,7 +223,7 @@ public function isValidTablename($strTableName) * * @return bool true if the column is a system column, false otherwise. */ - public function isValidColumnName($strColName) + public function isValidColumnName(string $strColName): bool { return $this->isValidMySQLIdentifier($strColName) && !$this->isReservedWord($strColName) @@ -231,7 +237,7 @@ public function isValidColumnName($strColName) * * @return bool true if the column is a system column, false otherwise. */ - public function isSystemColumn($strColName) + public function isSystemColumn(string $strColName): bool { return in_array($strColName, $this->systemColumns); } @@ -245,7 +251,7 @@ public function isSystemColumn($strColName) * * @throws InvalidTableNameException If an invalid table name has been passed. */ - public function checkTablename($strTableName) + public function checkTablename(string $strTableName): void { if (!$this->isValidTablename($strTableName)) { throw InvalidTableNameException::invalidCharacters($strTableName); @@ -257,9 +263,8 @@ public function checkTablename($strTableName) * * If there is any problem, an Exception is raised, stating the nature of the error in the Exception message. * - * @param string $strColName The name of the column. - * - * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. + * @param string $strColName The name of the column. + * @param bool $blnAllowSystemCol If this is set to true, no system column name checking will be applied. * * @return void * @@ -267,7 +272,7 @@ public function checkTablename($strTableName) * * @see{MetaModelTableManipulation::isSystemColumn()} and @see{MetaModelTableManipulation::isValidColumnName()}. */ - public function checkColumnName($strColName, $blnAllowSystemCol = false) + public function checkColumnName(string $strColName, bool $blnAllowSystemCol = false): void { if (!$this->isValidColumnName($strColName)) { throw InvalidColumnNameException::invalidCharacters($strColName); @@ -287,13 +292,14 @@ public function checkColumnName($strColName, $blnAllowSystemCol = false) * * @throws InvalidTableNameException If an invalid table name has been passed. * @throws TableDoesNotExistException If the table does not exist. + * @throws Exception * * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag */ - public function checkTableExists($strTableName) + public function checkTableExists(string $strTableName): void { $this->checkTablename($strTableName); - if (!$this->connection->getSchemaManager()->tablesExist([$strTableName])) { + if (!$this->connection->createSchemaManager()->tablesExist([$strTableName])) { throw TableDoesNotExistException::withName($strTableName); } } @@ -307,13 +313,14 @@ public function checkTableExists($strTableName) * * @throws InvalidTableNameException If an invalid table name has been passed. * @throws TableExistsException If a table with the given name exists. + * @throws Exception * * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag */ - public function checkTableDoesNotExist($strTableName) + public function checkTableDoesNotExist(string $strTableName): void { $this->checkTablename($strTableName); - if ($this->connection->getSchemaManager()->tablesExist([$strTableName])) { + if ($this->connection->createSchemaManager()->tablesExist([$strTableName])) { throw TableExistsException::withName($strTableName); } } @@ -327,18 +334,18 @@ public function checkTableDoesNotExist($strTableName) * * @throws InvalidTableNameException If an invalid table name has been passed. * @throws TableExistsException If a table with the given name exists. + * @throws Exception If query error. */ - public function createTable($strTableName) + public function createTable(string $strTableName): void { $this->checkTableDoesNotExist($strTableName); - $this->connection->query(sprintf(self::STATEMENT_CREATE_TABLE, $strTableName)); + $this->connection->executeQuery(sprintf(self::STATEMENT_CREATE_TABLE, $strTableName)); } /** * Renames a table with the given name to the given new name. * * @param string $strTableName The name of the table to rename. - * * @param string $strNewTableName The name to which the table shall be renamed to. * * @return void @@ -346,13 +353,14 @@ public function createTable($strTableName) * @throws InvalidTableNameException If an invalid table name has been passed. * @throws TableDoesNotExistException If the source table does not exist. * @throws TableExistsException If a table with the given target name exists. + * @throws Exception If query error. */ - public function renameTable($strTableName, $strNewTableName) + public function renameTable(string $strTableName, string $strNewTableName): void { $this->checkTableExists($strTableName); $this->checkTableDoesNotExist($strNewTableName); - $this->connection->query(sprintf(self::STATEMENT_RENAME_TABLE, $strTableName, $strNewTableName)); + $this->connection->executeQuery(sprintf(self::STATEMENT_RENAME_TABLE, $strTableName, $strNewTableName)); } /** @@ -364,21 +372,20 @@ public function renameTable($strTableName, $strNewTableName) * * @throws InvalidTableNameException If an invalid table name has been passed. * @throws TableDoesNotExistException If the table does not exist. + * @throws Exception If query error. */ - public function deleteTable($strTableName) + public function deleteTable(string $strTableName): void { $this->checkTableExists($strTableName); - $this->connection->query(sprintf(self::STATEMENT_DROP_TABLE, $strTableName)); + $this->connection->executeQuery(sprintf(self::STATEMENT_DROP_TABLE, $strTableName)); } /** - * Add a index to given tablename for specified columnname + * Add an index to given tablename for specified columnname * * @param string $strTableName The table name. - * * @param string $strIndexType The index type. - * * @param string $strColName The column name to add a index. * * @return void @@ -387,11 +394,12 @@ public function deleteTable($strTableName) * @throws TableDoesNotExistException If the table does not exist. * @throws InvalidColumnNameException If an invalid column name has been passed. * @throws ColumnDoesNotExistException If the column does not exist. + * @throws Exception If query error. */ - public function addIndex($strTableName, $strIndexType, $strColName) + public function addIndex(string $strTableName, string $strIndexType, string $strColName): void { $this->checkColumnExists($strTableName, $strColName); - $this->connection->query( + $this->connection->executeQuery( sprintf( self::STATEMENT_ADD_INDEX_COLUMN, $strTableName, @@ -404,11 +412,9 @@ public function addIndex($strTableName, $strIndexType, $strColName) /** * Checks whether the given table exists. * - * @param string $strTableName The table name to check. - * - * @param string $strColName The column name to check. - * - * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. + * @param string $strTableName The table name to check. + * @param string $strColName The column name to check. + * @param bool $blnAllowSystemCol If this is set to true, no system column name checking will be applied. * * @return void * @@ -419,7 +425,7 @@ public function addIndex($strTableName, $strIndexType, $strColName) * * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag */ - public function checkColumnExists($strTableName, $strColName, $blnAllowSystemCol = false) + public function checkColumnExists(string $strTableName, string $strColName, bool $blnAllowSystemCol = false): void { $this->checkTableExists($strTableName); $this->checkColumnName($strColName, $blnAllowSystemCol); @@ -432,20 +438,24 @@ public function checkColumnExists($strTableName, $strColName, $blnAllowSystemCol /** * Checks whether the given column does not exist. * - * @param string $strTableName The table name to check. - * @param string $strColName The column name to check. - * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. + * @param string $strTableName The table name to check. + * @param string $strColName The column name to check. + * @param bool $blnAllowSystemCol If this is set to true, no system column name checking will be applied. * * @return void * - * @throws InvalidTableNameException If an invalid table name has been passed. - * @throws TableDoesNotExistException If the table does not exist. - * @throws InvalidColumnNameException If an invalid column name has been passed. - * @throws ColumnExistsException If the column does exist. + * @throws InvalidTableNameException If an invalid table name has been passed. + * @throws TableDoesNotExistException If the table does not exist. + * @throws InvalidColumnNameException If an invalid column name has been passed. + * @throws ColumnExistsException If the column does exist. * * @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag */ - public function checkColumnDoesNotExist($strTableName, $strColName, $blnAllowSystemCol = false) + public function checkColumnDoesNotExist( + string $strTableName, + string $strColName, + bool $blnAllowSystemCol = false + ): void { $this->checkTableExists($strTableName); $this->checkColumnName($strColName, $blnAllowSystemCol); @@ -460,20 +470,24 @@ public function checkColumnDoesNotExist($strTableName, $strColName, $blnAllowSys * * Throws Exception if the table does not exist, the column name is invalid or the column already exists. * - * @param string $strTableName The name of the table to add the column to. - * - * @param string $strColumnName The name of the new column. - * - * @param string $strType The SQL type notation of the new column. - * - * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. + * @param string $strTableName The name of the table to add the column to. + * @param string $strColumnName The name of the new column. + * @param string $strType The SQL type notation of the new column. + * @param bool $blnAllowSystemCol If this is set to true, no system column name checking will be applied. * * @return void + * + * @throws Exception If query error. */ - public function createColumn($strTableName, $strColumnName, $strType, $blnAllowSystemCol = false) + public function createColumn( + string $strTableName, + string $strColumnName, + string $strType, + bool $blnAllowSystemCol = false + ): void { $this->checkColumnDoesNotExist($strTableName, $strColumnName, $blnAllowSystemCol); - $this->connection->query( + $this->connection->executeQuery( sprintf( self::STATEMENT_CREATE_COLUMN, $strTableName, @@ -488,30 +502,29 @@ public function createColumn($strTableName, $strColumnName, $strType, $blnAllowS * * Throws Exception if the table does not exist, the column name is invalid or the column already exists. * - * @param string $strTableName The name of the table the column is in. - * - * @param string $strColumnName The current name of the column to be renamed. - * - * @param string $strNewColumnName The new name for the column. - * - * @param string $strNewType The new SQL type notation of the column. - * - * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. + * @param string $strTableName The name of the table the column is in. + * @param string $strColumnName The current name of the column to be renamed. + * @param string $strNewColumnName The new name for the column. + * @param string $strNewType The new SQL type notation of the column. + * @param bool $blnAllowSystemCol If this is set to true, no system column name checking will be applied. * * @return void + * + * @throws Exception */ public function renameColumn( - $strTableName, - $strColumnName, - $strNewColumnName, - $strNewType, - $blnAllowSystemCol = false - ) { + string $strTableName, + string $strColumnName, + string $strNewColumnName, + string $strNewType, + bool $blnAllowSystemCol = false + ): void + { if ($strColumnName != $strNewColumnName) { $this->checkColumnExists($strTableName, $strColumnName, $blnAllowSystemCol); $this->checkColumnDoesNotExist($strTableName, $strNewColumnName, $blnAllowSystemCol); } - $this->connection->query( + $this->connection->executeQuery( sprintf( self::STATEMENT_RENAME_COLUMN, $strTableName, @@ -527,18 +540,18 @@ public function renameColumn( * * Throws Exception if the table does not exist, the column name is invalid or the column does not exist. * - * @param string $strTableName The name of the table the column is in. - * - * @param string $strColumnName The name of the column to drop. - * - * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. + * @param string $strTableName The name of the table the column is in. + * @param string $strColumnName The name of the column to drop. + * @param bool $blnAllowSystemCol If this is set to true, no system column name checking will be applied. * * @return void + * + * @throws Exception */ - public function dropColumn($strTableName, $strColumnName, $blnAllowSystemCol = false) + public function dropColumn(string $strTableName, string $strColumnName, bool $blnAllowSystemCol = false): void { $this->checkColumnExists($strTableName, $strColumnName, $blnAllowSystemCol); - $this->connection->query( + $this->connection->executeQuery( sprintf( self::STATEMENT_DROP_COLUMN, $strTableName, @@ -551,15 +564,16 @@ public function dropColumn($strTableName, $strColumnName, $blnAllowSystemCol = f * Enables or disables Variant support on a certain MetaModel table. * * @param string $strTableName The table name of the MetaModel. - * * @param bool $blnVariantSupport Flag if the support shall be turned on or off. * * @return void + * + * @throws Exception */ - public function setVariantSupport($strTableName, $blnVariantSupport) + public function setVariantSupport(string $strTableName, bool $blnVariantSupport): void { if ($blnVariantSupport) { - if ($this->connection->getSchemaManager()->tablesExist([$strTableName]) + if ($this->connection->createSchemaManager()->tablesExist([$strTableName]) && (!$this->fieldExists($strTableName, 'varbase'))) { $this->createColumn($strTableName, 'varbase', 'char(1) NOT NULL default \'\'', true); $this->createColumn($strTableName, 'vargroup', 'int(11) NOT NULL default 0', true); @@ -570,13 +584,11 @@ public function setVariantSupport($strTableName, $blnVariantSupport) sprintf('UPDATE `%1$s` SET %1$s.vargroup=id, %1$s.varbase=1', $strTableName) ); } - } else { - if ($this->connection->getSchemaManager()->tablesExist([$strTableName]) - && $this->fieldExists($strTableName, 'varbase') - ) { - $this->dropColumn($strTableName, 'varbase', true); - $this->dropColumn($strTableName, 'vargroup', true); - } + } elseif ($this->connection->createSchemaManager()->tablesExist([$strTableName]) + && $this->fieldExists($strTableName, 'varbase') + ) { + $this->dropColumn($strTableName, 'varbase', true); + $this->dropColumn($strTableName, 'vargroup', true); } } @@ -587,10 +599,12 @@ public function setVariantSupport($strTableName, $blnVariantSupport) * @param string $strColumnName Column name. * * @return bool + * + * @throws Exception */ - private function fieldExists($strTableName, $strColumnName) + private function fieldExists(string $strTableName, string $strColumnName): bool { - $columns = $this->connection->getSchemaManager()->listTableColumns($strTableName); + $columns = $this->connection->createSchemaManager()->listTableColumns($strTableName); return isset($columns[$strColumnName]); } From 7a583086a271044fc59c0256fb898dd9df058f3c Mon Sep 17 00:00:00 2001 From: e-spin Date: Sun, 19 Feb 2023 10:59:33 +0100 Subject: [PATCH 162/224] Add LegacyEventDispatcherProxy --- src/ItemList.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ItemList.php b/src/ItemList.php index 0ac10bc8a..680931da1 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -51,6 +51,7 @@ use MetaModels\Render\Template; use RuntimeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; /** * Implementation of a general purpose MetaModel listing. From 07609eb2eda992d4194afd1c0960fc4b5de7716c Mon Sep 17 00:00:00 2001 From: e-spin Date: Sun, 19 Feb 2023 11:05:28 +0100 Subject: [PATCH 163/224] Fix typo --- src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php | 2 +- .../Resources/contao/languages/en/tl_metamodel_attribute.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php index 6d0e29ba4..90d2ceff4 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php @@ -87,5 +87,5 @@ $GLOBALS['TL_LANG']['tl_metamodel']['deleteConfirm'] = 'Do you really want to delete MetaModel ID %s?'; $GLOBALS['TL_LANG']['tl_metamodel']['hint_schema_manager'] = - 'After creating a model, the database must be migrated (console, Contao Manager) -' . + 'After creating an model, the database must be migrated (console, Contao Manager) -' . ' even if the table name is changed. When changing the table name, the user data itself must be transferred.'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php index aa01a4596..88ab281c7 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php @@ -69,5 +69,5 @@ $GLOBALS['TL_LANG']['tl_metamodel_attribute']['deleteConfirm'] = 'Do you really want to delete attribute ID %s?'; $GLOBALS['TL_LANG']['tl_metamodel_attribute']['hint_schema_manager'] = - 'After creating a attribute, the database must be migrated (console, Contao Manager) -' . + 'After creating an attribute, the database must be migrated (console, Contao Manager) -' . ' even if the column name is changed. When changing the column name, the user data itself must be transferred.'; From 2786b6a018d7f2389790e6001fe41b9d7543ee2e Mon Sep 17 00:00:00 2001 From: e-spin Date: Sun, 12 Feb 2023 19:58:18 +0100 Subject: [PATCH 164/224] Add sorting links --- .../Controller/ListControllerTrait.php | 52 +++-- .../Resources/contao/dca/tl_content.php | 16 +- .../Resources/contao/dca/tl_module.php | 80 ++++--- .../Resources/contao/languages/en/default.php | 8 +- .../contao/languages/en/tl_content.php | 7 +- .../contao/languages/en/tl_module.php | 7 +- src/Helper/SortingLinkGenerator.php | 210 ++++++++++++++++++ src/ItemList.php | 72 ++++-- src/Render/Template.php | 4 + 9 files changed, 381 insertions(+), 75 deletions(-) create mode 100644 src/Helper/SortingLinkGenerator.php diff --git a/src/CoreBundle/Controller/ListControllerTrait.php b/src/CoreBundle/Controller/ListControllerTrait.php index 247a5cf80..36bbffbfe 100644 --- a/src/CoreBundle/Controller/ListControllerTrait.php +++ b/src/CoreBundle/Controller/ListControllerTrait.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,6 +32,7 @@ use MetaModels\Filter\FilterUrl; use MetaModels\Filter\FilterUrlBuilder; use MetaModels\Filter\Setting\IFilterSettingFactory; +use MetaModels\Helper\SortingLinkGenerator; use MetaModels\IFactory; use MetaModels\IItem; use MetaModels\ItemList; @@ -211,27 +212,34 @@ private function getResponseInternal(Template $template, Model $model, Request $ $template->searchable = !$model->metamodel_donotindex; - $sorting = $model->metamodel_sortby; - $direction = $model->metamodel_sortby_direction; + $sorting = $model->metamodel_sortby; + $direction = $model->metamodel_sortby_direction; + $sortParamType = $model->metamodel_sort_param_type; + $sortOrderByParam = 'orderBy'; + $sortOrderDirParam = 'orderDir'; + $sortOverride = $model->metamodel_sort_override; + $sortFragment = $model->metamodel_sort_urlfragment; // @codingStandardsIgnoreStart // FIXME: filter URL should be created from local request and not from master request. // @codingStandardsIgnoreEnd $filterUrl = $this->filterUrlBuilder->getCurrentFilterUrl(); - if ($model->metamodel_sort_override) { + if ($sortOverride) { + $sortOrderByParam = $model->metamodel_order_by_param ?: $sortOrderByParam; + $sortOrderDirParam = $model->metamodel_order_dir_param ?: $sortOrderDirParam; if (null !== $value = $this->tryReadFromSlugOrGet( $filterUrl, - ($model->metamodel_order_by_param ?: 'orderBy'), - $model->metamodel_sort_param_type + $sortOrderByParam, + $sortParamType )) { $sorting = $value; } if (null !== $value = $this->tryReadFromSlugOrGet( $filterUrl, - ($model->metamodel_order_dir_param ?: 'orderDir'), - $model->metamodel_sort_param_type + $sortOrderDirParam, + $sortParamType )) { $direction = $value; } @@ -244,6 +252,18 @@ private function getResponseInternal(Template $template, Model $model, Request $ ->setLimit($model->metamodel_use_limit, $model->metamodel_offset, $model->metamodel_limit) ->setPageBreak($model->perPage) ->setSorting($sorting, $direction) + ->setSortingLinkGenerator( + new SortingLinkGenerator( + $this->filterUrlBuilder, + $this->translator, + $sortParamType, + $sortOrderByParam, + $sortOrderDirParam, + $sortFragment, + $model->metamodel_sortby, + $model->metamodel_sortby_direction + ) + ) ->setFilterSettings($model->metamodel_filtering) ->setFilterParameters($filterParams, $this->getFilterParameters($filterUrl, $itemRenderer)) ->setMetaTags($model->metamodel_meta_title, $model->metamodel_meta_description); @@ -256,11 +276,11 @@ private function getResponseInternal(Template $template, Model $model, Request $ $template->numberOfItems = $itemRenderer->getItems()->getCount(); $template->pagination = $itemRenderer->getPagination(); - $responseTags = array_map( + $responseTags = \array_map( static function (IItem $item) { return sprintf('contao.db.%s.%d', $item->getMetaModel()->getTableName(), $item->get('id')); }, - iterator_to_array($itemRenderer->getItems(), false) + \iterator_to_array($itemRenderer->getItems(), false) ); $response = $template->getResponse(); @@ -377,14 +397,14 @@ private function getWildcardInfoText(Model $model, string $href, string $name): $metaModel = $this->factory->getMetaModel($metaModelName); $header = $name . ': ' . $metaModel->getName(); if ($href) { - $header .= sprintf( + $header .= \sprintf( ' (ID: %3$s)', $href, REQUEST_TOKEN, $model->id ); } - $infoText = sprintf( + $infoText = \sprintf( $infoTemplate, $this->translator->trans('MSC.mm_be_info_name.1', [], 'contao_default'), $this->translator->trans('MSC.mm_be_info_name.0', [], 'contao_default'), @@ -399,10 +419,10 @@ private function getWildcardInfoText(Model $model, string $href, string $name): $filterparams[] = $filterparam['value']; } } - $infoFiPa = count($filterparams) ? ': ' . implode(', ', $filterparams) : ''; + $infoFiPa = \count($filterparams) ? ': ' . \implode(', ', $filterparams) : ''; $infoFi = $this->filterFactory->createCollection($model->metamodel_filtering)->get('name'); if ($infoFi) { - $infoText .= sprintf( + $infoText .= \sprintf( $infoTemplate, $this->translator->trans('MSC.mm_be_info_filter.1', [], 'contao_default'), $this->translator->trans('MSC.mm_be_info_filter.0', [], 'contao_default'), @@ -417,7 +437,7 @@ private function getWildcardInfoText(Model $model, string $href, string $name): ->createCollection($metaModel, $model->metamodel_rendersettings) ->get('name'); if ($infoRs) { - $infoText .= sprintf( + $infoText .= \sprintf( $infoTemplate, $this->translator->trans('MSC.mm_be_info_render_setting.1', [], 'contao_default'), $this->translator->trans('MSC.mm_be_info_render_setting.0', [], 'contao_default'), diff --git a/src/CoreBundle/Resources/contao/dca/tl_content.php b/src/CoreBundle/Resources/contao/dca/tl_content.php index d452d8a3b..e99aa85bb 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_content.php +++ b/src/CoreBundle/Resources/contao/dca/tl_content.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Ingolf Steinhardt * @author Richard Henkenjohann * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -69,7 +69,7 @@ 1, [ 'metamodel_use_limit' => 'metamodel_offset,metamodel_limit', - 'metamodel_sort_override' => 'metamodel_sort_param_type,metamodel_order_by_param,metamodel_order_dir_param', + 'metamodel_sort_override' => 'metamodel_sort_param_type,metamodel_order_by_param,metamodel_order_dir_param,metamodel_sort_urlfragment', 'metamodel_use_parameters' => 'metamodel_parameters' ] ); @@ -266,6 +266,16 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], + 'metamodel_sort_urlfragment' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_content']['metamodel_sort_urlfragment'], + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ + 'tl_class' => 'clr w50', + 'rgxp' => 'alias' + ], + 'sql' => "char(255) NOT NULL default ''" + ], 'metamodel_filtering' => [ 'label' => &$GLOBALS['TL_LANG']['tl_content']['metamodel_filtering'], diff --git a/src/CoreBundle/Resources/contao/dca/tl_module.php b/src/CoreBundle/Resources/contao/dca/tl_module.php index 53476fecf..405fd55ed 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_module.php +++ b/src/CoreBundle/Resources/contao/dca/tl_module.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -65,7 +65,7 @@ 1, [ 'metamodel_use_limit' => 'metamodel_offset,metamodel_limit', - 'metamodel_sort_override' => 'metamodel_sort_param_type,metamodel_order_by_param,metamodel_order_dir_param', + 'metamodel_sort_override' => 'metamodel_sort_param_type,metamodel_order_by_param,metamodel_order_dir_param,metamodel_sort_urlfragment', 'metamodel_use_parameters' => 'metamodel_parameters' ] ); @@ -75,7 +75,7 @@ $GLOBALS['TL_DCA']['tl_module']['fields'], 1, [ - 'metamodel' => [ + 'metamodel' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel'], 'exclude' => true, 'inputType' => 'select', @@ -92,7 +92,7 @@ ], 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'metamodel_layout' => [ + 'metamodel_layout' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_layout'], 'exclude' => true, 'inputType' => 'select', @@ -103,7 +103,7 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'metamodel_use_limit' => [ + 'metamodel_use_limit' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_use_limit'], 'exclude' => true, 'inputType' => 'checkbox', @@ -113,7 +113,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'metamodel_limit' => [ + 'metamodel_limit' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_limit'], 'exclude' => true, 'inputType' => 'text', @@ -123,7 +123,7 @@ ], 'sql' => "smallint(5) NOT NULL default '0'" ], - 'metamodel_offset' => [ + 'metamodel_offset' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_offset'], 'exclude' => true, 'inputType' => 'text', @@ -133,7 +133,7 @@ ], 'sql' => "smallint(5) NOT NULL default '0'" ], - 'metamodel_sortby' => [ + 'metamodel_sortby' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_sortby'], 'exclude' => true, 'inputType' => 'select', @@ -145,7 +145,7 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'metamodel_sortby_direction' => [ + 'metamodel_sortby_direction' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_sortby_direction'], 'exclude' => true, 'inputType' => 'select', @@ -158,7 +158,7 @@ ], 'sql' => "varchar(4) NOT NULL default ''" ], - 'metamodel_sort_override' => [ + 'metamodel_sort_override' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_sort_override'], 'exclude' => true, 'inputType' => 'checkbox', @@ -168,7 +168,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'metamodel_sort_param_type' => [ + 'metamodel_sort_param_type' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_sort_param_type'], 'exclude' => true, 'inputType' => 'select', @@ -180,7 +180,7 @@ ], 'sql' => "varchar(64) NOT NULL default 'slug'" ], - 'metamodel_order_by_param' => [ + 'metamodel_order_by_param' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_order_by_param'], 'exclude' => true, 'inputType' => 'text', @@ -190,7 +190,7 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'metamodel_order_dir_param' => [ + 'metamodel_order_dir_param' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_order_dir_param'], 'exclude' => true, 'inputType' => 'text', @@ -200,7 +200,17 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'metamodel_filtering' => [ + 'metamodel_sort_urlfragment' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_sort_urlfragment'], + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ + 'tl_class' => 'clr w50', + 'rgxp' => 'alias' + ], + 'sql' => "char(255) NOT NULL default ''" + ], + 'metamodel_filtering' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_filtering'], 'exclude' => true, 'inputType' => 'select', @@ -217,7 +227,7 @@ ], 'sql' => "int(10) NOT NULL default '0'" ], - 'metamodel_rendersettings' => [ + 'metamodel_rendersettings' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_rendersettings'], 'exclude' => true, 'inputType' => 'select', @@ -234,7 +244,7 @@ ], 'sql' => "int(10) NOT NULL default '0'" ], - 'metamodel_noparsing' => [ + 'metamodel_noparsing' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_noparsing'], 'exclude' => true, 'inputType' => 'checkbox', @@ -244,7 +254,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'metamodel_page_param_type' => [ + 'metamodel_page_param_type' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_page_param_type'], 'exclude' => true, 'inputType' => 'select', @@ -256,7 +266,7 @@ ], 'sql' => "varchar(64) NOT NULL default 'slugNget'" ], - 'metamodel_page_param' => [ + 'metamodel_page_param' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_page_param'], 'exclude' => true, 'inputType' => 'text', @@ -266,7 +276,7 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'metamodel_maxpaginationlinks' => [ + 'metamodel_maxpaginationlinks' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_maxpaginationlinks'], 'exclude' => true, 'inputType' => 'text', @@ -276,7 +286,7 @@ ], 'sql' => "smallint(5) NOT NULL default '0'" ], - 'metamodel_pagination' => [ + 'metamodel_pagination' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_pagination'], 'exclude' => true, 'inputType' => 'select', @@ -287,7 +297,7 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'metamodel_pagination_urlfragment' => [ + 'metamodel_pagination_urlfragment' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_pagination_urlfragment'], 'exclude' => true, 'inputType' => 'text', @@ -297,7 +307,7 @@ ], 'sql' => "char(255) NOT NULL default ''" ], - 'metamodel_donotindex' => [ + 'metamodel_donotindex' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_donotindex'], 'exclude' => true, 'inputType' => 'checkbox', @@ -307,7 +317,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'metamodel_available_values' => [ + 'metamodel_available_values' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_available_values'], 'exclude' => true, 'inputType' => 'checkbox', @@ -316,7 +326,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'metamodel_filterparams' => [ + 'metamodel_filterparams' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_filterparams'], 'exclude' => true, 'inputType' => 'mm_subdca', @@ -332,7 +342,7 @@ ], 'sql' => 'longblob NULL' ], - 'metamodel_jumpTo' => [ + 'metamodel_jumpTo' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_jumpTo'], 'exclude' => true, 'inputType' => 'pageTree', @@ -342,7 +352,7 @@ ], 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'metamodel_fef_urlfragment' => [ + 'metamodel_fef_urlfragment' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_fef_urlfragment'], 'exclude' => true, 'inputType' => 'text', @@ -352,7 +362,7 @@ ], 'sql' => "char(255) NOT NULL default ''" ], - 'metamodel_fef_params' => [ + 'metamodel_fef_params' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_fef_params'], 'exclude' => true, 'inputType' => 'checkboxWizard', @@ -363,7 +373,7 @@ ], 'sql' => 'blob NULL' ], - 'metamodel_fef_autosubmit' => [ + 'metamodel_fef_autosubmit' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_fef_autosubmit'], 'exclude' => true, 'default' => '1', @@ -373,7 +383,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'metamodel_fef_hideclearfilter' => [ + 'metamodel_fef_hideclearfilter' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_fef_hideclearfilter'], 'exclude' => true, 'inputType' => 'checkbox', @@ -382,7 +392,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'metamodel_fef_template' => [ + 'metamodel_fef_template' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_fef_template'], 'exclude' => true, 'inputType' => 'select', @@ -393,7 +403,7 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'metamodel_meta_title' => [ + 'metamodel_meta_title' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_meta_title'], 'exclude' => true, 'inputType' => 'select', @@ -405,7 +415,7 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'metamodel_meta_description' => [ + 'metamodel_meta_description' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_meta_description'], 'exclude' => true, 'inputType' => 'select', @@ -417,7 +427,7 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'metamodel_use_parameters' => [ + 'metamodel_use_parameters' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_use_parameters'], 'exclude' => true, 'inputType' => 'checkbox', @@ -427,7 +437,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'metamodel_parameters' => [ + 'metamodel_parameters' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_parameters'], 'exclude' => true, 'inputType' => 'multiColumnWizard', diff --git a/src/CoreBundle/Resources/contao/languages/en/default.php b/src/CoreBundle/Resources/contao/languages/en/default.php index b327c357a..b9c29d47b 100644 --- a/src/CoreBundle/Resources/contao/languages/en/default.php +++ b/src/CoreBundle/Resources/contao/languages/en/default.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Ingolf Steinhardt * @author David Molineus * @author Sven Baumann - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -125,6 +125,10 @@ ' (No matching combinations found.)'; $GLOBALS['TL_LANG']['MSC']['metamodel_filtersettings_parameter']['simplelookup'][0] = 'Filter value for attribute "%s"'; $GLOBALS['TL_LANG']['MSC']['metamodel_filtersettings_parameter']['simplelookup'][1] = ''; +$GLOBALS['TL_LANG']['MSC']['orderMetaModelListByAscending'] = + 'Sort by %s in ascending order'; +$GLOBALS['TL_LANG']['MSC']['orderMetaModelListByDescending'] = + 'Sort by %s in descending order'; $GLOBALS['TL_LANG']['MSC']['metamodels_support']['main_headline'] = 'We are calling for your help!'; $GLOBALS['TL_LANG']['MSC']['metamodels_support']['purpose'] = 'Purpose'; $GLOBALS['TL_LANG']['MSC']['metamodels_support']['other_donations'] = diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_content.php b/src/CoreBundle/Resources/contao/languages/en/tl_content.php index e697426a1..ba76a4941 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_content.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_content.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -64,6 +64,9 @@ $GLOBALS['TL_LANG']['tl_content']['metamodel_order_dir_param'][0] = 'Override key for order direction'; $GLOBALS['TL_LANG']['tl_content']['metamodel_order_dir_param'][1] = 'You can override the default key \'orderDir\'.'; +$GLOBALS['TL_LANG']['tl_content']['metamodel_sort_urlfragment'][0] = 'URL fragment'; +$GLOBALS['TL_LANG']['tl_content']['metamodel_sort_urlfragment'][1] = + 'Add URL fragment to jump to anchor or id.'; $GLOBALS['TL_LANG']['tl_content']['metamodel_filtering'][0] = 'Filter settings to apply'; $GLOBALS['TL_LANG']['tl_content']['metamodel_filtering'][1] = 'Select the filter settings that shall get applied when compiling the list.'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_module.php b/src/CoreBundle/Resources/contao/languages/en/tl_module.php index d956b70d5..4b28ba6c4 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_module.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_module.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -61,6 +61,9 @@ $GLOBALS['TL_LANG']['tl_module']['metamodel_order_dir_param'][0] = 'Override key for order direction'; $GLOBALS['TL_LANG']['tl_module']['metamodel_order_dir_param'][1] = 'You can override the default key \'orderDir\'.'; +$GLOBALS['TL_LANG']['tl_module']['metamodel_sort_urlfragment'][0] = 'URL fragment'; +$GLOBALS['TL_LANG']['tl_module']['metamodel_sort_urlfragment'][1] = + 'Add URL fragment to jump to anchor or id.'; $GLOBALS['TL_LANG']['tl_module']['metamodel_filtering'][0] = 'Filter settings to apply'; $GLOBALS['TL_LANG']['tl_module']['metamodel_filtering'][1] = 'Select the filter settings that shall get applied when compiling the list.'; diff --git a/src/Helper/SortingLinkGenerator.php b/src/Helper/SortingLinkGenerator.php new file mode 100644 index 000000000..075670618 --- /dev/null +++ b/src/Helper/SortingLinkGenerator.php @@ -0,0 +1,210 @@ + + * @copyright 2012-2023 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\Helper; + +use Contao\Input; +use MetaModels\Attribute\IAttribute; +use MetaModels\Filter\FilterUrl; +use MetaModels\Filter\FilterUrlBuilder; +use RuntimeException; +use Symfony\Contracts\Translation\TranslatorInterface; + +use function strtolower; + +/** + * Provide methods to generate sorting links. + */ +class SortingLinkGenerator +{ + /** + * The filter url builder. + * + * @var FilterUrlBuilder + */ + private FilterUrlBuilder $urlBuilder; + + /** + * The translator interface. + * + * @var TranslatorInterface + */ + private TranslatorInterface $translator; + + /** + * The sorting type parameter. + * + * @var string + */ + private string $sortParamType; + + /** + * The sorting by parameter. + * + * @var string + */ + private string $sortOrderByParam; + + /** + * The sorting direction type. + * + * @var string + */ + private string $sortOrderDirParam; + + /** + * The URL fragment. + * + * @var string + */ + private string $sortFragment; + + /** + * The default sorting. + * + * @var string + */ + private string $defaultSorting; + + /** + * The default direction. + * + * @var string + */ + private string $defaultDirection; + + /** + * Create a new instance. + * + * @param FilterUrlBuilder $urlBuilder The filter url builder. + * @param TranslatorInterface $translator The translator. + * @param string $sortParamType The pagination parameter url type (slug, get or slugNget). + * @param string $sortOrderByParam The sorting by parameter name. + * @param string $sortOrderDirParam The sorting direction parameter name. + * @param string $sortFragment The URL fragment. + * @param string $defaultSorting The default sorting parameter name. + * @param string $defaultDirection The default sorting direction parameter name. + */ + public function __construct( + FilterUrlBuilder $urlBuilder, + TranslatorInterface $translator, + string $sortParamType, + string $sortOrderByParam, + string $sortOrderDirParam, + string $sortFragment, + string $defaultSorting, + string $defaultDirection, + ) { + $this->urlBuilder = $urlBuilder; + $this->translator = $translator; + $this->sortParamType = $sortParamType; + $this->sortOrderByParam = $sortOrderByParam; + $this->sortOrderDirParam = $sortOrderDirParam; + $this->sortFragment = $sortFragment; + $this->defaultSorting = $defaultSorting; + $this->defaultDirection = \strtolower($defaultDirection); + } + + public function generateSortingLink(IAttribute $attribute, string $type): array + { + $pageFilterUrl = $this->urlBuilder->getCurrentFilterUrl(); + $sortBy = $this->tryReadFromSlugOrGet($pageFilterUrl, $this->sortOrderByParam, $this->sortParamType) + ?: $this->defaultSorting; + $sortDirection = $this->tryReadFromSlugOrGet($pageFilterUrl, $this->sortOrderDirParam, $this->sortParamType) + ?: $this->defaultDirection; + $attributeName = $attribute->getColName(); + $active = $sortBy === $attributeName; + + switch ($type) { + case 'toggle': + // In case of toggle, we override the type with the desired direction. + $type = 'asc'; + if ($active) { + $type = \strtolower($sortDirection) === 'desc' ? 'asc' : 'desc'; + } + // NO break here! + case 'asc': + case 'desc': + $dir = $type; + break; + default: + throw new RuntimeException('Unknown link type: ' . $type); + } + + if ($attributeName === $this->defaultSorting && $dir === $this->defaultDirection) { + $attributeName = ''; + } + + if ('get' === $this->sortParamType) { + $pageFilterUrl->setGet($this->sortOrderByParam, $attributeName); + $pageFilterUrl->setGet($this->sortOrderDirParam, $attributeName ? $dir : ''); + } else { + // Use slug or slugNget. + $pageFilterUrl->setSlug($this->sortOrderByParam, $attributeName); + $pageFilterUrl->setSlug($this->sortOrderDirParam, $attributeName ? $dir : ''); + } + + return [ + 'attribute' => $attribute, + 'name' => $attribute->getName(), + 'href' => $this->urlBuilder->generate($pageFilterUrl) . + ($this->sortFragment ? '#' . $this->sortFragment : ''), + 'direction' => $dir, + 'active' => (bool) $active, + 'class' => 'sort' . ($active ? ' active' : '') . ' ' . $dir, + 'label' => $this->translator->trans( + 'MSC.orderMetaModelListBy' . ($dir === 'asc' ? 'Ascending' : 'Descending'), + [0 => $attribute->getName()], + 'contao_default' + ), + ]; + } + + /** + * Get parameter from get or slug. + * + * @param FilterUrl $filterUrl The filter URL to obtain parameters from. + * @param string $sortParam The sort parameter name to obtain. + * @param string $sortType The sort URL type. + * + * @return string|null + */ + private function tryReadFromSlugOrGet(FilterUrl $filterUrl, string $sortParam, string $sortType): ?string + { + $result = null; + + switch ($sortType) { + case 'get': + $result = $filterUrl->getGet($sortParam); + break; + case 'slug': + $result = $filterUrl->getSlug($sortParam); + break; + case 'slugNget': + $result = ($filterUrl->getGet($sortParam) ?? $filterUrl->getSlug($sortParam)); + break; + default: + } + + // Mark the parameter as used (otherwise, a 404 is thrown) + Input::get($sortParam); + + return $result; + } +} diff --git a/src/ItemList.php b/src/ItemList.php index 0ac10bc8a..84fadc30e 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -46,6 +46,7 @@ use MetaModels\Filter\Setting\IFilterSettingFactory; use MetaModels\Helper\LocaleUtil; use MetaModels\Helper\PaginationLimitCalculator; +use MetaModels\Helper\SortingLinkGenerator; use MetaModels\Render\Setting\ICollection as IRenderSettingCollection; use MetaModels\Render\Setting\IRenderSettingFactory; use MetaModels\Render\Template; @@ -172,6 +173,13 @@ class ItemList */ private ?string $language = null; + /** + * The sorting link generator. + * + * @var SortingLinkGenerator|null + */ + private ?SortingLinkGenerator $sortingLinkGenerator = null; + /** * Create a new instance. * @@ -226,7 +234,7 @@ public function __construct( * * @deprecated Use constructor injection instead. */ - public function setFilterFactory(IFilterSettingFactory $filterFactory) + public function setFilterFactory(IFilterSettingFactory $filterFactory): self { // @codingStandardsIgnoreStart @trigger_error( @@ -411,9 +419,7 @@ public function getServiceContainer(): ?IMetaModelsServiceContainer * Set the limit. * * @param bool $isLimit If true, use limit, if false no limit is applied. - * * @param int $offset Like in SQL, first element to be returned (0 based). - * * @param int $limit Like in SQL, amount of elements to retrieve. * * @return ItemList @@ -447,7 +453,6 @@ public function setPageBreak(int $limit): self * Set sorting to an attribute or system column optionally in the given direction. * * @param string $sortBy The name of the attribute or system column to be used for sorting. - * * @param string $sortDirection The direction, either ASC or DESC (optional). * * @return ItemList @@ -483,7 +488,6 @@ public function overrideOutputFormat(string $outputFormat = null): self * Set MetaModel and render settings. * * @param int $intMetaModel The MetaModel to use. - * * @param int $intView The render settings to use (if 0, the default will be used). * * @return ItemList @@ -657,7 +661,6 @@ public function setFilterSettings(int $intFilter): self * Set parameters. * * @param string[][] $presets The parameter preset values to use. - * * @param string[] $values The dynamic parameter values that may be used. * * @return ItemList @@ -693,7 +696,7 @@ public function setFilterParameters(array $presets, array $values): self continue; } - // Not a preset or allowed to overriding? - use value. + // Not a preset or allowed to override? - use value. if ((!array_key_exists($filterParameterKey, $presets)) || $presets[$filterParameterKey]['use_get']) { $processed[$filterParameterKey] = $values[$filterParameterKey]; } @@ -756,7 +759,7 @@ public function setListTemplate(ContaoTemplate $template): self * * @return void */ - public function setTemplateParameter(string $name, $value): void + public function setTemplateParameter(string $name, mixed $value): void { $this->templateParameter[$name] = $value; } @@ -881,8 +884,7 @@ public function prepare(): self // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. $this->language = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'] ?? 'en'); } - $previousLanguage = - $this->objMetaModel->selectLanguage($this->language); + $previousLanguage = $this->objMetaModel->selectLanguage($this->language); } $this->objItems = $this->objMetaModel->findByFilter( @@ -938,6 +940,7 @@ public function getObjItems(): IItems E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + return $this->getItems(); } @@ -1094,11 +1097,26 @@ private function setTitleAndDescription(): void } } + + /** + * Setter for SortingLinkGenerator. + * + * @param SortingLinkGenerator $generator The link generator. + * + * @return $this + */ + public function setSortingLinkGenerator(SortingLinkGenerator $generator): self + { + $this->sortingLinkGenerator = $generator; + + return $this; + } + /** * Render the list view. * * @param bool $isNoNativeParsing Flag determining if the parsing shall be done internal or if the template - * will handle the parsing on it's own. + * will handle the parsing on its own. * @param object|null $caller The object calling us, might be a Module or ContentElement or anything * else. * @@ -1130,10 +1148,34 @@ public function render(bool $isNoNativeParsing, object $caller = null): string $this->setTitleAndDescription(); - $this->objTemplate->caller = $caller; - $this->objTemplate->items = $this->objItems; - $this->objTemplate->filterParams = $this->arrParam; - $this->objTemplate->parameter = $this->templateParameter; + $generateSortingLink = function (string $attributeName, string $type): array { + if (null === $this->sortingLinkGenerator) { + return []; + } + + $attribute = $this->objMetaModel->getAttribute($attributeName); + + if (null === $attribute) { + throw new \RuntimeException('Attribute not found: ' . $attributeName); + } + + return $this->sortingLinkGenerator->generateSortingLink($attribute, $type); + }; + + $renderSortingLink = function (string $attributeName, string $type) use ($generateSortingLink): string { + $sortingLink = $generateSortingLink($attributeName, $type); + + return <<{$sortingLink['label']} + EOF; + }; + + $this->objTemplate->generateSortingLink = $generateSortingLink; + $this->objTemplate->renderSortingLink = $renderSortingLink; + $this->objTemplate->caller = $caller; + $this->objTemplate->items = $this->objItems; + $this->objTemplate->filterParams = $this->arrParam; + $this->objTemplate->parameter = $this->templateParameter; return $this->objTemplate->parse($outputFormat); } diff --git a/src/Render/Template.php b/src/Render/Template.php index bed56313f..95e1adf67 100644 --- a/src/Render/Template.php +++ b/src/Render/Template.php @@ -127,6 +127,10 @@ class Template */ public function __call($strMethod, $arrArgs) { + if (isset($this->$strMethod) && is_callable($this->$strMethod)) { + return call_user_func_array($this->$strMethod, $arrArgs); + } + return call_user_func_array(array(ContaoController::getInstance(), $strMethod), $arrArgs); } From 87c380997947cf1529d2eb88fc99c7f5feb66403 Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 20 Feb 2023 15:32:03 +0100 Subject: [PATCH 165/224] Fix code --- .../MetaModel/TableNamePrefixingListener.php | 79 +++++++++++++------ .../config/dc-general/table/tl_metamodel.yml | 1 + .../Resources/contao/languages/en/default.php | 7 +- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php index 9857221d6..0edebbbdb 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,10 +23,13 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\EncodePropertyValueFromWidgetEvent; +use ContaoCommunityAlliance\Translator\TranslatorInterface; +use MetaModels\Exceptions\Database\InvalidTableNameException; use MetaModels\Helper\TableManipulator; +use MetaModels\IFactory; /** - * This prefixes all tables with "mm_". + * This prefixes all tables with "mm_" and check if exists. */ class TableNamePrefixingListener extends AbstractAbstainingListener { @@ -34,18 +38,30 @@ class TableNamePrefixingListener extends AbstractAbstainingListener * * @var TableManipulator */ - private $tableManipulator; + private TableManipulator $tableManipulator; + + /** + * The MetaModel factory. + * + * @var IFactory + */ + private IFactory $factory; /** * Create a new instance. * * @param RequestScopeDeterminator $scopeDeterminator The scope determinator. * @param TableManipulator $tableManipulator The table manipulator. + * @param IFactory $factory The MetaModel factory. */ - public function __construct(RequestScopeDeterminator $scopeDeterminator, TableManipulator $tableManipulator) - { + public function __construct( + RequestScopeDeterminator $scopeDeterminator, + TableManipulator $tableManipulator, + IFactory $factory + ) { parent::__construct($scopeDeterminator); $this->tableManipulator = $tableManipulator; + $this->factory = $factory; } /** @@ -60,42 +76,53 @@ public function __construct(RequestScopeDeterminator $scopeDeterminator, TableMa * * @throws \RuntimeException On invalid table names. */ - public function handle(EncodePropertyValueFromWidgetEvent $event) + public function handle(EncodePropertyValueFromWidgetEvent $event): void { if (!$this->wantToHandle($event) || ($event->getProperty() !== 'tableName')) { return; } - // See #49. - $tableName = strtolower($event->getValue()); + // See #49 (We can no longer find the correct issue number... :(). + $tableName = \strtolower($event->getValue()); - if (!strlen($tableName)) { + if ('' === $tableName) { throw new \RuntimeException('Table name not given'); } // Force mm_ prefix. - if (substr($tableName, 0, 3) !== 'mm_') { + if (!\str_starts_with($tableName, 'mm_')) { $tableName = 'mm_' . $tableName; } - $dataProvider = $event->getEnvironment()->getDataProvider('tl_metamodel'); - - try { - // New model, ensure the table does not exist. - if (!$event->getModel()->getId()) { - $this->tableManipulator->checkTableDoesNotExist($tableName); - } else { - // Edited model, ensure the value is unique and then that the table does not exist. - $oldVersion = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($event->getModel()->getId())); - - if ($oldVersion->getProperty('tableName') !== $event->getModel()->getProperty('tableName')) { - $this->tableManipulator->checkTableDoesNotExist($tableName); - } + // New model, ensure the table does not exist. + if (!$event->getModel()->getId()) { + $this->checkTableName($tableName, $event->getEnvironment()->getTranslator()); + } else { + $dataProvider = $event->getEnvironment()->getDataProvider('tl_metamodel'); + // Edited model, ensure the value is unique and then that the table does not exist. + $oldVersion = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($event->getModel()->getId())); + if ($oldVersion->getProperty('tableName') !== $event->getModel()->getProperty('tableName')) { + $this->checkTableName($tableName, $event->getEnvironment()->getTranslator()); } - } catch (\Exception $exception) { - throw new \RuntimeException($exception->getMessage(), $exception->getCode(), $exception); } $event->setValue($tableName); } + + private function checkTableName(string $tableName, TranslatorInterface $translator): void + { + try { + $this->tableManipulator->checkTablename($tableName); + } catch (InvalidTableNameException $exception) { + throw new \RuntimeException( + \sprintf($translator->translate('ERR.invalidTableName'), $tableName), + $exception->getCode(), + $exception + ); + } + $model = $this->factory->getMetaModel($tableName); + if (null !== $model) { + throw new \RuntimeException(\sprintf($translator->translate('ERR.tableExists'), $tableName)); + } + } } diff --git a/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml b/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml index 9e7cb23e7..c4ef56b07 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_metamodel.yml @@ -41,6 +41,7 @@ services: arguments: - "@cca.dc-general.scope-matcher" - "@metamodels.table_manipulator" + - "@metamodels.factory" tags: - name: kernel.event_listener event: dc-general.view.contao2backend.encode-property-value-from-widget diff --git a/src/CoreBundle/Resources/contao/languages/en/default.php b/src/CoreBundle/Resources/contao/languages/en/default.php index b327c357a..8d757c801 100644 --- a/src/CoreBundle/Resources/contao/languages/en/default.php +++ b/src/CoreBundle/Resources/contao/languages/en/default.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Ingolf Steinhardt * @author David Molineus * @author Sven Baumann - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -101,9 +101,6 @@ 'Attempt to access the MetaModel "%s" without input screen for current user %s.'; $GLOBALS['TL_LANG']['ERR']['no_view'] = 'Attempt to access the MetaModel "%s" without view for user %s.'; -$GLOBALS['TL_LANG']['ERR']['invalidTableName'] = 'The table name is invalid.'; -$GLOBALS['TL_LANG']['ERR']['upgrade_php_version'] = - 'The version of the PHP interpreter is too low, please upgrade to at least %s (you are currently running %s)'; $GLOBALS['TL_LANG']['ERR']['invalidTableName'] = 'The table name "%s" is invalid.'; $GLOBALS['TL_LANG']['ERR']['invalidColumnName'] = 'The column name "%s" is invalid.'; From 46fbfeb5668a6a2ad05bf437ff15af7237e13e29 Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 6 Feb 2023 20:04:35 +0100 Subject: [PATCH 166/224] Fix disabled legacy routing --- .../MetaModelsCoreExtension.php | 7 ++ src/CoreBundle/Resources/config/services.yml | 3 +- src/Filter/FilterUrlBuilder.php | 108 +++++++++++------- 3 files changed, 75 insertions(+), 43 deletions(-) diff --git a/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php b/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php index 71be7c640..039eec9d5 100644 --- a/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php +++ b/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php @@ -24,12 +24,14 @@ namespace MetaModels\CoreBundle\DependencyInjection; use MetaModels\CoreBundle\Migration\TableCollationMigration; +use MetaModels\Filter\FilterUrlBuilder; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\DependencyInjection\Reference; /** * This is the class that loads and manages the bundle configuration @@ -102,6 +104,11 @@ public function load(array $configs, ContainerBuilder $container) $container->getDefinition(TableCollationMigration::class) ->setArgument('$defaultTableOptions', $this->defaultTableOptions); + + if ($container->getParameter('contao.legacy_routing')) { + $container->getDefinition(FilterUrlBuilder::class) + ->setArgument(0, new Reference('contao.routing.url_generator')); + } } /** diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index 560d51335..b9eae2ef3 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -106,11 +106,12 @@ services: MetaModels\Filter\FilterUrlBuilder: arguments: - - '@contao.routing.url_generator' + - '@contao.routing.page_url_generator' - '@request_stack' - '%contao.prepend_locale%' - '%contao.url_suffix%' - "@=service('contao.framework').getAdapter('Contao\\\\PageModel')" + - '%contao.legacy_routing%' # Please inject the service "MetaModels\Filter\FilterUrlBuilder" directly. metamodels.filter_url: diff --git a/src/Filter/FilterUrlBuilder.php b/src/Filter/FilterUrlBuilder.php index efab1cf70..34aed1ce5 100644 --- a/src/Filter/FilterUrlBuilder.php +++ b/src/Filter/FilterUrlBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Ingolf Steinhardt * @author Stefan Heimes * @author Andreas Fischer - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,11 +25,11 @@ use Contao\Config; use Contao\CoreBundle\Framework\Adapter; -use Contao\CoreBundle\Routing\UrlGenerator; use Contao\PageModel; use Contao\System; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; /** * This class builds filter URLs. @@ -39,59 +39,69 @@ class FilterUrlBuilder /** * The URL generator. * - * @var UrlGenerator + * @var UrlGeneratorInterface */ - private $urlGenerator; + private UrlGeneratorInterface $urlGenerator; /** * The request stack. * * @var RequestStack */ - private $requestStack; + private RequestStack $requestStack; /** * Flag if the locale is prepended. * * @var bool */ - private $isLocalePrepended = true; + private bool $isLocalePrepended = true; /** * The Contao URL suffix. * * @var string */ - private $urlSuffix = '.html'; + private string $urlSuffix = '.html'; /** * The page model adapter. * * @var Adapter|PageModel */ - private $pageModelAdapter; + private Adapter|PageModel $pageModelAdapter; + + /** + * Flag if legacy routing is active. + * + * @var bool + */ + private bool $hasLegacyRouting; /** * Create a new instance. * - * @param UrlGenerator $urlGenerator The Contao URL generator. - * @param RequestStack $requestStack The request stack. - * @param bool $isLocalePrepended Flag if the locale is prepended to the URL. - * @param string $urlSuffix The URL suffix. - * @param Adapter $pageModelAdapter The page model adapter. + * @param UrlGeneratorInterface $urlGenerator The Contao URL generator. + * @param RequestStack $requestStack The request stack. + * @param bool $isLocalePrepended Flag if the locale is prepended to the URL. + * @param string $urlSuffix The URL suffix. + * @param Adapter $pageModelAdapter The page model adapter. + * @param bool $hasLegacyRouting Flag if legacy routing is active. */ public function __construct( - UrlGenerator $urlGenerator, + UrlGeneratorInterface $urlGenerator, RequestStack $requestStack, bool $isLocalePrepended, string $urlSuffix, - Adapter $pageModelAdapter + Adapter $pageModelAdapter, + bool $hasLegacyRouting ) { $this->urlGenerator = $urlGenerator; $this->requestStack = $requestStack; $this->isLocalePrepended = $isLocalePrepended; $this->urlSuffix = $urlSuffix; $this->pageModelAdapter = $pageModelAdapter; + $this->hasLegacyRouting = $hasLegacyRouting; } /** @@ -104,7 +114,7 @@ public function __construct( * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.Superglobals) */ - public function generate(FilterUrl $filterUrl) + public function generate(FilterUrl $filterUrl): string { $jumpTo = $filterUrl->getPage(); @@ -114,31 +124,28 @@ public function generate(FilterUrl $filterUrl) $jumpTo = $filterUrl->getPage(); } - $alias = $jumpTo['alias']; $parameters = $filterUrl->getGetParameters(); - $url = $alias; + $url = ''; if ($filterUrl->hasSlug('auto_item')) { $url .= '/' . $this->encodeForAllowEncodedSlashes($filterUrl->getSlug('auto_item')); } - if (!empty($jumpTo['domain'])) { - $parameters['_domain'] = $jumpTo['domain']; - } - if (!empty($jumpTo['rootUseSSL'])) { - $parameters['_ssl'] = (bool) $jumpTo['rootUseSSL']; + if ($this->hasLegacyRouting) { + if (!empty($jumpTo['domain'])) { + $parameters['_domain'] = $jumpTo['domain']; + } + if (!empty($jumpTo['rootUseSSL'])) { + $parameters['_ssl'] = (bool) $jumpTo['rootUseSSL']; + } } - // Initialize with current language - locale is MANDATORY. - // See https://github.com/contao/contao/pull/4119 - $parameters['_locale'] = $GLOBALS['TL_LANGUAGE']; - if (null !== ($locale = $jumpTo['language'] ?? null)) { $parameters['_locale'] = $locale; } foreach ($filterUrl->getSlugParameters() as $name => $value) { - if (in_array($name, ['auto_item'])) { + if (\in_array($name, ['auto_item'])) { continue; } @@ -149,17 +156,22 @@ public function generate(FilterUrl $filterUrl) '/' . $this->encodeForAllowEncodedSlashes($value); } - return $this->urlGenerator->generate($url, $parameters); + if ($this->hasLegacyRouting) { + return $this->urlGenerator->generate($jumpTo['alias'] . $url, $parameters); + } + + $parameters['parameters'] = $url; + return $this->urlGenerator->generate('tl_page.' . $jumpTo['id'], $parameters); } /** * Generate a filter URL from the current request. * - * @param array $options The options for updating - for details see FilterUrlBuilder::addFromCurrentRequest(). + * @param array|null $options The options for updating - for details see FilterUrlBuilder::addFromCurrentRequest(). * * @return FilterUrl */ - public function getCurrentFilterUrl($options = null): FilterUrl + public function getCurrentFilterUrl(array $options = null): FilterUrl { $this->addFromCurrentRequest($filterUrl = new FilterUrl(), $options); @@ -179,12 +191,12 @@ public function getCurrentFilterUrl($options = null): FilterUrl * bool preserveGet Flag if the GET parameters shall be added to the filter URL. * default: true * - * @param FilterUrl $filterUrl The filter URL to update. - * @param array $options The options for updating. + * @param FilterUrl $filterUrl The filter URL to update. + * @param array|null $options The options for updating. * * @return void */ - public function addFromCurrentRequest(FilterUrl $filterUrl, $options = null): void + public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = null): void { if (null === $options) { $options = [ @@ -194,7 +206,7 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, $options = null): vo ]; } - $request = $this->requestStack->getMasterRequest(); + $request = $this->requestStack->getCurrentRequest(); if (null === $request) { return; } @@ -205,11 +217,23 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, $options = null): vo } } - if (null === $fragments = $this->determineFragments($request)) { - $filterUrl->setPageValue('alias', 'index'); - $this->extractPostData($filterUrl, $options, $request); + if ($this->hasLegacyRouting) { + if (null === $fragments = $this->determineFragments($request)) { + $filterUrl->setPageValue('alias', 'index'); + $this->extractPostData($filterUrl, $options, $request); - return; + return; + } + } else { + if (!\str_starts_with($routeName = $request->attributes->get('_route'), 'tl_page.')) { + throw new \RuntimeException('Unknown route name: ' . $routeName); + } + $filterUrl->setPageValue('id', substr($routeName, 8)); + $requestUri = \rawurldecode(\substr($request->getPathInfo(), 1)); + $fragments = \explode( + '/', + \substr($requestUri, \strlen($request->attributes->get('pageModel')->urlPrefix ?? '') + 1) + ); } // If alias part is empty, this means we have the 'index' page. @@ -218,9 +242,9 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, $options = null): vo } $filterUrl->setPageValue('alias', $fragments[0]); - // Add the fragments to the slug array + // Add the fragments to the slug array. for ($i = 1, $c = \count($fragments); $i < $c; $i += 2) { - // Skip key value pairs if the key is empty (see contao/core/#4702) + // Skip key value pairs if the key is empty (see contao/core/#4702). if ('' === $fragments[$i]) { continue; } From e49a467bc809c8e0e74fcb2f993bde9af475548c Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 20 Feb 2023 17:57:40 +0100 Subject: [PATCH 167/224] Fix sorting --- src/CoreBundle/Controller/ListControllerTrait.php | 12 +++++++----- src/ItemList.php | 4 +++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/CoreBundle/Controller/ListControllerTrait.php b/src/CoreBundle/Controller/ListControllerTrait.php index 36bbffbfe..f3eff1e4c 100644 --- a/src/CoreBundle/Controller/ListControllerTrait.php +++ b/src/CoreBundle/Controller/ListControllerTrait.php @@ -252,7 +252,11 @@ private function getResponseInternal(Template $template, Model $model, Request $ ->setLimit($model->metamodel_use_limit, $model->metamodel_offset, $model->metamodel_limit) ->setPageBreak($model->perPage) ->setSorting($sorting, $direction) - ->setSortingLinkGenerator( + ->setFilterSettings($model->metamodel_filtering) + ->setFilterParameters($filterParams, $this->getFilterParameters($filterUrl, $itemRenderer)) + ->setMetaTags($model->metamodel_meta_title, $model->metamodel_meta_description); + if ($sortOverride) { + $itemRenderer->setSortingLinkGenerator( new SortingLinkGenerator( $this->filterUrlBuilder, $this->translator, @@ -263,10 +267,8 @@ private function getResponseInternal(Template $template, Model $model, Request $ $model->metamodel_sortby, $model->metamodel_sortby_direction ) - ) - ->setFilterSettings($model->metamodel_filtering) - ->setFilterParameters($filterParams, $this->getFilterParameters($filterUrl, $itemRenderer)) - ->setMetaTags($model->metamodel_meta_title, $model->metamodel_meta_description); + ); + } foreach (StringUtil::deserialize(($model->metamodel_parameters ?? null), true) as $key => $value) { $itemRenderer->setTemplateParameter($key, $value); diff --git a/src/ItemList.php b/src/ItemList.php index 277876461..867862ff9 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -1164,7 +1164,9 @@ public function render(bool $isNoNativeParsing, object $caller = null): string }; $renderSortingLink = function (string $attributeName, string $type) use ($generateSortingLink): string { - $sortingLink = $generateSortingLink($attributeName, $type); + if ([] === $sortingLink = $generateSortingLink($attributeName, $type)) { + return ''; + } return <<{$sortingLink['label']} From 0f975d96af961d0706a1ae568f15f5847b0eb001 Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 20 Feb 2023 18:30:42 +0100 Subject: [PATCH 168/224] Delete old symfony event --- src/ItemList.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/ItemList.php b/src/ItemList.php index 867862ff9..6cc657d52 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -52,7 +52,6 @@ use MetaModels\Render\Template; use RuntimeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; /** * Implementation of a general purpose MetaModel listing. @@ -351,7 +350,7 @@ public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): s E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - $this->eventDispatcher = LegacyEventDispatcherProxy::decorate($eventDispatcher); + $this->eventDispatcher = $eventDispatcher; return $this; } @@ -375,9 +374,7 @@ private function getEventDispatcher(): EventDispatcherInterface ); // @codingStandardsIgnoreEnd - return $this->eventDispatcher = LegacyEventDispatcherProxy::decorate( - System::getContainer()->get('event_dispatcher') - ); + return $this->eventDispatcher = System::getContainer()->get('event_dispatcher'); } /** From 90e0af42ae851df4d6cc68b0c5642ac65d8440e6 Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 20 Feb 2023 15:38:10 +0100 Subject: [PATCH 169/224] Set unique --- src/CoreBundle/Resources/contao/dca/tl_metamodel.php | 6 +++--- .../Resources/contao/dca/tl_metamodel_attribute.php | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel.php index 49f8d9df8..62cb7be25 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,7 +21,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Cliff Parnitzky - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -34,7 +34,7 @@ 'sql' => [ 'keys' => [ 'id' => 'primary', - 'tableName' => 'index', + 'tableName' => 'unique', ], ], ], diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php index 4542b7a9b..9297eb29a 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php @@ -31,10 +31,10 @@ 'enableVersioning' => false, 'sql' => [ 'keys' => [ - 'id' => 'primary', - 'pid' => 'index', - 'colname' => 'index' - // TODO: new unique index over pid + colname + 'id' => 'primary', + 'pid' => 'index', + 'colname' => 'index', + 'pid,colname' => 'unique', ], ], ], From fb8d022c581a2808dd147bf4059f06be54d4b902 Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 20 Feb 2023 21:10:24 +0100 Subject: [PATCH 170/224] Fix code in Filterurlbuilder --- src/Filter/FilterUrlBuilder.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Filter/FilterUrlBuilder.php b/src/Filter/FilterUrlBuilder.php index 34aed1ce5..a51cfcf7e 100644 --- a/src/Filter/FilterUrlBuilder.php +++ b/src/Filter/FilterUrlBuilder.php @@ -228,11 +228,14 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = nul if (!\str_starts_with($routeName = $request->attributes->get('_route'), 'tl_page.')) { throw new \RuntimeException('Unknown route name: ' . $routeName); } + $filterUrl->setPageValue('id', substr($routeName, 8)); $requestUri = \rawurldecode(\substr($request->getPathInfo(), 1)); + $pageModel = $request->attributes->get('_route_object')->getPageModel(); + $length = $pageModel->urlSuffix ? -strlen($pageModel->urlSuffix) : null; $fragments = \explode( '/', - \substr($requestUri, \strlen($request->attributes->get('pageModel')->urlPrefix ?? '') + 1) + \substr($requestUri, \strlen($pageModel->urlPrefix ?? '') + 1, $length) ); } From f34af64fd1e690f27f84fc3c99b67445a80491ce Mon Sep 17 00:00:00 2001 From: e-spin Date: Thu, 23 Feb 2023 12:44:11 +0100 Subject: [PATCH 171/224] Fix PHP8 warning --- .../Hooks/AbstractContentElementAndModuleCallback.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php index 46e05c820..75de36946 100644 --- a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php +++ b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author Marc Reimann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -350,7 +350,7 @@ protected function buildFilterParamsFor(DC_Table $dataContainer, $elementName) $dca = $collection->getParameterDCA(); foreach ($dca as $fieldName => $subField) { $options = []; - foreach ($subField['options'] as $key => $value) { + foreach (($subField['options'] ?? []) as $key => $value) { $options[$this->loadCallback($key)] = $value; } From e27a56a5a9c3fd55bd37520d3fa87ad146d0000e Mon Sep 17 00:00:00 2001 From: e-spin Date: Sun, 26 Feb 2023 15:32:14 +0100 Subject: [PATCH 172/224] Fix subHeadline at create item --- .../Table/DcaSetting/EditMaskSubHeadlineListener.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php index b22790215..7e57d6735 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php @@ -79,9 +79,13 @@ public function __invoke(GetEditMaskSubHeadlineEvent $event): void return; } - // Retrieve the settings of the input mask for member attribute. - $status = 'editRecord'; - $environment = $event->getEnvironment(); + // Nothing to do on create item. + $environment = $event->getEnvironment(); + if ('create' === $environment->getInputProvider()->getParameter('act')) { + return; + } + + // Retrieve the settings of the input mask for item attribute. $dataDefinition = $environment->getDataDefinition(); /** @var IMetaModelDefinition $metaModels */ $metaModel = $dataDefinition->getDefinition(IMetaModelDefinition::NAME); @@ -104,7 +108,7 @@ public function __invoke(GetEditMaskSubHeadlineEvent $event): void // Translate language key and add headline part. $subHeadline = - $this->translator->trans('tl_metamodel_item.' . $status, [0 => $headlineAdd], 'contao_tl_metamodel_item'); + $this->translator->trans('tl_metamodel_item.editRecord', [0 => $headlineAdd], 'contao_tl_metamodel_item'); $event->setHeadline($subHeadline); } From 1b069996d860e722894c5623d322c0e45d59b9c7 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Mon, 27 Feb 2023 12:34:07 +0100 Subject: [PATCH 173/224] Force clear 'get' when setting 'slug' parameter Otherwise we will generate invalid links, as the URI 'foo/page/2?page=3' is not routable in Contao and produces a 404. --- src/Filter/Setting/Simple.php | 8 ++++++-- src/Helper/PaginationGenerator.php | 2 +- src/Helper/SortingLinkGenerator.php | 8 ++++++-- src/Render/Setting/Collection.php | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Filter/Setting/Simple.php b/src/Filter/Setting/Simple.php index 070bcbecd..6411bf252 100644 --- a/src/Filter/Setting/Simple.php +++ b/src/Filter/Setting/Simple.php @@ -384,7 +384,9 @@ protected function prepareFrontendFilterOptions($arrWidget, $arrFilterUrl, $arrJ ? $GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'] : $arrWidget['eval']['blankOptionLabel'] ), - 'href' => $this->filterUrlBuilder->generate($filterUrl->clone()->setSlug($parameterName, '')), + 'href' => $this->filterUrlBuilder->generate( + $filterUrl->clone()->setSlug($parameterName, '')->setGet($parameterName, '') + ), 'active' => $blnActive, 'class' => 'doNotFilter' . ($blnActive ? ' active' : ''), ]; @@ -397,7 +399,9 @@ protected function prepareFrontendFilterOptions($arrWidget, $arrFilterUrl, $arrJ $arrOptions[] = [ 'key' => $strKeyOption, 'value' => $strOption, - 'href' => $this->filterUrlBuilder->generate($filterUrl->clone()->setSlug($parameterName, $strValue)), + 'href' => $this->filterUrlBuilder->generate( + $filterUrl->clone()->setSlug($parameterName, $strValue)->setGet($parameterName, '') + ), 'active' => $blnActive, 'class' => StringUtil::standardize($strKeyOption) . ($blnActive ? ' active' : '') ]; diff --git a/src/Helper/PaginationGenerator.php b/src/Helper/PaginationGenerator.php index eaa5b5662..51bb8a279 100644 --- a/src/Helper/PaginationGenerator.php +++ b/src/Helper/PaginationGenerator.php @@ -322,7 +322,7 @@ private function linkToPage(FilterUrl $filterUrl, int $page): string if ($this->paramType === 'get') { $pageFilterUrl->setGet($this->pageParam, $page); } else { - $pageFilterUrl->setSlug($this->pageParam, $page); + $pageFilterUrl->setSlug($this->pageParam, $page)->setGet($this->pageParam, ''); } return $this->urlBuilder->generate($pageFilterUrl); diff --git a/src/Helper/SortingLinkGenerator.php b/src/Helper/SortingLinkGenerator.php index 075670618..c01a49b9a 100644 --- a/src/Helper/SortingLinkGenerator.php +++ b/src/Helper/SortingLinkGenerator.php @@ -156,8 +156,12 @@ public function generateSortingLink(IAttribute $attribute, string $type): array $pageFilterUrl->setGet($this->sortOrderDirParam, $attributeName ? $dir : ''); } else { // Use slug or slugNget. - $pageFilterUrl->setSlug($this->sortOrderByParam, $attributeName); - $pageFilterUrl->setSlug($this->sortOrderDirParam, $attributeName ? $dir : ''); + $pageFilterUrl + ->setSlug($this->sortOrderByParam, $attributeName) + ->setGet($this->sortOrderByParam, ''); + $pageFilterUrl + ->setSlug($this->sortOrderDirParam, $attributeName ? $dir : '') + ->setGet($this->sortOrderDirParam, ''); } return [ diff --git a/src/Render/Setting/Collection.php b/src/Render/Setting/Collection.php index 7241ce6e7..eddf15154 100644 --- a/src/Render/Setting/Collection.php +++ b/src/Render/Setting/Collection.php @@ -337,7 +337,7 @@ public function buildJumpToUrlFor(IItem $item) foreach ($parameterList as $strKey => $strValue) { // Sadly the filter values are currently encoded due to legacy reasons. // For MetaModels 3, they should be passed around decoded everywhere. - $filterUrl->setSlug($strKey, rawurldecode($strValue)); + $filterUrl->setSlug($strKey, rawurldecode($strValue))->setGet($strKey, ''); } } From d76ca155a719a2aac16e9158e3896b16b8560146 Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 1 Mar 2023 08:03:22 +0100 Subject: [PATCH 174/224] Fix to disable the contao crawler --- .../Resources/contao/templates/mm_filteritem_linklist.html5 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CoreBundle/Resources/contao/templates/mm_filteritem_linklist.html5 b/src/CoreBundle/Resources/contao/templates/mm_filteritem_linklist.html5 index 0b32246ec..8a60235ac 100644 --- a/src/CoreBundle/Resources/contao/templates/mm_filteritem_linklist.html5 +++ b/src/CoreBundle/Resources/contao/templates/mm_filteritem_linklist.html5 @@ -19,6 +19,7 @@ ?>
  • From 46fd7da0daeb43b111bb8882c183f9f0812324f0 Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 1 Mar 2023 15:38:23 +0100 Subject: [PATCH 175/224] Fix sorting link disable for contao crawler --- src/ItemList.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ItemList.php b/src/ItemList.php index 6cc657d52..f5bade48d 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -1166,7 +1166,8 @@ public function render(bool $isNoNativeParsing, object $caller = null): string } return <<{$sortingLink['label']} + {$sortingLink['label']} EOF; }; From 98eb29c73a7a2867f91db4bf98bcff52ce3ce2f7 Mon Sep 17 00:00:00 2001 From: e-spin Date: Thu, 2 Mar 2023 20:37:16 +0100 Subject: [PATCH 176/224] Fix module template --- .../Resources/contao/templates/mod_metamodel_list.html5 | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/CoreBundle/Resources/contao/templates/mod_metamodel_list.html5 b/src/CoreBundle/Resources/contao/templates/mod_metamodel_list.html5 index 0482b9a0a..5e34a57b3 100644 --- a/src/CoreBundle/Resources/contao/templates/mod_metamodel_list.html5 +++ b/src/CoreBundle/Resources/contao/templates/mod_metamodel_list.html5 @@ -1,8 +1,5 @@ extend($this->searchable ? 'block_searchable' : 'block_unsearchable'); ?> block('content'); ?> -editEnable): ?> - - items ?> pagination ?> endblock(); ?> From 2813ce44b595379b4d676dad45d769b4e4a84f0a Mon Sep 17 00:00:00 2001 From: e-spin Date: Sat, 25 Feb 2023 14:13:49 +0100 Subject: [PATCH 177/224] Fix non legacy routing --- src/Filter/FilterUrlBuilder.php | 65 ++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/src/Filter/FilterUrlBuilder.php b/src/Filter/FilterUrlBuilder.php index a51cfcf7e..aba8338df 100644 --- a/src/Filter/FilterUrlBuilder.php +++ b/src/Filter/FilterUrlBuilder.php @@ -23,6 +23,7 @@ namespace MetaModels\Filter; +use Contao\ArrayUtil; use Contao\Config; use Contao\CoreBundle\Framework\Adapter; use Contao\PageModel; @@ -30,6 +31,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\Route; /** * This class builds filter URLs. @@ -231,12 +233,23 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = nul $filterUrl->setPageValue('id', substr($routeName, 8)); $requestUri = \rawurldecode(\substr($request->getPathInfo(), 1)); - $pageModel = $request->attributes->get('_route_object')->getPageModel(); - $length = $pageModel->urlSuffix ? -strlen($pageModel->urlSuffix) : null; - $fragments = \explode( - '/', - \substr($requestUri, \strlen($pageModel->urlPrefix ?? '') + 1, $length) - ); + + if (null === ($route = $request->attributes->get('_route_object'))) { + return; + } + assert($route instanceof Route); + + $pageModel = $route->getDefault('pageModel'); + assert($pageModel instanceof PageModel); + + $length = $pageModel->urlSuffix ? -\strlen($pageModel->urlSuffix) : null; + $start = \strlen($pageModel->urlPrefix ?? '') + \strlen($pageModel->alias); + $fragments = \explode('/', \substr($requestUri, $start ? $start + 1 : 0, $length)); + + if (1 === \count($fragments) % 2) { + array_unshift($fragments, 'auto_item'); + } + array_unshift($fragments, $pageModel->alias); } // If alias part is empty, this means we have the 'index' page. @@ -255,7 +268,7 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = nul // Decode slashes in slugs - They got encoded in generate() above. $filterUrl->setSlug( $this->decodeForAllowEncodedSlashes($fragments[$i]), - $this->decodeForAllowEncodedSlashes($fragments[($i + 1)]) + $this->decodeForAllowEncodedSlashes($fragments[($i + 1)] ?? '') ); } @@ -273,7 +286,7 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = nul */ private function encodeForAllowEncodedSlashes(string $value): string { - return str_replace(['/', '\\'], ['%2F', '%5C'], $value); + return \str_replace(['/', '\\'], ['%2F', '%5C'], $value); } /** @@ -287,7 +300,7 @@ private function encodeForAllowEncodedSlashes(string $value): string */ private function decodeForAllowEncodedSlashes(string $value): string { - return str_replace(['%2F', '%5C'], ['/', '\\'], $value); + return \str_replace(['%2F', '%5C'], ['/', '\\'], $value); } /** @@ -308,7 +321,7 @@ private function determineFragments(Request $request): ?array $fragments = null; // Use folder-style URLs - if (Config::get('folderUrl') && false !== strpos($requestUri, '/')) { + if (Config::get('folderUrl') && false !== \strpos($requestUri, '/')) { $fragments = $this->getFolderUrlFragments( $requestUri, $request->getHttpHost(), @@ -321,12 +334,12 @@ private function determineFragments(Request $request): ?array if ('/' === $requestUri) { return null; } - $fragments = explode('/', $requestUri); + $fragments = \explode('/', $requestUri); } // Add the second fragment as auto_item if the number of fragments is even if (Config::get('useAutoItem') && 0 === (\count($fragments) % 2)) { - array_insert($fragments, 1, ['auto_item']); + ArrayUtil::arrayInsert($fragments, 1, ['auto_item']); } $fragments = $this->getPageIdFromUrlHook($fragments); @@ -344,27 +357,27 @@ private function determineFragments(Request $request): ?array * * @param Request $request The request. * - * @return string + * @return string|null */ private function strippedUri(Request $request): ?string { // Strip leading slash. - if (null === $request || '' === $requestUri = rawurldecode(substr($request->getPathInfo(), 1))) { + if (null === $request || '' === $requestUri = \rawurldecode(substr($request->getPathInfo(), 1))) { return null; } if ($this->isLocalePrepended) { $matches = []; // Use the matches instead of substr() (thanks to Mario Müller) - if (preg_match('@^([a-z]{2}(-[A-Z]{2})?)/(.*)$@', $requestUri, $matches)) { + if (\preg_match('@^([a-z]{2}(-[A-Z]{2})?)/(.*)$@', $requestUri, $matches)) { $requestUri = $matches[3]; } } // Remove the URL suffix if not just a language root (e.g. en/) is requested if ('' !== $this->urlSuffix && '' !== $requestUri && ( - !$this->isLocalePrepended || !preg_match('@^[a-z]{2}(-[A-Z]{2})?/$@', $requestUri) + !$this->isLocalePrepended || !\preg_match('@^[a-z]{2}(-[A-Z]{2})?/$@', $requestUri) )) { - $requestUri = substr($requestUri, 0, -\strlen($this->urlSuffix)); + $requestUri = \substr($requestUri, 0, -\strlen($this->urlSuffix)); } return $requestUri; @@ -377,7 +390,7 @@ private function strippedUri(Request $request): ?string * @param string $host The host part of the current request. * @param string|null $locale The current locale or null if none requested. * - * @return array + * @return array|null * * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ @@ -402,7 +415,7 @@ private function getFolderUrlFragments(string $alias, string $host, string $loca if (!$this->isLocalePrepended) { // Use the first result (see #4872) - $pages = current($languages); + $pages = \current($languages); } elseif ($locale && isset($languages[$locale])) { // Try to find a page matching the language parameter $pages = $languages[$locale]; @@ -421,8 +434,8 @@ private function getFolderUrlFragments(string $alias, string $host, string $loca $arrFragments = [$alias]; } else { // Remove the alias from the request string, explode it and then re-insert it at the beginning. - $arrFragments = explode('/', substr($alias, (\strlen($page->alias) + 1))); - array_unshift($arrFragments, $page->alias); + $arrFragments = explode('/', \substr($alias, (\strlen($page->alias) + 1))); + \array_unshift($arrFragments, $page->alias); } return $arrFragments; @@ -435,7 +448,7 @@ private function getFolderUrlFragments(string $alias, string $host, string $loca * * @return array|null */ - private function getPageCandidates(string $alias) + private function getPageCandidates(string $alias): ?array { $aliases = [$alias]; // Compile all possible aliases by applying dirname() to the request. @@ -497,7 +510,7 @@ private function getPageIdFromUrlHook(?array $fragments): ?array * * @return void */ - private function extractPostData(FilterUrl $filterUrl, $options, Request $request): void + private function extractPostData(FilterUrl $filterUrl, array $options, Request $request): void { if (!$request->isMethod('POST')) { return; @@ -508,13 +521,13 @@ private function extractPostData(FilterUrl $filterUrl, $options, Request $reques } foreach ($request->request->all() as $name => $value) { - if (is_array($value)) { + if (\is_array($value)) { $value = implode(',', $value); } - if (in_array($name, $options['postAsSlug'])) { + if (\in_array($name, $options['postAsSlug'])) { $filterUrl->setSlug($name, $value); } - if (in_array($name, $options['postAsGet'])) { + if (\in_array($name, $options['postAsGet'])) { $filterUrl->setGet($name, $value); } } From 734360a92ac87d02eb22f5330a1d6779d16c7bcb Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 13 Mar 2023 15:48:57 +0100 Subject: [PATCH 178/224] Delete obsolete AttributeDeletedListener and AttributeSavendListener --- .../Attribute/AttributeDeletedListener.php | 98 ------------------- .../Attribute/AttributeSavedListener.php | 83 ---------------- .../config/dc-general/table/tl_attribute.yml | 16 --- 3 files changed, 197 deletions(-) delete mode 100644 src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeDeletedListener.php delete mode 100644 src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSavedListener.php diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeDeletedListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeDeletedListener.php deleted file mode 100644 index bdc0dc70b..000000000 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeDeletedListener.php +++ /dev/null @@ -1,98 +0,0 @@ - - * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\Attribute; - -use ContaoCommunityAlliance\DcGeneral\Event\PreDeleteModelEvent; - -/** - * This class takes care of deleting an attribute. - */ -class AttributeDeletedListener extends BaseListener -{ - /** - * Handle the update of an attribute and all attached data. - * - * @param PreDeleteModelEvent $event The event. - * - * @return void - */ - public function handle(PreDeleteModelEvent $event) - { - if (!$this->wantToHandle($event)) { - return; - } - - if ($attribute = $this->createAttributeInstance($event->getModel())) { - $this->deleteConditionSettings($event); - $attribute->destroyAUX(); - } - } - - /** - * Delete joint condition setting with attribute. - * - * @param PreDeleteModelEvent $event The event. - * - * @return void - */ - protected function deleteConditionSettings(PreDeleteModelEvent $event) - { - $environment = $event->getEnvironment(); - $model = $event->getModel(); - $dataProvider = $environment->getDataProvider('tl_metamodel_dcasetting_condition'); - - $conditions = $dataProvider->fetchAll( - $dataProvider->getEmptyConfig()->setFilter( - [['operation' => '=', 'property' => 'attr_id', 'value' => $model->getId()]] - ) - ); - - if ($conditions->count() < 1) { - return; - } - - $conditionsGeneral = new \DC_General($dataProvider->getEmptyModel()->getProviderName()); - $conditionsEnvironment = $conditionsGeneral->getEnvironment(); - $conditionsDataDefinition = $conditionsEnvironment->getDataDefinition(); - $conditionsPalettesDefinition = $conditionsDataDefinition->getPalettesDefinition(); - - /** @var \Iterator $conditionsIterator */ - $conditionsIterator = $conditions->getIterator(); - while ($currentCondition = $conditionsIterator->current()) { - $conditionPalette = $conditionsPalettesDefinition->getPaletteByName( - $currentCondition->getProperty('type') - ); - $conditionProperties = $conditionPalette->getVisibleProperties( - $currentCondition - ); - - foreach ($conditionProperties as $conditionProperty) { - if ($conditionProperty->getName() !== 'attr_id') { - continue; - } - - $dataProvider->delete($currentCondition); - } - - $conditionsIterator->next(); - } - } -} diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSavedListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSavedListener.php deleted file mode 100644 index 8f749c329..000000000 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSavedListener.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\Attribute; - -use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; -use ContaoCommunityAlliance\DcGeneral\Event\PostPersistModelEvent; - -/** - * This class takes care of updating all data when an attribute has been saved. - */ -class AttributeSavedListener extends BaseListener -{ - /** - * Handle the update of an attribute and all attached data. - * - * @param PostPersistModelEvent $event The event. - * - * @return void - */ - public function handle(PostPersistModelEvent $event) - { - if (!$this->wantToHandle($event)) { - return; - } - - $old = $event->getOriginalModel(); - $new = $event->getModel(); - $oldInstance = $old->getProperty('pid') ? $this->createAttributeInstance($old) : null; - $newInstance = $this->createAttributeInstance($new); - - // If type or column name has been changed, destroy old data and initialize new. - if ($this->isAttributeNameOrTypeChanged($new, $old)) { - // Destroy old instance. - if ($oldInstance) { - $oldInstance->destroyAUX(); - } - - // Create new instance aux info. - if ($newInstance) { - $newInstance->initializeAUX(); - } - } - - if ($newInstance) { - // Now loop over all values and update the meta in the instance. - foreach ($new->getPropertiesAsArray() as $strKey => $varValue) { - $newInstance->handleMetaChange($strKey, $varValue); - } - } - } - - /** - * Check if either type or column name have been changed within the model. - * - * @param ModelInterface $new The new model. - * @param ModelInterface $old The old model (or null). - * - * @return bool - */ - private function isAttributeNameOrTypeChanged(ModelInterface $new, ModelInterface $old) - { - return ($old->getProperty('type') !== $new->getProperty('type')) - || ($old->getProperty('colname') !== $new->getProperty('colname')); - } -} diff --git a/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml b/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml index ddf34f008..6c89298ca 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_attribute.yml @@ -40,22 +40,6 @@ services: event: dc-general.model.pre-edit-model method: handle - metamodels.listener.table.tl_metamodel_attribute.attribute_saved_listener: - class: MetaModels\CoreBundle\EventListener\DcGeneral\Table\Attribute\AttributeSavedListener - parent: metamodels.listener.table.tl_metamodel_attribute.listener_base - tags: - - name: kernel.event_listener - event: dc-general.model.post-persist - method: handle - - metamodels.listener.table.tl_metamodel_attribute.attribute_deleted_listener: - class: MetaModels\CoreBundle\EventListener\DcGeneral\Table\Attribute\AttributeDeletedListener - parent: metamodels.listener.table.tl_metamodel_attribute.listener_base - tags: - - name: kernel.event_listener - event: dc-general.model.pre-delete - method: handle - metamodels.dc_general.table.tl_metamodel_attribute.type_renderer: class: MetaModels\CoreBundle\EventListener\DcGeneral\Table\Attribute\AttributeRendererListener parent: metamodels.listener.table.tl_metamodel_attribute.listener_base From 77b825edf3281e22e5fa2d42b18ece61297935b8 Mon Sep 17 00:00:00 2001 From: e-spin Date: Tue, 14 Mar 2023 14:10:28 +0100 Subject: [PATCH 179/224] Fix unused auto_item at non legacy routing --- src/Filter/FilterUrlBuilder.php | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/Filter/FilterUrlBuilder.php b/src/Filter/FilterUrlBuilder.php index aba8338df..eefa26ee3 100644 --- a/src/Filter/FilterUrlBuilder.php +++ b/src/Filter/FilterUrlBuilder.php @@ -227,9 +227,7 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = nul return; } } else { - if (!\str_starts_with($routeName = $request->attributes->get('_route'), 'tl_page.')) { - throw new \RuntimeException('Unknown route name: ' . $routeName); - } + $routeName = $this->determineRouteName($request); $filterUrl->setPageValue('id', substr($routeName, 8)); $requestUri = \rawurldecode(\substr($request->getPathInfo(), 1)); @@ -243,8 +241,9 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = nul assert($pageModel instanceof PageModel); $length = $pageModel->urlSuffix ? -\strlen($pageModel->urlSuffix) : null; - $start = \strlen($pageModel->urlPrefix ?? '') + \strlen($pageModel->alias); - $fragments = \explode('/', \substr($requestUri, $start ? $start + 1 : 0, $length)); + $start = ($pageModel->urlPrefix ? \strlen($pageModel->urlPrefix . '/') : 0) + + \strlen($pageModel->alias . '/'); + $fragments = \explode('/', \substr($requestUri, $start, $length)); if (1 === \count($fragments) % 2) { array_unshift($fragments, 'auto_item'); @@ -532,4 +531,23 @@ private function extractPostData(FilterUrl $filterUrl, array $options, Request $ } } } + + /** + * Determine route name. + * + * @param Request $request + * + * @return string + */ + public function determineRouteName(Request $request): string + { + $pageModel = $request->attributes->get('pageModel'); + + return 'tl_page.' . match (true) { + ($pageModel instanceof PageModel) => $pageModel->id, + is_int($pageModel) => (string) $pageModel, + default => + throw new \RuntimeException('Unknown page model encountered: ' . get_debug_type($pageModel)), + }; + } } From 2d5fc65ab971ae1d10b888c6f8ca001f10669b03 Mon Sep 17 00:00:00 2001 From: e-spin Date: Thu, 23 Mar 2023 13:39:24 +0100 Subject: [PATCH 180/224] Cast attribute id as int --- src/MetaModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MetaModel.php b/src/MetaModel.php index 1f7a7725c..f59bf909e 100644 --- a/src/MetaModel.php +++ b/src/MetaModel.php @@ -830,7 +830,7 @@ public function getAttribute($strAttributeName) public function getAttributeById($intId) { foreach ($this->getAttributes() as $objAttribute) { - if ($objAttribute->get('id') === $intId) { + if ((int) $objAttribute->get('id') === (int) $intId) { return $objAttribute; } } From ff191117e95cd889a366751a591291c726f3d499 Mon Sep 17 00:00:00 2001 From: e-spin Date: Fri, 24 Mar 2023 22:00:50 +0100 Subject: [PATCH 181/224] Fix list params if is not activated --- src/CoreBundle/Controller/ListControllerTrait.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/CoreBundle/Controller/ListControllerTrait.php b/src/CoreBundle/Controller/ListControllerTrait.php index f3eff1e4c..7fbafb887 100644 --- a/src/CoreBundle/Controller/ListControllerTrait.php +++ b/src/CoreBundle/Controller/ListControllerTrait.php @@ -270,8 +270,10 @@ private function getResponseInternal(Template $template, Model $model, Request $ ); } - foreach (StringUtil::deserialize(($model->metamodel_parameters ?? null), true) as $key => $value) { - $itemRenderer->setTemplateParameter($key, $value); + if ($model->metamodel_use_parameters) { + foreach (StringUtil::deserialize(($model->metamodel_parameters ?? null), true) as $key => $value) { + $itemRenderer->setTemplateParameter($key, $value); + } } $template->items = StringUtil::encodeEmail($itemRenderer->render($model->metamodel_noparsing, $model)); From f2a7bd680a682eb466f5f90d81c4b3039d2c52c1 Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 29 Mar 2023 09:55:59 +0200 Subject: [PATCH 182/224] Fix reverse sorting for filter rule rsort changed the array keys. --- src/Filter/Setting/SimpleLookup.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Filter/Setting/SimpleLookup.php b/src/Filter/Setting/SimpleLookup.php index c949ee89e..e27b5ac3e 100644 --- a/src/Filter/Setting/SimpleLookup.php +++ b/src/Filter/Setting/SimpleLookup.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Stefan Heimes * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -114,12 +114,14 @@ protected function getParameterFilterOptions($objAttribute, $arrIds, &$arrCount } } + // Sorting option for filter items. switch ($this->get('apply_sorting')) { case 'natsort_asc': \natcasesort($arrOptions); break; case 'natsort_desc': - \rsort($arrOptions, (SORT_NATURAL | SORT_FLAG_CASE)); + \natcasesort($arrOptions); + $arrOptions = \array_reverse($arrOptions, true); break; default: } From 80522b920eba6b6a798318bfd151a008d1df4422 Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 3 Apr 2023 20:54:32 +0200 Subject: [PATCH 183/224] Add support ShowHandler --- .../contao/dca/tl_metamodel_item.php | 100 ++++++++---------- .../contao/languages/en/tl_metamodel_item.php | 11 +- 2 files changed, 52 insertions(+), 59 deletions(-) diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php index 9d5fd0c39..ebb94f70c 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,8 @@ * @author Oliver Lohoff * @author Stefan Heimes * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,61 +26,46 @@ This file defines the basic structure of ALL MetaModel items. Note however, that various MetaModel extensions might remove or add stuff here. */ - -$GLOBALS['TL_DCA']['tl_metamodel_item'] = array -( - 'config' => array - ( - 'dataContainer' => 'General', - 'switchToEdit' => false, - 'enableVersioning' => false, - ), - 'dca_config' => array - ( - 'data_provider' => array - ( - 'default' => array - ( - 'class' => 'MetaModels\DcGeneral\Data\Driver', - ) - ), - ), - - 'list' => array - ( - 'sorting' => array - ( +$GLOBALS['TL_DCA']['tl_metamodel_item'] = [ + 'config' => [ + 'dataContainer' => 'General', + 'switchToEdit' => false, + 'enableVersioning' => false, + ], + 'dca_config' => [ + 'data_provider' => [ + 'default' => [ + 'class' => 'MetaModels\DcGeneral\Data\Driver', + ] + ], + ], + 'list' => [ + 'sorting' => [ // This means: 1 default sorting value, 2 switchable sorting value. - 'mode' => 1, - 'headerFields' => array - ( + 'mode' => 1, + 'headerFields' => [ 'tstamp' - ), - ), - - 'label' => array - ( - 'fields' => array - ( - ), - 'format' => '%s', - ), - ), + ], + ], - 'fields' => array - ( - 'id' => array - ( - ), - 'pid' => array - ( - ), - 'sorting' => array - ( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_item']['sorting'], - ), - 'tstamp' => array - ( - ) - ) -); + 'label' => [ + 'fields' => [ + ], + 'format' => '%s', + ], + ], + 'fields' => [ + 'id' => [ + 'label' => 'id.0', + ], + 'pid' => [ + 'label' => 'pid.0', + ], + 'sorting' => [ + 'label' => 'sorting.0', + ], + 'tstamp' => [ + 'label' => 'tstamp.0', + ] + ] +]; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_item.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_item.php index 63a35724c..e060cca8f 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_item.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_item.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2018 The MetaModels team. + * (c) 2012-2023 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,8 @@ * @subpackage Core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2018 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -48,3 +49,9 @@ $GLOBALS['TL_LANG']['tl_metamodel_item']['newRecord'] = 'Create a new item'; $GLOBALS['TL_LANG']['tl_metamodel_item']['sorting'][0] = 'Sorting'; $GLOBALS['TL_LANG']['tl_metamodel_item']['sorting'][1] = 'The manual sorting'; +$GLOBALS['TL_LANG']['tl_metamodel_item']['id'][0] = 'ID of the item'; +$GLOBALS['TL_LANG']['tl_metamodel_item']['id'][1] = 'The id of the item'; +$GLOBALS['TL_LANG']['tl_metamodel_item']['pid'][0] = 'Parent item id'; +$GLOBALS['TL_LANG']['tl_metamodel_item']['pid'][1] = 'The id of the parent item'; +$GLOBALS['TL_LANG']['tl_metamodel_item']['tstamp'][0] = 'Revision date'; +$GLOBALS['TL_LANG']['tl_metamodel_item']['tstamp'][1] = 'The date when the item revision was created'; From dba30675df5dcf72cafbcc2663cbee54de0558cd Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 12 Apr 2023 14:05:37 +0200 Subject: [PATCH 184/224] Fix create variants --- .../DcGeneral/MetaModel/CreateVariantButtonListener.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/MetaModel/CreateVariantButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/MetaModel/CreateVariantButtonListener.php index 1cf862ce4..a8c5220ac 100644 --- a/src/CoreBundle/EventListener/DcGeneral/MetaModel/CreateVariantButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/MetaModel/CreateVariantButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,8 @@ * @author Christopher Boelter * @author Sven Baumann * @author Richard Henkenjohann - * @copyright 2012-2021 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -146,7 +147,7 @@ public function handleCreateVariantAction(ActionEvent $event) $postFunction = function ($environment, $model) { /** @var EnvironmentInterface $environment */ $copyEvent = new PostCreateModelEvent($environment, $model); - $environment->getEventDispatcher()->dispatch($copyEvent::NAME, $copyEvent); + $environment->getEventDispatcher()->dispatch($copyEvent, $copyEvent::NAME); }; if (!$view instanceof BackendViewInterface) { From a0d6277f09f25810129dcb68c7db9034e830a5ff Mon Sep 17 00:00:00 2001 From: e-spin Date: Thu, 13 Apr 2023 08:30:29 +0200 Subject: [PATCH 185/224] Add sorting pages by route priority --- src/Filter/FilterUrlBuilder.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Filter/FilterUrlBuilder.php b/src/Filter/FilterUrlBuilder.php index eefa26ee3..c48080128 100644 --- a/src/Filter/FilterUrlBuilder.php +++ b/src/Filter/FilterUrlBuilder.php @@ -456,13 +456,13 @@ private function getPageCandidates(string $alias): ?array $aliases[] = $alias; } - // Check if there are pages with a matching alias - $pages = $this->pageModelAdapter->findByAliases($aliases); + // Check if there are pages with a matching alias - sort by priority desc. + $pages = $this->pageModelAdapter->findByAliases($aliases, ['order' => 'tl_page.routePriority DESC']); if (null === $pages) { return null; } $arrPages = []; - // Order by domain and language + // Order by domain and language. while ($pages->next()) { /** @var PageModel $objModel */ $objModel = $pages->current(); @@ -470,11 +470,12 @@ private function getPageCandidates(string $alias): ?array $domain = $objPage->domain ?: '*'; $arrPages[$domain][$objPage->rootLanguage][] = $objPage; - // Also store the fallback language + // Also store the fallback language. if ($objPage->rootIsFallback) { $arrPages[$domain]['*'][] = $objPage; } } + return $arrPages; } From 4be9b36fe1101f61e85d95e920f085fc4237e686 Mon Sep 17 00:00:00 2001 From: e-spin Date: Wed, 19 Apr 2023 18:33:33 +0200 Subject: [PATCH 186/224] Add second sort parameter for fixed order --- src/Filter/FilterUrlBuilder.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Filter/FilterUrlBuilder.php b/src/Filter/FilterUrlBuilder.php index c48080128..3d2a53b33 100644 --- a/src/Filter/FilterUrlBuilder.php +++ b/src/Filter/FilterUrlBuilder.php @@ -456,8 +456,9 @@ private function getPageCandidates(string $alias): ?array $aliases[] = $alias; } - // Check if there are pages with a matching alias - sort by priority desc. - $pages = $this->pageModelAdapter->findByAliases($aliases, ['order' => 'tl_page.routePriority DESC']); + // Check if there are pages with a matching alias - sort by priority desc and id asc. + $pages = + $this->pageModelAdapter->findByAliases($aliases, ['order' => 'tl_page.routePriority DESC, tl_page.id ASC']); if (null === $pages) { return null; } From 59795b4672063615ed0606da7676ae68ffe19ca5 Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 24 Apr 2023 12:07:48 +0200 Subject: [PATCH 187/224] Add own form id to manipulate FORM_SUBMIT value e.g. if you use the redirect option --- src/CoreBundle/Resources/contao/dca/tl_content.php | 14 ++++++++++++-- src/CoreBundle/Resources/contao/dca/tl_module.php | 14 ++++++++++++-- .../Resources/contao/languages/en/tl_content.php | 6 +++++- .../Resources/contao/languages/en/tl_module.php | 4 ++++ src/FrontendIntegration/FrontendFilter.php | 6 +++--- 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/CoreBundle/Resources/contao/dca/tl_content.php b/src/CoreBundle/Resources/contao/dca/tl_content.php index e99aa85bb..96541a033 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_content.php +++ b/src/CoreBundle/Resources/contao/dca/tl_content.php @@ -47,7 +47,7 @@ '{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,' . - 'metamodel_jumpTo,metamodel_fef_urlfragment;' . + 'metamodel_jumpTo,metamodel_fef_id,metamodel_fef_urlfragment;' . '{protected_legend:hide},protected;' . '{expert_legend:hide},guests,cssID,space;' . '{invisible_legend:hide},invisible,start,stop'; @@ -355,12 +355,22 @@ ], 'sql' => "int(10) unsigned NOT NULL default '0'" ], + 'metamodel_fef_id' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_content']['metamodel_fef_id'], + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ + 'tl_class' => 'w50', + 'rgxp' => 'alias' + ], + 'sql' => "char(255) NOT NULL default ''" + ], 'metamodel_fef_urlfragment' => [ 'label' => &$GLOBALS['TL_LANG']['tl_content']['metamodel_fef_urlfragment'], 'exclude' => true, 'inputType' => 'text', 'eval' => [ - 'tl_class' => 'w50', + 'tl_class' => 'clr w50', 'rgxp' => 'alias' ], 'sql' => "char(255) NOT NULL default ''" diff --git a/src/CoreBundle/Resources/contao/dca/tl_module.php b/src/CoreBundle/Resources/contao/dca/tl_module.php index 405fd55ed..7ecff74a8 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_module.php +++ b/src/CoreBundle/Resources/contao/dca/tl_module.php @@ -45,7 +45,7 @@ '{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,' . - 'metamodel_jumpTo,metamodel_fef_urlfragment;' . + 'metamodel_jumpTo,metamodel_fef_id,metamodel_fef_urlfragment;' . '{protected_legend:hide},protected;' . '{expert_legend:hide},guests,cssID,space'; @@ -352,12 +352,22 @@ ], 'sql' => "int(10) unsigned NOT NULL default '0'" ], + 'metamodel_fef_id' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_fef_id'], + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ + 'tl_class' => 'w50', + 'rgxp' => 'alias' + ], + 'sql' => "char(255) NOT NULL default ''" + ], 'metamodel_fef_urlfragment' => [ 'label' => &$GLOBALS['TL_LANG']['tl_module']['metamodel_fef_urlfragment'], 'exclude' => true, 'inputType' => 'text', 'eval' => [ - 'tl_class' => 'w50', + 'tl_class' => 'clr w50', 'rgxp' => 'alias' ], 'sql' => "char(255) NOT NULL default ''" diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_content.php b/src/CoreBundle/Resources/contao/languages/en/tl_content.php index ba76a4941..d0c553bde 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_content.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_content.php @@ -112,7 +112,11 @@ $GLOBALS['TL_LANG']['tl_content']['metamodel_jumpTo'][0] = 'Redirect page'; $GLOBALS['TL_LANG']['tl_content']['metamodel_jumpTo'][1] = 'Please choose the page to which visitors will be redirected when clicking a link or submitting a form.'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_fef_urlfragment'][0] = 'URL fragment'; +$GLOBALS['TL_LANG']['tl_content']['metamodel_fef_id'][0] = 'Form ID'; +$GLOBALS['TL_LANG']['tl_content']['metamodel_fef_id'][1] = + 'Set ID as own postfix for "FORM_SUBMIT" value e.g. to use redirect and another filter -' . + ' in which case the value must be the same. '; +$GLOBALS['TL_LANG']['tl_content']['metamodel_fef_urlfragment'][0] = 'URL fragment'; $GLOBALS['TL_LANG']['tl_content']['metamodel_fef_urlfragment'][1] = 'Add URL fragment to jump to anchor or id.'; $GLOBALS['TL_LANG']['tl_content']['metamodel_fef_params'][0] = 'Attributes'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_module.php b/src/CoreBundle/Resources/contao/languages/en/tl_module.php index 4b28ba6c4..abceb32d3 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_module.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_module.php @@ -108,6 +108,10 @@ $GLOBALS['TL_LANG']['tl_module']['metamodel_jumpTo'][0] = 'Redirect page'; $GLOBALS['TL_LANG']['tl_module']['metamodel_jumpTo'][1] = 'Please choose the page to which visitors will be redirected when clicking a link or submitting a form.'; +$GLOBALS['TL_LANG']['tl_module']['metamodel_fef_id'][0] = 'Form ID'; +$GLOBALS['TL_LANG']['tl_module']['metamodel_fef_id'][1] = + 'Set ID as own postfix for "FORM_SUBMIT" value e.g. to use redirect and another filter -' . + ' in which case the value must be the same. '; $GLOBALS['TL_LANG']['tl_module']['metamodel_fef_urlfragment'][0] = 'URL fragment'; $GLOBALS['TL_LANG']['tl_module']['metamodel_fef_urlfragment'][1] = 'Add URL fragment to jump to anchor or id.'; diff --git a/src/FrontendIntegration/FrontendFilter.php b/src/FrontendIntegration/FrontendFilter.php index 9e36dc36f..475ead06d 100644 --- a/src/FrontendIntegration/FrontendFilter.php +++ b/src/FrontendIntegration/FrontendFilter.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -20,7 +20,7 @@ * @author David Molineus * @author Marc Reimann * @author Richard Henkenjohann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -124,7 +124,7 @@ public function getMetaModelFrontendFilter(HybridFilterBlock $objFilterConfig) { $this->objFilterConfig = $objFilterConfig; - $this->formId .= $this->objFilterConfig->id; + $this->formId .= $this->objFilterConfig->metamodel_fef_id ?: $this->objFilterConfig->id; return $this->getFilters(); } From d38b8f20bd8f30dfb9731f09f41ee46032a334fd Mon Sep 17 00:00:00 2001 From: e-spin Date: Tue, 23 May 2023 21:33:14 +0200 Subject: [PATCH 188/224] Add feature to chose own widget template --- src/Attribute/Base.php | 8 +- .../DcaSetting/ManipulateWidgetListener.php | 107 ++++++++++++++++++ .../DcaSetting/TemplateOptionListener.php | 96 ++++++++++++++++ .../config/dc-general/table/tl_dcasetting.yml | 17 +++ .../contao/dca/tl_metamodel_dcasetting.php | 16 ++- .../languages/en/tl_metamodel_dcasetting.php | 7 +- 6 files changed, 245 insertions(+), 6 deletions(-) create mode 100644 src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ManipulateWidgetListener.php create mode 100644 src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/TemplateOptionListener.php diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index b8081246b..1c14d2fa2 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -381,7 +381,9 @@ public function getAttributeSettingNames() 'isvariant', // Settings originating from tl_metamodel_dcasetting. 'tl_class', - 'readonly' + 'readonly', + 'be_template', + 'fe_template', ]; } @@ -501,7 +503,9 @@ private function setBaseEval($fieldDefinition, $overrides) 'spaceToUnderscore', 'includeBlankOption', 'submitOnChange', - 'readonly' + 'readonly', + 'be_template', + 'fe_template', ]; foreach ($names as $name) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ManipulateWidgetListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ManipulateWidgetListener.php new file mode 100644 index 000000000..9bf3d4999 --- /dev/null +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ManipulateWidgetListener.php @@ -0,0 +1,107 @@ + + * @copyright 2012-2023 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\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\ManipulateWidgetEvent; +use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; +use MetaModels\Attribute\IInternal; +use MetaModels\DcGeneral\Data\Model; + +final class ManipulateWidgetListener +{ + /** + * The scope determinator. + * + * @var RequestScopeDeterminator + */ + private RequestScopeDeterminator $scopeDeterminator; + + /** + * Create a new instance. + * + * @param RequestScopeDeterminator $scopeDeterminator The scope determinator. + */ + public function __construct( + RequestScopeDeterminator $scopeDeterminator + ) { + $this->scopeDeterminator = $scopeDeterminator; + } + /** + * Change the widget template with your own choice. + * + * @param BuildWidgetEvent $event The event. + * + * @return void + */ + public function handle(ManipulateWidgetEvent $event) + { + if (!$this->wantToHandle($event)) { + return; + } + + $model = $event->getModel(); + if (!$model instanceof Model) { + return; + } + + $property = $event->getProperty(); + if (null === $attribute = $model->getItem()->getMetaModel()->getAttribute($property->getName())) { + return; + } + + // Check virtual types. + if ($attribute instanceof IInternal) { + return; + } + + if (!\in_array('be_template', $attribute->getAttributeSettingNames(), true)) { + return; + } + + $propExtra = $property->getExtra(); + + if (null !== ($template = $propExtra['be_template'] ?? null)) { + $event->getWidget()->template = $template; + } + } + + /** + * Test if the event is for the correct table and in backend scope. + * + * @param AbstractEnvironmentAwareEvent $event The event to test. + * + * @return bool + */ + protected function wantToHandle(AbstractEnvironmentAwareEvent $event): bool + { + if (!$this->scopeDeterminator->currentScopeIsBackend()) { + return false; + } + + $environment = $event->getEnvironment(); + + if ('mm_' !== \substr($environment->getDataDefinition()->getName(), 0, 3)) { + return false; + } + + return true; + } +} diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/TemplateOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/TemplateOptionListener.php new file mode 100644 index 000000000..b45a6edcd --- /dev/null +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/TemplateOptionListener.php @@ -0,0 +1,96 @@ + + * @copyright 2012-2023 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\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; +use MetaModels\BackendIntegration\TemplateList; + +/** + * This handles the providing of available templates. + */ +class TemplateOptionListener +{ + /** + * The scope determinator. + * + * @var RequestScopeDeterminator + */ + private RequestScopeDeterminator $scopeDeterminator; + + /** + * The template list provider. + * + * @var TemplateList + */ + private TemplateList $templateList; + + /** + * Create a new instance. + * + * @param RequestScopeDeterminator $scopeDeterminator The scope determinator. + * @param TemplateList $templateList The template list provider. + */ + public function __construct( + RequestScopeDeterminator $scopeDeterminator, + TemplateList $templateList + ) { + $this->scopeDeterminator = $scopeDeterminator; + $this->templateList = $templateList; + } + + /** + * Retrieve the options for the frontend widget template. + * + * @param GetPropertyOptionsEvent $event The event. + * + * @return void + */ + public function handle(GetPropertyOptionsEvent $event): void + { + if (!$this->wantToHandle($event) || ($event->getPropertyName() !== 'be_template')) { + return; + } + + $event->setOptions($this->templateList->getTemplatesForBase('be_widget')); + } + + /** + * Test if the event is for the correct table and in backend scope. + * + * @param AbstractEnvironmentAwareEvent $event The event to test. + * + * @return bool + */ + protected function wantToHandle(AbstractEnvironmentAwareEvent $event): bool + { + if (!$this->scopeDeterminator->currentScopeIsBackend()) { + return false; + } + + $environment = $event->getEnvironment(); + if ('tl_metamodel_dcasetting' !== $environment->getDataDefinition()->getName()) { + return false; + } + + return true; + } +} 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 c66485de8..c31924af2 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_dcasetting.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_dcasetting.yml @@ -124,3 +124,20 @@ services: tags: - name: kernel.event_listener event: dc-general.view.contao2backend.get-edit-mask-subheadline + + MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting\TemplateOptionListener: + arguments: + - "@cca.dc-general.scope-matcher" + - "@metamodels.template_list" + tags: + - name: kernel.event_listener + event: dc-general.view.contao2backend.get-property-options + method: handle + + MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting\ManipulateWidgetListener: + arguments: + - "@cca.dc-general.scope-matcher" + tags: + - 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 16be0964b..37f818630 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,7 +21,7 @@ * @author Cliff Parnitzky * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -225,6 +225,7 @@ // * advanced // Core fields: // * tl_class css class to use in backend. + // * be_template template for backend widget. // * mandatory mandatory. // * alwaysSave always save. // * filterable can be filtered (in backend). @@ -299,6 +300,17 @@ 'explanation' => 'tl_class', 'sql' => ['type' => 'string', 'length' => 64, 'default' => 'w50'] ], + 'be_template' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['be_template'], + 'exclude' => true, + 'inputType' => 'select', + 'sql' => 'varchar(255) NOT NULL default \'\'', + 'eval' => [ + 'includeBlankOption' => true, + 'tl_class' => 'clr w50', + 'chosen' => 'true' + ] + ], 'legendhide' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['legendhide'], 'exclude' => true, diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php index dc56d7e97..ca0a9afe9 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Cliff Parnitzky * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -36,6 +36,9 @@ $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['tl_class'][0] = 'Backend class'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['tl_class'][1] = 'Here you can set backend class(es). Open the wizard for an overview of the classes.'; +$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['be_template'][0] = 'Template at backend'; +$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['be_template'][1] = + 'You can chose own template for widget in backend - add file in root folder of template.'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['legendhide'][0] = 'Collapse section'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['legendhide'][1] = 'Collapse the section by default.'; $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['legendtitle'][0] = 'Legend title'; From 67515b5d2d37e31faf16915e550e262a48fa1b56 Mon Sep 17 00:00:00 2001 From: e-spin Date: Thu, 25 May 2023 10:29:20 +0200 Subject: [PATCH 189/224] Fix PHP 8 warnings --- .../Contao2BackendViewDefinitionBuilder.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php index f1ffab41e..506cddd8e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php @@ -206,13 +206,13 @@ private function parseListSorting(ListingConfigInterface $listing) $definitions = $listing->getGroupAndSortingDefinition(); foreach ($this->inputScreen['groupSort'] as $information) { - if (!$information['published']) { + if (empty($information['published'])) { continue; } $definition = $definitions->add(); $definition->setName($information['name']); - if ($information['isdefault'] && !$definitions->hasDefault()) { + if (!empty($information['isdefault']) && !$definitions->hasDefault()) { $definitions->markDefault($definition); } @@ -220,7 +220,7 @@ private function parseListSorting(ListingConfigInterface $listing) $groupType = $this->convertRenderGroupType($information['rendergrouptype']); if ($groupType !== GroupAndSortingInformationInterface::GROUP_NONE - && $information['col_name'] + && !empty($information['col_name']) ) { $propertyInformation = $definition->add(0); $propertyInformation @@ -244,7 +244,7 @@ private function handleSorting( $information, GroupAndSortingDefinitionInterface $definition ) { - if ($information['ismanualsort']) { + if (!empty($information['ismanualsort'])) { $definition ->add() ->setManualSorting() @@ -252,7 +252,7 @@ private function handleSorting( ->setSortingMode(GroupAndSortingInformationInterface::SORT_ASC); return; } - if ($information['col_name']) { + if (!empty($information['col_name'])) { $definition ->add() ->setProperty($information['col_name']) From 726b3d5d27f3fea2978e5883fb050014a256e211 Mon Sep 17 00:00:00 2001 From: Stefan Heimes Date: Fri, 7 Jul 2023 14:39:02 +0000 Subject: [PATCH 190/224] Update file ConditionBuilderWithVariants.php --- .../ConditionBuilderWithVariants.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php index 43328f95f..d466a9847 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,8 +12,9 @@ * * @package MetaModels/core * @author Christian Schiffler + * @author Stefan Heimes * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -46,8 +47,18 @@ protected function calculate() [['property' => 'varbase', 'value' => '1']], $relationship->getSetters() )); + } + + protected function addHierarchicalConditions() + { + // Not hierarchical? Get out. + if ($this->container->getBasicDefinition()->getMode() !== BasicDefinitionInterface::MODE_HIERARCHICAL) { + return; + } + + $relationship = $this->getRootCondition(); - $builder = FilterBuilder::fromArrayForRoot((array) $relationship->getFilterArray())->getFilter(); + $builder = FilterBuilder::fromArrayForRoot((array)$relationship->getFilterArray())->getFilter(); $builder->andPropertyEquals('varbase', 1); From 1222e93007c585e7461eb9bc6cd7f0cc277fc68e Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Mon, 10 Jul 2023 12:28:05 +0200 Subject: [PATCH 191/224] Make return value non nullable There is no legal possibility to ever return null here and calling code breaks if ever null should be returned. --- src/CoreBundle/Controller/ContentElement/ItemListController.php | 2 +- src/CoreBundle/Controller/FrontendModule/ItemListController.php | 2 +- src/CoreBundle/Controller/ListControllerTrait.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CoreBundle/Controller/ContentElement/ItemListController.php b/src/CoreBundle/Controller/ContentElement/ItemListController.php index f694d366b..497ca4ad6 100644 --- a/src/CoreBundle/Controller/ContentElement/ItemListController.php +++ b/src/CoreBundle/Controller/ContentElement/ItemListController.php @@ -79,7 +79,7 @@ public function __invoke( * * @return Response The response. */ - protected function getResponse(Template $template, ContentModel $model, Request $request): ?Response + protected function getResponse(Template $template, ContentModel $model, Request $request): Response { $response = $this->getResponseInternal($template, $model, $request); $this->addSharedMaxAgeToResponse($response, $model); diff --git a/src/CoreBundle/Controller/FrontendModule/ItemListController.php b/src/CoreBundle/Controller/FrontendModule/ItemListController.php index 3d01d27bc..40990854b 100644 --- a/src/CoreBundle/Controller/FrontendModule/ItemListController.php +++ b/src/CoreBundle/Controller/FrontendModule/ItemListController.php @@ -96,7 +96,7 @@ protected function getBackendWildcard(ModuleModel $module): Response * * @return Response The response. */ - protected function getResponse(Template $template, ModuleModel $model, Request $request): ?Response + protected function getResponse(Template $template, ModuleModel $model, Request $request): Response { return $this->getResponseInternal($template, $model, $request); } diff --git a/src/CoreBundle/Controller/ListControllerTrait.php b/src/CoreBundle/Controller/ListControllerTrait.php index 7fbafb887..8f81520b6 100644 --- a/src/CoreBundle/Controller/ListControllerTrait.php +++ b/src/CoreBundle/Controller/ListControllerTrait.php @@ -182,7 +182,7 @@ public function __construct( * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - private function getResponseInternal(Template $template, Model $model, Request $request): ?Response + private function getResponseInternal(Template $template, Model $model, Request $request): Response { if (empty($pageParam = $model->metamodel_page_param)) { switch ($model->type) { From 109ddc3b25b4ef83aebd89b34198b7f665d665fc Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Mon, 10 Jul 2023 12:33:19 +0200 Subject: [PATCH 192/224] Add new url parsing option 'removeGetOnSlug' This will prevent get parameters from getting set if a slug parameter with the same name exists. --- src/Filter/FilterUrlBuilder.php | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Filter/FilterUrlBuilder.php b/src/Filter/FilterUrlBuilder.php index 3d2a53b33..9d57937a4 100644 --- a/src/Filter/FilterUrlBuilder.php +++ b/src/Filter/FilterUrlBuilder.php @@ -186,12 +186,14 @@ public function getCurrentFilterUrl(array $options = null): FilterUrl * This is mostly based on \Contao\Frontend::getPageIdFromUrl() but stripped off of some checks. * * Options may be: - * bool postAsSlug Fields of POST data that shall be added to the slug entries. - * default: [] - * bool postAsGet Fields of POST data that shall be added to the GET entries. - * default: [] - * bool preserveGet Flag if the GET parameters shall be added to the filter URL. - * default: true + * bool postAsSlug Fields of POST data that shall be added to the slug entries. + * default: [] + * bool postAsGet Fields of POST data that shall be added to the GET entries. + * default: [] + * bool preserveGet Flag if the GET parameters shall be added to the filter URL. + * default: true + * bool removeGetOnSlug Flag to remove GET parameters from the filter URL when a same named slug parameter exists. + * default: true * * @param FilterUrl $filterUrl The filter URL to update. * @param array|null $options The options for updating. @@ -202,9 +204,10 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = nul { if (null === $options) { $options = [ - 'postAsSlug' => [], - 'postAsGet' => [], - 'preserveGet' => true + 'postAsSlug' => [], + 'postAsGet' => [], + 'preserveGet' => true, + 'removeGetOnSlug' => true ]; } @@ -213,7 +216,7 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = nul return; } - if (isset($options['preserveGet'])) { + if ($options['preserveGet'] ?? true) { foreach ($request->query->all() as $name => $value) { $filterUrl->setGet($name, $value); } @@ -265,10 +268,14 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = nul } // Decode slashes in slugs - They got encoded in generate() above. + $name = $this->decodeForAllowEncodedSlashes($fragments[$i]); $filterUrl->setSlug( - $this->decodeForAllowEncodedSlashes($fragments[$i]), - $this->decodeForAllowEncodedSlashes($fragments[($i + 1)] ?? '') + $name, + $this->decodeForAllowEncodedSlashes($fragments[($i + 1)]) ); + if (($options['removeGetOnSlug'] ?? true) && $filterUrl->hasGet($name)) { + $filterUrl->setGet($name, ''); + } } $this->extractPostData($filterUrl, $options, $request); From f862d19c80b8377f103919b8662de1e552b9ab08 Mon Sep 17 00:00:00 2001 From: zonky Date: Sat, 22 Jul 2023 13:18:39 +0200 Subject: [PATCH 193/224] Fix raw data if null --- src/CoreBundle/EventListener/InsertTagsListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/EventListener/InsertTagsListener.php b/src/CoreBundle/EventListener/InsertTagsListener.php index 715d77184..83854d918 100644 --- a/src/CoreBundle/EventListener/InsertTagsListener.php +++ b/src/CoreBundle/EventListener/InsertTagsListener.php @@ -337,7 +337,7 @@ private function getAttribute( $outputFormat = 'raw'; } - return $arrAttr[$outputFormat]; + return $arrAttr[$outputFormat] ?? false; } /** From 985ceca12e4be7b48f89ff4028f583db9f4ec5a1 Mon Sep 17 00:00:00 2001 From: zonky Date: Wed, 26 Jul 2023 09:03:06 +0200 Subject: [PATCH 194/224] Fix classes and methods --- .../AbstractConditionBuilder.php | 86 +++---------------- .../ConditionBuilderWithVariants.php | 22 +++-- .../ConditionBuilderWithoutVariants.php | 76 +++++++++++++++- src/DcGeneral/Data/FilterBuilder.php | 11 ++- 4 files changed, 103 insertions(+), 92 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/AbstractConditionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/AbstractConditionBuilder.php index 89050be84..7052d33a2 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/AbstractConditionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/AbstractConditionBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,16 +13,14 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\DefinitionBuilder; -use Contao\Input; -use ContaoCommunityAlliance\DcGeneral\Data\ModelId; -use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\BasicDefinitionInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\DefaultModelRelationshipDefinition; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\ModelRelationshipDefinitionInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\ModelRelationship\FilterBuilder; @@ -33,7 +31,7 @@ use MetaModels\DcGeneral\DataDefinition\IMetaModelDataDefinition; /** - * This class is the abstract base for the condition builders. + * This class is the abstract base for the hierarchical/variant model condition builders. */ abstract class AbstractConditionBuilder { @@ -42,21 +40,21 @@ abstract class AbstractConditionBuilder * * @var IMetaModelDataDefinition */ - protected $container; + protected IMetaModelDataDefinition $container; /** * The input screen. * * @var array */ - protected $inputScreen; + protected array $inputScreen; /** * The model relationship interface. * * @var ModelRelationshipDefinitionInterface */ - protected $definition; + protected ModelRelationshipDefinitionInterface $definition; /** * Parse the correct conditions. @@ -97,14 +95,14 @@ public static function calculateConditions(IMetaModelDataDefinition $container, * * @throws \RuntimeException When the conditions can not be determined. */ - abstract protected function calculate(); + abstract protected function calculate(): void; /** * Parse the correct conditions for a MetaModel with variant support. * * @return void */ - protected function addParentCondition() + protected function addParentCondition(): void { if ($this->inputScreen['meta']['rendertype'] === 'standalone') { return; @@ -143,73 +141,11 @@ protected function addParentCondition() } /** - * Parse the correct conditions for a MetaModel with variant support. - * - * @return void - */ - protected function addHierarchicalConditions() - { - // Not hierarchical? Get out. - if ($this->container->getBasicDefinition()->getMode() !== BasicDefinitionInterface::MODE_HIERARCHICAL) { - return; - } - - $relationship = $this->getRootCondition(); - - // NOTE: this might bear problems when the definition will get serialized as the input value will not change. - if (Input::get('pid')) { - $parentValue = ModelId::fromSerialized(Input::get('pid'))->getId(); - } else { - $parentValue = '0'; - } - - if (!$relationship->getSetters()) { - $relationship - ->setSetters([['property' => 'pid', 'value' => $parentValue]]); - } - - $builder = FilterBuilder::fromArrayForRoot((array) $relationship->getFilterArray())->getFilter(); - - $builder->andPropertyEquals('pid', $parentValue); - - $relationship - ->setFilterArray($builder->getAllAsArray()); - - $setter = [['to_field' => 'pid', 'from_field' => 'id']]; - $inverse = []; - - /** @var ParentChildConditionInterface $relationship */ - $relationship = $this->definition->getChildCondition($this->container->getName(), $this->container->getName()); - if ($relationship === null) { - $relationship = new ParentChildCondition(); - $relationship - ->setSourceName($this->container->getName()) - ->setDestinationName($this->container->getName()); - $this->definition->addChildCondition($relationship); - } else { - $setter = array_merge_recursive($setter, $relationship->getSetters()); - $inverse = array_merge_recursive($inverse, $relationship->getInverseFilterArray()); - } - - // For tl_ prefix, the only unique target can be the id? - // maybe load parent dc and scan for unique in config then. - $relationship - ->setFilterArray( - FilterBuilder::fromArray($relationship->getFilterArray()) - ->getFilter() - ->andRemotePropertyEquals('pid', 'id') - ->getAllAsArray() - ) - ->setSetters($setter) - ->setInverseFilterArray($inverse); - } - - /** - * Parse the correct conditions for a MetaModel with variant support. + * Parse the root conditions for a MetaModel with hierarchical/variant support. * * @return RootConditionInterface */ - protected function getRootCondition() + protected function getRootCondition(): RootConditionInterface { $rootProvider = $this->container->getName(); diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php index d466a9847..efec3a79e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php @@ -14,6 +14,7 @@ * @author Christian Schiffler * @author Stefan Heimes * @author Sven Baumann + * @author Ingolf Steinhardt * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource @@ -21,12 +22,14 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\DefinitionBuilder; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\BasicDefinitionInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\ModelRelationship\FilterBuilder; use ContaoCommunityAlliance\DcGeneral\DataDefinition\ModelRelationship\ParentChildCondition; use ContaoCommunityAlliance\DcGeneral\DataDefinition\ModelRelationship\ParentChildConditionInterface; /** - * This class is the abstract base for the condition builders. + * This class is for the variant model condition builders. + * The variant model is a special form of the hierarchy model. */ class ConditionBuilderWithVariants extends AbstractConditionBuilder { @@ -35,10 +38,10 @@ class ConditionBuilderWithVariants extends AbstractConditionBuilder * * @return void */ - protected function calculate() + protected function calculate(): void { // Basic conditions. - $this->addHierarchicalConditions(); + $this->addVariantConditions(); $this->addParentCondition(); // Conditions for metamodels variants. @@ -49,7 +52,12 @@ protected function calculate() )); } - protected function addHierarchicalConditions() + /** + * Parse the correct conditions for a MetaModel with variant support. + * + * @return void + */ + protected function addVariantConditions(): void { // Not hierarchical? Get out. if ($this->container->getBasicDefinition()->getMode() !== BasicDefinitionInterface::MODE_HIERARCHICAL) { @@ -58,7 +66,7 @@ protected function addHierarchicalConditions() $relationship = $this->getRootCondition(); - $builder = FilterBuilder::fromArrayForRoot((array)$relationship->getFilterArray())->getFilter(); + $builder = FilterBuilder::fromArrayForRoot((array) $relationship->getFilterArray())->getFilter(); $builder->andPropertyEquals('varbase', 1); @@ -80,8 +88,8 @@ protected function addHierarchicalConditions() ->setDestinationName($this->container->getName()); $this->definition->addChildCondition($relationship); } else { - $setter = array_merge_recursive($setter, $relationship->getSetters()); - $inverse = array_merge_recursive($inverse, $relationship->getInverseFilterArray()); + $setter = \array_merge_recursive($setter, $relationship->getSetters()); + $inverse = \array_merge_recursive($inverse, $relationship->getInverseFilterArray()); } $relationship diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithoutVariants.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithoutVariants.php index d5b3696d4..bd6a9c56d 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithoutVariants.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithoutVariants.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,17 +13,23 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\DefinitionBuilder; +use Contao\Input; +use ContaoCommunityAlliance\DcGeneral\Data\ModelId; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\BasicDefinitionInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ModelRelationship\FilterBuilder; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ModelRelationship\ParentChildCondition; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ModelRelationship\ParentChildConditionInterface; /** - * This class is the abstract base for the condition builders. + * This class is for the hierarchical model condition builders. */ class ConditionBuilderWithoutVariants extends AbstractConditionBuilder { @@ -34,7 +40,7 @@ class ConditionBuilderWithoutVariants extends AbstractConditionBuilder * * @throws \RuntimeException When the conditions can not be determined yet. */ - protected function calculate() + protected function calculate(): void { if ($this->inputScreen['meta']['rendertype'] !== 'standalone') { if ($this->container->getBasicDefinition()->getMode() == BasicDefinitionInterface::MODE_HIERARCHICAL) { @@ -45,4 +51,66 @@ protected function calculate() $this->addHierarchicalConditions(); $this->addParentCondition(); } + + /** + * Parse the correct conditions for a MetaModel with hierarchical support. + * + * @return void + */ + protected function addHierarchicalConditions(): void + { + // Not hierarchical? Get out. + if ($this->container->getBasicDefinition()->getMode() !== BasicDefinitionInterface::MODE_HIERARCHICAL) { + return; + } + + $relationship = $this->getRootCondition(); + + // NOTE: this might bear problems when the definition will get serialized as the input value will not change. + if (Input::get('pid')) { + $parentValue = ModelId::fromSerialized(Input::get('pid'))->getId(); + } else { + $parentValue = '0'; + } + + if (!$relationship->getSetters()) { + $relationship + ->setSetters([['property' => 'pid', 'value' => $parentValue]]); + } + + $builder = FilterBuilder::fromArrayForRoot((array) $relationship->getFilterArray())->getFilter(); + + $builder->andPropertyEquals('pid', $parentValue); + + $relationship + ->setFilterArray($builder->getAllAsArray()); + + $setter = [['to_field' => 'pid', 'from_field' => 'id']]; + $inverse = []; + + /** @var ParentChildConditionInterface $relationship */ + $relationship = $this->definition->getChildCondition($this->container->getName(), $this->container->getName()); + if ($relationship === null) { + $relationship = new ParentChildCondition(); + $relationship + ->setSourceName($this->container->getName()) + ->setDestinationName($this->container->getName()); + $this->definition->addChildCondition($relationship); + } else { + $setter = \array_merge_recursive($setter, $relationship->getSetters()); + $inverse = \array_merge_recursive($inverse, $relationship->getInverseFilterArray()); + } + + // For tl_ prefix, the only unique target can be the id? + // maybe load parent dc and scan for unique in config then. + $relationship + ->setFilterArray( + FilterBuilder::fromArray($relationship->getFilterArray()) + ->getFilter() + ->andRemotePropertyEquals('pid', 'id') + ->getAllAsArray() + ) + ->setSetters($setter) + ->setInverseFilterArray($inverse); + } } diff --git a/src/DcGeneral/Data/FilterBuilder.php b/src/DcGeneral/Data/FilterBuilder.php index 2f4cce4d4..ef0f9cda4 100644 --- a/src/DcGeneral/Data/FilterBuilder.php +++ b/src/DcGeneral/Data/FilterBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author David Molineus * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -276,14 +276,13 @@ private function getFilterForLike($attribute, IFilter $filter, $operation) * Calculate a native SQL sub procedure. * * @param FilterBuilderSql $procedure The procedure to which to append to. - * * @param array $children The children to calculate. * * @return array */ - protected function buildNativeSqlProcedure(FilterBuilderSql $procedure, $children) + protected function buildNativeSqlProcedure(FilterBuilderSql $procedure, $children): array { - $skipped = array(); + $skipped = []; $metaModel = $this->getMetaModel(); $tableName = $metaModel->getTableName(); foreach ($children as $child) { @@ -296,7 +295,7 @@ protected function buildNativeSqlProcedure(FilterBuilderSql $procedure, $childre // Try to parse the sub procedure and extract as much as possible. if (('AND' === $child['operation']) || ('OR' === $child['operation'])) { - if (null === $child['children']) { + if (empty($child['children'])) { continue; } From 660b3da415185db205946842b7945ec6176a985f Mon Sep 17 00:00:00 2001 From: zonky Date: Wed, 26 Jul 2023 17:20:37 +0200 Subject: [PATCH 195/224] Change to contao framework --- .../Contao/InsertTag/ReplaceParam.php | 54 +++++++++++-------- .../Resources/config/insert-tags.yml | 4 +- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/CoreBundle/Contao/InsertTag/ReplaceParam.php b/src/CoreBundle/Contao/InsertTag/ReplaceParam.php index 333c511ad..8250df960 100644 --- a/src/CoreBundle/Contao/InsertTag/ReplaceParam.php +++ b/src/CoreBundle/Contao/InsertTag/ReplaceParam.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Oliver Hoff * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -27,8 +27,9 @@ namespace MetaModels\CoreBundle\Contao\InsertTag; use Contao\CoreBundle\Framework\Adapter; +use Contao\CoreBundle\Framework\ContaoFramework; use Contao\Input; -use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\RequestStack; /** * This replaces the insert tag param. @@ -36,29 +37,36 @@ final class ReplaceParam { /** - * The input. + * The input framework. * - * @var Input + * @var ContaoFramework */ - private $input; + private ContaoFramework $framework; /** - * The session. + * The adapter. * - * @var Session + * @var Adapter|null */ - private $session; + private ?Adapter $input = null; + + /** + * The request stack. + * + * @var RequestStack + */ + private RequestStack $requestStack; /** * ReplaceParam constructor. * - * @param Adapter $input The input. - * @param Session $session The session. + * @param ContaoFramework $framework The input framework. + * @param RequestStack $requestStack The session. */ - public function __construct(Adapter $input, Session $session) + public function __construct(ContaoFramework $framework, RequestStack $requestStack) { - $this->input = $input; - $this->session = $session; + $this->framework = $framework; + $this->requestStack = $requestStack; } /** @@ -71,7 +79,7 @@ public function __construct(Adapter $input, Session $session) */ public function replace(string $content): ?string { - if (false === \strpos($content, '{{') + if (!\str_contains($content, '{{') || !($tags = preg_split('@\{\{(.*)\}\}@', $content, -1, PREG_SPLIT_DELIM_CAPTURE)) || (\count($tags) < 2) ) { @@ -111,7 +119,11 @@ private function replaceInputParameter(array $chunks, ?string $content, string $ return $content; } - if ((false === \strpos($tag, '&default='))) { + if (null === $this->input) { + $this->input = $this->framework->getAdapter(Input::class); + } + + if ((!\str_contains($tag, '&default='))) { if (null === ($result = $this->input->{$arguments[0]}($arguments[1]))) { return null; } @@ -148,9 +160,9 @@ private function replaceSessionParameter(array $chunks, ?string $content, string return $content; } - $sessionBag = $this->session->getBag('contao_frontend'); + $sessionBag = $this->requestStack->getSession()->getBag('contao_frontend'); - if ((false === \strpos($tag, '&default='))) { + if ((!\str_contains($tag, '&default='))) { $result = $sessionBag->get($arguments[1]); return \str_replace( '{{' . $tag . '}}', @@ -177,12 +189,12 @@ private function replaceSessionParameter(array $chunks, ?string $content, string private function splitParameter(string $parameter): ?array { if ((2 !== \count($chunks = \explode('?', $parameter))) - || (0 !== \strpos($chunks[1], 'name=')) + || (!\str_starts_with($chunks[1], 'name=')) ) { return null; } - if (false === \strpos($chunks[1], '&default=')) { + if (!\str_contains($chunks[1], '&default=')) { return [$chunks[0], \substr($chunks[1], \strlen('name='))]; } @@ -205,7 +217,7 @@ private function isParameterSupported(string $parameter, array $supported): bool { $isSupported = false; foreach ($supported as $name) { - if (0 !== \strpos($parameter, $name)) { + if (!\str_starts_with($parameter, $name)) { continue; } diff --git a/src/CoreBundle/Resources/config/insert-tags.yml b/src/CoreBundle/Resources/config/insert-tags.yml index 0cf7ee155..785599cad 100644 --- a/src/CoreBundle/Resources/config/insert-tags.yml +++ b/src/CoreBundle/Resources/config/insert-tags.yml @@ -5,8 +5,8 @@ services: MetaModels\CoreBundle\Contao\InsertTag\ReplaceParam: public: false arguments: - - '@metamodels.contao_input' - - '@session' + - '@contao.framework' + - '@request_stack' MetaModels\CoreBundle\Contao\InsertTag\ResolveLanguageTag: public: false From 03d839591eeac597102928ce192c40aee5bbad1c Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 9 Aug 2023 21:10:51 +0200 Subject: [PATCH 196/224] Fix filter URL builder if option folderurl is set --- src/Filter/FilterUrlBuilder.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Filter/FilterUrlBuilder.php b/src/Filter/FilterUrlBuilder.php index 9d57937a4..d92069644 100644 --- a/src/Filter/FilterUrlBuilder.php +++ b/src/Filter/FilterUrlBuilder.php @@ -463,12 +463,18 @@ private function getPageCandidates(string $alias): ?array $aliases[] = $alias; } - // Check if there are pages with a matching alias - sort by priority desc and id asc. - $pages = - $this->pageModelAdapter->findByAliases($aliases, ['order' => 'tl_page.routePriority DESC, tl_page.id ASC']); + // Check if there are pages with a matching alias - sort by priority desc and alias* desc. + // *: You can assume that if folderurl is enabled, the lower hierarchy pages will have a + // longer alias string - hence descending sorting. + $pages = $this->pageModelAdapter->findByAliases( + $aliases, + ['order' => 'tl_page.routePriority DESC, tl_page.alias DESC'] + ); + if (null === $pages) { return null; } + $arrPages = []; // Order by domain and language. while ($pages->next()) { From b9539c0a611d4a392e3c084f61d7ae5fc6fdd5e6 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 5 Sep 2023 10:05:47 +0200 Subject: [PATCH 197/224] Fix routing at non-legacy-roting for sitemap.xml --- .../EventListener/GetSearchablePagesListener.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/CoreBundle/EventListener/GetSearchablePagesListener.php b/src/CoreBundle/EventListener/GetSearchablePagesListener.php index 68318087e..5eb018354 100644 --- a/src/CoreBundle/EventListener/GetSearchablePagesListener.php +++ b/src/CoreBundle/EventListener/GetSearchablePagesListener.php @@ -352,7 +352,13 @@ private function getBaseUrl(array $pageDetails, string $path = null): UrlBuilder // Get the path. if ($path === null) { - $event = new GenerateFrontendUrlEvent($pageDetails, null, $pageDetails['language'], true); + // Add dummy parameter, because non legacy mode parameter must not be null. + $event = new GenerateFrontendUrlEvent( + $pageDetails, + ($pageDetails['requireItem'] ?? false) ? '/foo/bar' : null, + $pageDetails['language'], + true + ); $this->dispatcher->dispatch($event, ContaoEvents::CONTROLLER_GENERATE_FRONTEND_URL); $url->setPath($event->getUrl()); } else { From 971f3b574ecb6abb92bdef41d309f6d3af91107b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 12 Oct 2023 15:12:20 +0200 Subject: [PATCH 198/224] Fix PHP8 warning --- .../Resources/contao/templates/mm_filter_default.html5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/Resources/contao/templates/mm_filter_default.html5 b/src/CoreBundle/Resources/contao/templates/mm_filter_default.html5 index 46cc1452e..ee4b43f42 100644 --- a/src/CoreBundle/Resources/contao/templates/mm_filter_default.html5 +++ b/src/CoreBundle/Resources/contao/templates/mm_filter_default.html5 @@ -10,7 +10,7 @@
    filters) ? $this->filters : []) as $filter): ?> -
    > +
    >
    From f22b0a31cd2935ad4a9394eb76308f9f63def84b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Fri, 27 Oct 2023 20:19:45 +0200 Subject: [PATCH 199/224] Fix for DCG --- .../DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php index 972fa7f3f..4a4612ee6 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php @@ -297,7 +297,7 @@ private function setFilterable(PropertyInterface $property, $propInfo) */ private function setWidgetType(PropertyInterface $property, $propInfo) { - if (null !== $property->getWidgetType() || !isset($propInfo['inputType'])) { + if ('' !== $property->getWidgetType() || !isset($propInfo['inputType'])) { return; } From 1a82398d84a28d43905d29ee41a7fc934d0b5606 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 31 Oct 2023 19:27:25 +0100 Subject: [PATCH 200/224] Fix for DCG --- .../DefinitionBuilder/PropertyDefinitionBuilder.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php index 972fa7f3f..96d84a712 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2021 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -297,7 +298,8 @@ private function setFilterable(PropertyInterface $property, $propInfo) */ private function setWidgetType(PropertyInterface $property, $propInfo) { - if (null !== $property->getWidgetType() || !isset($propInfo['inputType'])) { + // FIXME: String cast for old DCG. + if ('' !== ((string) $property->getWidgetType()) || !isset($propInfo['inputType'])) { return; } From 3e238c168d94d72f055ab1efe469a9122e3c8fb7 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 9 Nov 2023 08:42:10 +0100 Subject: [PATCH 201/224] Change to DCG 2.3 release --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 421ef6af7..fa3e59ff5 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "require": { "php": "^8.1", "ext-dom": "*", - "contao-community-alliance/dc-general": "^2.3@dev", + "contao-community-alliance/dc-general": "^2.3", "contao-community-alliance/events-contao-bindings": "^4.13", "contao-community-alliance/meta-palettes": "^2.0.10", "contao-community-alliance/translator": "^2.3", From 77a3c869c29cda02181582fdf9abf00344192d4b Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 15 Nov 2023 21:46:32 +0100 Subject: [PATCH 202/224] Fix to fast translated sorting --- src/Attribute/TranslatedReference.php | 65 +++++++++++---------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/src/Attribute/TranslatedReference.php b/src/Attribute/TranslatedReference.php index 79506e733..e576cdb62 100644 --- a/src/Attribute/TranslatedReference.php +++ b/src/Attribute/TranslatedReference.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author David Molineus * @author Andreas Fischer - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -27,6 +27,7 @@ namespace MetaModels\Attribute; use Contao\System; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\QueryBuilder; use MetaModels\Filter\Rules\SimpleQuery; @@ -298,42 +299,30 @@ public function searchForInLanguages($strPattern, $arrLanguages = array()) */ public function sortIds($idList, $strDirection) { - $langSet = sprintf( - '\'%s\',\'%s\'', - $this->getActiveLanguage(), - $this->getFallbackLanguage() - ); - - $statement = $this->connection - ->executeQuery( - sprintf( - 'SELECT t1.item_id - FROM %1$s AS t1 - INNER JOIN %1$s as t3 ON (t1.id = (SELECT - t2.id - FROM %1$s AS t2 - WHERE (t2.att_id=%2$s) - AND langcode IN (%3$s) - AND (t2.item_id=t1.item_id) - ORDER BY FIELD(t2.langcode,%3$s) - LIMIT 1 - )) - WHERE (t1.item_id IN (?)) - AND (t3.item_id IN (?)) - GROUP BY t1.id - ORDER BY t1.value %4$s', - // @codingStandardsIgnoreStart - we want to keep the numbers at the end of the lines below. - $this->getValueTable(), // 1 - $this->get('id'), // 2 - $langSet, // 3 - $strDirection // 4 - // @codingStandardsIgnoreEnd - ), - [$idList, $idList], - [Connection::PARAM_STR_ARRAY, Connection::PARAM_STR_ARRAY] - ); - - return $statement->fetchFirstColumn(); + $builder = $this->connection->createQueryBuilder(); + $expr = $builder->expr(); + $builder + ->select('IF(t2.item_id IS NOT NULL, t2.item_id, t1.item_id)') + ->from($this->getValueTable(), 't1') + ->leftJoin( + 't1', + $this->getValueTable(), + 't2', + $expr + ->andX() + ->add($expr->eq('t1.att_id', 't2.att_id')) + ->add($expr->eq('t1.item_id', 't2.item_id')) + ->add($expr->eq('t2.langcode', ':langcode')) + ) + ->where($expr->eq('t1.att_id', ':att_id')) + ->andWhere($expr->in('t1.item_id', ':id_list')) + ->andWhere($expr->in('t1.langcode', ':langfallbackcode')) + ->setParameter('langcode', $this->getActiveLanguage()) + ->setParameter('langfallbackcode', $this->getFallbackLanguage()) + ->setParameter('att_id', $this->get('id')) + ->setParameter('id_list', \array_unique($idList), ArrayParameterType::STRING); + + return $builder->executeQuery()->fetchFirstColumn(); } /** From cc79d3ec0d3548a29668931aba4f9b5541bd26ae Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 16 Nov 2023 11:59:08 +0100 Subject: [PATCH 203/224] Fix to fast translated sorting --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 421ef6af7..b1eba7317 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ "contao/core-bundle": "^4.13.5, <5.0", "discordier/justtextwidgets": "^1.3", "doctrine/cache": "^2.1", - "doctrine/dbal": "^3.3.2", + "doctrine/dbal": "^3.6.0", "menatwork/contao-multicolumnwizard-bundle": "^3.5.7", "symfony/asset": "^5.4", "symfony/cache": "^5.4", From 1282c1c552433bd0a6e0191cf9580d42d259b111 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 20 Nov 2023 17:25:10 +0100 Subject: [PATCH 204/224] Add missing labels and move field "move" --- .../Resources/contao/dca/tl_metamodel.php | 14 ++++++-------- .../Resources/contao/languages/en/tl_metamodel.php | 2 ++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel.php index 62cb7be25..f614c9921 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel.php @@ -406,12 +406,13 @@ ], ], 'fields' => [ - 'id' => - [ - 'sql' => 'int(10) unsigned NOT NULL auto_increment' - ], + 'id' => [ + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['id'], + 'sql' => 'int(10) unsigned NOT NULL auto_increment' + ], 'tstamp' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['tstamp'], + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['sorting'], @@ -450,9 +451,6 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'mode' => [ - 'sql' => "int(1) unsigned NOT NULL default '1'" - ], 'translated' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['translated'], 'exclude' => true, diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php index 90d2ceff4..68f0edf53 100644 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php @@ -21,6 +21,8 @@ * @filesource */ +$GLOBALS['TL_LANG']['tl_metamodel']['id'][0] = 'Id'; +$GLOBALS['TL_LANG']['tl_metamodel']['id'][1] = 'Id of the MetaModel'; $GLOBALS['TL_LANG']['tl_metamodel']['name'][0] = 'Name'; $GLOBALS['TL_LANG']['tl_metamodel']['name'][1] = 'MetaModel name.'; $GLOBALS['TL_LANG']['tl_metamodel']['tstamp'][0] = 'Revision date'; From 181813e4a431bc423adcf2ea21d32b46d36929a3 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Wed, 22 Nov 2023 20:07:05 +0100 Subject: [PATCH 205/224] Fix aggregate at custom SQL --- .../Resources/contao/dca/tl_metamodel_dca.php | 4 +- src/Filter/Setting/CustomSql.php | 43 ++++++++++--------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php index 9b0e940e2..73b0bda1b 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php @@ -327,8 +327,8 @@ 'inputType' => 'select', 'options' => $this->getLanguages(), 'eval' => [ - 'tl_class' => 'clr', - 'style' => 'width:100%', + 'tl_class' => '', + 'style' => 'width:400px', 'chosen' => 'true' ] ], diff --git a/src/Filter/Setting/CustomSql.php b/src/Filter/Setting/CustomSql.php index d81693af1..ee9c9969a 100644 --- a/src/Filter/Setting/CustomSql.php +++ b/src/Filter/Setting/CustomSql.php @@ -52,42 +52,42 @@ class CustomSql implements ISimple, ServiceSubscriberInterface * * @var ICollection */ - private $collection = null; + private ?ICollection $collection = null; /** * The attributes of this filter setting. * * @var array */ - private $data = []; + private array $data = []; /** * The filter params (should be an array or null). * * @var array */ - private $filterParameters; + private array $filterParameters; /** * The query string. * * @var string */ - private $queryString; + private string $queryString; /** * The query parameters. * * @var array */ - private $queryParameter; + private array $queryParameter; /** * The service container. * * @var ContainerInterface */ - private $container; + private ContainerInterface $container; /** * Constructor - initialize the object and store the parameters. @@ -174,9 +174,9 @@ public function getParameters() { $arrParams = []; - preg_match_all('@\{\{param::filter\?([^}]*)\}\}@', $this->get('customsql'), $arrMatches); + \preg_match_all('@\{\{param::filter\?([^}]*)\}\}@', $this->get('customsql'), $arrMatches); foreach ($arrMatches[1] as $strQuery) { - parse_str($strQuery, $arrArgs); + \parse_str($strQuery, $arrArgs); if (isset($arrArgs['name'])) { $arrName = (array) $arrArgs['name']; $arrParams[] = $arrName[0]; @@ -263,7 +263,7 @@ private function addParameters(array $parameters) return; } - $this->queryParameter = array_merge($this->queryParameter, $parameters); + $this->queryParameter = \array_merge($this->queryParameter, $parameters); } /** @@ -307,8 +307,8 @@ private function getValueFromServiceContainer(string $valueName, array $argument } $service = $this->container->get(IMetaModelsServiceContainer::class)->getService($serviceName); - if (is_callable($service)) { - return call_user_func($service, $valueName, $arguments); + if (\is_callable($service)) { + return \call_user_func($service, $valueName, $arguments); } return 'NULL'; @@ -328,7 +328,7 @@ private function getValueFromServiceContainer(string $valueName, array $argument */ private function getValueFromSource(string $source, string $valueName, array $arguments) { - switch (strtolower($source)) { + switch (\strtolower($source)) { case 'get': case 'post': case 'cookie': @@ -336,7 +336,7 @@ private function getValueFromSource(string $source, string $valueName, array $ar return $this->executeInsertTagReplaceParam($source, $arguments); case 'filter': - if (is_array($this->filterParameters)) { + if (\is_array($this->filterParameters)) { if (\array_key_exists($valueName, $this->filterParameters)) { return $this->filterParameters[$valueName]; } @@ -392,7 +392,6 @@ function ($carry, $item) use ($filteredArguments) { * Convert a parameter using an aggregate function. * * @param array $var The parameter value. - * * @param array $arguments The arguments of the parameter. * * @return string @@ -413,6 +412,10 @@ private function convertParameterAggregate(array $var, array $arguments) return 'NULL'; } + if ($arguments['aggregate'] === 'list') { + $var = \array_merge(...\array_map(static fn ($value) => \explode(',', $value), $var)); + } + if (!empty($arguments['key'])) { $var = \array_keys($var); } else { @@ -420,7 +423,7 @@ private function convertParameterAggregate(array $var, array $arguments) $var = \array_values($var); } - if ($arguments['aggregate'] == 'set') { + if (!\in_array($arguments['aggregate'], ['set', 'list'], true)) { $this->addParameter(implode(',', $var)); return '?'; @@ -440,15 +443,15 @@ private function convertParameterAggregate(array $var, array $arguments) */ private function convertParameter(string $strMatch): string { - list($strSource, $strQuery) = explode('?', $strMatch, 2); - parse_str($strQuery, $arrArgs); + list($strSource, $strQuery) = \explode('?', $strMatch, 2); + \parse_str($strQuery, $arrArgs); $arrName = (array) $arrArgs['name']; - $var = $this->getValueFromSource($strSource, array_shift($arrName), $arrArgs); + $var = $this->getValueFromSource($strSource, \array_shift($arrName), $arrArgs); $index = 0; - $count = count($arrName); - while ($index < $count && is_array($var)) { + $count = \count($arrName); + while ($index < $count && \is_array($var)) { $var = $var[$arrName[$index++]]; } From 0659f47bc89b703172e497bb1fa407fea44613f9 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 27 Nov 2023 16:14:43 +0100 Subject: [PATCH 206/224] Add workaround for special key 'language' in filter url. --- src/Filter/Setting/SimpleLookup.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Filter/Setting/SimpleLookup.php b/src/Filter/Setting/SimpleLookup.php index e27b5ac3e..203ac3fe3 100644 --- a/src/Filter/Setting/SimpleLookup.php +++ b/src/Filter/Setting/SimpleLookup.php @@ -51,7 +51,13 @@ protected function getParamName() $objAttribute = $this->getFilteredAttribute(); if ($objAttribute) { - return $objAttribute->getColName(); + $paramName = $objAttribute->getColName(); + // Work around #1505. + if ($paramName === 'language') { + $paramName .= '__'; + } + + return $paramName; } return null; From 4f076e93d0d6fa5097ffe57813c3561c84c07de0 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Mon, 27 Nov 2023 17:20:48 +0100 Subject: [PATCH 207/224] Add workaround for special key 'language' and 'items' in filter url. --- src/Filter/Setting/SimpleLookup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Filter/Setting/SimpleLookup.php b/src/Filter/Setting/SimpleLookup.php index 203ac3fe3..93a9f7f4a 100644 --- a/src/Filter/Setting/SimpleLookup.php +++ b/src/Filter/Setting/SimpleLookup.php @@ -53,7 +53,7 @@ protected function getParamName() if ($objAttribute) { $paramName = $objAttribute->getColName(); // Work around #1505. - if ($paramName === 'language') { + if (\in_array($paramName, ['language', 'items'], true)) { $paramName .= '__'; } From 07dadd7d78b166d277a7f9afbb6f7bc247b7665a Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 15 Jan 2024 22:40:57 +0100 Subject: [PATCH 208/224] Fix labels --- .../Resources/contao/dca/tl_metamodel.php | 18 +++++++++--------- .../contao/dca/tl_metamodel_attribute.php | 14 +++++++++----- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel.php index f614c9921..99ffe2c3f 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel.php @@ -406,21 +406,21 @@ ], ], 'fields' => [ - 'id' => [ + 'id' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['id'], 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], - 'tstamp' => [ + 'tstamp' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['tstamp'], 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'sorting' => [ + 'sorting' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['sorting'], 'sorting' => true, 'flag' => 11, 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'name' => [ + 'name' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['name'], 'sorting' => true, 'flag' => 3, @@ -435,7 +435,7 @@ ], 'sql' => "varchar(255) NOT NULL default ''" ], - 'tableName' => [ + 'tableName' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['tableName'], 'sorting' => true, 'exclude' => true, @@ -451,7 +451,7 @@ ], 'sql' => "varchar(64) NOT NULL default ''" ], - 'translated' => [ + 'translated' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['translated'], 'exclude' => true, 'inputType' => 'checkbox', @@ -461,7 +461,7 @@ ], 'sql' => "char(1) NOT NULL default ''" ], - 'languages' => [ + 'languages' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['languages'], 'exclude' => true, 'inputType' => 'multiColumnWizard', @@ -490,12 +490,12 @@ ], 'sql' => 'text NULL' ], - 'varsupport' => [ + 'varsupport' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['varsupport'], 'exclude' => true, 'inputType' => 'checkbox', 'eval' => [ - 'tl_class' => 'clr w50' + 'tl_class' => 'clr w50' ], 'sql' => "char(1) NOT NULL default ''" ], diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php index 9297eb29a..a75add074 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -249,17 +249,21 @@ // Fields. 'fields' => [ 'id' => [ - 'sql' => 'int(10) unsigned NOT NULL auto_increment' + 'label' => 'id.0', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'pid.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ + 'label' => 'sorting.0', 'sorting' => true, 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'tstamp.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'type' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['type'], From 312983b5a83aa48d37f1eb504f7067bef9fc8fbc Mon Sep 17 00:00:00 2001 From: e-spin Date: Mon, 15 Jan 2024 22:59:48 +0100 Subject: [PATCH 209/224] Fix labels --- .../Resources/contao/dca/tl_content.php | 8 +- .../Resources/contao/dca/tl_metamodel_dca.php | 12 +- .../contao/dca/tl_metamodel_dca_combine.php | 8 +- .../contao/dca/tl_metamodel_dca_sortgroup.php | 31 +- .../contao/dca/tl_metamodel_dcasetting.php | 20 +- .../dca/tl_metamodel_dcasetting_condition.php | 16 +- .../contao/dca/tl_metamodel_filter.php | 13 +- .../contao/dca/tl_metamodel_filtersetting.php | 14 +- .../contao/dca/tl_metamodel_item.php | 8 +- .../contao/dca/tl_metamodel_rendersetting.php | 296 ++++++++---------- .../dca/tl_metamodel_rendersettings.php | 7 +- .../dca/tl_metamodel_searchable_pages.php | 18 +- .../Resources/contao/dca/tl_module.php | 8 +- 13 files changed, 221 insertions(+), 238 deletions(-) diff --git a/src/CoreBundle/Resources/contao/dca/tl_content.php b/src/CoreBundle/Resources/contao/dca/tl_content.php index 96541a033..84dea8ed5 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_content.php +++ b/src/CoreBundle/Resources/contao/dca/tl_content.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Ingolf Steinhardt * @author Richard Henkenjohann * @author Sven Baumann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -64,7 +64,7 @@ $GLOBALS['TL_DCA']['tl_content']['palettes']['__selector__'][] = 'metamodel_use_parameters'; // Insert new Subpalettes after position 1. -array_insert( +\array_insert( $GLOBALS['TL_DCA']['tl_content']['subpalettes'], 1, [ @@ -75,7 +75,7 @@ ); // Fields. -array_insert( +\array_insert( $GLOBALS['TL_DCA']['tl_content']['fields'], 1, [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php index 73b0bda1b..e212c9a16 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php @@ -223,16 +223,20 @@ ], 'fields' => [ 'id' => [ - 'sql' => 'int(10) unsigned NOT NULL auto_increment' + 'label' => 'id.0', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'pid.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'sorting.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'tstamp.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'name' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['name'], diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php index 78fc38153..ca4cac19c 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -75,15 +75,19 @@ ], 'fields' => [ 'id' => [ + 'label' => 'id.0', 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ + 'label' => 'pid.0', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ + 'label' => 'sorting.0', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ + 'label' => 'tstamp.0', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'rows' => [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php index 741f05d95..a62c732c3 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php @@ -73,16 +73,16 @@ ] ], [ - 'from' => 'tl_metamodel', - 'to' => 'tl_metamodel_dca', - 'setOn' => + 'from' => 'tl_metamodel', + 'to' => 'tl_metamodel_dca', + 'setOn' => [ [ 'to_field' => 'pid', 'from_field' => 'id', ], ], - 'filter' => [ + 'filter' => [ [ 'local' => 'pid', 'remote' => 'id', @@ -179,17 +179,20 @@ ], 'fields' => [ 'id' => [ - 'sql' => 'int(10) unsigned NOT NULL auto_increment' + 'label' => 'id.0', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'pid.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" + ], + 'sorting' => [ + 'label' => 'sorting.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'sorting' => - [ - 'sql' => "int(10) unsigned NOT NULL default '0'" - ], 'tstamp' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'tstamp.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'name' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['name'], @@ -261,8 +264,8 @@ 'exclude' => true, 'inputType' => 'select', 'eval' => [ - 'tl_class' => 'w50', - 'chosen' => true + 'tl_class' => 'w50', + 'chosen' => true ], 'sql' => "int(10) unsigned NOT NULL default '0'" ], @@ -276,7 +279,7 @@ ], 'sql' => "int(10) unsigned NOT NULL default '1'" ], - 'published' => [ + 'published' => [ 'default' => 1, 'sql' => "char(1) NOT NULL default '1'" ] diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php index 37f818630..54d654468 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,7 +21,7 @@ * @author Cliff Parnitzky * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -40,7 +40,7 @@ ], 'dca_config' => [ 'data_provider' => [ - 'root' => [ + 'root' => [ 'source' => 'tl_metamodel_dcasetting' ], 'parent' => [ @@ -246,16 +246,20 @@ ], 'fields' => [ 'id' => [ - 'sql' => 'int(10) unsigned NOT NULL auto_increment' + 'label' => 'id.0', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'pid.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'sorting.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'tstamp.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'published' => [ 'default' => 1, @@ -300,7 +304,7 @@ 'explanation' => 'tl_class', 'sql' => ['type' => 'string', 'length' => 64, 'default' => 'w50'] ], - 'be_template' => [ + 'be_template' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['be_template'], 'exclude' => true, 'inputType' => 'select', diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php index 882e9390d..ba57b1c59 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Ingolf Steinhardt * @author Richard Henkenjohann * @author Sven Baumann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -235,16 +235,20 @@ ], 'fields' => [ 'id' => [ - 'sql' => 'int(10) unsigned NOT NULL auto_increment' + 'label' => 'id.0', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'pid.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'sorting.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'tstamp.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'settingId' => [ // Keep this empty but keep it here! diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php index 87f612452..4583933bf 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Richard Henkenjohann * @author Cliff Parnitzky * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -166,13 +166,16 @@ 'fields' => [ 'id' => [ - 'sql' => 'int(10) unsigned NOT NULL auto_increment' + 'label' => 'id.0', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'pid.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'tstamp.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'name' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['name'], diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php index 96b10f26c..411c92156 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -20,7 +20,7 @@ * @author Ingolf Steinhardt * @author Richard Henkenjohann * @author Sven Baumann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -255,17 +255,21 @@ ], 'fields' => [ 'id' => [ - 'sql' => 'int(10) unsigned NOT NULL auto_increment' + 'label' => 'id.0', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'pid.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ + 'label' => 'sorting.0', 'sorting' => true, 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'tstamp.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'fid' => [ // Keep this empty but keep it here! diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php index ebb94f70c..8354e1e4b 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Stefan Heimes * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -39,7 +39,7 @@ ] ], ], - 'list' => [ + 'list' => [ 'sorting' => [ // This means: 1 default sorting value, 2 switchable sorting value. 'mode' => 1, @@ -54,7 +54,7 @@ 'format' => '%s', ], ], - 'fields' => [ + 'fields' => [ 'id' => [ 'label' => 'id.0', ], diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php index b79fb1604..1aa22e2ea 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -20,163 +20,129 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author David Molineus - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -$GLOBALS['TL_DCA']['tl_metamodel_rendersetting'] = array -( - 'config' => array - ( +$GLOBALS['TL_DCA']['tl_metamodel_rendersetting'] = [ + 'config' => [ 'dataContainer' => 'General', 'ptable' => 'tl_metamodel_rendersettings', 'switchToEdit' => true, 'enableVersioning' => false, - 'sql' => array - ( - 'keys' => array - ( + 'sql' => [ + 'keys' => [ 'id' => 'primary', 'pid' => 'index' - ), - ) - ), - 'dca_config' => array - ( - 'data_provider' => array - ( - 'default' => array - ( + ], + ] + ], + 'dca_config' => [ + 'data_provider' => [ + 'default' => [ 'source' => 'tl_metamodel_rendersetting' - ), - 'parent' => array - ( + ], + 'parent' => [ 'source' => 'tl_metamodel_rendersettings' - ), - 'tl_metamodel' => array - ( + ], + 'tl_metamodel' => [ 'source' => 'tl_metamodel' - ) - ), - 'childCondition' => array - ( - array( - 'from' => 'tl_metamodel_rendersettings', - 'to' => 'tl_metamodel_rendersetting', - 'setOn' => array - ( - array - ( + ] + ], + 'childCondition' => [ + [ + 'from' => 'tl_metamodel_rendersettings', + 'to' => 'tl_metamodel_rendersetting', + 'setOn' => [ + [ 'to_field' => 'pid', 'from_field' => 'id', - ), - ), - 'filter' => array - ( - array - ( + ], + ], + 'filter' => [ + [ 'local' => 'pid', 'remote' => 'id', 'operation' => '=', - ), - ), - 'inverse' => array - ( - array - ( + ], + ], + 'inverse' => [ + [ 'local' => 'pid', 'remote' => 'id', 'operation' => '=', - ), - ) - ), - array( + ], + ] + ], + [ 'from' => 'tl_metamodel', 'to' => 'tl_metamodel_rendersettings', - 'setOn' => array - ( - array - ( + 'setOn' => [ + [ 'to_field' => 'pid', 'from_field' => 'id', - ), - ), - 'filter' => array - ( - array - ( + ], + ], + 'filter' => [ + [ 'local' => 'pid', 'remote' => 'id', 'operation' => '=', - ), - ), - 'inverse' => array - ( - array - ( + ], + ], + 'inverse' => [ + [ 'local' => 'pid', 'remote' => 'id', 'operation' => '=', - ), - ) - ) - ), - 'child_list' => array - ( - 'tl_metamodel_rendersetting' => array - ( - 'fields' => array - ( + ], + ] + ] + ], + 'child_list' => [ + 'tl_metamodel_rendersetting' => [ + 'fields' => [ 'type', 'attr_id', 'urlparam', 'comment' - ), + ], 'format' => '%s %s', - ), - ), - ), - 'list' => array - ( - 'sorting' => array - ( + ], + ], + ], + 'list' => [ + 'sorting' => [ 'mode' => 4, - 'fields' => array('sorting'), + 'fields' => ['sorting'], 'panelLayout' => 'limit', - 'headerFields' => array('name'), - ), - 'global_operations' => array - ( - 'addall' => array - ( + 'headerFields' => ['name'], + ], + 'global_operations' => [ + 'addall' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall'], 'class' => 'header_add_all rendersetting_add_all', 'attributes' => 'onclick="Backend.getScrollOffset();"' - ), - 'all' => array - ( + ], + 'all' => [ 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], 'href' => 'act=select', 'class' => 'header_edit_all', 'attributes' => 'onclick="Backend.getScrollOffset();"' - ) - ), - 'operations' => array - ( - 'edit' => array - ( + ] + ], + 'operations' => [ + 'edit' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit'], 'href' => 'act=edit', 'icon' => 'edit.svg' - ), - 'cut' => array - ( + ], + 'cut' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['cut'], 'icon' => 'cut.svg' - ), - 'delete' => array - ( + ], + 'delete' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['delete'], 'href' => 'act=delete', 'icon' => 'delete.svg', @@ -184,65 +150,56 @@ 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['deleteConfirm'] ?? '' ) - ), - 'show' => array - ( + ], + 'show' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['show'], 'href' => 'act=show', 'icon' => 'show.svg' - ), - 'toggle' => array - ( + ], + 'toggle' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle'], 'icon' => 'visible.svg', 'toggleProperty' => 'enabled', - ) - ) - ), - 'palettes' => array - ( - '__selector__' => array - ( + ] + ] + ], + 'palettes' => [ + '__selector__' => [ 'attr_id' - ) - ), - 'metapalettes' => array - ( - 'default' => array - ( - 'title' => array - ( + ] + ], + 'metapalettes' => [ + 'default' => [ + 'title' => [ 'attr_id', 'template', 'additional_class' - ) - ), - ), + ] + ], + ], // Fields. - 'fields' => array - ( - 'id' => array - ( - 'sql' => 'int(10) unsigned NOT NULL auto_increment' - ), - 'pid' => array - ( - 'sql' => "int(10) unsigned NOT NULL default '0'" - ), - 'sorting' => array - ( - 'sql' => "int(10) unsigned NOT NULL default '0'" - ), - 'tstamp' => array - ( - 'sql' => "int(10) unsigned NOT NULL default '0'" - ), - 'attr_id' => array - ( + 'fields' => [ + 'id' => [ + 'label' => 'id.0', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' + ], + 'pid' => [ + 'label' => 'pid.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" + ], + 'sorting' => [ + 'label' => 'sorting.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" + ], + 'tstamp' => [ + 'label' => 'tstamp.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" + ], + 'attr_id' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id'], 'exclude' => true, 'inputType' => 'select', - 'eval' => array( + 'eval' => [ 'doNotSaveEmpty' => true, 'alwaysSave' => true, 'submitOnChange' => true, @@ -250,38 +207,33 @@ 'mandatory' => true, 'chosen' => true, 'tl_class' => 'w50' - ), + ], 'sql' => "int(10) unsigned NOT NULL default '0'" - ), - 'template' => array - ( + ], + 'template' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template'], 'exclude' => true, 'inputType' => 'select', - 'eval' => array - ( + 'eval' => [ 'tl_class' => 'w50', 'chosen' => true, 'includeBlankOption' => true, - ), + ], 'sql' => "varchar(64) NOT NULL default ''" - ), - 'additional_class' => array - ( + ], + 'additional_class' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['additional_class'], 'exclude' => true, 'inputType' => 'text', - 'eval' => array - ( + 'eval' => [ 'tl_class' => 'w50', 'maxlength' => 64, - ), + ], 'sql' => "varchar(64) NOT NULL default ''" - ), - 'enabled' => array - ( + ], + 'enabled' => [ 'default' => 1, 'sql' => "char(1) NOT NULL default ''" - ) - ) -); + ] + ] +]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php index 19efc4225..3b4618a4b 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,7 +21,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Cliff Parnitzky - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -189,12 +189,15 @@ ], 'fields' => [ 'id' => [ + 'label' => 'id.0', 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ + 'label' => 'pid.0', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ + 'label' => 'tstamp.0', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'name' => [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php index ca176d2ed..d4a5ea3d9 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Richard Henkenjohann * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -139,14 +139,16 @@ ], 'fields' => [ 'id' => [ - 'sql' => 'int(10) unsigned NOT NULL auto_increment' + 'label' => 'id.0', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' + ], + 'pid' => [ + 'label' => 'pid.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], - 'pid' => - [ - 'sql' => "int(10) unsigned NOT NULL default '0'" - ], 'tstamp' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'tstamp.0', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'name' => [ 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['name'], diff --git a/src/CoreBundle/Resources/contao/dca/tl_module.php b/src/CoreBundle/Resources/contao/dca/tl_module.php index 7ecff74a8..c882f7a77 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_module.php +++ b/src/CoreBundle/Resources/contao/dca/tl_module.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-20243 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -60,7 +60,7 @@ $GLOBALS['TL_DCA']['tl_module']['palettes']['__selector__'][] = 'metamodel_use_parameters'; // Insert new Subpalettes after position 1. -array_insert( +\array_insert( $GLOBALS['TL_DCA']['tl_module']['subpalettes'], 1, [ @@ -71,7 +71,7 @@ ); // Fields. -array_insert( +\array_insert( $GLOBALS['TL_DCA']['tl_module']['fields'], 1, [ From 908216c19cfd89c64685fce015a227e70726dc04 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Thu, 4 Apr 2024 10:54:38 +0000 Subject: [PATCH 210/224] Fix any errors and warnings from PHPCQ2 --- .composer-require-checker.json | 12 + .github/workflows/diagnostics.yml | 66 ++-- .gitignore | 7 +- .phpcq.lock | 1 + .phpcq.yaml.dist | 111 ++++++ .phpmd.xml | 37 ++ README.md | 78 +++-- build.default.properties | 24 -- build.xml | 12 - composer.json | 53 +-- psalm.xml | 35 ++ .../AbstractAttributeTypeFactory.php | 21 +- src/Attribute/AttributeFactory.php | 45 ++- src/Attribute/Base.php | 125 +++---- src/Attribute/BaseSimple.php | 102 ++++-- ...lectMetaModelAttributeInformationEvent.php | 224 ++++++------- src/Attribute/Events/CreateAttributeEvent.php | 11 +- src/Attribute/IAttribute.php | 57 ++-- src/Attribute/IAttributeFactory.php | 26 +- src/Attribute/IComplex.php | 13 +- src/Attribute/ISimple.php | 2 +- src/Attribute/ITranslated.php | 33 +- src/Attribute/ManagedAttributeTrait.php | 18 +- src/Attribute/TranslatedReference.php | 220 ++++++------ .../InputScreen/IInputScreen.php | 15 +- .../InputScreen/InputScreen.php | 133 ++++---- .../InputScreenGroupingAndSorting.php | 22 +- src/BackendIntegration/Module.php | 22 +- src/BackendIntegration/PurgeAssets.php | 11 +- src/BackendIntegration/PurgeCache.php | 2 +- src/BackendIntegration/ViewCombinations.php | 31 +- src/CoreBundle/Assets/IconBuilder.php | 42 ++- .../Command/SchemaValidatorCommand.php | 8 +- .../Contao/Compat/ContaoFactory.php | 13 +- ...bstractContentElementAndModuleCallback.php | 102 ++++-- .../Contao/Hooks/ContentElementCallback.php | 8 +- .../Contao/Hooks/FixupUserGroupModules.php | 40 ++- .../Contao/Hooks/LoadDataContainer.php | 110 +++--- .../Contao/Hooks/ModuleCallback.php | 15 +- .../Contao/InsertTag/ReplaceParam.php | 63 ++-- .../Contao/InsertTag/ResolveLanguageTag.php | 6 +- src/CoreBundle/ContaoManager/Plugin.php | 8 +- .../Backend/AbstractAddAllController.php | 73 ++-- .../Backend/InputScreenAddAllController.php | 18 +- .../Backend/RenderSettingAddAllController.php | 2 +- .../ContentElement/ItemListController.php | 5 +- .../FrontendModule/ItemListController.php | 11 +- .../Controller/ListControllerTrait.php | 92 +++-- .../AbstractAttributeConditionFactory.php | 7 +- ...actRestrictedAttributeConditionFactory.php | 1 + .../FallbackPropertyConditionFactory.php | 9 +- .../DcGeneral/PropertyConditionFactory.php | 19 +- .../CollectDoctrineSchemaGeneratorsPass.php | 2 +- .../CompilerPass/CollectFactoriesPass.php | 23 +- .../CollectSchemaGeneratorsPass.php | 2 +- .../CollectSchemaManagersPass.php | 2 +- .../DependencyInjection/Configuration.php | 18 +- .../IdProvidingServiceLocator.php | 2 +- .../MetaModelsCoreExtension.php | 25 +- .../EventListener/AttributeAddingListener.php | 7 +- .../BackendNavigationListener.php | 38 ++- .../Breadcrumb/AbstractBreadcrumbListener.php | 23 +- .../BreadcrumbAttributeListener.php | 21 +- .../BreadcrumbDcaCombineListener.php | 21 +- .../Breadcrumb/BreadcrumbDcaListener.php | 23 +- .../BreadcrumbDcaSettingConditionListener.php | 26 +- .../BreadcrumbDcaSettingListener.php | 23 +- .../BreadcrumbDcaSortGroupListener.php | 21 +- .../Breadcrumb/BreadcrumbFilterListener.php | 23 +- .../BreadcrumbFilterSettingListener.php | 26 +- .../BreadcrumbMetaModelListener.php | 13 +- .../BreadcrumbRenderSettingListener.php | 24 +- .../BreadcrumbRenderSettingsListener.php | 26 +- .../BreadcrumbSearchablePagesListener.php | 23 +- .../Breadcrumb/GetMetaModelTrait.php | 20 +- .../AbstractConditionBuilder.php | 27 +- .../BasicDefinitionBuilder.php | 14 +- .../DefinitionBuilder/CommandBuilder.php | 66 ++-- .../ConditionBuilderWithVariants.php | 5 +- .../ConditionBuilderWithoutVariants.php | 5 +- .../Contao2BackendViewDefinitionBuilder.php | 69 ++-- .../DefinitionBuilder/DataProviderBuilder.php | 11 +- .../MetaModelDefinitionBuilder.php | 9 +- .../DefinitionBuilder/PaletteBuilder.php | 31 +- .../DefinitionBuilder/PanelBuilder.php | 41 +-- .../PropertyDefinitionBuilder.php | 62 ++-- .../EnvironmentPopulator/AssetPopulator.php | 1 + .../AttributePopulator.php | 16 +- .../DataProviderPopulator.php | 30 +- .../TranslatorPopulator.php | 31 +- .../DcGeneral/ItemRendererListener.php | 56 ++-- .../MetaModel/CreateVariantButtonListener.php | 93 ++++-- .../DcGeneral/MetaModel/CutButtonListener.php | 9 +- .../MetaModel/PasteButtonListener.php | 179 +++++----- .../AbstractPaletteRestrictionListener.php | 4 +- .../Attribute/AttributeCreateListener.php | 17 +- .../Attribute/AttributeRendererListener.php | 31 +- .../Table/Attribute/BaseListener.php | 16 +- .../Attribute/ColNameValidationListener.php | 7 +- .../Attribute/GetAttributeTypeListener.php | 26 +- .../Dca/BackendSectionOptionListener.php | 17 +- .../Table/Dca/ParentTableOptionListener.php | 24 +- .../Dca/ParentTableVisibilityListener.php | 15 +- .../Table/Dca/RenderModeHintListener.php | 13 +- .../Table/Dca/RenderModeOptionListener.php | 20 +- .../Table/Dca/RenderTypeOptionListener.php | 15 +- .../Table/DcaCombine/FixSortingListener.php | 19 +- .../DcaCombine/FixTypeSafetyListener.php | 31 +- .../Table/DcaCombine/GroupOptionListener.php | 22 +- .../DcaCombine/InputScreenOptionListener.php | 16 +- .../RenderSettingOptionListener.php | 16 +- .../DcaSetting/AbstractAbstainingListener.php | 16 +- .../Table/DcaSetting/AbstractListener.php | 14 +- .../Table/DcaSetting/AddAllButtonListener.php | 32 +- .../DcaSetting/AttributeOptionListener.php | 10 +- .../DcaSetting/DisableMandatoryListener.php | 19 +- .../DcaSetting/DisableReadOnlyListener.php | 26 +- .../EditMaskSubHeadlineListener.php | 30 +- .../Table/DcaSetting/LegendTitleListener.php | 22 +- .../DcaSetting/ManipulateWidgetListener.php | 17 +- .../Table/DcaSetting/ModelToLabelListener.php | 32 +- .../RemoveOverrideButtonListener.php | 17 +- .../SetVisibilityConditionIconListener.php | 45 ++- .../DcaSetting/TemplateOptionListener.php | 7 +- .../DcaSettingCondition/AbstractListener.php | 37 +- .../AttributeIdListener.php | 34 +- .../ModelToLabelListener.php | 21 +- .../PasteButtonListener.php | 34 +- .../DcaSettingCondition/ValueListener.php | 64 ++-- .../AbstractAbstainingListener.php | 16 +- .../Table/DcaSortGroup/AbstractListener.php | 17 +- .../DcaSortGroup/AttributeOptionsListener.php | 16 +- .../DcaSortGroup/SortGroupCreateListener.php | 14 +- .../VisibilityConditionBuildingListener.php | 5 +- .../AbstractFilterSettingTypeRenderer.php | 42 ++- .../Table/FilterSetting/AttributeListener.php | 66 ++-- .../FilterSetting/DefaultOptionListener.php | 26 +- .../FilterSettingTypeRendererCore.php | 7 +- .../FilterSetting/PasteButtonListener.php | 16 +- .../FilterSetting/TemplateOptionListener.php | 17 +- .../FilterSetting/TypeOptionListener.php | 22 +- .../MetaModel/AbstractAbstainingListener.php | 17 +- .../MetaModel/DcaCombineButtonListener.php | 18 +- .../MetaModel/LanguageOptionsListener.php | 13 +- .../Table/MetaModel/ModelToLabelListener.php | 7 +- .../MetaModel/TableNamePrefixingListener.php | 16 +- .../AbstractAbstainingListener.php | 17 +- .../Table/RenderSetting/AbstractListener.php | 17 +- .../RenderSetting/AddAllButtonListener.php | 32 +- .../AttributeOptionsListener.php | 15 +- .../RenderSetting/ModelToLabelListener.php | 3 + .../PaletteRestrictionListener.php | 14 +- .../RenderSetting/TemplateOptionListener.php | 6 +- .../AbstractAbstainingListener.php | 17 +- .../Table/RenderSettings/AddAssetListener.php | 36 +- .../Table/RenderSettings/JumpToListener.php | 33 +- .../LanguageCodeWizardListener.php | 45 ++- .../AbstractAbstainingListener.php | 15 +- .../SearchablePages/FilterOptionListener.php | 6 +- .../PaletteRestrictionListener.php | 5 +- .../RenderSettingOptionListener.php | 12 +- .../EventListener/DoctrineSchemaListener.php | 61 ++-- .../GetSearchablePagesListener.php | 61 ++-- .../EventListener/InsertTagsListener.php | 138 ++++---- .../EventListener/PurgeListener.php | 3 +- .../EventListener/SubSystemBootListener.php | 50 +-- src/CoreBundle/EventListener/UserListener.php | 44 +-- .../ServiceContainerInitializer.php | 4 +- src/CoreBundle/MetaModelsCoreBundle.php | 7 +- .../FindClearAllTemplateMigration.php | 2 +- .../Migration/FindXhtmlTemplateMigration.php | 2 +- .../Migration/SetDefaultZeroMigration.php | 40 +-- .../Migration/TableCollationMigration.php | 29 +- src/CoreBundle/Resources/config/listeners.yml | 17 - .../Resources/contao/config/config.php | 4 +- .../Resources/contao/config/services.php | 5 +- .../Resources/contao/dca/tl_content.php | 4 +- .../Resources/contao/dca/tl_module.php | 4 +- src/CoreBundle/Sorter/AttributeSorter.php | 4 + src/DcGeneral/Data/Driver.php | 287 ++++++++-------- src/DcGeneral/Data/DriverBcLayerTrait.php | 19 +- src/DcGeneral/Data/FilterBuilder.php | 268 +++++++-------- src/DcGeneral/Data/FilterBuilderSql.php | 52 ++- src/DcGeneral/Data/Model.php | 88 +++-- src/DcGeneral/Data/ModelIterator.php | 41 ++- .../Definition/IMetaModelDefinition.php | 2 +- .../Definition/MetaModelDefinition.php | 7 +- .../MetaModelDataDefinition.php | 10 +- .../Palette/RenderSettingAttributeIs.php | 28 +- .../Property/AttributeByIdIsOfType.php | 4 +- .../ConditionTableNameIsMetaModel.php | 16 +- .../Property/InputScreenAttributeIs.php | 14 +- .../Property/InputScreenRenderModeIs.php | 30 +- .../Condition/Property/IsVariantAttribute.php | 18 +- .../PropertyContainAnyOfCondition.php | 22 +- .../Property/PropertyValueCondition.php | 1 + .../Property/RenderSettingAttributeIs.php | 14 +- src/DcGeneral/Events/BaseSubscriber.php | 22 +- .../Events/MetaModel/BuildAttributeEvent.php | 2 +- .../BuildMetaModelOperationsEvent.php | 19 +- .../Events/MetaModel/DuplicateModel.php | 11 +- .../MetaModel/PopulateAttributeEvent.php | 2 +- .../MetaModel/PropertyOptionsProvider.php | 17 +- .../FilterSettingTypeRenderer.php | 28 +- src/Dca/Helper.php | 62 ++-- .../CollectMetaModelTableNamesEvent.php | 2 +- src/Events/CreateMetaModelEvent.php | 14 +- src/Events/CreatePropertyConditionEvent.php | 16 +- src/Events/DatabaseBackedListener.php | 48 +-- src/Events/GetMetaModelNameFromIdEvent.php | 15 +- src/Events/MetaModelsBootEvent.php | 14 +- src/Events/RenderItemListEvent.php | 22 +- .../Database/ColumnDoesNotExistException.php | 14 +- .../Database/ColumnExistsException.php | 12 +- .../Database/InvalidColumnNameException.php | 13 +- .../Database/InvalidTableNameException.php | 9 +- .../Database/TableDoesNotExistException.php | 10 +- .../Database/TableExistsException.php | 10 +- src/Exceptions/DifferentValuesException.php | 83 ++--- src/Factory.php | 38 ++- src/Filter/Filter.php | 30 +- src/Filter/FilterUrl.php | 46 +-- src/Filter/FilterUrlBuilder.php | 98 +++--- src/Filter/IFilter.php | 2 +- src/Filter/IFilterRule.php | 7 +- src/Filter/Rules/Comparing/GreaterThan.php | 11 +- src/Filter/Rules/Comparing/LessThan.php | 11 +- src/Filter/Rules/Comparing/NotEqual.php | 10 +- src/Filter/Rules/Condition/ConditionAnd.php | 16 +- src/Filter/Rules/Condition/ConditionOr.php | 23 +- src/Filter/Rules/SearchAttribute.php | 23 +- src/Filter/Rules/SimpleQuery.php | 32 +- src/Filter/Rules/StaticIdList.php | 11 +- .../AbstractFilterSettingTypeFactory.php | 54 +-- src/Filter/Setting/Collection.php | 32 +- .../ConditionAndFilterSettingTypeFactory.php | 9 +- .../ConditionOrFilterSettingTypeFactory.php | 9 +- src/Filter/Setting/CustomSql.php | 124 +++---- src/Filter/Setting/FilterSettingFactory.php | 27 +- src/Filter/Setting/ICollection.php | 20 +- src/Filter/Setting/IFilterSettingFactory.php | 6 +- .../Setting/IFilterSettingTypeFactory.php | 7 +- src/Filter/Setting/ISimple.php | 36 +- src/Filter/Setting/Simple.php | 98 +++--- src/Filter/Setting/SimpleLookup.php | 122 ++++--- .../StaticIdListFilterSettingTypeFactory.php | 7 +- src/Filter/Setting/WithChildren.php | 19 +- src/FrontendIntegration/Content/Filter.php | 8 +- .../Content/FilterClearAll.php | 8 +- src/FrontendIntegration/Content/ModelList.php | 7 +- src/FrontendIntegration/FrontendFilter.php | 174 ++++++---- src/FrontendIntegration/HybridFilterBlock.php | 71 ++-- .../HybridFilterClearAll.php | 33 +- src/FrontendIntegration/HybridList.php | 56 +++- src/FrontendIntegration/MetaModelHybrid.php | 99 ++++-- src/FrontendIntegration/Module/Filter.php | 7 +- .../Module/FilterClearAll.php | 7 +- src/FrontendIntegration/Module/ModelList.php | 7 +- src/FrontendIntegration/ViewCombinations.php | 12 +- src/Helper/ContaoController.php | 7 +- src/Helper/EmptyTest.php | 19 +- src/Helper/LocaleUtil.php | 5 +- src/Helper/PaginationGenerator.php | 75 +++-- src/Helper/PaginationLimitCalculator.php | 93 ++++-- src/Helper/SortingLinkGenerator.php | 114 +++++-- src/Helper/TableManipulation.php | 109 +++--- src/Helper/TableManipulator.php | 50 +-- src/Helper/ToolboxFile.php | 143 ++++---- src/Helper/UpgradeHandler.php | 76 +++-- src/Helper/ViewCombinations.php | 125 ++++--- src/IFactory.php | 7 +- src/IItem.php | 25 +- src/IItems.php | 11 +- src/IMetaModel.php | 72 ++-- src/IMetaModelsServiceContainer.php | 7 +- src/IServiceContainerAware.php | 13 +- src/ITranslatedMetaModel.php | 7 +- src/Information/AttributeInformation.php | 2 +- .../AttributeInformationInterface.php | 2 +- src/Information/ConfigurationTrait.php | 2 +- src/Information/MetaModelCollection.php | 4 +- .../MetaModelCollectionInterface.php | 8 +- src/Information/MetaModelInformation.php | 17 +- .../MetaModelInformationInterface.php | 6 +- ...ontaoDatabaseBackedInformationProvider.php | 8 +- .../InformationProviderInterface.php | 9 +- .../MetaModelInformationCollector.php | 19 +- src/InsertTag/Node.php | 11 +- src/InsertTag/NodeList.php | 6 +- src/InsertTag/Parser.php | 26 +- src/Item.php | 123 ++++--- src/ItemList.php | 263 ++++++++++----- src/Items.php | 47 ++- src/MetaModel.php | 315 ++++++++++-------- src/MetaModelsEvents.php | 16 +- src/MetaModelsServiceContainer.php | 64 ++-- src/Render/Setting/Collection.php | 72 ++-- src/Render/Setting/ICollection.php | 2 +- src/Render/Setting/IRenderSettingFactory.php | 5 +- src/Render/Setting/ISimple.php | 6 +- src/Render/Setting/RenderSettingFactory.php | 62 ++-- src/Render/Setting/Simple.php | 20 +- src/Render/Template.php | 198 ++++++----- .../AbstractAttributeTypeSchemaGenerator.php | 13 +- .../Doctrine/DoctrineSchemaGenerator.php | 2 +- .../DoctrineSchemaGeneratorHelperTrait.php | 2 +- .../DoctrineSchemaGeneratorInterface.php | 2 +- .../Doctrine/DoctrineSchemaInformation.php | 2 +- src/Schema/Doctrine/DoctrineSchemaManager.php | 2 +- .../Doctrine/DoctrineSchemaManipulator.php | 86 ++++- .../Doctrine/SchemaProcessorInterface.php | 2 +- .../Doctrine/SystemColumnSchemaGenerator.php | 8 +- src/Schema/LegacySchemaGenerator.php | 18 +- src/Schema/LegacySchemaInformation.php | 2 +- src/Schema/LegacySchemaManager.php | 41 ++- src/Schema/SchemaGenerator.php | 2 +- src/Schema/SchemaGeneratorInterface.php | 2 +- src/Schema/SchemaInformation.php | 4 +- src/Schema/SchemaInformationInterface.php | 2 +- src/Schema/SchemaManager.php | 4 +- src/Schema/SchemaManagerInterface.php | 2 +- src/TranslatedMetaModel.php | 14 +- .../InputScreenInformationBuilder.php | 191 ++++++----- src/ViewCombination/ViewCombination.php | 43 ++- .../ViewCombinationBuilder.php | 21 +- src/Widgets/FileSelectorWidget.php | 42 ++- src/Widgets/MultiTextWidget.php | 16 +- src/Widgets/SubDcaWidget.php | 154 +++++---- src/Widgets/TagsWidget.php | 63 ++-- tests/Attribute/AttributeFactoryTest.php | 4 +- tests/Attribute/BaseTest.php | 2 + ...ollectDoctrineSchemaGeneratorsPassTest.php | 2 +- .../CollectSchemaGeneratorsPassTest.php | 2 +- .../CollectSchemaManagersPassTest.php | 2 +- tests/Data/FilterBuilderSqlTest.php | 37 +- tests/Data/FilterBuilderTest.php | 47 +-- tests/Filter/FilterUrlBuilderTest.php | 19 +- tests/Filter/Rules/SimpleQueryTest.php | 14 +- tests/Filter/Setting/CustomSqlTest.php | 66 ++-- tests/Helper/TableManipulatorTest.php | 20 +- tests/Helper/ToolBoxFileTest.php | 2 +- .../Information/AttributeInformationTest.php | 2 +- tests/Information/ConfigurationTraitTest.php | 2 +- tests/Information/MetaModelCollectionTest.php | 2 +- .../Information/MetaModelInformationTest.php | 2 +- .../MetaModelInformationCollectorTest.php | 2 +- tests/ItemListTest.php | 28 +- tests/MetaModelsTest.php | 193 +++++------ tests/Render/TemplateTest.php | 2 + .../Doctrine/DoctrineSchemaGeneratorTest.php | 2 +- .../DoctrineSchemaInformationTest.php | 2 +- .../Doctrine/DoctrineSchemaManagerTest.php | 2 +- tests/Schema/LegacySchemaGeneratorTest.php | 4 +- tests/Schema/LegacySchemaInformationTest.php | 2 +- tests/Schema/LegacySchemaManagerTest.php | 2 +- tests/Schema/SchemaGeneratorTest.php | 2 +- tests/Schema/SchemaInformationTest.php | 2 +- tests/Schema/SchemaManagerTest.php | 2 +- 358 files changed, 6848 insertions(+), 4697 deletions(-) create mode 100644 .composer-require-checker.json create mode 100644 .phpcq.lock create mode 100644 .phpcq.yaml.dist create mode 100644 .phpmd.xml delete mode 100644 build.default.properties delete mode 100644 build.xml create mode 100644 psalm.xml diff --git a/.composer-require-checker.json b/.composer-require-checker.json new file mode 100644 index 000000000..8a45915bd --- /dev/null +++ b/.composer-require-checker.json @@ -0,0 +1,12 @@ +{ + "symbol-whitelist": [ + "array", "bool", "false", "int", "null", "self", "static", "parent", "string", "true", "void", "mixed", + "Contao\\ManagerBundle\\ContaoManagerBundle", + "Contao\\ManagerPlugin\\Bundle\\BundlePluginInterface", + "Contao\\ManagerPlugin\\Bundle\\Config\\BundleConfig", + "Contao\\ManagerPlugin\\Bundle\\Parser\\ParserInterface", + "Contao\\ManagerPlugin\\Routing\\RoutingPluginInterface", + "Doctrine\\Bundle\\DoctrineBundle\\DoctrineBundle", + "tl_user_group" + ] +} diff --git a/.github/workflows/diagnostics.yml b/.github/workflows/diagnostics.yml index 190c2f42c..c4e707777 100644 --- a/.github/workflows/diagnostics.yml +++ b/.github/workflows/diagnostics.yml @@ -1,52 +1,74 @@ name: MetaModels core - on: - push: - branches-ignore: - - '**-translation' pull_request: + push: + branches: jobs: build: runs-on: ubuntu-latest + name: 'PHP: ${{ matrix.php }} Contao: ${{ matrix.contao }}' strategy: + fail-fast: false matrix: - php: [7.4, 8,0] - contao: [~4.13.0] + php: [ '8.1', '8.2' ] + contao: [ '~4.13.0' ] + phpcq_install: [ 'update' ] + output: [ '-o github-action -o default' ] steps: - - name: PHP ${{ matrix.php }} ${{ matrix.contao }} Pull source + - name: Pull source uses: actions/checkout@v3 - with: - fetch-depth: 0 - # see https://github.com/shivammathur/setup-php - - name: PHP ${{ matrix.php }} ${{ matrix.contao }} Setup PHP. + - name: Setup PHP with PECL extension uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - coverage: none - - name: PHP ${{ matrix.php }} ${{ matrix.contao }} Cache composer cache directory + # setup caches + - name: Cache composer cache directory uses: actions/cache@v3 env: cache-name: composer-cache-dir with: path: ~/.cache/composer - key: ${{ runner.os }}-build-${{ env.cache-name }} + key: ${{ runner.os }}-${{ matrix.php }}-build-${{ env.cache-name }} - - name: PHP ${{ matrix.php }} ${{ matrix.contao }} Cache vendor directory + - name: Cache vendor directory uses: actions/cache@v3 env: - cache-name: composer-vendor + cache-name: vendor with: path: vendor - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-${{ matrix.php }}-${{ matrix.contao }}-build-${{ env.cache-name }}-${{ hashFiles('**/composer.lock') }} restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-${{ matrix.php }}-${{ matrix.contao }}-build-${{ env.cache-name }}- - - name: PHP ${{ matrix.php }} ${{ matrix.contao }} Install composer dependencies - run: composer update --prefer-dist --no-interaction --no-suggest + - name: Cache phpcq directory + uses: actions/cache@v3 + env: + cache-name: phpcq + with: + path: .phpcq + key: ${{ runner.os }}-${{ matrix.php }}-build-${{ env.cache-name }}-${{ hashFiles('**/.phpcq.lock') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.php }}-build-${{ env.cache-name }}- + + # install dependencies and tools + - name: Install composer dependencies + run: | + composer require contao/core-bundle ${{ matrix.contao }} --no-update + composer install + - name: Install phpcq toolchain + run: ./vendor/bin/phpcq ${{ matrix.phpcq_install }} -v - - name: PHP ${{ matrix.php }} ${{ matrix.contao }} Run tests - run: ant -keep-going + # run tests + - name: Run tests + run: ./vendor/bin/phpcq run -v ${{ matrix.output }} + + - name: Upload build directory to artifact + uses: actions/upload-artifact@v3 + if: ${{ success() }} || ${{ failure() }} + with: + name: phpcq-builds-php-${{ matrix.php }}-${{ matrix.contao }} + path: .phpcq/build/ diff --git a/.gitignore b/.gitignore index f0ec851e1..6561ee7c1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ .DS_Store Thumbs.db -# IDEs +# IDEs .buildpath .project .settings/ @@ -16,6 +16,5 @@ vendor/ composer.lock # build -build/ -build.properties -.phpunit.result.cache \ No newline at end of file +.phpunit.result.cache +/.phpcq/* diff --git a/.phpcq.lock b/.phpcq.lock new file mode 100644 index 000000000..4ec1fc353 --- /dev/null +++ b/.phpcq.lock @@ -0,0 +1 @@ +{"plugins":{"phpunit":{"api-version":"1.0.0","version":"1.0.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpunit/phpunit-1.0.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0"},"tool":{"phpunit":"^6.0 || ^7.0 || ^8.0 || ^9.0"}},"checksum":{"type":"sha-512","value":"c73f15658e3ba62665f09492ec91c3a6a715760bfaa88473a987538439fff442540148e086e46a6aa18ce55a3ea2fbf76caaa581384cb84a38859fcc609ae7e4"},"tools":{"phpunit":{"version":"9.6.18","url":"https://phar.phpunit.de/phpunit-9.6.18.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*","ext-json":"*","ext-libxml":"*","ext-mbstring":"*","ext-xml":"*","ext-xmlwriter":"*"}},"checksum":{"type":"sha-256","value":"fc3729afdbab93cbf9f662de730bcc2f936bd9255bb08c6c53d41b9b0a30ec62"},"signature":"https://phar.phpunit.de/phpunit-9.6.18.phar.asc"}},"composerLock":null},"psalm":{"api-version":"1.0.0","version":"1.2.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/psalm/psalm-1.2.0.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0","ext-dom":"*"},"tool":{"psalm":"^3.0 || ^4.0 || ^5.0"}},"checksum":{"type":"sha-512","value":"4a550c9226d7bca582d7c10bd87cce01190c96398936b1613421640c83df62ed1c6e0d44c1b39635414ea8cf4a892a6458d27590793238add24e7cb5547e6ffd"},"tools":{"psalm":{"version":"5.23.1","url":"https://github.com/vimeo/psalm/releases/download/5.23.1/psalm.phar","requirements":{"php":{"php":"^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0","ext-SimpleXML":"*","ext-ctype":"*","ext-dom":"*","ext-json":"*","ext-libxml":"*","ext-mbstring":"*","ext-tokenizer":"*"}},"checksum":null,"signature":"https://github.com/vimeo/psalm/releases/download/5.23.1/psalm.phar.asc"}},"composerLock":null},"composer-require-checker":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/composer-require-checker/composer-require-checker-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0"},"tool":{"composer-require-checker":"^3.8 || ^4.0"}},"checksum":{"type":"sha-512","value":"d5415bddfe024c5749d894034583882aee4e5c3e1087815d9fdd81cb5e71630f631a0e35de0ff84b97fbbf738c16ece5f83bd8c00695913eb846aa6f04577dc2"},"tools":{"composer-require-checker":{"version":"4.7.1","url":"https://github.com/maglnet/ComposerRequireChecker/releases/download/4.7.1/composer-require-checker.phar","requirements":{"php":{"php":"~8.1.0 || ~8.2.0 || ~8.3.0","ext-phar":"*"}},"checksum":null,"signature":"https://github.com/maglnet/ComposerRequireChecker/releases/download/4.7.1/composer-require-checker.phar.asc"}},"composerLock":null},"phpmd":{"api-version":"1.0.0","version":"1.0.2.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpmd/phpmd-1.0.2.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpmd":"^2.6.1"}},"checksum":{"type":"sha-512","value":"f22280a6dec8dbdd2ec1d83b294f23237fe32c34f4a298e52038e0a7a0074d541635b2b488b1a6098a42d8418a6cd8eb804406ea82b91e362be2b5d11a0915b0"},"tools":{"phpmd":{"version":"2.15.0","url":"https://github.com/phpmd/phpmd/releases/download/2.15.0/phpmd.phar","requirements":{"php":{"php":">=5.3.9","ext-xml":"*"}},"checksum":null,"signature":"https://github.com/phpmd/phpmd/releases/download/2.15.0/phpmd.phar.asc"}},"composerLock":null},"phpcpd":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpcpd/phpcpd-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpcpd":"^6.0"}},"checksum":{"type":"sha-512","value":"1189ce0bf3fade4cb4241f1d96f915ef8fc7651f4450dc79fdf464ee3d6be3009316f0d423ce2d4af9d76ad50807b7fdf4d77bfa6d9ee2c91d6eda32ea214433"},"tools":{"phpcpd":{"version":"6.0.3","url":"https://phar.phpunit.de/phpcpd-6.0.3.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*"}},"checksum":{"type":"sha-256","value":"2cbaea7cfda1bb4299d863eb075e977c3f49055dd16d88529fae5150d48a84cb"},"signature":"https://phar.phpunit.de/phpcpd-6.0.3.phar.asc"}},"composerLock":null},"phploc":{"api-version":"1.0.0","version":"1.0.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phploc/phploc-1.0.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*","ext-json":"*"},"tool":{"phploc":"^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0"}},"checksum":{"type":"sha-512","value":"f67b02d494796adf553cb3dd13ec06c1cb8e53c799954061749424251379541637538199afb3afa3c7a01cabd1cb6f1c53eb621f015dff9644c6c7cbf10c56d1"},"tools":{"phploc":{"version":"7.0.2","url":"https://phar.phpunit.de/phploc-7.0.2.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*","ext-json":"*"}},"checksum":{"type":"sha-256","value":"3d59778ec86faf25fd00e3a329b2f9ad4a3c751ca91601ea7dab70f887b0bf46"},"signature":"https://phar.phpunit.de/phploc-7.0.2.phar.asc"}},"composerLock":null},"phpcs":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpcs/phpcs-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpcs":"^3.0 || ^2.0","phpcbf":"^3.0 || ^2.0"}},"checksum":{"type":"sha-512","value":"2737022369da1318cc4e0ea194e8a81019f7b079080d869aab878b7486052fdbe68fee3f28131f35573226def1aabd4bd005e038ee7b767c137b1107c1492a83"},"tools":{"phpcs":{"version":"3.9.1","url":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.1/phpcs.phar","requirements":{"php":{"php":">=5.4.0","ext-simplexml":"*","ext-tokenizer":"*","ext-xmlwriter":"*"}},"checksum":null,"signature":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.1/phpcs.phar.asc"},"phpcbf":{"version":"3.9.1","url":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.1/phpcbf.phar","requirements":{"php":{"php":">=5.4.0","ext-simplexml":"*","ext-tokenizer":"*","ext-xmlwriter":"*"}},"checksum":null,"signature":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.1/phpcbf.phar.asc"}},"composerLock":null},"composer-normalize":{"api-version":"1.0.0","version":"1.1.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/composer-normalize/composer-normalize-1.1.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-json":"*"},"tool":{"composer-normalize":"^2.1"}},"checksum":{"type":"sha-512","value":"d59d3557cb20630734878a9115df5dd32d5aff815e5b15be36f6fb5d6e9d83dd36efd84215ab6529edcc924f600946f739a0d9e67723deff95c88346ab502498"},"tools":{"composer-normalize":{"version":"2.42.0","url":"https://github.com/ergebnis/composer-normalize/releases/download/2.42.0/composer-normalize.phar","requirements":{"php":{"php":"~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0","ext-json":"*"}},"checksum":null,"signature":"https://github.com/ergebnis/composer-normalize/releases/download/2.42.0/composer-normalize.phar.asc"}},"composerLock":null}},"tools":[]} \ No newline at end of file diff --git a/.phpcq.yaml.dist b/.phpcq.yaml.dist new file mode 100644 index 000000000..6dd1dffd9 --- /dev/null +++ b/.phpcq.yaml.dist @@ -0,0 +1,111 @@ +phpcq: + repositories: + - https://phpcq.github.io/repository/repository.json + directories: + - src + - tests + artifact: .phpcq/build + composer: + autodiscover: false + + plugins: + phpunit: + version: ^1.0 + signed: false + psalm: + version: ^1.0 + signed: false + composer-require-checker: + version: ^1.0 + signed: false + phpmd: + version: ^1.0 + signed: false + phpcpd: + version: ^1.1 + signed: false + phploc: + version: ^1.0 + signed: false + phpcs: + version: ^1.0 + signed: false + composer-normalize: + version: ^1.0 + signed: false + trusted-keys: + # composer-require-checker + - 033E5F8D801A2F8D + # sb@sebastian-bergmann.de + - 4AA394086372C20A + # psalm + - 8A03EA3B385DBAA1 + - 12CE0F1D262429A5 + # magl@magll.net + - D2CCAC42F6295E7D + # PHP_CodeSniffer + - 31C7E470E2138192 + # Composer normalize + - C00543248C87FB13 + # phpmd + - A4E55EA12C7C085C + +tasks: + fix: + - composer-normalize-fix + - phpcbf + + verify: + - composer-require-checker + - composer-normalize + + analyze: + - phploc + - phpcpd + - phpmd + - phpcs + - psalm + - phpunit + + default: + - verify + - analyze + + phpcpd: + plugin: phpcpd + config: + exclude: + - tests + - src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder + - src/CoreBundle/Resources/contao/dca + + phpmd: + plugin: phpmd + config: + ruleset: + - ./.phpmd.xml + + composer-require-checker: + plugin: composer-require-checker + config: + config_file: '.composer-require-checker.json' + + phpcs: + plugin: phpcs + config: &phpcs-config + standard: PSR12 + excluded: + - '*/CoreBundle/Resources/contao/dca/*' + - '*/CoreBundle/Resources/contao/languages/*' + - '*/CoreBundle/Resources/public/*' + + phpcbf: + plugin: phpcs + config: + <<: *phpcs-config + fix: true + + composer-normalize-fix: + plugin: composer-normalize + config: + dry_run: false diff --git a/.phpmd.xml b/.phpmd.xml new file mode 100644 index 000000000..78eb716f3 --- /dev/null +++ b/.phpmd.xml @@ -0,0 +1,37 @@ + + + + PHPMD rule set + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index fdda7c717..91e2c185b 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,17 @@ [![Latest Version on Packagist](http://img.shields.io/packagist/v/MetaModels/core.svg)](https://packagist.org/packages/MetaModels/core) [![Installations via composer per month](http://img.shields.io/packagist/dm/MetaModels/core.svg)](https://packagist.org/packages/MetaModels/core) -MetaModels -========== +# MetaModels -So what are MetaModels? ------------------------ +Deutsch - s.u. + +## So what are MetaModels? MetaModels are data models you can configure in the Contao Backend. Every MetaModel consists of various attributes of -certain data types (attribute types are available as extensions and get registered upon installation). +certain data types (attribute types are available as extensions and get registered upon installation). In addition, +several MetaModel can be linked to each other via relations as single or multiple selections can be linked with each +other. This allows very complex data structures to be mapped in Contao, e.g. for product catalogues, employee lists, +event management, etc. Programming knowledge is generally not necessary for the creation not necessary. To present the data on the screen (i.e. website, RSS feed, etc.), you define render settings for the MetaModel which define how the various attribute output shall look like (image sizes, use light boxes, etc.). @@ -21,10 +24,7 @@ can be nested (AND/OR conditions i.e.) and be of various nature. Before you start it is helpful to look at the [MetaModels manual](http://metamodels.readthedocs.org/de/latest/index.html). There you will find actual information about the usage and the installation. -How to use it. --------------- - -### Install +## Install You can install MetaModels core with Contao Manager - search "metamodels/core" - or you can use composer @@ -32,13 +32,16 @@ You can install MetaModels core with Contao Manager - search "metamodels/core" - Then add all the necessary [attributes, filters or MetaModel extensions](https://extensions.contao.org/?q=metamodels). +Please [check the manual to see which versions are available](https://metamodels.readthedocs.io/de/latest/manual/install.html#ubersicht-der-versionen) +and which Contao version works with them. Please also note that the latest version is not always available on Github +and that a newer version may only be available as an "early adopter" with special access - [see Fundrasing](https://now.metamodel.me/en/supporters/fundraising). + For the first evaluation of the possibilities of MetaModels you can also use [metamodels/bundle_start](https://extensions.contao.org/?q=metamodels%252Fbundle_start), which installs some attributes and filters. Please do not forget to perform the migration of the database! -Docs: ------ +## Docs: * [The official MetaModel Documentation (de)](http://metamodels.readthedocs.org/de/latest/index.html) (Currently the main documentation) * [The official MetaModel Documentation (en)](http://metamodels.readthedocs.org/en/latest/index.html) @@ -47,16 +50,14 @@ Docs: Feel free to contribute the MetaModel Documentation in [EN](https://github.com/MetaModels/docs) or [DE](https://github.com/MetaModels/docs-de) -Resources: ----------- +## Resources: * [MetaModels Website](https://now.metamodel.me) * [MetaModels Contao Wiki [DE]](https://de.contaowiki.org/MetaModels) * [MetaModels Contao Community Subforum [DE]](https://community.contao.org/de/forumdisplay.php?149-MetaModels) * [MetaModels Channel on Contao Slack #metamodels](https://contao.slack.com/archives/CKGEBDV60) -History: --------- +## History: Metamodels are the replacement for the famous Catalog extension for [Contao CMS](https://github.com/contao/core). @@ -69,12 +70,51 @@ likely be possible both in implementation and learning curve but that this will resembling only of the name with it's ancestor. Therefore, we rebranded everything as "MetaModels". -Who did it? ------------ +## Who did it? See the [CONTRIBUTORS.md](https://github.com/MetaModels/core/tree/master/CONTRIBUTORS.md) file. -Third Party Licenses: ---------------------- +## Third Party Licenses: Icons: This software uses the [Fugue Icons](http://p.yusukekamiyamane.com) + +## Deutsch + +## Was ist MetaModells? + +MetaModels sind Datenmodelle, die Sie im Contao Backend konfigurieren können. Jedes MetaModel besteht aus verschiedenen +Attributen von bestimmten Datentypen wie Text, Checkbox, Dateien (Attributtypen sind als Erweiterungen verfügbar und +werden bei der Installation registriert). Zudem können mehrere MetaModel über Relationen als Einzel- oder Mehrfachauswahl +miteinander verknüpft werden. Damit lassen sich sehr komplexe Datenstrukturen in Contao abbilden wie z. B. für +Produktkataloge, Mitarbeiterlisten, Eventmanagements usw. Programmierkenntnisse sind in der Regel für die Erstellung +nicht notwendig. + +Um die Daten auf dem Bildschirm (z. B. Website, RSS-Feed, etc.) darzustellen, definieren Sie Rendereinstellungen für +das MetaModel, die festlegen, wie die verschiedenen Attributausgaben aussehen sollen (Bildgrößen, Verwendung von +Lightboxes usw.). + +Das Filtern von Daten in Listenansichten erfordert die Konfiguration von Filtereinstellungen. Filtereinstellungen sind +ein sehr komplexes Thema, da sie verschachtelt (z.B. AND/OR-Bedingungen) und von unterschiedlicher Natur sein können. + +Vor dem Start ist es hilfreich, einen Blick in das [MetaModels Handbuch](http://metamodels.readthedocs.org/de/latest/index.html) +zu werfen. Dort findet man aktuelle Informationen über die Verwendung, Installation und Tipps&Tricks. + +## Installation + +MetaModels Core kann mit dem Contao Manager installiert werden - suchen Sie nach "metamodels/core" - oder Sie können +composer verwenden + +``php public/contao-manager.phar.php composer require metamodels/core`` + +Dann fügen Sie alle notwendigen [Attribute, Filter oder MetaModel-Erweiterungen](https://extensions.contao.org/?q=metamodels) +hinzu, die Sie für ihr Model benötigen. + +Bitte [schauen Sie im Handbuch nach, welche Versionen verfügbar sind](https://metamodels.readthedocs.io/de/latest/manual/install.html#ubersicht-der-versionen) +und welche Contao-Version mit ihnen funktioniert. Bitte beachten Sie auch, dass nicht immer die neueste Version auf +Github verfügbar ist und dass eine neuere Version möglicherweise nur als "Early Adopter" mit speziellem Zugang +erhältlich ist - [siehe Fundrasing](https://now.metamodel.me/en/supporters/fundraising). + +Für eine erste Evaluierung der Möglichkeiten von MetaModels kann man auch [metamodels/bundle_start](https://extensions.contao.org/?q=metamodels%252Fbundle_start) +verwenden, das einige Attribute und Filter installiert. + +Bitte vergessen Sie nicht, die Migration der Datenbank durchzuführen! diff --git a/build.default.properties b/build.default.properties deleted file mode 100644 index 3520e42fc..000000000 --- a/build.default.properties +++ /dev/null @@ -1,24 +0,0 @@ -##################################################### -## This project is using the ## -## PHP code quality project (phpcq) ## -## ## -## https://github.com/phpcq/phpcq ## -##################################################### - -phpcs.standard=${basedir}/vendor/phpcq/coding-standard/phpcs/PhpCodeQuality/ruleset.xml -phpmd.ruleset=${basedir}/vendor/phpcq/coding-standard/phpmd/ruleset.xml - -# Exclude known "similar files" from cpd detection - We know these are code smells but can't refactor until 3.0 -# Sadly we can only exclude paths and not files. -phpcpd.excluded=src/CoreBundle/Resources/contao/dca \ - src/Helper \ - src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting \ - src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting \ - src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder \ - -# FIXME: phpcs changed the evaluation of ignored files -# from multiple occurrences of '--ignore' to a comma separated list in 3.0. -phpcs.excluded=*/Resources/public/*,\ -*/Resources/contao/config/*,\ -*/Resources/contao/dca/*,\ -*/Resources/contao/languages/* diff --git a/build.xml b/build.xml deleted file mode 100644 index 61e0fb463..000000000 --- a/build.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/composer.json b/composer.json index f0cc7f364..34642032b 100644 --- a/composer.json +++ b/composer.json @@ -1,14 +1,13 @@ { "name": "metamodels/core", "description": "MetaModels core", + "license": "LGPL-3.0-or-later", + "type": "contao-bundle", "keywords": [ "contao", "metamodels", "core" ], - "type": "contao-bundle", - "homepage": "https://now.metamodel.me/", - "license": "LGPL-3.0-or-later", "authors": [ { "name": "Christian Schiffler", @@ -22,6 +21,7 @@ "role": "Developer" } ], + "homepage": "https://now.metamodel.me/", "support": { "email": "mail@metamodel.me", "issues": "https://github.com/MetaModels/core/issues", @@ -37,25 +37,38 @@ "contao-community-alliance/meta-palettes": "^2.0.10", "contao-community-alliance/translator": "^2.3", "contao-community-alliance/url-builder": "^1.3.3", - "contao/core-bundle": "^4.13.5, <5.0", + "contao/core-bundle": "^4.13.5 <5.0", "discordier/justtextwidgets": "^1.3", "doctrine/cache": "^2.1", "doctrine/dbal": "^3.6.0", + "doctrine/orm": "^2.16.0", "menatwork/contao-multicolumnwizard-bundle": "^3.5.7", + "psr/container": "^1.1.2", + "psr/log": "^2.0.0", "symfony/asset": "^5.4", "symfony/cache": "^5.4", "symfony/config": "^5.4", + "symfony/console": "^5.4", "symfony/dependency-injection": "^5.4", + "symfony/deprecation-contracts": "^3.3.0", "symfony/event-dispatcher": "^5.4", + "symfony/event-dispatcher-contracts": "^2.5.2", "symfony/filesystem": "^5.4", "symfony/finder": "^5.4", - "terminal42/service-annotation-bundle": "^1.0" + "symfony/http-foundation": "^5.4", + "symfony/http-kernel": "^5.4", + "symfony/routing": "^5.4", + "symfony/security-core": "^5.4", + "symfony/service-contracts": "^2.5.2", + "symfony/translation-contracts": "^2.5.2", + "terminal42/service-annotation-bundle": "^1.0", + "twig/twig": "^3.7.0" }, "require-dev": { + "contao/manager-bundle": "^4.13.0 <5.0", "contao/manager-plugin": "^2.8", - "contao/manager-bundle": "^4.13.0, <5.0", - "doctrine/doctrine-bundle": "^1.8", - "phpcq/all-tasks": "^1.3" + "doctrine/doctrine-bundle": "^1.8.1 || ^2.8.3", + "phpcq/runner-bootstrap": "^1.0@dev" }, "autoload": { "psr-4": { @@ -67,23 +80,23 @@ "MetaModels\\Test\\": "tests/" } }, - "extra": { - "contao-manager-plugin": "MetaModels\\CoreBundle\\ContaoManager\\Plugin", - "contao": { - "runonce": [ - "runonce/runonce.php" - ] - }, - "branch-alias": { - "dev-feature/2.3.0": "2.3.x-dev" - } - }, "config": { "allow-plugins": { "contao-components/installer": false, "contao/manager-plugin": false, - "php-http/discovery": true + "php-http/discovery": false }, "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-feature/2.3.0": "2.3.x-dev" + }, + "contao": { + "runonce": [ + "runonce/runonce.php" + ] + }, + "contao-manager-plugin": "MetaModels\\CoreBundle\\ContaoManager\\Plugin" } } diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 000000000..39a76c1f4 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Attribute/AbstractAttributeTypeFactory.php b/src/Attribute/AbstractAttributeTypeFactory.php index 11b57316f..3c13bb402 100644 --- a/src/Attribute/AbstractAttributeTypeFactory.php +++ b/src/Attribute/AbstractAttributeTypeFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @author Christian Schiffler * @author Sven Baumann * @author David Molineus - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -34,21 +35,21 @@ abstract class AbstractAttributeTypeFactory implements IAttributeTypeFactory * * @var string */ - protected $typeName; + protected $typeName = ''; /** * The name of the attribute class of this type. * - * @var string + * @var class-string */ - protected $typeClass; + protected $typeClass = IAttribute::class; /** - * The icon representing this attributy type. + * The icon representing this attribute type. * * @var string */ - protected $typeIcon; + protected $typeIcon = ''; /** * {@inheritdoc} @@ -89,7 +90,7 @@ protected function __construct() */ public function isTranslatedType() { - return in_array('MetaModels\Attribute\ITranslated', class_implements($this->typeClass, true)); + return \in_array('MetaModels\Attribute\ITranslated', \class_implements($this->typeClass), true); } /** @@ -99,7 +100,7 @@ public function isTranslatedType() */ public function isSimpleType() { - return in_array('MetaModels\Attribute\ISimple', class_implements($this->typeClass, true)); + return \in_array('MetaModels\Attribute\ISimple', \class_implements($this->typeClass), true); } /** @@ -109,6 +110,6 @@ public function isSimpleType() */ public function isComplexType() { - return in_array('MetaModels\Attribute\IComplex', class_implements($this->typeClass, true)); + return \in_array('MetaModels\Attribute\IComplex', \class_implements($this->typeClass), true); } } diff --git a/src/Attribute/AttributeFactory.php b/src/Attribute/AttributeFactory.php index ad33a7277..d00adbe6f 100644 --- a/src/Attribute/AttributeFactory.php +++ b/src/Attribute/AttributeFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2021 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,15 +33,19 @@ * This is the implementation of the Field factory to query instances of fields. * * Usually this is only used internally by {@link MetaModels\Factory} + * + * @psalm-suppress DeprecatedInterface */ class AttributeFactory implements IAttributeFactory { /** * The service container. * - * @var IMetaModelsServiceContainer + * @var IMetaModelsServiceContainer|null + * + * @psalm-suppress DeprecatedInterface */ - protected $serviceContainer; + protected $serviceContainer = null; /** * The event dispatcher. @@ -54,7 +59,7 @@ class AttributeFactory implements IAttributeFactory * * @var IAttributeTypeFactory[] */ - protected $typeFactories = array(); + protected $typeFactories = []; /** * Create a new instance. @@ -70,11 +75,12 @@ public function __construct(EventDispatcherInterface $eventDispatcher) * Set the service container. * * @param IMetaModelsServiceContainer $serviceContainer The service container to use. - * * @param bool $deprecationNotice Determine deprecated notice. * * @return AttributeFactory * + * @psalm-suppress DeprecatedInterface + * * @deprecated The service container will get removed, use the symfony service container instead. */ public function setServiceContainer(IMetaModelsServiceContainer $serviceContainer, $deprecationNotice = true) @@ -113,6 +119,8 @@ public function setServiceContainer(IMetaModelsServiceContainer $serviceContaine * * @return IMetaModelsServiceContainer * + * @psalm-suppress DeprecatedInterface + * * @deprecated The service container will get removed, use the symfony service container instead. */ public function getServiceContainer() @@ -123,6 +131,10 @@ public function getServiceContainer() E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + if (null === $this->serviceContainer) { + throw new \RuntimeException('The deprecated service container has not been set anymore.'); + } + return $this->serviceContainer; } @@ -130,7 +142,6 @@ public function getServiceContainer() * Create an attribute instance from an information array. * * @param array $information The attribute information. - * * @param IMetaModel $metaModel The MetaModel instance for which the attribute shall be created. * * @return IAttribute|null @@ -143,8 +154,11 @@ public function createAttribute($information, $metaModel) if ($event->getAttribute()) { return $event->getAttribute(); } + if (null === ($type = $information['type'] ?? null)) { + return null; + } - $factory = $this->getTypeFactory($information['type']); + $factory = $this->getTypeFactory($type); if (!$factory) { return null; @@ -175,15 +189,18 @@ public function addTypeFactory(IAttributeTypeFactory $typeFactory) */ public function getTypeFactory($typeFactory) { - return isset($this->typeFactories[(string) $typeFactory]) ? $this->typeFactories[(string) $typeFactory] : null; + return $this->typeFactories[$typeFactory] ?? null; } /** * {@inheritdoc} */ - public function attributeTypeMatchesFlags($name, $flags) + public function attributeTypeMatchesFlags($factory, $flags) { - $factory = $this->getTypeFactory($name); + $factory = $this->getTypeFactory($factory); + if (null === $factory) { + return false; + } // Shortcut, if all are valid, return all. :) if ($flags === self::FLAG_ALL) { @@ -204,8 +221,8 @@ public function getTypeNames($flags = false) $flags = self::FLAG_ALL; } - $result = array(); - foreach (array_keys($this->typeFactories) as $name) { + $result = []; + foreach (\array_keys($this->typeFactories) as $name) { if (!$this->attributeTypeMatchesFlags($name, $flags)) { continue; } @@ -249,6 +266,6 @@ public function createAttributesForMetaModel($metaModel) */ public function getIconForType($type) { - return isset($this->typeFactories[(string) $type]) ? $this->typeFactories[(string) $type]->getTypeIcon() : null; + return isset($this->typeFactories[$type]) ? $this->typeFactories[$type]->getTypeIcon() : ''; } } diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 1c14d2fa2..6c6c28c43 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -39,6 +39,7 @@ * This class is the reference implementation for {@link IMetaModelAttribute}. * * @SuppressWarnings(PHPMD.TooManyPublicMethods) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ abstract class Base implements IAttribute { @@ -49,12 +50,12 @@ abstract class Base implements IAttribute * * @var IMetaModel */ - private $metaModel; + private IMetaModel $metaModel; /** * The meta information of this attribute. * - * @var array + * @var array */ protected $arrData = []; @@ -64,17 +65,20 @@ abstract class Base implements IAttribute * Note that you should not use this directly but use the factory classes to instantiate attributes. * * @param IMetaModel $objMetaModel The MetaModel instance this attribute belongs to. - * * @param array $arrData The information array, for attribute information, refer to documentation of * table tl_metamodel_attribute and documentation of the certain attribute classes * for information what values are understood. */ - public function __construct(IMetaModel $objMetaModel, $arrData = array()) + public function __construct(IMetaModel $objMetaModel, $arrData = []) { + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ if (!($objMetaModel instanceof ITranslatedMetaModel) && $objMetaModel->isTranslated(false)) { // @codingStandardsIgnoreStart @\trigger_error( - sprintf( + \sprintf( 'Support for translated "\MetaModel\IMetamodel" instances is deprecated since MetaModels 2.2 ' . 'and to be removed in 3.0. The MetaModel "%s" must implement "\MetaModels\ITranslatedMetaModel".', $objMetaModel->getTableName() @@ -85,7 +89,7 @@ public function __construct(IMetaModel $objMetaModel, $arrData = array()) } // Meta information. - foreach (array_intersect($this->getAttributeSettingNames(), array_keys($arrData)) as $strSettingName) { + foreach (\array_intersect($this->getAttributeSettingNames(), \array_keys($arrData)) as $strSettingName) { $this->set($strSettingName, $arrData[$strSettingName]); } $this->metaModel = $objMetaModel; @@ -106,7 +110,7 @@ public function __construct(IMetaModel $objMetaModel, $arrData = array()) */ protected function parameterMask($parameters) { - return implode(',', array_fill(0, count($parameters), '?')); + return \implode(',', \array_fill(0, \count($parameters), '?')); } /** @@ -119,10 +123,13 @@ protected function parameterMask($parameters) */ public function getName() { - if (isset($this->arrData['name']) && is_array($this->arrData['name'])) { + if (isset($this->arrData['name']) && \is_array($this->arrData['name'])) { $metaModel = $this->getMetaModel(); - return $this->getLangValue( - $this->get('name'), + $langValue = $this->get('name'); + assert(\is_array($langValue) || \is_string($langValue)); + /** @psalm-suppress DeprecatedMethod */ + return (string) $this->getLangValue( + $langValue, ($metaModel instanceof ITranslatedMetaModel) ? $metaModel->getLanguage() : $metaModel->getActiveLanguage() ) ?: $this->getColName(); @@ -137,15 +144,16 @@ public function getName() * If the language is not contained within the value array, the fallback language from the parenting * {@link IMetaModel} instance is tried as well. * - * @param array $arrValues The array holding all language values in the form array('langcode' => $varValue). - * @param string|null $strLangCode The language code of the language to fetch. + * @param array|string $arrValues The array holding all language values in the form + * array('langcode' => $varValue). + * @param string|null $strLangCode The language code of the language to fetch. * - * @return mixed|null the value for the given language or the fallback language, NULL if neither is present. + * @return string|null the value for the given language or the fallback language, NULL if neither is present. * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - protected function getLangValue($arrValues, $strLangCode = null): mixed + protected function getLangValue($arrValues, $strLangCode = null): ?string { // Not a valid lookup array, exit. if (!\is_array($arrValues)) { @@ -154,14 +162,18 @@ protected function getLangValue($arrValues, $strLangCode = null): mixed $metaModel = $this->getMetaModel(); // Not translated, exit. + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { - return $arrValues; + return reset($arrValues); } if (null === $strLangCode) { // @codingStandardsIgnoreStart @\trigger_error( - sprintf( + \sprintf( 'Not passing the language code to "%s" is deprecated since MetaModels 2.2 and will fail in 3.0 ', __METHOD__ ), @@ -171,6 +183,7 @@ protected function getLangValue($arrValues, $strLangCode = null): mixed // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. // In future versions we try to read from locale request, otherwise we raise an exception. + /** @psalm-suppress DeprecatedMethod */ $strLangCode = LocaleUtil::formatAsLocale( $GLOBALS['TL_LANGUAGE'] ?? (($this->metaModel instanceof ITranslatedMetaModel) @@ -187,7 +200,8 @@ protected function getLangValue($arrValues, $strLangCode = null): mixed if ($metaModel instanceof ITranslatedMetaModel) { $strLangCode = $metaModel->getMainLanguage(); } else { - $strLangCode = $metaModel->getFallbackLanguage(); + /** @psalm-suppress DeprecatedMethod */ + $strLangCode = (string) $metaModel->getFallbackLanguage(); } if (\array_key_exists($strLangCode, $arrValues)) { @@ -200,11 +214,11 @@ protected function getLangValue($arrValues, $strLangCode = null): mixed /** * Hook additional attribute formatter that want to format the value. * - * @param array $arrBaseFormatted The current result array. The keys "raw" and "text" are always - * populated. - * @param array $arrRowData The Raw values from the database. - * @param string $strOutputFormat The output format to use. - * @param ISimpleRenderSetting $objSettings The output format settings. + * @param array $arrBaseFormatted The current result array. The keys "raw" and "text" are always + * populated. + * @param array $arrRowData The Raw values from the database. + * @param string $strOutputFormat The output format to use. + * @param ISimpleRenderSetting|null $objSettings The output format settings. * * @return mixed * @@ -228,8 +242,8 @@ public function hookAdditionalFormatters($arrBaseFormatted, $arrRowData, $strOut foreach ($GLOBALS['METAMODEL_HOOKS']['parseValue'] as $callback) { [$strClass, $strMethod] = $callback; - $objCallback = (\in_array('getInstance', get_class_methods($strClass))) - ? call_user_func(array($strClass, 'getInstance')) + $objCallback = (\in_array('getInstance', \get_class_methods($strClass))) + ? \call_user_func(array($strClass, 'getInstance')) : new $strClass(); $arrResult = $objCallback->$strMethod( @@ -256,15 +270,15 @@ public function hookAdditionalFormatters($arrBaseFormatted, $arrRowData, $strOut */ protected function prepareTemplate(Template $objTemplate, $arrRowData, $objSettings) { + $additionalClass = (string) $objSettings->get('additional_class'); + $objTemplate->setData( [ 'attribute' => $this, 'settings' => $objSettings, 'row' => $arrRowData, 'raw' => ($arrRowData[$this->getColName()] ?? null), - 'additional_class' => $objSettings->get('additional_class') - ? ' ' . $objSettings->get('additional_class') - : '' + 'additional_class' => $additionalClass ? ' ' . $additionalClass : '' ] ); } @@ -274,7 +288,10 @@ protected function prepareTemplate(Template $objTemplate, $arrRowData, $objSetti */ public function getColName() { - return $this->arrData['colname']; + $colName = $this->arrData['colname']; + \assert(\is_string($colName)); + + return $colName; } /** @@ -290,7 +307,7 @@ public function getMetaModel() */ public function get($strKey) { - return isset($this->arrData[$strKey]) ? $this->arrData[$strKey] : null; + return $this->arrData[$strKey] ?? null; } /** @@ -299,8 +316,8 @@ public function get($strKey) public function set($strKey, $varValue) { if (in_array($strKey, $this->getAttributeSettingNames())) { - if (!is_array($varValue) && (substr($varValue, 0, 2) == 'a:')) { - $unSerialized = unserialize($varValue); + if (null !== $varValue && !\is_array($varValue) && (\str_starts_with($varValue, 'a:'))) { + $unSerialized = \unserialize($varValue); } if (isset($unSerialized) && is_array($unSerialized)) { @@ -400,11 +417,11 @@ private function setLanguageStrings(): void // Only overwrite the language if not already set. if (empty($GLOBALS['TL_LANG'][$this->getMetaModel()->getTableName()][$this->getColName()])) { // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. + /** @psalm-suppress DeprecatedMethod */ $language = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'] ?? ( ($this->metaModel instanceof ITranslatedMetaModel) ? $this->metaModel->getLanguage() - : $this->metaModel->getActiveLanguage()) - ); + : $this->metaModel->getActiveLanguage())); $GLOBALS['TL_LANG'][$this->getMetaModel()->getTableName()][$this->getColName()] = [ $this->getLangValue($this->get('name'), $language), @@ -435,6 +452,7 @@ private function getBaseDefinition() } if (!isset($definition['label'])) { + /** @psalm-suppress UnsupportedReferenceUsage */ $definition['label'] = &$GLOBALS['TL_LANG'][$tableName][$this->getColName()]; } @@ -460,7 +478,6 @@ private function isAllowedValue($name) * Extract an override value. * * @param string $name The name of the value. - * * @param array $overrides The overrides containing the values to be overridden. * * @return mixed @@ -478,7 +495,6 @@ protected function getOverrideValue($name, $overrides) * Extract an override value. * * @param array $fieldDefinition The field definition. - * * @param array $overrides The overrides containing the values to be overridden. * * @return array @@ -509,7 +525,8 @@ private function setBaseEval($fieldDefinition, $overrides) ]; foreach ($names as $name) { - if (empty($fieldDefinition['eval'][$name]) + if ( + empty($fieldDefinition['eval'][$name]) && ($value = $this->getOverrideValue($name, $overrides)) ) { $fieldDefinition['eval'][$name] = $value; @@ -527,14 +544,14 @@ private function setBaseEval($fieldDefinition, $overrides) /** * {@inheritdoc} */ - public function getFieldDefinition($arrOverrides = array()) + public function getFieldDefinition($arrOverrides = []) { $arrFieldDef = $this->setBaseEval($this->getBaseDefinition(), $arrOverrides); if ($this->isAllowedValue('trailingSlash')) { - $trailingSlash = $this->getOverrideValue('trailingSlash', $arrOverrides); - if ($trailingSlash != 2) { - $arrFieldDef['eval']['trailingSlash'] = (bool) $arrOverrides['trailingSlash']; + $trailingSlash = (int) $this->getOverrideValue('trailingSlash', $arrOverrides); + if ($trailingSlash !== 2) { + $arrFieldDef['eval']['trailingSlash'] = (bool) ($arrOverrides['trailingSlash'] ?? false); } } @@ -559,14 +576,12 @@ public function getFieldDefinition($arrOverrides = array()) */ public function getItemDCA($arrOverrides = []) { - $arrReturn = [ - 'fields' => array_merge( + return [ + 'fields' => \array_merge( [$this->getColName() => $this->getFieldDefinition($arrOverrides)], - (array) $GLOBALS['TL_DCA'][$this->getMetaModel()->getTableName()]['fields'][$this->getColName()] + (array) ($GLOBALS['TL_DCA'][$this->getMetaModel()->getTableName()]['fields'][$this->getColName()] ?? []) ), ]; - - return $arrReturn; } /** @@ -590,9 +605,7 @@ public function widgetToValue($varValue, $itemId) */ public function getDefaultRenderSettings() { - $objSetting = new Simple(['template' => 'mm_attr_' . $this->get('type')]); - - return $objSetting; + return new Simple(['template' => 'mm_attr_' . ($this->get('type') ?? '')]); } /** @@ -602,10 +615,7 @@ public function parseValue($arrRowData, $strOutputFormat = 'text', $objSettings { $arrResult = ['raw' => ($arrRowData[$this->getColName()] ?? null)]; - /** @var ISimpleRenderSetting $objSettings */ - if ($objSettings && $objSettings->get('template')) { - $strTemplate = $objSettings->get('template'); - + if ($objSettings && ($strTemplate = (string) $objSettings->get('template'))) { $objTemplate = new Template($strTemplate); $this->prepareTemplate($objTemplate, $arrRowData, $objSettings); @@ -623,7 +633,7 @@ public function parseValue($arrRowData, $strOutputFormat = 'text', $objSettings } catch (\Exception $e) { $objSettingsFallback = $this->getDefaultRenderSettings()->setParent($objSettings->getParent()); - $objTemplate = new Template($objSettingsFallback->get('template')); + $objTemplate = new Template($objSettingsFallback->get('template') ?? ''); $this->prepareTemplate($objTemplate, $arrRowData, $objSettingsFallback); $arrResult['text'] = $objTemplate->parse('text', true); @@ -634,6 +644,7 @@ public function parseValue($arrRowData, $strOutputFormat = 'text', $objSettings } // HOOK: apply additional formatters to attribute. + /** @psalm-suppress DeprecatedMethod */ $arrResult = $this->hookAdditionalFormatters($arrResult, $arrRowData, $strOutputFormat, $objSettings); return $arrResult; @@ -649,7 +660,7 @@ public function getFilterUrlValue($varValue) // We are parsing as text here as this was the way before this method was implemented. See #216. $arrResult = $this->parseValue([$this->getColName() => $varValue], 'text'); - return $arrResult['text']; + return (string) $arrResult['text']; } /** @@ -700,7 +711,7 @@ public function filterLessThan($varValue, $blnInclusive = false) */ public function filterNotEqual($varValue) { - return array_merge($this->filterLessThan($varValue), $this->filterGreaterThan($varValue)); + return \array_merge($this->filterLessThan($varValue) ?? [], $this->filterGreaterThan($varValue) ?? []); } /** diff --git a/src/Attribute/BaseSimple.php b/src/Attribute/BaseSimple.php index 492e3c48d..f95de6c6c 100644 --- a/src/Attribute/BaseSimple.php +++ b/src/Attribute/BaseSimple.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Sven Baumann * @author David Molineus * @author Marc Reimann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,7 +26,9 @@ namespace MetaModels\Attribute; use Contao\System; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use MetaModels\Helper\TableManipulator; use MetaModels\IMetaModel; @@ -60,13 +62,13 @@ class BaseSimple extends Base implements ISimple * * Note that you should not use this directly but use the factory classes to instantiate attributes. * - * @param IMetaModel $objMetaModel The MetaModel instance this attribute belongs to. - * @param array $arrData The information array, for attribute information, refer to - * documentation of table tl_metamodel_attribute and documentation of the - * certain attribute classes for information what values are understood. - * @param Connection $connection The database connection. - * - * @param TableManipulator $tableManipulator Table manipulator instance. + * @param IMetaModel $objMetaModel The MetaModel instance this attribute belongs to. + * @param array $arrData The information array, for attribute information, refer to + * documentation of table tl_metamodel_attribute and documentation + * of the certain attribute classes for information what values are + * understood. + * @param Connection|null $connection The database connection. + * @param TableManipulator|null $tableManipulator Table manipulator instance. */ public function __construct( IMetaModel $objMetaModel, @@ -84,7 +86,9 @@ public function __construct( ); // @codingStandardsIgnoreEnd $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); } + $this->connection = $connection; if (null === $tableManipulator) { // @codingStandardsIgnoreStart @@ -95,9 +99,8 @@ public function __construct( // @codingStandardsIgnoreEnd $tableManipulator = System::getContainer()->get('metamodels.table_manipulator'); + assert($tableManipulator instanceof TableManipulator); } - - $this->connection = $connection; $this->tableManipulator = $tableManipulator; } @@ -106,17 +109,18 @@ public function __construct( * * This tells the attribute to perform any actions that must be done to correctly initialize the new value * and to perform any action to undo the changes that had been done for the previous value. - * i.e.: when an attribute type needs columns in an an auxiliary table, these will have to be updated herein. + * i.e.: when an attribute type needs columns in an auxiliary table, these will have to be updated herein. * * This method may throw an exception, when the new value is invalid or any problems appear, the MetaModelAttribute * will then keep the old meta value. * * @param string $strMetaName Name of the meta information that shall be updated. - * - * @param mixed $varNewValue The new value for this meta information. + * @param mixed $varNewValue The new value for this meta information. * * @return \MetaModels\Attribute\IAttribute The instance of this attribute, to support chaining. * + * @throws Exception + * * @deprecated Implement schema generators instead. */ public function handleMetaChange($strMetaName, $varNewValue) @@ -126,13 +130,17 @@ public function handleMetaChange($strMetaName, $varNewValue) return $this; } - // By default we accept any change of meta information. - if ($strMetaName == 'colname') { - if ($this->get($strMetaName) != $varNewValue) { + // By default, we accept any change of meta information. + if ($strMetaName === 'colname') { + if ($this->get($strMetaName) !== $varNewValue) { + /** @psalm-suppress DeprecatedMethod */ $this->renameColumn($varNewValue); } + return $this; } + + /** @psalm-suppress DeprecatedMethod */ return parent::handleMetaChange($strMetaName, $varNewValue); } @@ -142,6 +150,8 @@ public function handleMetaChange($strMetaName, $varNewValue) * @param mixed $arrValues The values to be stored into database. Mapping is item id=>value. * * @return void + * + * @throws Exception */ public function setDataFor($arrValues) { @@ -153,7 +163,7 @@ public function setDataFor($arrValues) ->update($strTable, 't') ->where('t.id=:id') ->set('t.' . $strColName, ':' . $strColName) - ->setParameter($strColName, is_array($varData) ? serialize($varData) : $varData) + ->setParameter($strColName, \is_array($varData) ? \serialize($varData) : $varData) ->setParameter('id', $intId) ->executeQuery(); } @@ -161,6 +171,8 @@ public function setDataFor($arrValues) /** * {@inheritDoc} + * + * @throws Exception */ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) { @@ -177,7 +189,7 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) ->where('t.id IN (:ids)') ->groupBy('t.' . $strCol) ->orderBy('MIN(FIELD(t.id, :ids))') - ->setParameter('ids', $idList, Connection::PARAM_STR_ARRAY) + ->setParameter('ids', $idList, ArrayParameterType::STRING) ->executeQuery(); } else { $statement = $this->connection->createQueryBuilder() @@ -190,12 +202,13 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) $arrResult = []; while ($objRow = $statement->fetchAssociative()) { - if (is_array($arrCount)) { + if (\is_array($arrCount)) { $arrCount[$objRow[$strCol]] = $objRow['mm_count']; } $arrResult[$objRow[$strCol]] = $objRow[$strCol]; } + return $arrResult; } @@ -203,20 +216,20 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) * {@inheritdoc} * * This base implementation does a plain SQL sort by native value as defined by MySQL. + * + * @throws Exception */ public function sortIds($idList, $strDirection) { // Base implementation, do a simple sorting on given column. - $idList = $this->connection->createQueryBuilder() + return $this->connection->createQueryBuilder() ->select('t.id') ->from($this->getMetaModel()->getTableName(), 't') ->where('t.id IN (:ids)') - ->setParameter('ids', $idList, Connection::PARAM_STR_ARRAY) + ->setParameter('ids', $idList, ArrayParameterType::STRING) ->orderBy('t.' . $this->getColName(), $strDirection) ->executeQuery() ->fetchFirstColumn(); - - return $idList; } /** @@ -227,12 +240,15 @@ public function sortIds($idList, $strDirection) * * @param string $strPattern The text to search for. This may contain wildcards. * - * @return int[] the ids of matching items. + * @return list The ids of matching items. + * + * @throws Exception */ public function searchFor($strPattern) { // Base implementation, do a simple search on given column. - $strPattern = str_replace(array('*', '?'), array('%', '_'), $strPattern); + $strPattern = \str_replace(['*', '?'], ['%', '_'], $strPattern); + return $this->connection->createQueryBuilder() ->select('t.id') ->from($this->getMetaModel()->getTableName(), 't') @@ -272,12 +288,16 @@ public function destroyAUX() { if ($this->isManagedAttribute($this->get('type'))) { $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); + return; } $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); + /** @psalm-suppress DeprecatedMethod */ parent::destroyAUX(); + + /** @psalm-suppress DeprecatedMethod */ $this->deleteColumn(); } @@ -286,18 +306,24 @@ public function destroyAUX() * * @return void * + * @throws Exception + * * @deprecated Implement schema generators instead - see #1267. */ public function initializeAUX() { if ($this->isManagedAttribute($this->get('type'))) { $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); + return; } $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); + /** @psalm-suppress DeprecatedMethod */ parent::initializeAUX(); + + /** @psalm-suppress DeprecatedMethod */ $this->createColumn(); } @@ -308,18 +334,22 @@ public function initializeAUX() * * @return void * + * @throws Exception + * * @deprecated Implement schema generators instead - see #1267. */ public function createColumn() { if ($this->isManagedAttribute($this->get('type'))) { $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); + return; } $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); if ($this->getColName()) { + /** @psalm-suppress DeprecatedMethod */ $this->tableManipulator->createColumn( $this->getMetaModel()->getTableName(), $this->getColName(), @@ -333,18 +363,21 @@ public function createColumn() * * @return void * + * @throws Exception + * * @deprecated Implement schema generators instead - see #1267. */ public function deleteColumn() { if ($this->isManagedAttribute($this->get('type'))) { $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); + return; } $this->triggerDeprecationIsUnmanagedAttribute(static::class, __METHOD__); - $schemaManager = $this->connection->getSchemaManager(); + $schemaManager = $this->connection->createSchemaManager(); $columns = $schemaManager->listTableColumns($this->getMetaModel()->getTableName()); // Try to delete the column. If it does not exist as we can assume it has been deleted already then. @@ -360,12 +393,15 @@ public function deleteColumn() * * @return void * + * @throws Exception + * * @deprecated Implement schema generators instead - see #1267. */ public function renameColumn($strNewColumnName) { if ($this->isManagedAttribute($this->get('type'))) { $this->triggerDeprecationShouldNotCallManaged(static::class, __METHOD__); + return; } @@ -373,10 +409,11 @@ public function renameColumn($strNewColumnName) $this->tableManipulator->checkColumnName($strNewColumnName); - $schemaManager = $this->connection->getSchemaManager(); + $schemaManager = $this->connection->createSchemaManager(); $columns = $schemaManager->listTableIndexes($this->getMetaModel()->getTableName()); if ($this->getColName() && isset($columns[$this->getColName()])) { + /** @psalm-suppress DeprecatedMethod */ $this->tableManipulator->renameColumn( $this->getMetaModel()->getTableName(), $this->getColName(), @@ -386,6 +423,7 @@ public function renameColumn($strNewColumnName) } else { $strBackupColName = $this->getColName(); $this->set('colname', $strNewColumnName); + /** @psalm-suppress DeprecatedMethod */ $this->createColumn(); $this->set('colname', $strBackupColName); } @@ -408,10 +446,14 @@ public function unserializeData($value) * * @param mixed $value The input value. * - * @return string + * @return string|null */ public function serializeData($value) { - return $value; + if (empty($value)) { + return null; + } + + return (string) $value; } } diff --git a/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php b/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php index e2dce95aa..ca3eab987 100644 --- a/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php +++ b/src/Attribute/Events/CollectMetaModelAttributeInformationEvent.php @@ -1,112 +1,112 @@ - - * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -namespace MetaModels\Attribute\Events; - -use MetaModels\IMetaModel; -use Symfony\Contracts\EventDispatcher\Event; - -/** - * This event is triggered for every metamodel when the attribute information for the MetaModel shall be retrieved. - * - * @SuppressWarnings(PHPMD.LongClassName) - */ -class CollectMetaModelAttributeInformationEvent extends Event -{ - /** - * The event name. - */ - const NAME = 'metamodels.metamodel.collect-metamodel-attribute-information'; - - /** - * The MetaModel instance being created. - * - * @var IMetaModel - */ - protected $metaModel; - - /** - * The attribute information. - * - * @var array[] - */ - protected $attributeInformation = array(); - - /** - * Create a new instance. - * - * @param IMetaModel $metaModel The name of the MetaModel to collect the attribute information for. - */ - public function __construct(IMetaModel $metaModel) - { - $this->metaModel = $metaModel; - } - - /** - * Retrieve the MetaModel instance. - * - * @return IMetaModel - */ - public function getMetaModel() - { - return $this->metaModel; - } - - /** - * Retrieve the attribute information. - * - * @return array - */ - public function getAttributeInformation() - { - return $this->attributeInformation; - } - - /** - * Set the attribute information. - * - * @param array[] $attributeInformation The attribute information. - * - * @return CollectMetaModelAttributeInformationEvent - */ - public function setAttributeInformation($attributeInformation) - { - $this->attributeInformation = $attributeInformation; - - return $this; - } - - /** - * Set the MetaModel instance. - * - * @param string $attributeName The internal name of the attribute (column name). - * - * @param array $attributeInformation The attribute information. - * - * @return CollectMetaModelAttributeInformationEvent - */ - public function addAttributeInformation($attributeName, $attributeInformation) - { - $this->attributeInformation[$attributeName] = $attributeInformation; - - return $this; - } -} + + * @author Sven Baumann + * @author Ingolf Steinhardt + * @copyright 2012-2022 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\Attribute\Events; + +use MetaModels\IMetaModel; +use Symfony\Contracts\EventDispatcher\Event; + +/** + * This event is triggered for every metamodel when the attribute information for the MetaModel shall be retrieved. + * + * @SuppressWarnings(PHPMD.LongClassName) + */ +class CollectMetaModelAttributeInformationEvent extends Event +{ + /** + * The event name. + */ + public const NAME = 'metamodels.metamodel.collect-metamodel-attribute-information'; + + /** + * The MetaModel instance being created. + * + * @var IMetaModel + */ + protected $metaModel; + + /** + * The attribute information. + * + * @var array[] + */ + protected $attributeInformation = array(); + + /** + * Create a new instance. + * + * @param IMetaModel $metaModel The name of the MetaModel to collect the attribute information for. + */ + public function __construct(IMetaModel $metaModel) + { + $this->metaModel = $metaModel; + } + + /** + * Retrieve the MetaModel instance. + * + * @return IMetaModel + */ + public function getMetaModel() + { + return $this->metaModel; + } + + /** + * Retrieve the attribute information. + * + * @return array + */ + public function getAttributeInformation() + { + return $this->attributeInformation; + } + + /** + * Set the attribute information. + * + * @param array[] $attributeInformation The attribute information. + * + * @return CollectMetaModelAttributeInformationEvent + */ + public function setAttributeInformation($attributeInformation) + { + $this->attributeInformation = $attributeInformation; + + return $this; + } + + /** + * Set the MetaModel instance. + * + * @param string $attributeName The internal name of the attribute (column name). + * + * @param array $attributeInformation The attribute information. + * + * @return CollectMetaModelAttributeInformationEvent + */ + public function addAttributeInformation($attributeName, $attributeInformation) + { + $this->attributeInformation[$attributeName] = $attributeInformation; + + return $this; + } +} diff --git a/src/Attribute/Events/CreateAttributeEvent.php b/src/Attribute/Events/CreateAttributeEvent.php index e0740ef09..6ecd2932d 100644 --- a/src/Attribute/Events/CreateAttributeEvent.php +++ b/src/Attribute/Events/CreateAttributeEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -33,7 +33,7 @@ class CreateAttributeEvent extends Event /** * The event name. */ - const NAME = 'metamodels.attribute.create'; + public const NAME = 'metamodels.attribute.create'; /** * The attribute information. @@ -52,7 +52,7 @@ class CreateAttributeEvent extends Event /** * The attribute instance. * - * @var IAttribute + * @var IAttribute|null */ protected $attribute; @@ -60,7 +60,6 @@ class CreateAttributeEvent extends Event * Create a new instance. * * @param array $attributeInformation The attribute information array. - * * @param IMetaModel $metaModel The MetaModel instance for which the attribute shall get created for. */ public function __construct($attributeInformation, $metaModel) @@ -92,7 +91,7 @@ public function getMetaModel() /** * Retrieve the attribute instance. * - * @return IAttribute + * @return IAttribute|null */ public function getAttribute() { diff --git a/src/Attribute/IAttribute.php b/src/Attribute/IAttribute.php index d9b1b5e51..775362930 100644 --- a/src/Attribute/IAttribute.php +++ b/src/Attribute/IAttribute.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author David Maack * @author Stefan Heimes * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,17 +36,17 @@ interface IAttribute { /** - * Retrieve the human readable name (or title) from the attribute. + * Retrieve the human-readable name (or title) from the attribute. * * If the MetaModel is translated, the currently active language is used, * with properly falling back to the defined fallback language. * - * @return string the human readable name + * @return string the human-readable name */ public function getName(); /** - * Queries the attribute for it's column name within it's MetaModel. + * Queries the attribute for its column name within it's MetaModel. * * @return string the attributes column name. */ @@ -70,13 +71,12 @@ public function get($strKey); /** * Override a meta information setting. * - * All changes to an attribute via set() are considered to be non persistent and therefore will not update any + * All changes to an attribute via set() are considered to be non-persistent and therefore will not update any * structural information or auxiliary properties that might be needed within the attribute type. * * For persistent updates, use {@link IAttribute::handleMetaChange()} instead. * * @param string $strKey The meta information name that shall be set. - * * @param mixed $varValue The value to set. * * @return IAttribute Instance of this attribute, for chaining support. @@ -94,7 +94,6 @@ public function set($strKey, $varValue); * will then keep the old meta value. * * @param string $strMetaName Name of the meta information that shall be updated. - * * @param mixed $varNewValue The new value for this meta information. * * @return IAttribute The instance of this attribute, to support chaining. @@ -124,8 +123,8 @@ public function initializeAUX(); /** * Returns all valid settings for the attribute type. * - * @return string[] All valid setting names, this re-ensembles the columns in tl_metamodel_attribute - * this attribute class understands. + * @return list All valid setting names, this re-ensembles the columns in tl_metamodel_attribute + * this attribute class understands. */ public function getAttributeSettingNames(); @@ -136,8 +135,8 @@ public function getAttributeSettingNames(); * Using the optional override parameter, settings known by this attribute can be overridden for the * generating of the output array. * - * @param array $arrOverrides The values to override, for a list of valid parameters, call - * getAttributeSettingNames(). + * @param array $arrOverrides The values to override, for a list of valid parameters, call + * getAttributeSettingNames(). * * @return array The DCA array to use as $GLOBALS['TL_DCA']['tablename']['fields']['attribute-name] */ @@ -151,7 +150,7 @@ public function getFieldDefinition($arrOverrides = array()); * Due to the fact that it calls getFieldDefinition() internally, the result at least contains * the sub array 'fields' with the information of this field's settings. * - * @param array $arrOverrides See documentation in getFieldDefinition() method. + * @param array $arrOverrides See documentation in getFieldDefinition() method. * * @return array The DCA array to use as $GLOBALS['tablename'] * @@ -181,7 +180,6 @@ public function valueToWidget($varValue); * value. * * @param mixed $varValue The value to be transformed. - * * @param string $itemId The id of the item the value belongs to. * * @return mixed The resulting native value @@ -191,7 +189,7 @@ public function widgetToValue($varValue, $itemId); /** * This method is called to store the data for certain items to the database. * - * @param mixed[] $arrValues The values to be stored into database. Mapping is item id=>value. + * @param array $arrValues The values to be stored into database. Mapping is item id=>value. * * @return void */ @@ -212,9 +210,7 @@ public function getDefaultRenderSettings(); * Each attribute class MAY return as many other values in this array with custom keys as it wants. * * @param array $arrRowData The (native) row data from the MetaModel table. - * * @param string $strOutputFormat The desired output format. - * * @param ISimpleRenderSetting|null $objSettings Custom settings to be passed to the renderer. * * @return array An array with all the converted data. @@ -233,11 +229,10 @@ public function getFilterUrlValue($varValue); /** * Sorts the given array list by field value in the given direction. * - * @param string[] $idList A list of Ids from the MetaModel table. + * @param list $idList A list of Ids from the MetaModel table. + * @param string $strDirection The direction for sorting. either 'ASC' or 'DESC', as in plain SQL. * - * @param string $strDirection The direction for sorting. either 'ASC' or 'DESC', as in plain SQL. - * - * @return string[] The sorted array. + * @return list The sorted array. */ public function sortIds($idList, $strDirection); @@ -253,12 +248,10 @@ public function sortIds($idList, $strDirection); * This is only relevant, when using "null" as id list for attributes that have pre configured * values like select lists and tags i.e. * - * @param string[]|null $idList The ids of items that the values shall be fetched from - * (If empty or null, all items). - * - * @param bool $usedOnly Determines if only "used" values shall be returned. - * - * @param array|null $arrCount Array for the counted values. + * @param list|null $idList The ids of items that the values shall be fetched from + * (If empty or null, all items). + * @param bool $usedOnly Determines if only "used" values shall be returned. + * @param array|null $arrCount Array for the counted values. * * @return array All options matching the given conditions as name => value. */ @@ -271,7 +264,7 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null); * * @param string $strPattern The text to search for. This may contain wildcards. * - * @return string[]|null The list of item ids of all items matching the condition or null if all match. + * @return list The list of item ids of all items matching the condition or null if all match. */ public function searchFor($strPattern); @@ -279,10 +272,9 @@ public function searchFor($strPattern); * Filter all values greater than the passed value. * * @param mixed $varValue The value to use as lower end. - * * @param bool $blnInclusive If true, the passed value will be included, if false, it will be excluded. * - * @return string[]|null The list of item ids of all items matching the condition or null if all match. + * @return list|null The list of item ids of all items matching the condition or null if all match. */ public function filterGreaterThan($varValue, $blnInclusive = false); @@ -290,10 +282,9 @@ public function filterGreaterThan($varValue, $blnInclusive = false); * Filter all values less than the passed value. * * @param mixed $varValue The value to use as upper end. - * * @param bool $blnInclusive If true, the passed value will be included, if false, it will be excluded. * - * @return string[]|null The list of item ids of all items matching the condition or null if all match. + * @return list|null The list of item ids of all items matching the condition or null if all match. */ public function filterLessThan($varValue, $blnInclusive = false); @@ -302,7 +293,7 @@ public function filterLessThan($varValue, $blnInclusive = false); * * @param mixed $varValue The value to use as upper end. * - * @return string[]|null The list of item ids of all items matching the condition or null if all match. + * @return list|null The list of item ids of all items matching the condition or null if all match. */ public function filterNotEqual($varValue); diff --git a/src/Attribute/IAttributeFactory.php b/src/Attribute/IAttributeFactory.php index 8118c62fa..8b272abe7 100644 --- a/src/Attribute/IAttributeFactory.php +++ b/src/Attribute/IAttributeFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,36 +33,35 @@ interface IAttributeFactory extends IServiceContainerAware /** * Flag for filtering translated attributes. */ - const FLAG_INCLUDE_TRANSLATED = 1; + public const FLAG_INCLUDE_TRANSLATED = 1; /** * Flag for translated attributes. */ - const FLAG_INCLUDE_SIMPLE = 2; + public const FLAG_INCLUDE_SIMPLE = 2; /** * Flag for complex attributes. */ - const FLAG_INCLUDE_COMPLEX = 4; + public const FLAG_INCLUDE_COMPLEX = 4; /** * Flag for retrieving all attribute types. */ - const FLAG_ALL = 7; + public const FLAG_ALL = 7; /** * Flag for filtering untranslated attributes. * * NOTE: When using this flag, translated complex and translated simple types will also get returned. */ - const FLAG_ALL_UNTRANSLATED = 6; + public const FLAG_ALL_UNTRANSLATED = 6; /** * Create an attribute instance from an information array. * - * @param array $information The attribute information. - * - * @param IMetaModel $metaModel The MetaModel instance for which the attribute shall be created. + * @param array $information The attribute information. + * @param IMetaModel $metaModel The MetaModel instance for which the attribute shall be created. * * @return IAttribute|null */ @@ -81,7 +81,7 @@ public function addTypeFactory(IAttributeTypeFactory $typeFactory); * * @param string $typeFactory The name of the type factory to retrieve. * - * @return IAttributeTypeFactory + * @return IAttributeTypeFactory|null */ public function getTypeFactory($typeFactory); @@ -99,9 +99,9 @@ public function attributeTypeMatchesFlags($factory, $flags); /** * Retrieve the type names registered in the factory. * - * @param bool|int $flags The flags for retrieval. See the interface constants for the different values. + * @param false|int $flags The flags for retrieval. See the interface constants for the different values. * - * @return string[] + * @return list */ public function getTypeNames($flags = false); diff --git a/src/Attribute/IComplex.php b/src/Attribute/IComplex.php index 1d173dc2b..2b5603d49 100644 --- a/src/Attribute/IComplex.php +++ b/src/Attribute/IComplex.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @author Christian Schiffler * @author David Maack * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -31,17 +32,17 @@ interface IComplex extends IAttribute /** * This method is called to retrieve the data for certain items from the database. * - * @param string[] $arrIds The ids of the items to retrieve. + * @param list $arrIds The ids of the items to retrieve. * - * @return mixed[] The nature of the resulting array is a mapping from id => "native data" where - * the definition of "native data" is only of relevance to the given item. + * @return array The nature of the resulting array is a mapping from id => "native data" where + * the definition of "native data" is only of relevance to the given item. */ public function getDataFor($arrIds); /** * Remove values for items. * - * @param string[] $arrIds The ids of the items to retrieve. + * @param list $arrIds The ids of the items to retrieve. * * @return void */ diff --git a/src/Attribute/ISimple.php b/src/Attribute/ISimple.php index bb33d4f92..4614acfb3 100644 --- a/src/Attribute/ISimple.php +++ b/src/Attribute/ISimple.php @@ -80,7 +80,7 @@ public function unserializeData($value); * * @param mixed $value The input value. * - * @return string + * @return string|null */ public function serializeData($value); } diff --git a/src/Attribute/ITranslated.php b/src/Attribute/ITranslated.php index 84aa3a415..144f2955f 100644 --- a/src/Attribute/ITranslated.php +++ b/src/Attribute/ITranslated.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -39,21 +40,19 @@ public function getMetaModel(); /** * Search matches for the given expression. * - * @param string $strPattern The text to search for. This may contain wildcards. + * @param string $strPattern The text to search for. This may contain wildcards. + * @param list $arrLanguages Array of valid language codes that shall be searched. + * (optional) If empty, all languages will be taken into account. * - * @param array $arrLanguages Array of valid language codes that shall be searched. (optional) - * If empty, all languages will be taken into account. - * - * @return string[] the ids of matching items. + * @return list the ids of matching items. */ - public function searchForInLanguages($strPattern, $arrLanguages = array()); + public function searchForInLanguages($strPattern, $arrLanguages = []); /** * Set a value for an item in a certain language. * - * @param mixed[] $arrValues The values to be set in id => value layout. - * - * @param string $strLangCode The language code for which the data shall be retrieved. + * @param array> $arrValues The values to be set in id => value layout. + * @param string $strLangCode The language code for which the data shall be retrieved. * * @return void */ @@ -62,20 +61,18 @@ public function setTranslatedDataFor($arrValues, $strLangCode); /** * Get values for the given items in a certain language. * - * @param string[] $arrIds The ids for which values shall be retrieved. + * @param list $arrIds The ids for which values shall be retrieved. + * @param string $strLangCode The language code for which the data shall be retrieved. * - * @param string $strLangCode The language code for which the data shall be retrieved. - * - * @return mixed[] the values. + * @return array> the values. */ public function getTranslatedDataFor($arrIds, $strLangCode); /** * Remove values for items in a certain language. * - * @param string[] $arrIds The ids for which values shall be removed. - * - * @param string $strLangCode The language code for which the data shall be removed. + * @param list $arrIds The ids for which values shall be removed. + * @param string $strLangCode The language code for which the data shall be removed. * * @return void */ diff --git a/src/Attribute/ManagedAttributeTrait.php b/src/Attribute/ManagedAttributeTrait.php index 32237fd49..235dbd107 100644 --- a/src/Attribute/ManagedAttributeTrait.php +++ b/src/Attribute/ManagedAttributeTrait.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,8 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,13 +27,12 @@ trait ManagedAttributeTrait private function isManagedAttribute(string $type): bool { $container = System::getContainer(); - return in_array( - $type, - $container->hasParameter('metamodels.managed-schema-type-names') - ? ($container->getParameter('metamodels.managed-schema-type-names') ?? []) - : [], - true - ); + $parameter = []; + if ($container->hasParameter('metamodels.managed-schema-type-names')) { + $parameter = $container->getParameter('metamodels.managed-schema-type-names'); + assert(\is_array($parameter)); + } + return \in_array($type, $parameter, true); } private function triggerDeprecationIsUnmanagedAttribute(string $class, string $method): void diff --git a/src/Attribute/TranslatedReference.php b/src/Attribute/TranslatedReference.php index e576cdb62..4c0dea630 100644 --- a/src/Attribute/TranslatedReference.php +++ b/src/Attribute/TranslatedReference.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author David Molineus * @author Andreas Fischer - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -30,12 +30,13 @@ use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\QueryBuilder; -use MetaModels\Filter\Rules\SimpleQuery; use MetaModels\IMetaModel; use MetaModels\ITranslatedMetaModel; /** * This is the MetaModelAttribute class for handling translated attributes that reference another table. + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ abstract class TranslatedReference extends BaseComplex implements ITranslated { @@ -51,11 +52,11 @@ abstract class TranslatedReference extends BaseComplex implements ITranslated * * Note that you should not use this directly but use the factory classes to instantiate attributes. * - * @param IMetaModel $objMetaModel The MetaModel instance this attribute belongs to. - * @param array $arrData The information array, for attribute information, refer to documentation of - * table tl_metamodel_attribute and documentation of the certain attribute classes - * for information what values are understood. - * @param Connection $connection Database connection. + * @param IMetaModel $objMetaModel The MetaModel instance this attribute belongs to. + * @param array $arrData The information array, for attribute information, refer to documentation of + * table tl_metamodel_attribute and documentation of the certain attribute + * classes for information what values are understood. + * @param Connection|null $connection Database connection. */ public function __construct(IMetaModel $objMetaModel, $arrData = [], Connection $connection = null) { @@ -69,8 +70,8 @@ public function __construct(IMetaModel $objMetaModel, $arrData = [], Connection ); // @codingStandardsIgnoreEnd $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); } - $this->connection = $connection; } @@ -84,54 +85,52 @@ abstract protected function getValueTable(); /** * Build a where clause for the given id(s) and language code. * - * @param QueryBuilder $queryBuilder The query builder for the query being build. - * @param string[]|string|null $mixIds One, none or many ids to use. - * @param string|string[] $mixLangCode The language code/s to use, optional. + * @param QueryBuilder $queryBuilder The query builder for the query being build. + * @param list|string|null $mixIds One, none or many ids to use. + * @param list $mixLangCode The language code/s to use, optional. * * @return void */ - private function buildWhere(QueryBuilder $queryBuilder, $mixIds, $mixLangCode = '') - { - $alias = ''; - if (null !== $firstFromAlias = $queryBuilder->getQueryPart('from')[0]['alias'] ?? null) { - $alias = $firstFromAlias . '.'; - } - + private function buildWhere( + QueryBuilder $queryBuilder, + array|string|null $mixIds, + array $mixLangCode, + string $alias + ): void { $queryBuilder - ->andWhere($alias . 'att_id = :att_id') + ->andWhere($alias . '.att_id = :att_id') ->setParameter('att_id', $this->get('id')); - if (!empty($mixIds)) { - if (is_array($mixIds)) { - $queryBuilder - ->andWhere($alias . 'item_id IN (:item_ids)') - ->setParameter('item_ids', $mixIds, Connection::PARAM_STR_ARRAY); + if (null !== $mixIds) { + if (\is_array($mixIds)) { + if ([] === $mixIds) { + $queryBuilder + ->andWhere('1=0'); + } else { + $queryBuilder + ->andWhere($alias . '.item_id IN (:item_ids)') + ->setParameter('item_ids', $mixIds, ArrayParameterType::STRING); + } } else { $queryBuilder - ->andWhere($alias . 'item_id = :item_id') + ->andWhere($alias . '.item_id = :item_id') ->setParameter('item_id', $mixIds); } } - if (!empty($mixLangCode)) { - if (is_array($mixLangCode)) { - $queryBuilder - ->andWhere($alias . 'langcode IN (:langcode)') - ->setParameter('langcode', $mixLangCode, Connection::PARAM_STR_ARRAY); - } else { - $queryBuilder - ->andWhere($alias . 'langcode = :langcode') - ->setParameter('langcode', $mixLangCode); - } + if ([] !== $mixLangCode) { + $queryBuilder + ->andWhere($alias . '.langcode IN (:langcode)') + ->setParameter('langcode', $mixLangCode, ArrayParameterType::STRING); } } /** * Retrieve the values to be used in the INSERT or UPDATE SQL for the given parameters. * - * @param array $arrValue The native value of the attribute. - * @param int $intId The id of the item to be saved. - * @param string $strLangCode The language code of the language the value is in. + * @param array{value: mixed, ...} $arrValue The native value of the attribute. + * @param string $intId The id of the item to be saved. + * @param string $strLangCode The language code of the language the value is in. * * @return array * @@ -139,18 +138,22 @@ private function buildWhere(QueryBuilder $queryBuilder, $mixIds, $mixLangCode = */ protected function getSetValues($arrValue, $intId, $strLangCode) { - if (($arrValue !== null) && !is_array($arrValue)) { - throw new \InvalidArgumentException(sprintf('Invalid value provided: %s', var_export($arrValue, true))); + /** + * @psalm-suppress DocblockTypeContradiction + * @psalm-suppress RedundantConditionGivenDocblockType + * Remove when we have strict type hints in the method signature. + */ + if (($arrValue === null) || !\is_array($arrValue)) { + throw new \InvalidArgumentException(\sprintf('Invalid value provided: %s', \var_export($arrValue, true))); } - return array - ( - 'tstamp' => time(), - 'value' => (string) $arrValue['value'], - 'att_id' => $this->get('id'), + return [ + 'tstamp' => \time(), + 'value' => (string) $arrValue['value'], + 'att_id' => $this->get('id'), 'langcode' => $strLangCode, - 'item_id' => $intId, - ); + 'item_id' => $intId, + ]; } /** @@ -185,7 +188,7 @@ public function valueToWidget($varValue) public function widgetToValue($varValue, $itemId) { return [ - 'tstamp' => time(), + 'tstamp' => \time(), 'value' => $varValue, 'att_id' => $this->get('id'), ]; @@ -196,14 +199,16 @@ public function widgetToValue($varValue, $itemId) */ public function getDataFor($arrIds) { - $strActiveLanguage = $this->getActiveLanguage(); + /** @psalm-suppress DeprecatedMethod */ + $strActiveLanguage = $this->getActiveLanguage(); + /** @psalm-suppress DeprecatedMethod */ $strFallbackLanguage = $this->getFallbackLanguage(); $arrReturn = $this->getTranslatedDataFor($arrIds, $strActiveLanguage); // Second round, fetch fallback languages if not all items could be resolved. - if ((count($arrReturn) < count($arrIds)) && ($strActiveLanguage != $strFallbackLanguage)) { - $arrFallbackIds = array(); + if ((\count($arrReturn) < \count($arrIds)) && ($strActiveLanguage !== $strFallbackLanguage)) { + $arrFallbackIds = []; foreach ($arrIds as $intId) { if (empty($arrReturn[$intId])) { $arrFallbackIds[] = $intId; @@ -211,7 +216,7 @@ public function getDataFor($arrIds) } if ($arrFallbackIds) { - $arrFallbackData = $this->getTranslatedDataFor($arrFallbackIds, $strFallbackLanguage); + $arrFallbackData = $this->getTranslatedDataFor($arrFallbackIds, $strFallbackLanguage ?? ''); // Cannot use array_merge here as it would renumber the keys. foreach ($arrFallbackData as $intId => $arrValue) { $arrReturn[$intId] = $arrValue; @@ -224,7 +229,7 @@ public function getDataFor($arrIds) /** * Determine the available languages. * - * @return null|\string[] + * @return list * * @throws \RuntimeException When an untranslated MetaModel is encountered. */ @@ -235,12 +240,14 @@ private function determineLanguages() return $metaModel->getLanguages(); } + /** @psalm-suppress DeprecatedMethod */ $languages = $this->getMetaModel()->getAvailableLanguages(); if ($languages === null) { throw new \RuntimeException( 'MetaModel ' . $this->getMetaModel()->getName() . ' does not seem to be translated.' ); } + return $languages; } @@ -269,17 +276,20 @@ public function unsetDataFor($arrIds) */ public function searchFor($strPattern) { - return $this->searchForInLanguages($strPattern, array($this->getActiveLanguage())); + return $this->searchForInLanguages($strPattern, [$this->getActiveLanguage()]); } /** * {@inheritDoc} */ - public function searchForInLanguages($strPattern, $arrLanguages = array()) + public function searchForInLanguages($strPattern, $arrLanguages = []) { - $optionizer = $this->getOptionizer(); + if (empty($optionizer = $this->getOptionizer())) { + return []; + } + $procedure = 't.' . $optionizer['value'] . ' LIKE :pattern'; - $strPattern = str_replace(['*', '?'], ['%', '_'], $strPattern); + $strPattern = \str_replace(['*', '?'], ['%', '_'], $strPattern); $queryBuilder = $this->connection->createQueryBuilder() ->select('DISTINCT t.item_id') @@ -287,11 +297,9 @@ public function searchForInLanguages($strPattern, $arrLanguages = array()) ->andWhere($procedure) ->setParameter('pattern', $strPattern); - $this->buildWhere($queryBuilder, null, $arrLanguages); - - $filterRule = SimpleQuery::createFromQueryBuilder($queryBuilder, 'item_id'); + $this->buildWhere($queryBuilder, null, $arrLanguages, 't'); - return $filterRule->getMatchingIds(); + return $queryBuilder->executeQuery()->fetchFirstColumn(); } /** @@ -308,11 +316,11 @@ public function sortIds($idList, $strDirection) 't1', $this->getValueTable(), 't2', - $expr - ->andX() - ->add($expr->eq('t1.att_id', 't2.att_id')) - ->add($expr->eq('t1.item_id', 't2.item_id')) - ->add($expr->eq('t2.langcode', ':langcode')) + (string) $expr->and( + $expr->eq('t1.att_id', 't2.att_id'), + $expr->eq('t1.item_id', 't2.item_id'), + $expr->eq('t2.langcode', ':langcode'), + ) ) ->where($expr->eq('t1.att_id', ':att_id')) ->andWhere($expr->in('t1.item_id', ':id_list')) @@ -334,7 +342,7 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) ->select('t.*') ->from($this->getValueTable(), 't'); - $this->buildWhere($queryBuilder, $idList, $this->getActiveLanguage()); + $this->buildWhere($queryBuilder, $idList, [$this->getActiveLanguage()], 't'); $statement = $queryBuilder->executeQuery(); $arrOptionizer = $this->getOptionizer(); @@ -351,20 +359,23 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) */ public function setTranslatedDataFor($arrValues, $strLangCode) { + if ('' === $strLangCode) { + throw new \InvalidArgumentException('Empty language code provided.'); + } // First off determine those to be updated and those to be inserted. - $arrIds = array_keys($arrValues); + $arrIds = \array_keys($arrValues); $arrExisting = $this->fetchExistingIdsFor($arrIds, $strLangCode); - $arrNewIds = array_diff($arrIds, $arrExisting); + $arrNewIds = \array_diff($arrIds, $arrExisting); // Update existing values - delete if empty. foreach ($arrExisting as $intId) { $queryBuilder = $this->connection->createQueryBuilder(); - $this->buildWhere($queryBuilder, $intId, $strLangCode); - - if ($arrValues[$intId]['value'] != '') { + $this->buildWhere($queryBuilder, $intId, [$strLangCode], 't'); + $itemValues = $arrValues[$intId] ?? []; + if ($this->isValidItemValue($itemValues)) { $queryBuilder->update($this->getValueTable(), 't'); - foreach ($this->getSetValues($arrValues[$intId], $intId, $strLangCode) as $name => $value) { + foreach ($this->getSetValues($itemValues, $intId, $strLangCode) as $name => $value) { $queryBuilder ->set('t.' . $name, ':' . $name) ->setParameter($name, $value); @@ -378,37 +389,36 @@ public function setTranslatedDataFor($arrValues, $strLangCode) // Insert the new values. foreach ($arrNewIds as $intId) { - if (!isset($arrValues[$intId]['value']) || $arrValues[$intId]['value'] == '') { + $itemValues = $arrValues[$intId] ?? []; + if (!$this->isValidItemValue($itemValues)) { continue; } - $this->connection->insert( - $this->getValueTable(), - $this->getSetValues($arrValues[$intId], $intId, $strLangCode) - ); + $this->connection->insert($this->getValueTable(), $this->getSetValues($itemValues, $intId, $strLangCode)); } } /** * Filter the item ids for ids that exist in the database. * - * @param array $idList The id list. - * @param string $langCode The language code. + * @param list $idList The id list. + * @param string $langCode The language code. * * @return string[] */ protected function fetchExistingIdsFor($idList, $langCode) { + if ('' === $langCode) { + throw new \InvalidArgumentException('Empty language code provided.'); + } $queryBuilder = $this ->connection ->createQueryBuilder() ->select('t.item_id') ->from($this->getValueTable(), 't'); - $this->buildWhere($queryBuilder, $idList, $langCode); - - $statement = $queryBuilder->executeQuery(); + $this->buildWhere($queryBuilder, $idList, [$langCode], 't'); - return $statement->fetchFirstColumn(); + return $queryBuilder->executeQuery()->fetchFirstColumn(); } /** @@ -416,16 +426,18 @@ protected function fetchExistingIdsFor($idList, $langCode) */ public function getTranslatedDataFor($arrIds, $strLangCode) { + if ('' === $strLangCode) { + throw new \InvalidArgumentException('Empty language code provided.'); + } $queryBuilder = $this->connection->createQueryBuilder() ->select('t.*') ->from($this->getValueTable(), 't'); - $this->buildWhere($queryBuilder, $arrIds, $strLangCode); + $this->buildWhere($queryBuilder, $arrIds, [$strLangCode], 't'); $statement = $queryBuilder->executeQuery(); $arrReturn = []; while ($value = $statement->fetchAssociative()) { - /** @noinspection PhpUndefinedFieldInspection */ $arrReturn[$value['item_id']] = $value; } return $arrReturn; @@ -436,8 +448,11 @@ public function getTranslatedDataFor($arrIds, $strLangCode) */ public function unsetValueFor($arrIds, $strLangCode) { - $queryBuilder = $this->connection->createQueryBuilder()->delete($this->getValueTable()); - $this->buildWhere($queryBuilder, $arrIds, $strLangCode); + if ('' === $strLangCode) { + throw new \InvalidArgumentException('Empty language code provided.'); + } + $queryBuilder = $this->connection->createQueryBuilder()->delete($this->getValueTable(), 't'); + $this->buildWhere($queryBuilder, $arrIds, [$strLangCode], 't'); $queryBuilder->executeQuery(); } @@ -445,30 +460,45 @@ public function unsetValueFor($arrIds, $strLangCode) /** * Retrieve the current language of the MetaModel we are attached to. * - * @return string + * @return non-empty-string */ - private function getActiveLanguage() + private function getActiveLanguage(): string { $metaModel = $this->getMetaModel(); if (!$metaModel instanceof ITranslatedMetaModel) { - return $metaModel->getActiveLanguage(); + /** @psalm-suppress DeprecatedMethod */ + $activeLanguage = $metaModel->getActiveLanguage(); + assert('' !== $activeLanguage); + + return $activeLanguage; } + $activeLanguage = $metaModel->getLanguage(); + assert('' !== $activeLanguage); - return $metaModel->getLanguage(); + return $activeLanguage; } /** * Retrieve the main language of the MetaModel we are attached to. * - * @return string + * @return string|null */ - private function getFallbackLanguage() + private function getFallbackLanguage(): ?string { $metaModel = $this->getMetaModel(); if (!$metaModel instanceof ITranslatedMetaModel) { + /** @psalm-suppress DeprecatedMethod */ return $metaModel->getFallbackLanguage(); } return $metaModel->getMainLanguage(); } + + /** @psalm-assert-if-true array{value: non-empty-string, ...} $itemValues */ + private function isValidItemValue(array $itemValues): bool + { + return \array_key_exists('value', $itemValues) + && \is_string($itemValues['value']) + && '' !== $itemValues['value']; + } } diff --git a/src/BackendIntegration/InputScreen/IInputScreen.php b/src/BackendIntegration/InputScreen/IInputScreen.php index 43a06f441..921316cb8 100644 --- a/src/BackendIntegration/InputScreen/IInputScreen.php +++ b/src/BackendIntegration/InputScreen/IInputScreen.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author Stefan Heimes * @author Alexander Menk * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -28,6 +29,8 @@ /** * This interface describes the abstraction of an input screen. * + * @psalm-type TLegend=array{name: string, visible: bool, properties: list} + * * @deprecated This will get removed. */ interface IInputScreen @@ -42,14 +45,14 @@ public function getId(); /** * Retrieve all legends. * - * @return string[] + * @return array */ public function getLegends(); /** * Retrieve the names of all legends. * - * @return string[] + * @return list */ public function getLegendNames(); @@ -58,7 +61,7 @@ public function getLegendNames(); * * @param string $name The name of the legend. * - * @return array + * @return TLegend */ public function getLegend($name); @@ -81,7 +84,7 @@ public function getProperty($name); /** * Retrieve the names of all contained properties. * - * @return string[] + * @return list */ public function getPropertyNames(); diff --git a/src/BackendIntegration/InputScreen/InputScreen.php b/src/BackendIntegration/InputScreen/InputScreen.php index 83a5e9402..3e787a72a 100644 --- a/src/BackendIntegration/InputScreen/InputScreen.php +++ b/src/BackendIntegration/InputScreen/InputScreen.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Ingolf Steinhardt * @author Sven Baumann * @author Richard Henkenjohann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -36,17 +36,27 @@ use MetaModels\IMetaModel; use MetaModels\IMetaModelsServiceContainer; use MetaModels\ITranslatedMetaModel; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Implementation of IInputScreen. * + * @psalm-import-type TLegend from IInputScreen + * * @deprecated This class will get removed. + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * + * @psalm-suppress DeprecatedInterface */ class InputScreen implements IInputScreen { /** * The service container. * + * @psalm-suppress DeprecatedInterface + * * @var IMetaModelsServiceContainer */ protected $container; @@ -61,57 +71,55 @@ class InputScreen implements IInputScreen /** * The legends contained within the input screen. * - * @var array + * @var array */ - protected $legends = array(); + protected $legends = []; /** * The properties contained within the input screen. * * @var array */ - protected $properties = array(); + protected $properties = []; /** * The conditions. * * @var ConditionChainInterface[] */ - protected $conditions = array(); + protected $conditions = []; /** * Grouping and sorting information. * - * @var IInputScreenGroupingAndSorting[] + * @var list */ - protected $groupSort = array(); + protected $groupSort = []; /** * Simple map from property setting id to property name. * * @var array */ - protected $propertyMap = array(); + protected $propertyMap = []; /** * Simple map from property name to property setting id. * * @var array */ - protected $propertyMap2 = array(); + protected $propertyMap2 = []; /** * Create a new instance. * * @param IMetaModelsServiceContainer $container The service container. - * * @param array $data The information about the input screen. - * * @param array $propertyRows The information about all contained properties. - * * @param array $conditions The property condition information. - * * @param array $groupSort The grouping and sorting information. + * + * @psalm-suppress DeprecatedInterface */ public function __construct($container, $data, $propertyRows, $conditions, $groupSort) { @@ -127,7 +135,6 @@ public function __construct($container, $data, $propertyRows, $conditions, $grou * Transform a legend information into the property legends. * * @param array $legend The legend to transform. - * * @param IMetaModel $metaModel The metamodel the legend belongs to. * * @return string @@ -139,20 +146,19 @@ public function __construct($container, $data, $propertyRows, $conditions, $grou protected function translateLegend($legend, $metaModel) { $arrLegend = StringUtil::deserialize($legend['legendtitle']); - if (is_array($arrLegend)) { - $strLegend = $this->extractLegendName($arrLegend); + if (\is_array($arrLegend)) { + $strLegend = $this->extractLegendName($arrLegend, $metaModel); } else { - $strLegend = $legend['legendtitle'] ? $legend['legendtitle'] : 'legend'; + $strLegend = $legend['legendtitle'] ?: 'legend'; } $legendName = StringUtil::standardize($strLegend); - $this->legends[$legendName] = array - ( + $this->legends[$legendName] = [ 'name' => $strLegend, 'visible' => !(isset($legend['legendhide']) && (bool) $legend['legendhide']), - 'properties' => array() - ); + 'properties' => [] + ]; return $legendName; } @@ -177,9 +183,9 @@ private function extractLegendName(array $legend, IMetaModel $metaModel): string return $result; } // Is it a regional locale? - if (false !== strpos($language, '_')) { - $chunks = explode('_', $language); - $language = array_shift($chunks); + if (\str_contains($language, '_')) { + $chunks = \explode('_', $language); + $language = \array_shift($chunks); unset($chunks); if (null !== ($result = $legend[$language] ?? null)) { return $result; @@ -188,26 +194,25 @@ private function extractLegendName(array $legend, IMetaModel $metaModel): string // Try fallback language then. if ($metaModel instanceof ITranslatedMetaModel) { - if (null !== ($result = $legend[$metaModel->getMainLanguage()] ?? null)) { + if (null !== ($result = ($legend[$metaModel->getMainLanguage()] ?? null))) { return $result; } } else { - if (null !== ($result = $legend[$metaModel->getFallbackLanguage()] ?? null)) { + /** @psalm-suppress DeprecatedMethod */ + if (null !== ($result = ($legend[(string) $metaModel->getFallbackLanguage()] ?? null))) { return $result; } } // Last resort, simply "legend". See issue #926. - return 'legend' . (count($this->legends) + 1); + return 'legend' . (\count($this->legends) + 1); } /** * Translate a property. * * @param array $property The property information to transform. - * * @param IMetaModel $metaModel The MetaModel the property belongs to. - * * @param string $legend The legend the property belongs to. * * @return bool @@ -225,10 +230,9 @@ protected function translateProperty($property, $metaModel, $legend) $this->legends[$legend]['properties'][] = $propName; - $this->properties[$propName] = array - ( - 'info' => $attribute->getFieldDefinition($property), - ); + $this->properties[$propName] = [ + 'info' => $attribute->getFieldDefinition($property), + ]; return true; } @@ -269,13 +273,13 @@ protected function translateRows($rows) { $metaModel = $this->getMetaModel(); $activeLegend = $this->translateLegend( - array('legendtitle' => $metaModel->getName(), 'legendhide' => false), + ['legendtitle' => $metaModel->getName(), 'legendhide' => false], $metaModel ); $activeLegendId = null; // First pass, fetch all attribute names. - $columnNames = array(); + $columnNames = []; foreach ($rows as $row) { if ($row['dcatype'] != 'attribute') { continue; @@ -301,7 +305,7 @@ protected function translateRows($rows) case 'attribute': $exists = $this->translateProperty($row, $metaModel, $activeLegend); - if ($exists && $activeLegendId) { + if ($exists && null !== $activeLegendId) { $this->applyLegendConditions($row['id'], $activeLegendId); } @@ -325,19 +329,25 @@ protected function translateRows($rows) protected function transformCondition($condition) { $dispatcher = System::getContainer()->get('event_dispatcher'); - $event = new CreatePropertyConditionEvent($condition, $this->getMetaModel()); + assert($dispatcher instanceof EventDispatcherInterface); - /** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher */ + /** @psalm-suppress DeprecatedClass */ + $event = new CreatePropertyConditionEvent($condition, $this->getMetaModel()); + + /** + * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher + * @psalm-suppress DeprecatedClass + */ $dispatcher->dispatch($event, CreatePropertyConditionEvent::NAME); - if ($event->getInstance() === null) { - throw new \RuntimeException(sprintf( + if (($instance = $event->getInstance()) === null) { + throw new \RuntimeException(\sprintf( 'Condition of type %s could not be transformed to an instance.', $condition['type'] )); } - return $event->getInstance(); + return $instance; } /** @@ -350,14 +360,14 @@ protected function transformCondition($condition) protected function transformConditions($conditions) { // First pass, sort them into pid. - $sorted = array(); - $byPid = array(); - foreach ($conditions as $i => $condition) { - $sorted[$condition['id']] = $conditions[$i]; + $sorted = []; + $byPid = []; + foreach ($conditions as $condition) { + $sorted[$condition['id']] = $condition; $byPid[$condition['pid']][] = $condition['id']; } - $instances = array(); + $instances = []; // Second pass, handle them. foreach ($sorted as $id => $condition) { $instances[$id] = $this->transformCondition($condition); @@ -372,7 +382,7 @@ protected function transformConditions($conditions) } $result = $this->conditions[$settingId]; $condition = $instances[$id]; - $parent = ($pid == 0) ? $result : $instances[$pid]; + $parent = ($pid === 0) ? $result : $instances[$pid]; // have other classes in the future. if ($parent instanceof ConditionChainInterface) { @@ -403,7 +413,7 @@ protected function transformGroupSort($rows) */ public function getId() { - return $this->data['id']; + return (int) $this->data['id']; } /** @@ -419,7 +429,7 @@ public function getLegends() */ public function getLegendNames() { - return array_keys($this->legends); + return \array_keys($this->legends); } /** @@ -443,7 +453,7 @@ public function getProperties() */ public function getProperty($name) { - return isset($this->properties[$name]) ? $this->properties[$name] : null; + return $this->properties[$name]; } /** @@ -451,9 +461,9 @@ public function getProperty($name) */ public function getPropertyNames() { - $result = array(); + $result = []; foreach ($this->getLegends() as $legend) { - $result = array_merge($result, $legend['properties']); + $result = \array_merge($result, $legend['properties']); } return $result; @@ -465,7 +475,8 @@ public function getPropertyNames() public function getConditionsFor($name) { $property = $this->propertyMap2[$name]; - return isset($this->conditions[$property]) ? $this->conditions[$property] : null; + + return $this->conditions[$property] ?? null; } /** @@ -483,12 +494,14 @@ public function getGroupingAndSorting() */ public function getMetaModel() { + /** @psalm-suppress DocblockTypeContradiction */ if (null === $this->data) { throw new \RuntimeException( 'No input screen data available, did you forget to define the view combinations?' ); } + /** @psalm-suppress DeprecatedMethod */ $factory = $this->container->getFactory(); $metaModel = $factory->getMetaModel($factory->translateIdToMetaModelName($this->data['pid'])); @@ -509,7 +522,7 @@ public function getIcon() return $this->data['backendicon']; } - return null; + return ''; } /** @@ -517,7 +530,7 @@ public function getIcon() */ public function getBackendSection() { - return trim($this->data['backendsection']); + return trim($this->data['backendsection'] ?? ''); } /** @@ -525,7 +538,7 @@ public function getBackendSection() */ public function getBackendCaption() { - return StringUtil::deserialize($this->data['backendcaption'], true); + return StringUtil::deserialize($this->data['backendcaption'] ?? [], true); } /** @@ -533,7 +546,7 @@ public function getBackendCaption() */ public function getParentTable() { - return $this->data['ptable']; + return $this->data['ptable'] ?? null; } /** @@ -555,7 +568,7 @@ public function getRenderMode() return 'hierarchical'; } - return $this->data['rendermode']; + return $this->data['rendermode'] ?? ''; } /** @@ -611,7 +624,7 @@ public function isDeletable() */ public function getPanelLayout() { - return $this->data['panelLayout']; + return $this->data['panelLayout'] ?? ''; } /** diff --git a/src/BackendIntegration/InputScreen/InputScreenGroupingAndSorting.php b/src/BackendIntegration/InputScreen/InputScreenGroupingAndSorting.php index 18629a46a..e73fbee3c 100644 --- a/src/BackendIntegration/InputScreen/InputScreenGroupingAndSorting.php +++ b/src/BackendIntegration/InputScreen/InputScreenGroupingAndSorting.php @@ -31,6 +31,8 @@ class InputScreenGroupingAndSorting implements IInputScreenGroupingAndSorting * The parenting input screen. * * @var IInputScreen + * + * @psalm-suppress DeprecatedInterface */ protected $inputScreen; @@ -47,6 +49,8 @@ class InputScreenGroupingAndSorting implements IInputScreenGroupingAndSorting * @param array $data The information about the input screen. * * @param IInputScreen $inputScreen The information about all contained properties. + * + * @psalm-suppress DeprecatedInterface */ public function __construct($data, IInputScreen $inputScreen) { @@ -79,7 +83,7 @@ public function getRenderGroupType() */ public function getRenderGroupLength() { - return (int) $this->data['rendergrouplen']; + return (string) $this->data['rendergrouplen']; } /** @@ -89,11 +93,9 @@ public function getRenderGroupAttribute() { if (!empty($this->data['rendergroupattr'])) { $metaModel = $this->getMetaModel(); - if ($metaModel) { - $attribute = $metaModel->getAttributeById((int) $this->data['rendergroupattr']); - if ($attribute) { - return $attribute->getColName(); - } + $attribute = $metaModel->getAttributeById((int) $this->data['rendergroupattr']); + if ($attribute) { + return $attribute->getColName(); } } @@ -115,11 +117,9 @@ public function getRenderSortAttribute() { if (!empty($this->data['rendersortattr'])) { $metaModel = $this->getMetaModel(); - if ($metaModel) { - $attribute = $metaModel->getAttributeById((int) $this->data['rendersortattr']); - if ($attribute) { - return $attribute->getColName(); - } + $attribute = $metaModel->getAttributeById((int) $this->data['rendersortattr']); + if ($attribute) { + return $attribute->getColName(); } } diff --git a/src/BackendIntegration/Module.php b/src/BackendIntegration/Module.php index 5e2d55118..662466eed 100644 --- a/src/BackendIntegration/Module.php +++ b/src/BackendIntegration/Module.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,14 +15,17 @@ * @author Andreas Isaak * @author Stefan Heimes * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\BackendIntegration; +use Contao\Input; use ContaoCommunityAlliance\DcGeneral\Action; +use ContaoCommunityAlliance\DcGeneral\Controller\ControllerInterface; use ContaoCommunityAlliance\DcGeneral\DataContainerInterface; use ContaoCommunityAlliance\DcGeneral\Contao\Callback\Callbacks; @@ -37,7 +40,7 @@ class Module * * @var DataContainerInterface */ - private $dataContainer; + private DataContainerInterface $dataContainer; /** * Create a new instance. @@ -62,15 +65,18 @@ public function generate() $GLOBALS['TL_CSS'][] = 'bundles/metamodelscore/css/style.css'; $arrModule = $GLOBALS['BE_MOD']['metamodels']['metamodels']; // Custom action (if key is not defined in config.php the default action will be called). - if (\Input::get('key') && isset($arrModule[\Input::get('key')])) { - Callbacks::call($arrModule[\Input::get('key')], $this, $arrModule); + if (Input::get('key') && isset($arrModule[Input::get('key')])) { + Callbacks::call($arrModule[Input::get('key')], $this, $arrModule); } - $act = \Input::get('act'); - if (!strlen($act)) { + $act = Input::get('act'); + if (!\strlen($act)) { $act = 'showAll'; } - return $this->dataContainer->getEnvironment()->getController()->handle(new Action($act)); + $controller = $this->dataContainer->getEnvironment()->getController(); + assert($controller instanceof ControllerInterface); + + return $controller->handle(new Action($act)); } } diff --git a/src/BackendIntegration/PurgeAssets.php b/src/BackendIntegration/PurgeAssets.php index a3508e4a0..d4683fcc5 100644 --- a/src/BackendIntegration/PurgeAssets.php +++ b/src/BackendIntegration/PurgeAssets.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,13 +15,15 @@ * @author Sven Baumann * @author Christian Schiffler * @author Richard Henkenjohann - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\BackendIntegration; +use Contao\CoreBundle\Monolog\ContaoContext; +use Contao\Folder; use Contao\System; use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; use ContaoCommunityAlliance\Contao\Bindings\Events\System\LogEvent; @@ -44,13 +46,14 @@ public function purge() { foreach ($GLOBALS['TL_PURGE']['folders']['metamodels_assets']['affected'] as $folderName) { // Purge the folder - $folder = new \Folder($folderName); + $folder = new Folder($folderName); $folder->purge(); } $dispatcher = System::getContainer()->get('event_dispatcher'); + assert($dispatcher instanceof EventDispatcherInterface); $dispatcher->dispatch( - new LogEvent('Purged the MetaModels assets', __METHOD__, TL_CRON), + new LogEvent('Purged the MetaModels assets', __METHOD__, ContaoContext::CRON), ContaoEvents::SYSTEM_LOG ); } diff --git a/src/BackendIntegration/PurgeCache.php b/src/BackendIntegration/PurgeCache.php index b6d527236..2ac6adbe0 100644 --- a/src/BackendIntegration/PurgeCache.php +++ b/src/BackendIntegration/PurgeCache.php @@ -75,7 +75,7 @@ public function purge() $this->logger->log( LogLevel::INFO, 'Purged the MetaModels cache', - ['contao' => new ContaoContext(__METHOD__, TL_CRON)] + ['contao' => new ContaoContext(__METHOD__, ContaoContext::CRON)] ); } } diff --git a/src/BackendIntegration/ViewCombinations.php b/src/BackendIntegration/ViewCombinations.php index 7ea5b4d5e..e360c2c07 100644 --- a/src/BackendIntegration/ViewCombinations.php +++ b/src/BackendIntegration/ViewCombinations.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,7 @@ namespace MetaModels\BackendIntegration; use Contao\Environment; +use Contao\System; /** * Class ViewCombinations. @@ -28,6 +30,8 @@ * Retrieve combinations of view and input screens for the currently logged in user (either frontend or backend). * * @deprecated This will get removed. + * + * @psalm-suppress DeprecatedClass */ class ViewCombinations extends \MetaModels\Helper\ViewCombinations { @@ -38,30 +42,30 @@ class ViewCombinations extends \MetaModels\Helper\ViewCombinations */ protected function authenticateUser() { - if (\System::getContainer()->get('cca.dc-general.scope-matcher')->currentScopeIsUnknown()) { + $scopeMatcher = System::getContainer()->get('cca.dc-general.scope-matcher'); + if (null === $scopeMatcher || $scopeMatcher->currentScopeIsUnknown()) { return false; } // Do not execute anything if we are on the login page because no User is logged in. - if (strpos(Environment::get('script'), 'contao/login') !== false) { + if (\str_contains(Environment::get('script'), 'contao/login')) { return false; } // Issue #66 - contao/install.php is not working anymore. Thanks to Stefan Lindecke (@lindesbs). - if (strpos(Environment::get('request'), 'install') !== false) { + if (\str_contains(Environment::get('request'), 'install')) { return false; } - if (strpos(Environment::get('script'), 'system/bin') !== false) { + if (\str_contains(Environment::get('script'), 'system/bin')) { return false; } // Bug fix: If the user is not authenticated, contao will redirect to contao/index.php - // But in this moment the TL_PATH is not defined, so the $this->Environment->request - // generate a url without replacing the basepath(TL_PATH) with an empty string. - $authResult = $this->getUser()->authenticate(); - - return ($authResult === true || $authResult === null) ? true : false; + // But at this moment the TL_PATH is not defined, so the $this->Environment->request + // generate an url without replacing the basepath(TL_PATH) with an empty string. + /** @psalm-suppress DeprecatedMethod */ + return $this->getUser()->authenticate(); } /** @@ -70,13 +74,14 @@ protected function authenticateUser() protected function getUserGroups() { // Try to get the group(s) - // there might be a NULL in there as BE admins have no groups and user might have one but it is not mandatory. + // there might be a NULL in there as BE admins have no groups and user might have one, but it is not mandatory. // I would prefer a default group for both, fe and be groups. + /** @psalm-suppress DeprecatedClass */ $groups = parent::getUserGroups(); /** @noinspection PhpUndefinedFieldInspection */ // Special case in combinations, admins have the implicit group id -1. - if ($this->getUser()->admin) { + if ((bool) $this->getUser()->admin) { $groups[] = -1; } diff --git a/src/CoreBundle/Assets/IconBuilder.php b/src/CoreBundle/Assets/IconBuilder.php index 552e14ea0..c7795cfc0 100644 --- a/src/CoreBundle/Assets/IconBuilder.php +++ b/src/CoreBundle/Assets/IconBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author David Molineus - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,6 +24,8 @@ use Contao\CoreBundle\Framework\Adapter; use Contao\CoreBundle\Image\ImageFactoryInterface; +use Contao\FilesModel; +use Contao\Image; use Contao\Validator; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Path; @@ -38,59 +40,59 @@ class IconBuilder * * @var string */ - private $rootPath; + private string $rootPath; /** * The output path for assets. * * @var string */ - private $outputPath; + private string $outputPath; /** * The web reachable path for assets. * * @var string */ - private $webPath; + private string $webPath; /** * The project web reachable path for assets. * * @var string */ - private $projectWebPath; + private string $projectWebPath; /** * Adapter to the Contao\FilesModel class. * - * @var \Contao\FilesModel|Adapter + * @var Adapter */ - private $filesAdapter; + private Adapter $filesAdapter; /** * The image factory. * * @var ImageFactoryInterface */ - private $imageFactory; + private ImageFactoryInterface $imageFactory; /** * The image adapter. * - * @var \Contao\Image|Adapter + * @var Adapter */ - private $image; + private Adapter $image; /** * Create a new instance. * - * @param Adapter $filesAdapter Adapter to the Contao files model class. + * @param Adapter $filesAdapter Adapter to the Contao files model class. * @param ImageFactoryInterface $imageFactory The image factory for resizing images. * @param string $rootPath The root path of the application. * @param string $outputPath The output path for assets. * @param string $webPath The web reachable path for assets. - * @param Adapter $imageAdapter The image adapter to generate HTML code images. + * @param Adapter $imageAdapter The image adapter to generate HTML code images. * @param string $projectWebPath The project web reachable path for assets. */ public function __construct( @@ -126,10 +128,10 @@ public function __construct( public function getBackendIcon($icon, $defaultIcon = 'bundles/metamodelscore/images/icons/metamodels.png') { $realIcon = $this->convertValueToPath($icon, $defaultIcon); - $targetPath = $this->outputPath . '/' . basename($realIcon); + $targetPath = $this->outputPath . '/' . \basename($realIcon); if (\file_exists($targetPath)) { - return $this->webPath . '/' . basename($realIcon); + return $this->webPath . '/' . \basename($realIcon); } if (!Path::isAbsolute($realIcon)) { @@ -138,7 +140,7 @@ public function getBackendIcon($icon, $defaultIcon = 'bundles/metamodelscore/ima $this->imageFactory->create($realIcon, [16, 16, 'center_center'], $targetPath); - return $this->webPath . '/' . basename($realIcon); + return $this->webPath . '/' . \basename($realIcon); } /** @@ -157,6 +159,7 @@ public function getBackendIconImageTag( $attributes = '', $defaultIcon = 'bundles/metamodelscore/images/icons/metamodels.png' ) { + /** @psalm-suppress InternalMethod - Class Adapter is internal, not the __call() method. Blame Contao. */ return $this->image->getHtml($this->getBackendIcon($icon, $defaultIcon), $alt, $attributes); } @@ -171,13 +174,16 @@ public function getBackendIconImageTag( public function convertValueToPath($varValue, $fallback) { if (Validator::isUuid($varValue)) { + /** @psalm-suppress InternalMethod - Class Adapter is internal, not the __call() method. Blame Contao. */ $model = $this->filesAdapter->findByPk($varValue); - if ($model !== null && file_exists($this->rootPath . '/' . $model->path)) { + if (($model instanceof FilesModel) && \file_exists($this->rootPath . '/' . $model->path)) { return $model->path; } + return $fallback; } - if (file_exists($varValue)) { + + if (\file_exists($varValue)) { return $varValue; } diff --git a/src/CoreBundle/Command/SchemaValidatorCommand.php b/src/CoreBundle/Command/SchemaValidatorCommand.php index 8eccf17fe..7a4583fe3 100644 --- a/src/CoreBundle/Command/SchemaValidatorCommand.php +++ b/src/CoreBundle/Command/SchemaValidatorCommand.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,8 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -59,7 +60,7 @@ public function __construct( parent::__construct('metamodels:schema-update'); } - protected function configure() + protected function configure(): void { parent::configure(); $this->addOption('force', null, InputOption::VALUE_NONE, 'Perform the update'); @@ -73,6 +74,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $this->manager->preprocess($information); $this->manager->process($information); $this->manager->postprocess($information); + return 0; } diff --git a/src/CoreBundle/Contao/Compat/ContaoFactory.php b/src/CoreBundle/Contao/Compat/ContaoFactory.php index 4629839c4..0a50cb247 100644 --- a/src/CoreBundle/Contao/Compat/ContaoFactory.php +++ b/src/CoreBundle/Contao/Compat/ContaoFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 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,8 @@ * @author Christian Schiffler * @author binron * @author Stefan Heimes - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -36,13 +37,17 @@ class ContaoFactory * The Contao framework. * * @var ContaoFrameworkInterface + * + * @psalm-suppress DeprecatedInterface */ - private $framework; + private ContaoFrameworkInterface $framework; /** * Create a new instance. * * @param ContaoFrameworkInterface $framework The Contao framework. + * + * @psalm-suppress DeprecatedInterface */ public function __construct(ContaoFrameworkInterface $framework) { @@ -64,7 +69,7 @@ public function createInsertTags() /** * Create an adapter. * - * @param string $className The class name to create an adapter for. + * @param class-string $className The class name to create an adapter for. * * @return Adapter */ diff --git a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php index 75de36946..dfb2bb455 100644 --- a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php +++ b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author Marc Reimann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -28,14 +28,26 @@ use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; use ContaoCommunityAlliance\UrlBuilder\UrlBuilderFactoryInterface; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use MetaModels\BackendIntegration\TemplateList; use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\Filter\Setting\FilterSettingFactory; use MetaModels\IFactory; +use RuntimeException; use Symfony\Component\HttpFoundation\RequestStack; +use function asort; +use function base64_decode; +use function base64_encode; +use function in_array; +use function reset; +use function sprintf; +use function trim; + /** * This class is the abstract base for building the "edit MetaModel" button in the backend. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ abstract class AbstractContentElementAndModuleCallback { @@ -51,49 +63,49 @@ abstract class AbstractContentElementAndModuleCallback * * @var IconBuilder */ - private $iconBuilder; + private IconBuilder $iconBuilder; /** * The URL builder factory. * * @var UrlBuilderFactoryInterface */ - private $urlBuilderFactory; + private UrlBuilderFactoryInterface $urlBuilderFactory; /** * The MetaModel factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The filtersetting factory. * * @var FilterSettingFactory */ - private $filterFactory; + private FilterSettingFactory $filterFactory; /** * The database connection. * * @var Connection */ - private $connection; + private Connection $connection; /** * The template list. * * @var TemplateList */ - private $templateList; + private TemplateList $templateList; /** * The request stack. * * @var RequestStack */ - private $requestStack; + private RequestStack $requestStack; /** * Create a new instance. @@ -235,7 +247,13 @@ public function getAttributeNames(DC_Table $objDc) 'id' => $GLOBALS['TL_LANG']['MSC']['id'][0] ]; - $metaModelName = $this->factory->translateIdToMetaModelName($objDc->activeRecord->metamodel); + assert(null !== $objDc->activeRecord); + try { + $metaModelName = $this->factory->translateIdToMetaModelName($objDc->activeRecord->metamodel); + } catch (RuntimeException $exception) { + // No valid MetaModel selected, can not add attributes of it. + return $attributeNames; + } $metaModel = $this->factory->getMetaModel($metaModelName); if ($metaModel) { @@ -248,7 +266,7 @@ public function getAttributeNames(DC_Table $objDc) } /** - * Fetch all available filter settings for the current meta model. + * Fetch all available filter settings for the current MetaModel. * * @param DC_Table $objDC The data container calling this method. * @@ -256,6 +274,7 @@ public function getAttributeNames(DC_Table $objDc) */ public function getFilterSettings(DC_Table $objDC) { + assert(null !== $objDC->activeRecord); $filterSettings = $this->connection->createQueryBuilder() ->select('f.id', 'f.name') ->from('tl_metamodel_filter', 'f') @@ -287,6 +306,9 @@ public function getFilterSettings(DC_Table $objDC) */ public function getMetaTitleAttributes(DC_Table $objDC) { + assert(null !== $objDC->activeRecord); + + /** @psalm-suppress ArgumentTypeCoercion - We HOPE there is a list of strings. */ return $this->getFilteredAttributeNames( $objDC->activeRecord->metamodel, (array) $GLOBALS['METAMODELS']['metainformation']['allowedTitle'] @@ -305,6 +327,9 @@ public function getMetaTitleAttributes(DC_Table $objDC) */ public function getMetaDescriptionAttributes(DC_Table $objDC) { + assert(null !== $objDC->activeRecord); + + /** @psalm-suppress ArgumentTypeCoercion - We HOPE there is a list of strings. */ return $this->getFilteredAttributeNames( $objDC->activeRecord->metamodel, (array) $GLOBALS['METAMODELS']['metainformation']['allowedDescription'] @@ -319,17 +344,18 @@ public function getMetaDescriptionAttributes(DC_Table $objDC) * * @return void * - * @throws \Doctrine\DBAL\Exception + * @throws Exception * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ protected function buildFilterParamsFor(DC_Table $dataContainer, $elementName) { - if (!$this->requestStack->getCurrentRequest()->query->get('act')) { + $request = $this->requestStack->getCurrentRequest(); + if (null === $request || !$request->query->has('act')) { return; } - $filterId = $this->connection->createQueryBuilder() + $filterIds = $this->connection->createQueryBuilder() ->select('c.metamodel_filtering') ->from(static::$tableName, 'c') ->join('c', 'tl_metamodel', 'mm', 'mm.id=c.metamodel') @@ -341,17 +367,20 @@ protected function buildFilterParamsFor(DC_Table $dataContainer, $elementName) ->executeQuery() ->fetchFirstColumn(); - if (!reset($filterId)) { + if (false === ($filterId = reset($filterIds)) || 0 === $filterId) { unset($GLOBALS['TL_DCA'][static::$tableName]['fields']['metamodel_filterparams']); return; } - $collection = $this->filterFactory->createCollection(current($filterId)); + $collection = $this->filterFactory->createCollection($filterId); $dca = $collection->getParameterDCA(); foreach ($dca as $fieldName => $subField) { $options = []; foreach (($subField['options'] ?? []) as $key => $value) { - $options[$this->loadCallback($key)] = $value; + $newKey = $this->loadCallback($key); + if (null !== $newKey) { + $options[$newKey] = $value; + } } $dca[$fieldName]['options'] = $options; @@ -372,7 +401,7 @@ protected function buildFilterParamsFor(DC_Table $dataContainer, $elementName) */ public function saveCallback(string $value = null) { - return null === $value ? null : \base64_decode($value); + return null === $value ? null : base64_decode($value); } /** @@ -384,7 +413,7 @@ public function saveCallback(string $value = null) */ public function loadCallback(string $value = null) { - return null === $value ? null : trim(\base64_encode($value), '='); + return null === $value ? null : trim(base64_encode($value), '='); } /** @@ -396,16 +425,16 @@ public function loadCallback(string $value = null) */ public function getFilterParameterNames(DC_Table $objDc) { - $return = array(); + assert(null !== $objDc->activeRecord); + + $return = []; $filter = $objDc->activeRecord->metamodel_filtering; if (!$filter) { return $return; } - $collection = $this->filterFactory->createCollection($filter); - - return $collection->getParameterFilterNames(); + return $this->filterFactory->createCollection($filter)->getParameterFilterNames(); } /** @@ -417,6 +446,8 @@ public function getFilterParameterNames(DC_Table $objDc) */ public function getFilterTemplates(DC_Table $dcTable) { + assert(null !== $dcTable->activeRecord); + if ($dcTable->activeRecord->type === 'metamodels_frontendclearall') { return $this->templateList->getTemplatesForBase('mm_clearall_'); } @@ -437,7 +468,7 @@ protected function getTemplateList($base) } /** - * Fetch all available render settings for the current meta model. + * Fetch all available render settings for the current MetaModel. * * @param DC_Table $objDC The data container calling this method. * @@ -445,6 +476,8 @@ protected function getTemplateList($base) */ public function getRenderSettings(DC_Table $objDC) { + assert(null !== $objDC->activeRecord); + $filterSettings = $this->connection->createQueryBuilder() ->select('r.id', 'r.name') ->from('tl_metamodel_rendersettings', 'r') @@ -473,7 +506,7 @@ public function getRenderSettings(DC_Table $objDC) * * @return string */ - private function renderEditButton($caption, $title, UrlBuilder $url) + private function renderEditButton(string $caption, string $title, UrlBuilder $url): string { $icon = $this->iconBuilder->getBackendIconImageTag( 'system/themes/flexible/icons/alias.svg', @@ -494,19 +527,24 @@ private function renderEditButton($caption, $title, UrlBuilder $url) * * If the optional parameter arrTypes is not given, all attributes will be retrieved. * - * @param int $metaModelId The id of the MetaModel from which the attributes shall be retrieved from. - * - * @param string[] $allowedTypes The attribute type names that shall be retrieved (optional). + * @param string $metaModelId The id of the MetaModel from which the attributes shall be retrieved from. + * @param list $allowedTypes The attribute type names that shall be retrieved. * * @return array A list with all found attributes. */ - private function getFilteredAttributeNames($metaModelId, $allowedTypes = array()) + private function getFilteredAttributeNames(string $metaModelId, array $allowedTypes): array { - $attributeNames = array(); + $attributeNames = []; - if ($metaModel = $this->factory->getMetaModel($this->factory->translateIdToMetaModelName($metaModelId))) { + try { + $metaModelName = $this->factory->translateIdToMetaModelName($metaModelId); + } catch (RuntimeException $exception) { + // No valid MetaModel selected, can not add attributes of it. + return $attributeNames; + } + if ($metaModel = $this->factory->getMetaModel($metaModelName)) { foreach ($metaModel->getAttributes() as $attribute) { - if (empty($allowedTypes) || in_array($attribute->get('type'), $allowedTypes)) { + if (empty($allowedTypes) || in_array($attribute->get('type'), $allowedTypes, true)) { $attributeNames[$attribute->getColName()] = sprintf( '%s [%s]', diff --git a/src/CoreBundle/Contao/Hooks/ContentElementCallback.php b/src/CoreBundle/Contao/Hooks/ContentElementCallback.php index ede808094..f04697d1b 100644 --- a/src/CoreBundle/Contao/Hooks/ContentElementCallback.php +++ b/src/CoreBundle/Contao/Hooks/ContentElementCallback.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Marc Reimann * @author Stefan Heimes * @author Ingolf Steinhardt - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -60,9 +60,9 @@ public function buildFilterParameterList(DC_Table $dataContainer) */ public function getTemplates(DC_Table $objDC) { - /** @noinspection PhpUndefinedFieldInspection */ + assert(null !== $objDC->activeRecord); $type = $objDC->activeRecord->type; - if ($type == 'metamodel_content') { + if ($type === 'metamodel_content') { $type = 'metamodel_list'; } diff --git a/src/CoreBundle/Contao/Hooks/FixupUserGroupModules.php b/src/CoreBundle/Contao/Hooks/FixupUserGroupModules.php index 60256d1a4..b093c5dd2 100644 --- a/src/CoreBundle/Contao/Hooks/FixupUserGroupModules.php +++ b/src/CoreBundle/Contao/Hooks/FixupUserGroupModules.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Ben - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +24,7 @@ use Contao\DataContainer; use MetaModels\ViewCombination\InputScreenInformationBuilder; use MetaModels\ViewCombination\ViewCombinationBuilder; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; /** @@ -35,14 +37,14 @@ class FixupUserGroupModules * * @var ViewCombinationBuilder */ - private $combinationBuilder; + private ViewCombinationBuilder $combinationBuilder; /** * The input screen information builder. * * @var InputScreenInformationBuilder */ - private $inputScreens; + private InputScreenInformationBuilder $inputScreens; /** * The request stack. @@ -79,41 +81,47 @@ public function __construct( */ public function fixupModules(DataContainer $dataContainer) { - if (!class_exists('tl_user_group', false)) { + if (!\class_exists('tl_user_group', false)) { throw new \RuntimeException('data container is not loaded!'); } $original = new \tl_user_group(); + /** @var array> $modules */ $modules = $original->getModules($dataContainer); // 1. remove all MetaModels - foreach (array_keys($modules) as $group) { + foreach (\array_keys($modules) as $group) { foreach ($modules[$group] as $key => $module) { - if (strpos($module, 'metamodel_') === 0) { + if (\str_starts_with($module, 'metamodel_')) { unset($modules[$group][$key]); } } // Otherwise we end up with an associative array. - $modules[$group] = array_values($modules[$group]); + $modules[$group] = \array_values($modules[$group]); + } + if (!\is_array($modules['metamodels'] ?? null)) { + $modules['metamodels'] = []; } // 2. Add our "custom" modules and remove the main module. $modules['metamodels'][] = 'support_metamodels'; - if (false !== $index = array_search('metamodels', $modules['metamodels'], true)) { + if (false !== ($index = \array_search('metamodels', $modules['metamodels'], true))) { unset($modules['metamodels'][$index]); - $modules['metamodels'] = array_values($modules['metamodels']); + $modules['metamodels'] = \array_values($modules['metamodels']); } // 3. Add back all MetaModels for the current group. + assert(null !== $dataContainer->activeRecord); $combinations = $this->combinationBuilder->getCombinationsForUser([$dataContainer->activeRecord->id], 'be'); - $screenIds = array_map(function ($combination) { + $screenIds = \array_map(static function (array $combination): mixed { return $combination['dca_id']; - }, $combinations['byName']); - - $screens = $this->inputScreens->fetchInputScreens($screenIds); + }, $combinations['byName'] ?? []); - $locale = $this->requestStack->getCurrentRequest()->getLocale(); + $screens = $this->inputScreens->fetchInputScreens($screenIds); + $currentRequest = $this->requestStack->getCurrentRequest(); + assert($currentRequest instanceof Request); + $locale = $currentRequest->getLocale(); foreach ($screens as $metaModel => $screen) { if ('standalone' === $screen['meta']['rendertype']) { $modules[$screen['meta']['backendsection']][] = 'metamodel_' . $metaModel; @@ -136,7 +144,7 @@ public function fixupModules(DataContainer $dataContainer) * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - private function buildLanguageString($name, $screen, $locale) + private function buildLanguageString(string $name, array $screen, string $locale): void { if (isset($screen['label'][$locale])) { $GLOBALS['TL_LANG']['MOD'][$name] = $screen['label'][$locale]; diff --git a/src/CoreBundle/Contao/Hooks/LoadDataContainer.php b/src/CoreBundle/Contao/Hooks/LoadDataContainer.php index e8653c354..08ce3af38 100644 --- a/src/CoreBundle/Contao/Hooks/LoadDataContainer.php +++ b/src/CoreBundle/Contao/Hooks/LoadDataContainer.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +23,9 @@ use Contao\Controller; use Contao\CoreBundle\Framework\Adapter; +use Contao\StringUtil; +use Contao\System; +use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\Helper\LocaleUtil; @@ -38,30 +41,30 @@ class LoadDataContainer /** * Adapter to the Contao\Controller class. * - * @var Controller + * @var Adapter */ - private $controller; + private Adapter $controller; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The view combination. * * @var ViewCombination */ - private $combination; + private ViewCombination $combination; /** * The icon builder. * * @var IconBuilder */ - private $iconBuilder; + private IconBuilder $iconBuilder; /** * Create a new instance. @@ -90,22 +93,20 @@ public function __construct( * * @return void */ - public function onLoadDataContainer($tableName) + public function onLoadDataContainer($tableName): void { - // @codingStandardsIgnoreStart - // FIXME: make this beautiful. - // @codingStandardsIgnoreEnd - if (!\System::getContainer()->get('cca.dc-general.scope-matcher')->currentScopeIsBackend()) { + $scopeMatcher = System::getContainer()->get('cca.dc-general.scope-matcher'); + if (!($scopeMatcher instanceof RequestScopeDeterminator) || !$scopeMatcher->currentScopeIsBackend()) { return; } static $tableExists; // Test that the tables have been created. if (null === $tableExists) { - $tableExists = \System::getContainer() - ->get('database_connection') - ->getSchemaManager() - ->tablesExist(['tl_metamodel']); + if (null === ($connection = System::getContainer()->get('database_connection'))) { + return; + } + $tableExists = $connection->createSchemaManager()->tablesExist(['tl_metamodel']); } if (false === $tableExists) { return; @@ -125,14 +126,14 @@ public function onLoadDataContainer($tableName) * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - private function handleMetaModelTable($tableName) + private function handleMetaModelTable(string $tableName): void { static $tableNames; if (!$tableNames) { $tableNames = $this->factory->collectNames(); } // Not a MetaModel, get out now. - if (!in_array($tableName, $tableNames)) { + if (!\in_array($tableName, $tableNames)) { return; } @@ -142,7 +143,7 @@ private function handleMetaModelTable($tableName) $GLOBALS['TL_DCA'][$tableName] = []; } - $GLOBALS['TL_DCA'][$tableName] = array_replace_recursive( + $GLOBALS['TL_DCA'][$tableName] = \array_replace_recursive( (array) $GLOBALS['TL_DCA']['tl_metamodel_item'], (array) $GLOBALS['TL_DCA'][$tableName] ); @@ -158,10 +159,10 @@ private function handleMetaModelTable($tableName) * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - private function handleNonMetaModelTable($tableName) + private function handleNonMetaModelTable(string $tableName): void { // Nothing to do for MetaModel tables. - if (substr($tableName, 0, 3) === 'mm_') { + if (\str_starts_with($tableName, 'mm_')) { return; } @@ -180,16 +181,17 @@ private function handleNonMetaModelTable($tableName) $this->controller->loadLanguageFile('default'); foreach ($map[$tableName] as $metaModelTable => $inputScreen) { $metaModel = $this->factory->getMetaModel($metaModelTable); - $caption = $this->buildCaption($metaModel, $inputScreen); + assert($metaModel instanceof IMetaModel); + + $caption = $this->buildCaption($metaModel, $inputScreen); $operationName = 'edit_' . $metaModel->getTableName(); - $parentDCA['list']['operations'][$operationName] = array - ( + $parentDCA['list']['operations'][$operationName] = [ 'label' => &$caption, 'href' => 'table=' . $metaModelTable, 'icon' => $this->iconBuilder->getBackendIcon($inputScreen['meta']['backendicon']), 'attributes' => 'onclick="Backend.getScrollOffset()"', - ); + ]; // Is the destination table a metamodel with variants? if ($metaModel->hasVariants()) { @@ -203,7 +205,15 @@ private function handleNonMetaModelTable($tableName) $idParameter = $parentDCA['list']['operations'][$operationName]['idparam']; $parentDCA['list']['operations'][$operationName]['button_callback'] = - function ($row, $href, $label, $name, $icon, $attributes, $table) use ($idParameter) { + function ( + array $row, + string $href, + string $label, + string $name, + string $icon, + string $attributes, + string $table + ) use ($idParameter): string { return $this->buildChildOperationButton( $idParameter, $row['id'], @@ -224,7 +234,7 @@ function ($row, $href, $label, $name, $icon, $attributes, $table) use ($idParame * * @return array */ - private function buildMap() + private function buildMap(): array { $map = []; foreach ($this->combination->getParented() as $childName => $child) { @@ -245,10 +255,10 @@ private function buildMap() * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - private function buildCaption($metaModel, $inputScreen): array + private function buildCaption(IMetaModel $metaModel, array $inputScreen): array { $caption = [ - sprintf($GLOBALS['TL_LANG']['MSC']['metamodel_edit_as_child']['label'], $metaModel->getName()), + \sprintf($GLOBALS['TL_LANG']['MSC']['metamodel_edit_as_child']['label'], $metaModel->getName()), '' ]; @@ -270,25 +280,26 @@ private function buildCaption($metaModel, $inputScreen): array * This method exists only for being compatible when MetaModels are being used as child table from DC_Table context. * * @param string $idParameter The id parameter in use. - * - * @param string $itemId The current data row. - * - * @param string $href The href to be appended. - * - * @param string $label The operation label. - * - * @param string $name The operation name. - * - * @param string $icon The icon path. - * - * @param string $attributes The button attributes. - * - * @param string $table The table name. + * @param string $itemId The current data row. + * @param string $href The href to be appended. + * @param string $label The operation label. + * @param string $name The operation name. + * @param string $icon The icon path. + * @param string $attributes The button attributes. + * @param string $table The table name. * * @return string */ - private function buildChildOperationButton($idParameter, $itemId, $href, $label, $name, $icon, $attributes, $table) - { + private function buildChildOperationButton( + string $idParameter, + string $itemId, + string $href, + string $label, + string $name, + string $icon, + string $attributes, + string $table + ): string { $modelId = ModelId::fromValues($table, $itemId); $url = $href . '&' . $idParameter . '=' . $modelId->getSerialized(); @@ -299,14 +310,15 @@ private function buildChildOperationButton($idParameter, $itemId, $href, $label, $url = $this->controller->addToUrl($url); // If id parameter different, we have to clean out the id in the URL now. if ('id' !== $idParameter) { - $url = preg_replace('#(&)id=(?:&)?#', '$1', $url); + $url = \preg_replace('#(&)id=(?:&)?#', '$1', $url); } - $title = sprintf($label ?: $name, $itemId); - return sprintf( + $title = \sprintf($label ?: $name, $itemId); + + return \sprintf( '%4$s ', $url, - specialchars($title), + StringUtil::specialchars($title), $attributes, $this->iconBuilder->getBackendIconImageTag($icon, $label) ); diff --git a/src/CoreBundle/Contao/Hooks/ModuleCallback.php b/src/CoreBundle/Contao/Hooks/ModuleCallback.php index cfb5c1644..7879dc3d6 100644 --- a/src/CoreBundle/Contao/Hooks/ModuleCallback.php +++ b/src/CoreBundle/Contao/Hooks/ModuleCallback.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,13 +13,15 @@ * @package MetaModels/core * @author Christian Schiffler * @author Ingolf Steinhardt - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2024 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; + /** * This class provides callbacks for tl_module. */ @@ -35,11 +37,11 @@ class ModuleCallback extends AbstractContentElementAndModuleCallback /** * Called from tl_content.onload_callback. * - * @param \DC_Table $dataContainer The data container calling this method. + * @param DC_Table $dataContainer The data container calling this method. * * @return void */ - public function buildFilterParameterList(\DC_Table $dataContainer) + public function buildFilterParameterList(DC_Table $dataContainer) { parent::buildFilterParamsFor($dataContainer, 'metamodel_list'); } @@ -47,12 +49,13 @@ public function buildFilterParameterList(\DC_Table $dataContainer) /** * Fetch the template group for the current MetaModel frontend module. * - * @param \DC_Table $objDC The data container calling this method. + * @param DC_Table $objDC The data container calling this method. * * @return array */ - public function getTemplates(\DC_Table $objDC) + public function getTemplates(DC_Table $objDC) { + assert(null !== $objDC->activeRecord); $type = $objDC->activeRecord->type; return $this->getTemplateList('mod_' . $type); diff --git a/src/CoreBundle/Contao/InsertTag/ReplaceParam.php b/src/CoreBundle/Contao/InsertTag/ReplaceParam.php index 8250df960..2b0d67068 100644 --- a/src/CoreBundle/Contao/InsertTag/ReplaceParam.php +++ b/src/CoreBundle/Contao/InsertTag/ReplaceParam.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Oliver Hoff * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -30,6 +30,7 @@ use Contao\CoreBundle\Framework\ContaoFramework; use Contao\Input; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; /** * This replaces the insert tag param. @@ -79,7 +80,9 @@ public function __construct(ContaoFramework $framework, RequestStack $requestSta */ public function replace(string $content): ?string { - if (!\str_contains($content, '{{') + $tags = []; + if ( + !\str_contains($content, '{{') || !($tags = preg_split('@\{\{(.*)\}\}@', $content, -1, PREG_SPLIT_DELIM_CAPTURE)) || (\count($tags) < 2) ) { @@ -88,7 +91,8 @@ public function replace(string $content): ?string $newContent = null; foreach ($tags as $tag) { - if (!(2 === \count($chunks = \explode('::', $tag, 2))) + if ( + !(2 === \count($chunks = \explode('::', $tag, 2))) || !('param' === $chunks[0]) || !($this->isParameterSupported($chunks[1], ['get', 'post', 'cookie', 'session', 'filter'])) ) { @@ -104,22 +108,23 @@ public function replace(string $content): ?string /** * Replace the insert tag with the input value. * - * @param array $chunks The chunks. - * @param string|null $content The content. - * @param string $tag The tag. + * @param list $chunks The chunks. + * @param string|null $content The content. + * @param string $tag The tag. * * @return string|null + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ private function replaceInputParameter(array $chunks, ?string $content, string $tag): ?string { - if ((null === $content) - || !($this->isParameterSupported($chunks[1], ['get', 'post', 'cookie'])) - || !($arguments = $this->splitParameter($chunks[1])) - ) { + if (null === ($arguments = $this->getArguments($chunks[1], $content, ['get', 'post', 'cookie']))) { return $content; } + assert(\is_string($content)); if (null === $this->input) { + /** @psalm-suppress InternalMethod - Class ContaoFramework is internal, not the getAdapter() method. */ $this->input = $this->framework->getAdapter(Input::class); } @@ -145,22 +150,21 @@ private function replaceInputParameter(array $chunks, ?string $content, string $ /** * Replace the insert tag with the session value. * - * @param array $chunks The chunks. - * @param string|null $content The content. - * @param string $tag The tag. + * @param list $chunks The chunks. + * @param string|null $content The content. + * @param string $tag The tag. * * @return string|null */ private function replaceSessionParameter(array $chunks, ?string $content, string $tag): ?string { - if ((null === $content) - || !($this->isParameterSupported($chunks[1], ['session'])) - || !($arguments = $this->splitParameter($chunks[1])) - ) { + if (null === ($arguments = $this->getArguments($chunks[1], $content, ['session']))) { return $content; } + assert(\is_string($content)); $sessionBag = $this->requestStack->getSession()->getBag('contao_frontend'); + assert($sessionBag instanceof AttributeBagInterface); if ((!\str_contains($tag, '&default='))) { $result = $sessionBag->get($arguments[1]); @@ -179,16 +183,35 @@ private function replaceSessionParameter(array $chunks, ?string $content, string ); } + /** + * @param list $supported + * + * @return list|null + */ + private function getArguments(string $chunk, ?string $content, array $supported): ?array + { + if ((null === $content) || !$this->isParameterSupported($chunk, $supported)) { + return null; + } + $arguments = $this->splitParameter($chunk); + if ((null === $arguments) || ([] === $arguments)) { + return null; + } + + return $arguments; + } + /** * Split the parameter. * * @param string $parameter The parameter. * - * @return array|null + * @return list|null */ private function splitParameter(string $parameter): ?array { - if ((2 !== \count($chunks = \explode('?', $parameter))) + if ( + (2 !== \count($chunks = \explode('?', $parameter))) || (!\str_starts_with($chunks[1], 'name=')) ) { return null; diff --git a/src/CoreBundle/Contao/InsertTag/ResolveLanguageTag.php b/src/CoreBundle/Contao/InsertTag/ResolveLanguageTag.php index 47d092b32..77f9de229 100644 --- a/src/CoreBundle/Contao/InsertTag/ResolveLanguageTag.php +++ b/src/CoreBundle/Contao/InsertTag/ResolveLanguageTag.php @@ -13,6 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Oliver Willmes + * @author Ingolf Steinhardt * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource @@ -60,14 +61,15 @@ public function __construct(RequestStack $requestStack) public function resolve(string $queryString): string { // @codingStandardsIgnoreStart - if (\strpos($queryString, '{{iflng') === false && \strpos($queryString, '{{ifnlng') === false) { + if (!\str_contains($queryString, '{{iflng') && !\str_contains($queryString, '{{ifnlng')) { return $queryString; } $tags = \preg_split('~{{(ifn?lng[^{}]*)}}~', $queryString, -1, PREG_SPLIT_DELIM_CAPTURE ); $strBuffer = ''; + $arrCache = []; - for ($_rit=0, $_cnt=\count($tags); $_rit<$_cnt; $_rit+=2) { + for ($_rit = 0, $_cnt = \count($tags); $_rit < $_cnt; $_rit += 2) { $strBuffer .= $tags[$_rit]; if (!isset($tags[$_rit+1])) { diff --git a/src/CoreBundle/ContaoManager/Plugin.php b/src/CoreBundle/ContaoManager/Plugin.php index 5545faa07..0d882b31c 100644 --- a/src/CoreBundle/ContaoManager/Plugin.php +++ b/src/CoreBundle/ContaoManager/Plugin.php @@ -59,8 +59,10 @@ public function getBundles(ParserInterface $parser) */ public function getRouteCollection(LoaderResolverInterface $resolver, KernelInterface $kernel) { - return $resolver - ->resolve(__DIR__.'/../Resources/config/routing.yml') - ->load(__DIR__.'/../Resources/config/routing.yml'); + if (false === ($resolved = $resolver->resolve(__DIR__ . '/../Resources/config/routing.yml'))) { + return null; + } + + return $resolved->load(__DIR__ . '/../Resources/config/routing.yml'); } } diff --git a/src/CoreBundle/Controller/Backend/AbstractAddAllController.php b/src/CoreBundle/Controller/Backend/AbstractAddAllController.php index 1b40621ea..6db831cb1 100644 --- a/src/CoreBundle/Controller/Backend/AbstractAddAllController.php +++ b/src/CoreBundle/Controller/Backend/AbstractAddAllController.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -37,50 +37,54 @@ /** * This controller provides the base for the add-all handlers for input screens and render settings. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * + * @psalm-suppress PropertyNotSetInConstructor */ abstract class AbstractAddAllController { /** * Adapter to the Contao\System class. * - * @var System + * @var Adapter */ - private $systemAdapter; + private Adapter $systemAdapter; /** * The translator. * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The database connection. * * @var Connection */ - private $connection; + private Connection $connection; /** * The cache purger. * * @var PurgeCache */ - private $purger; + private PurgeCache $purger; /** * The list of known attributes. * * @var array */ - private $knownAttributes; + private array $knownAttributes; /** * The twig engine. @@ -94,7 +98,7 @@ abstract class AbstractAddAllController * * @var int */ - private $startSort; + private int $startSort; /** * Create a new instance. @@ -103,7 +107,7 @@ abstract class AbstractAddAllController * @param TranslatorInterface $translator The translator. * @param IFactory $factory The MetaModels factory. * @param Connection $connection The database connection. - * @param Adapter $systemAdapter Adapter to the Contao\System class. + * @param Adapter $systemAdapter Adapter to the Contao\System class. * @param PurgeCache $purger The cache purger. */ public function __construct( @@ -129,10 +133,11 @@ public function __construct( * @param string $parentId The parent id. * @param bool $activate Flag if the setting shall get activated. * @param int $sort The sorting value. + * @param string $tlclass The CSS class. * * @return array */ - abstract protected function createEmptyDataFor(IAttribute $attribute, $parentId, $activate, $sort); + abstract protected function createEmptyDataFor(IAttribute $attribute, $parentId, $activate, $sort, $tlclass = ''); /** * Test if the passed attribute is acceptable. @@ -194,7 +199,7 @@ protected function render($table, $metaModel, Request $request) return [ 'action' => '', - 'requestToken' => REQUEST_TOKEN, + 'requestToken' => System::getContainer()->get('contao.csrf.token_manager')?->getDefaultTokenValue(), 'href' => $this->getReferer($request, $table, true), 'backBt' => $this->translator->trans('MSC.backBT', [], 'contao_default'), 'add' => $this->translator->trans('MSC.continue', [], 'contao_default'), @@ -205,7 +210,7 @@ protected function render($table, $metaModel, Request $request) 'selectAll' => $this->translator->trans('MSC.selectAll', [], 'contao_default') . '.', 'cacheMessage' => '', 'updateMessage' => '', - 'hasCheckbox' => count($fields) > 0, + 'hasCheckbox' => \count($fields) > 0, 'fields' => $fields, 'stylesheets' => ['bundles/metamodelscore/css/style.css'] ]; @@ -219,7 +224,7 @@ protected function render($table, $metaModel, Request $request) * * @return array */ - private function fetchExisting($table, $parentId) + private function fetchExisting(string $table, string $parentId): array { // Keep the sorting value. $this->startSort = 0; @@ -249,9 +254,9 @@ private function fetchExisting($table, $parentId) * * @return bool */ - private function knowsAttribute($attribute) + private function knowsAttribute(IAttribute $attribute): bool { - return array_key_exists($attribute->get('id'), $this->knownAttributes); + return \array_key_exists($attribute->get('id'), $this->knownAttributes); } /** @@ -263,7 +268,7 @@ private function knowsAttribute($attribute) * * @return array */ - private function generateForm($table, $metaModel, Request $request) + private function generateForm(string $table, IMetaModel $metaModel, Request $request): array { $fields = []; // Loop over all attributes now. @@ -312,7 +317,7 @@ private function generateForm($table, $metaModel, Request $request) * * @return string */ - private function checkboxCaption($key, $table, IAttribute $attribute) + private function checkboxCaption(string $key, string $table, IAttribute $attribute): string { return $this->translator->trans( $table . '.' . $key, @@ -329,7 +334,7 @@ private function checkboxCaption($key, $table, IAttribute $attribute) * * @return bool */ - private function isAttributeSubmitted($attributeId, Request $request) + private function isAttributeSubmitted(string $attributeId, Request $request): bool { return $request->request->has('attribute_' . $attributeId); } @@ -344,37 +349,41 @@ private function isAttributeSubmitted($attributeId, Request $request) * * @return void */ - private function perform($table, Request $request, $metaModel, $parentId) + private function perform(string $table, Request $request, IMetaModel $metaModel, string $parentId): void { $activate = (bool) $request->request->get('activate'); - $tlclass = $request->request->get('tlclass'); + $tlclass = (string) $request->request->get('tlclass'); $query = $this ->connection ->createQueryBuilder() ->insert($table); foreach ($metaModel->getAttributes() as $attribute) { - if ($this->knowsAttribute($attribute) + if ( + $this->knowsAttribute($attribute) || !($this->accepts($attribute) && $this->isAttributeSubmitted($attribute->get('id'), $request)) ) { continue; } $data = []; - foreach ($this->createEmptyDataFor( - $attribute, - $parentId, - $activate, - $this->startSort, - $tlclass - ) as $key => $value) { + foreach ( + $this->createEmptyDataFor( + $attribute, + $parentId, + $activate, + $this->startSort, + $tlclass + ) as $key => $value + ) { $data[$key] = ':' . $key; $query->setParameter($key, $value); } - $query->values($data)->execute(); + $query->values($data)->executeQuery(); $this->startSort += 128; } + $this->purger->purge(); } @@ -387,7 +396,7 @@ private function perform($table, Request $request, $metaModel, $parentId) * * @return string */ - private function getReferer(Request $request, $table, $encodeAmp = false) + private function getReferer(Request $request, string $table, bool $encodeAmp = false): string { $uri = $this->systemAdapter->getReferer($encodeAmp, $table); // Make the location an absolute URL diff --git a/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php b/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php index dd7250116..0741fc633 100644 --- a/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php +++ b/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -43,7 +43,7 @@ class InputScreenAddAllController extends AbstractAddAllController * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * The twig engine. @@ -107,7 +107,15 @@ protected function render($table, $metaModel, Request $request) } /** - * {@inheritDoc} + * Create an empty data set for inclusion into the database. + * + * @param IAttribute $attribute The attribute to generate the data for. + * @param string $parentId The parent id. + * @param bool $activate Flag if the setting shall get activated. + * @param int $sort The sorting value. + * @param string $tlclass The CSS class. + * + * @return array * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ @@ -119,7 +127,7 @@ protected function createEmptyDataFor(IAttribute $attribute, $parentId, $activat 'attr_id' => $attribute->get('id'), 'pid' => $parentId, 'sorting' => $sort, - 'tstamp' => time(), + 'tstamp' => \time(), 'published' => $activate ? '1' : '' ]; } diff --git a/src/CoreBundle/Controller/Backend/RenderSettingAddAllController.php b/src/CoreBundle/Controller/Backend/RenderSettingAddAllController.php index 83431be7f..effff2e9f 100644 --- a/src/CoreBundle/Controller/Backend/RenderSettingAddAllController.php +++ b/src/CoreBundle/Controller/Backend/RenderSettingAddAllController.php @@ -49,7 +49,7 @@ public function __invoke($metaModel, $renderSetting, Request $request) * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - protected function createEmptyDataFor(IAttribute $attribute, $parentId, $activate, $sort) + protected function createEmptyDataFor(IAttribute $attribute, $parentId, $activate, $sort, $tlclass = '') { $result = [ 'attr_id' => $attribute->get('id'), diff --git a/src/CoreBundle/Controller/ContentElement/ItemListController.php b/src/CoreBundle/Controller/ContentElement/ItemListController.php index 497ca4ad6..080460bf9 100644 --- a/src/CoreBundle/Controller/ContentElement/ItemListController.php +++ b/src/CoreBundle/Controller/ContentElement/ItemListController.php @@ -36,6 +36,8 @@ * The item list content element. * * @ContentElement("metamodel_content", category="metamodels", template="ce_metamodel_content") + * + * @psalm-suppress PropertyNotSetInConstructor */ final class ItemListController extends AbstractContentElementController { @@ -63,7 +65,8 @@ public function __invoke( return $this->getBackendWildcard($model); } - if (!empty($model->metamodel_layout)) { + /** @psalm-suppress UndefinedMagicPropertyFetch */ + if (null !== $model->metamodel_layout) { $model->customTpl = $model->metamodel_layout; } diff --git a/src/CoreBundle/Controller/FrontendModule/ItemListController.php b/src/CoreBundle/Controller/FrontendModule/ItemListController.php index 40990854b..c26cee486 100644 --- a/src/CoreBundle/Controller/FrontendModule/ItemListController.php +++ b/src/CoreBundle/Controller/FrontendModule/ItemListController.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,6 +35,8 @@ * The item list front end module. * * @FrontendModule("metamodel_list", category="metamodels") + * + * @psalm-suppress PropertyNotSetInConstructor */ final class ItemListController extends AbstractFrontendModuleController { @@ -62,7 +64,8 @@ public function __invoke( return $this->getBackendWildcard($model); } - if (!empty($model->metamodel_layout)) { + /** @psalm-suppress UndefinedMagicPropertyFetch */ + if (null !== $model->metamodel_layout) { $model->customTpl = $model->metamodel_layout; } @@ -78,7 +81,7 @@ public function __invoke( */ protected function getBackendWildcard(ModuleModel $module): Response { - $name = $this->translator->trans('FMD.'.$this->getType().'.0', [], 'contao_modules'); + $name = $this->translator->trans('FMD.' . $this->getType() . '.0', [], 'contao_modules'); $href = $this->router->generate( 'contao_backend', ['do' => 'themes', 'table' => 'tl_module', 'act' => 'edit', 'id' => $module->id] diff --git a/src/CoreBundle/Controller/ListControllerTrait.php b/src/CoreBundle/Controller/ListControllerTrait.php index 8f81520b6..a6713bfe6 100644 --- a/src/CoreBundle/Controller/ListControllerTrait.php +++ b/src/CoreBundle/Controller/ListControllerTrait.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,6 +35,7 @@ use MetaModels\Helper\SortingLinkGenerator; use MetaModels\IFactory; use MetaModels\IItem; +use MetaModels\IMetaModel; use MetaModels\ItemList; use MetaModels\Render\Setting\IRenderSettingFactory; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -141,7 +142,9 @@ public function __construct( // @codingStandardsIgnoreEnd $translator = System::getContainer()->get('translator'); + assert($translator instanceof TranslatorInterface); } + $this->translator = $translator; if (null === $router) { // @codingStandardsIgnoreStart @@ -152,7 +155,9 @@ public function __construct( // @codingStandardsIgnoreEnd $router = System::getContainer()->get('router'); + assert($router instanceof RouterInterface); } + $this->router = $router; if (null === $scopeMatcher) { // @codingStandardsIgnoreStart @@ -163,10 +168,8 @@ public function __construct( // @codingStandardsIgnoreEnd $scopeMatcher = System::getContainer()->get('contao.routing.scope_matcher'); + assert($scopeMatcher instanceof ScopeMatcher); } - - $this->translator = $translator; - $this->router = $router; $this->scopeMatcher = $scopeMatcher; } @@ -181,10 +184,14 @@ public function __construct( * * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ private function getResponseInternal(Template $template, Model $model, Request $request): Response { - if (empty($pageParam = $model->metamodel_page_param)) { + /** @psalm-suppress UndefinedMagicPropertyFetch */ + if (null === ($pageParam = $model->metamodel_page_param)) { + /** @psalm-suppress UndefinedMagicPropertyFetch */ switch ($model->type) { case 'metamodel_content': $pageParam = 'page_mmce' . $model->id; @@ -197,6 +204,7 @@ private function getResponseInternal(Template $template, Model $model, Request $ } } + /** @psalm-suppress UndefinedMagicPropertyFetch */ $itemRenderer = new ItemList( $this->factory, $this->filterFactory, @@ -210,42 +218,59 @@ private function getResponseInternal(Template $template, Model $model, Request $ $model->metamodel_pagination_urlfragment ); + /** + * @psalm-suppress UndefinedMagicPropertyAssignment + * @psalm-suppress UndefinedMagicPropertyFetch + */ $template->searchable = !$model->metamodel_donotindex; - $sorting = $model->metamodel_sortby; - $direction = $model->metamodel_sortby_direction; + /** @psalm-suppress UndefinedMagicPropertyFetch */ + $sorting = $model->metamodel_sortby; + /** @psalm-suppress UndefinedMagicPropertyFetch */ + $direction = $model->metamodel_sortby_direction; + /** @psalm-suppress UndefinedMagicPropertyFetch */ $sortParamType = $model->metamodel_sort_param_type; $sortOrderByParam = 'orderBy'; $sortOrderDirParam = 'orderDir'; - $sortOverride = $model->metamodel_sort_override; - $sortFragment = $model->metamodel_sort_urlfragment; + /** @psalm-suppress UndefinedMagicPropertyFetch */ + $sortOverride = $model->metamodel_sort_override; + /** @psalm-suppress UndefinedMagicPropertyFetch */ + $sortFragment = $model->metamodel_sort_urlfragment; // @codingStandardsIgnoreStart // FIXME: filter URL should be created from local request and not from master request. // @codingStandardsIgnoreEnd $filterUrl = $this->filterUrlBuilder->getCurrentFilterUrl(); if ($sortOverride) { - $sortOrderByParam = $model->metamodel_order_by_param ?: $sortOrderByParam; + /** @psalm-suppress UndefinedMagicPropertyFetch */ + $sortOrderByParam = $model->metamodel_order_by_param ?: $sortOrderByParam; + /** @psalm-suppress UndefinedMagicPropertyFetch */ $sortOrderDirParam = $model->metamodel_order_dir_param ?: $sortOrderDirParam; - if (null !== + if ( + null !== $value = $this->tryReadFromSlugOrGet( $filterUrl, $sortOrderByParam, $sortParamType - )) { + ) + ) { $sorting = $value; } - if (null !== + if ( + null !== $value = $this->tryReadFromSlugOrGet( $filterUrl, $sortOrderDirParam, $sortParamType - )) { + ) + ) { $direction = $value; } } + /** @psalm-suppress UndefinedMagicPropertyFetch */ $filterParams = StringUtil::deserialize($model->metamodel_filterparams, true); + /** @psalm-suppress UndefinedMagicPropertyFetch */ $itemRenderer ->setMetaModel($model->metamodel, $model->metamodel_rendersettings) ->setListTemplate($template) @@ -256,6 +281,7 @@ private function getResponseInternal(Template $template, Model $model, Request $ ->setFilterParameters($filterParams, $this->getFilterParameters($filterUrl, $itemRenderer)) ->setMetaTags($model->metamodel_meta_title, $model->metamodel_meta_description); if ($sortOverride) { + /** @psalm-suppress UndefinedMagicPropertyFetch */ $itemRenderer->setSortingLinkGenerator( new SortingLinkGenerator( $this->filterUrlBuilder, @@ -270,19 +296,27 @@ private function getResponseInternal(Template $template, Model $model, Request $ ); } + /** @psalm-suppress UndefinedMagicPropertyFetch */ if ($model->metamodel_use_parameters) { + /** @psalm-suppress UndefinedMagicPropertyFetch */ foreach (StringUtil::deserialize(($model->metamodel_parameters ?? null), true) as $key => $value) { $itemRenderer->setTemplateParameter($key, $value); } } + /** + * @psalm-suppress UndefinedMagicPropertyAssignment + * @psalm-suppress UndefinedMagicPropertyFetch + */ $template->items = StringUtil::encodeEmail($itemRenderer->render($model->metamodel_noparsing, $model)); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ $template->numberOfItems = $itemRenderer->getItems()->getCount(); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ $template->pagination = $itemRenderer->getPagination(); $responseTags = \array_map( static function (IItem $item) { - return sprintf('contao.db.%s.%d', $item->getMetaModel()->getTableName(), $item->get('id')); + return \sprintf('contao.db.%s.%d', $item->getMetaModel()->getTableName(), $item->get('id')); }, \iterator_to_array($itemRenderer->getItems(), false) ); @@ -359,11 +393,14 @@ private function renderBackendWildcard(string $href, string $name, Model $model) { $template = new BackendTemplate('be_wildcard'); + /** @psalm-suppress UndefinedMagicPropertyFetch */ $headline = StringUtil::deserialize($model->headline); - + /** @psalm-suppress UndefinedMagicPropertyAssignment */ $template->wildcard = $this->getWildcardInfoText($model, $href, $name); - $template->title = (\is_array($headline) ? $headline['value'] : $headline); - $template->id = $model->id; + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->title = (\is_array($headline) ? $headline['value'] : $headline); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->id = $model->id; return new Response($template->parse()); } @@ -384,11 +421,12 @@ private function renderBackendWildcard(string $href, string $name, Model $model) */ private function getWildcardInfoText(Model $model, string $href, string $name): string { - if (empty($model->metamodel)) { + /** @psalm-suppress UndefinedMagicPropertyFetch */ + if (null === $model->metamodel) { return 'MetaModel not configured.'; } - if (null === $metaModelName = $this->factory->translateIdToMetaModelName($model->metamodel)) { + if ('' === ($metaModelName = $this->factory->translateIdToMetaModelName($model->metamodel))) { return 'Unknown MetaModel: ' . $model->metamodel; } // Add CSS file. @@ -399,13 +437,14 @@ private function getWildcardInfoText(Model $model, string $href, string $name): '
    %s: %s
    '; $metaModel = $this->factory->getMetaModel($metaModelName); + assert($metaModel instanceof IMetaModel); $header = $name . ': ' . $metaModel->getName(); if ($href) { $header .= \sprintf( ' (ID: %3$s)', $href, - REQUEST_TOKEN, - $model->id + System::getContainer()->get('contao.csrf.token_manager')?->getDefaultTokenValue() ?? '', + (string) $model->id ); } $infoText = \sprintf( @@ -416,8 +455,10 @@ private function getWildcardInfoText(Model $model, string $href, string $name): ); // Retrieve name of filter. + /** @psalm-suppress UndefinedMagicPropertyFetch */ if ($model->metamodel_filtering) { $filterparams = []; + /** @psalm-suppress UndefinedMagicPropertyFetch */ foreach (StringUtil::deserialize($model->metamodel_filterparams, true) as $filterparam) { if ($filterparam['value']) { $filterparams[] = $filterparam['value']; @@ -425,7 +466,7 @@ private function getWildcardInfoText(Model $model, string $href, string $name): } $infoFiPa = \count($filterparams) ? ': ' . \implode(', ', $filterparams) : ''; $infoFi = $this->filterFactory->createCollection($model->metamodel_filtering)->get('name'); - if ($infoFi) { + if (null !== $infoFi) { $infoText .= \sprintf( $infoTemplate, $this->translator->trans('MSC.mm_be_info_filter.1', [], 'contao_default'), @@ -436,11 +477,12 @@ private function getWildcardInfoText(Model $model, string $href, string $name): } // Retrieve name of rendersetting. + /** @psalm-suppress UndefinedMagicPropertyFetch */ if ($model->metamodel_rendersettings) { $infoRs = $this->renderSettingFactory ->createCollection($metaModel, $model->metamodel_rendersettings) ->get('name'); - if ($infoRs) { + if (null !== $infoRs) { $infoText .= \sprintf( $infoTemplate, $this->translator->trans('MSC.mm_be_info_render_setting.1', [], 'contao_default'), diff --git a/src/CoreBundle/DcGeneral/AbstractAttributeConditionFactory.php b/src/CoreBundle/DcGeneral/AbstractAttributeConditionFactory.php index bcc4421b6..efb20328a 100644 --- a/src/CoreBundle/DcGeneral/AbstractAttributeConditionFactory.php +++ b/src/CoreBundle/DcGeneral/AbstractAttributeConditionFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -31,7 +31,6 @@ abstract class AbstractAttributeConditionFactory implements AttributeAwareProper * Extract the attribute instance from the MetaModel. * * @param IMetaModel $metaModel The MetaModel instance. - * * @param int $attributeId The attribute id. * * @return string @@ -40,7 +39,7 @@ abstract class AbstractAttributeConditionFactory implements AttributeAwareProper */ protected function attributeIdToName(IMetaModel $metaModel, $attributeId) { - if (null === $attribute = $metaModel->getAttributeById((int) $attributeId)) { + if (null === $attribute = $metaModel->getAttributeById($attributeId)) { throw new \RuntimeException(sprintf( 'Could not retrieve attribute %s from MetaModel %s.', $attributeId, diff --git a/src/CoreBundle/DcGeneral/AbstractRestrictedAttributeConditionFactory.php b/src/CoreBundle/DcGeneral/AbstractRestrictedAttributeConditionFactory.php index 4f472a68a..79641839a 100644 --- a/src/CoreBundle/DcGeneral/AbstractRestrictedAttributeConditionFactory.php +++ b/src/CoreBundle/DcGeneral/AbstractRestrictedAttributeConditionFactory.php @@ -23,6 +23,7 @@ * This is the abstract base for attribute aware condition factories. * * @SuppressWarnings(PHPMD.LongClassName) + * @SuppressWarnings(PHPMD.LongVariable) */ abstract class AbstractRestrictedAttributeConditionFactory extends AbstractAttributeConditionFactory { diff --git a/src/CoreBundle/DcGeneral/FallbackPropertyConditionFactory.php b/src/CoreBundle/DcGeneral/FallbackPropertyConditionFactory.php index d368959d8..c497c98a9 100644 --- a/src/CoreBundle/DcGeneral/FallbackPropertyConditionFactory.php +++ b/src/CoreBundle/DcGeneral/FallbackPropertyConditionFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2021 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -37,7 +38,7 @@ class FallbackPropertyConditionFactory * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * Create a new instance. @@ -158,7 +159,9 @@ public function supportsAttribute($conditionType, $attribute) */ public function createCondition(array $configuration, IMetaModel $metaModel) { + /** @psalm-suppress DeprecatedClass */ $event = new CreatePropertyConditionEvent($configuration, $metaModel); + /** @psalm-suppress DeprecatedClass */ $this->dispatcher->dispatch($event, CreatePropertyConditionEvent::NAME); if (null === $instance = $event->getInstance()) { diff --git a/src/CoreBundle/DcGeneral/PropertyConditionFactory.php b/src/CoreBundle/DcGeneral/PropertyConditionFactory.php index fd37f0181..77b4ade10 100644 --- a/src/CoreBundle/DcGeneral/PropertyConditionFactory.php +++ b/src/CoreBundle/DcGeneral/PropertyConditionFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,8 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +26,8 @@ /** * This factory takes care of building property conditions. + * + * @psalm-suppress DeprecatedClass */ class PropertyConditionFactory { @@ -33,20 +36,22 @@ class PropertyConditionFactory * * @var IdProvidingServiceLocator */ - private $factories; + private IdProvidingServiceLocator $factories; /** * The fallback factory. * * @var FallbackPropertyConditionFactory */ - private $fallbackFactory; + private FallbackPropertyConditionFactory $fallbackFactory; /** * Create a new instance. * * @param IdProvidingServiceLocator $factories The factories. * @param FallbackPropertyConditionFactory $fallbackFactory The fallback factory. + * + * @psalm-suppress DeprecatedClass */ public function __construct(IdProvidingServiceLocator $factories, FallbackPropertyConditionFactory $fallbackFactory) { @@ -138,11 +143,7 @@ public function createCondition(array $configuration, IMetaModel $metaModel) } if (!$this->factories->has($typeName = $configuration['type'])) { - if ($result = $this->fallbackFactory->createCondition($configuration, $metaModel)) { - return $result; - } - - throw new \InvalidArgumentException('Unknown type: ' . $typeName); + return $this->fallbackFactory->createCondition($configuration, $metaModel); } return $this->getFactory($typeName)->buildCondition($configuration, $metaModel); diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php index b3864ddf0..d4493a479 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPass.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\CoreBundle\DependencyInjection\CompilerPass; diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectFactoriesPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectFactoriesPass.php index 7996dd543..a43d7453a 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectFactoriesPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectFactoriesPass.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,22 +33,22 @@ class CollectFactoriesPass implements CompilerPassInterface /** * The tag name to use for attribute factories. */ - const TAG_ATTRIBUTE_FACTORY = 'metamodels.attribute_factory'; + public const TAG_ATTRIBUTE_FACTORY = 'metamodels.attribute_factory'; /** * The tag name to use for filter factories. */ - const TAG_FILTER_FACTORY = 'metamodels.filter_factory'; + public const TAG_FILTER_FACTORY = 'metamodels.filter_factory'; /** * The tag name to use for property condition factories. */ - const TAG_PROPERTY_CONDITION_FACTORY = 'metamodels.condition_factory'; + public const TAG_PROPERTY_CONDITION_FACTORY = 'metamodels.condition_factory'; /** * {@inheritDoc} */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { $this->collectAttributeFactories($container); $this->collectFilterFactories($container); @@ -61,10 +62,10 @@ public function process(ContainerBuilder $container) * * @return void */ - private function collectAttributeFactories($container) + private function collectAttributeFactories(ContainerBuilder $container): void { $attributeFactory = $container->getDefinition('metamodels.attribute_factory'); - foreach (array_keys($container->findTaggedServiceIds(self::TAG_ATTRIBUTE_FACTORY)) as $factory) { + foreach (\array_keys($container->findTaggedServiceIds(self::TAG_ATTRIBUTE_FACTORY)) as $factory) { $attributeFactory->addMethodCall('addTypeFactory', [new Reference($factory)]); } } @@ -76,10 +77,10 @@ private function collectAttributeFactories($container) * * @return void */ - private function collectFilterFactories($container) + private function collectFilterFactories(ContainerBuilder $container): void { $attributeFactory = $container->getDefinition('metamodels.filter_setting_factory'); - foreach (array_keys($container->findTaggedServiceIds(self::TAG_FILTER_FACTORY)) as $factory) { + foreach (\array_keys($container->findTaggedServiceIds(self::TAG_FILTER_FACTORY)) as $factory) { $attributeFactory->addMethodCall('addTypeFactory', [new Reference($factory)]); } } @@ -91,7 +92,7 @@ private function collectFilterFactories($container) * * @return void */ - private function collectPropertyConditionFactories($container) + private function collectPropertyConditionFactories(ContainerBuilder $container): void { $factories = $container->getDefinition('metamodels.core_bundle.dc_general.property_condition_factories'); $args = $factories->getArgument(0); diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php index 7913a79fd..6bf79dfa5 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPass.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\CoreBundle\DependencyInjection\CompilerPass; diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php index 6fef35b94..e76815c52 100644 --- a/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php +++ b/src/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPass.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\CoreBundle\DependencyInjection\CompilerPass; diff --git a/src/CoreBundle/DependencyInjection/Configuration.php b/src/CoreBundle/DependencyInjection/Configuration.php index 2c5acaeab..e040e8daa 100644 --- a/src/CoreBundle/DependencyInjection/Configuration.php +++ b/src/CoreBundle/DependencyInjection/Configuration.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,14 +35,14 @@ class Configuration implements ConfigurationInterface * * @var bool */ - private $debug; + private bool $debug; /** * The root directory. * * @var string */ - private $rootDir; + private string $rootDir; /** * Constructor. @@ -52,7 +52,7 @@ class Configuration implements ConfigurationInterface */ public function __construct($debug, $rootDir) { - $this->debug = (bool) $debug; + $this->debug = $debug; $this->rootDir = $rootDir; } @@ -60,6 +60,8 @@ public function __construct($debug, $rootDir) * Generates the configuration tree builder. * * @return TreeBuilder + * + * @psalm-suppress UndefinedMethod */ public function getConfigTreeBuilder() { @@ -78,7 +80,7 @@ public function getConfigTreeBuilder() ->cannotBeEmpty() ->defaultValue($this->resolvePath($this->rootDir . '/assets/metamodels')) ->validate() - ->always(function ($value) { + ->always(function (string $value): string { return $this->resolvePath($value); }) ->end() @@ -99,12 +101,12 @@ public function getConfigTreeBuilder() * * @return string */ - private function resolvePath($value) + private function resolvePath(string $value): string { $path = Path::canonicalize($value); if ('\\' === DIRECTORY_SEPARATOR) { - $path = str_replace('/', '\\', $path); + $path = \str_replace('/', '\\', $path); } return $path; diff --git a/src/CoreBundle/DependencyInjection/IdProvidingServiceLocator.php b/src/CoreBundle/DependencyInjection/IdProvidingServiceLocator.php index 767041299..c1dc2d39c 100644 --- a/src/CoreBundle/DependencyInjection/IdProvidingServiceLocator.php +++ b/src/CoreBundle/DependencyInjection/IdProvidingServiceLocator.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\CoreBundle\DependencyInjection; diff --git a/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php b/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php index 039eec9d5..74ae196d4 100644 --- a/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php +++ b/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author Richard Henkenjohann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -43,7 +43,7 @@ class MetaModelsCoreExtension extends Extension implements PrependExtensionInter * * @var array */ - private $defaultTableOptions; + private array $defaultTableOptions = []; /** * The configuration files. @@ -88,14 +88,16 @@ public function prepend(ContainerBuilder $container): void /** * {@inheritDoc} */ - public function load(array $configs, ContainerBuilder $container) + public function load(array $configs, ContainerBuilder $container): void { $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); foreach (self::$files as $file) { $loader->load($file); } - $config = $this->processConfiguration($this->getConfiguration($configs, $container), $configs); + $configuration = $this->getConfiguration($configs, $container); + assert($configuration instanceof Configuration); + $config = $this->processConfiguration($configuration, $configs); $this->buildCacheService($container, $config); $container->setParameter('metamodels.resource_dir', __DIR__ . '/../Resources'); @@ -105,7 +107,7 @@ public function load(array $configs, ContainerBuilder $container) $container->getDefinition(TableCollationMigration::class) ->setArgument('$defaultTableOptions', $this->defaultTableOptions); - if ($container->getParameter('contao.legacy_routing')) { + if ((bool) $container->getParameter('contao.legacy_routing')) { $container->getDefinition(FilterUrlBuilder::class) ->setArgument(0, new Reference('contao.routing.url_generator')); } @@ -116,10 +118,9 @@ public function load(array $configs, ContainerBuilder $container) */ public function getConfiguration(array $config, ContainerBuilder $container) { - return new Configuration( - $container->getParameter('kernel.debug'), - $container->getParameter('kernel.project_dir') - ); + $projectDir = $container->getParameter('kernel.project_dir'); + assert(\is_string($projectDir)); + return new Configuration((bool) $container->getParameter('kernel.debug'), $projectDir); } /** @@ -130,7 +131,7 @@ public function getConfiguration(array $config, ContainerBuilder $container) * * @return void */ - private function buildCacheService(ContainerBuilder $container, array $config) + private function buildCacheService(ContainerBuilder $container, array $config): void { // if cache disabled, swap it out with the dummy cache. if (!$config['enable_cache']) { @@ -145,7 +146,7 @@ private function buildCacheService(ContainerBuilder $container, array $config) } /** - * Collect the default table options from the dcotrine extension. + * Collect the default table options from the doctrine extension. * * @param ContainerBuilder $container The container builder. * diff --git a/src/CoreBundle/EventListener/AttributeAddingListener.php b/src/CoreBundle/EventListener/AttributeAddingListener.php index 1fc3ff400..9cd90fd34 100644 --- a/src/CoreBundle/EventListener/AttributeAddingListener.php +++ b/src/CoreBundle/EventListener/AttributeAddingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -33,7 +34,7 @@ class AttributeAddingListener * * @var IAttributeFactory */ - private $attributeFactory; + private IAttributeFactory $attributeFactory; /** * Create a new instance. diff --git a/src/CoreBundle/EventListener/BackendNavigationListener.php b/src/CoreBundle/EventListener/BackendNavigationListener.php index 1ee915378..590445e9c 100644 --- a/src/CoreBundle/EventListener/BackendNavigationListener.php +++ b/src/CoreBundle/EventListener/BackendNavigationListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -48,28 +48,28 @@ class BackendNavigationListener * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * The translator in use. * * @var ViewCombination */ - private $viewCombination; + private ViewCombination $viewCombination; /** * The token storage. * * @var TokenStorageInterface */ - private $tokenStorage; + private TokenStorageInterface $tokenStorage; /** * The router. * * @var RouterInterface */ - private $router; + private RouterInterface $router; /** * Create a new instance. @@ -113,17 +113,18 @@ public function __invoke(MenuEvent $event): void return; } - if (null === $request = $this->requestStack->getCurrentRequest()) { + if (null === ($request = $this->requestStack->getCurrentRequest())) { return; } - $this->addBackendCss(); - - if (null !== ($user = $this->tokenStorage->getToken())) { - $userRights = $this->extractUserRights($user); + if (null === ($user = $this->tokenStorage->getToken())) { + return; } - $isAdmin = \in_array('ROLE_ADMIN', $user->getRoleNames(), true); + $this->addBackendCss(); + + $userRights = $this->extractUserRights($user); + $isAdmin = \in_array('ROLE_ADMIN', $user->getRoleNames(), true); $metaModelsNode = $tree->getChild('metamodels'); if (null !== $metaModelsNode && ($isAdmin || isset($userRights['support_metamodels']))) { @@ -133,7 +134,7 @@ public function __invoke(MenuEvent $event): void ->setLabel($this->translator->trans('MOD.support_metamodels.0', [], 'contao_modules')) ->setLinkAttribute('title', $this->translator->trans('MOD.support_metamodels.1', [], 'contao_modules')) ->setLinkAttribute('class', 'support_screen') - ->setCurrent('metamodels.support_screen' === $request->get('_route')); + ->setCurrent('metamodels.support_screen' === $request->attributes->get('_route')); $metaModelsNode->addChild($node); } @@ -158,7 +159,9 @@ public function __invoke(MenuEvent $event): void ->setLabel($this->extractLanguageValue($screen['label'], $locale)) ->setLinkAttribute('title', $this->extractLanguageValue($screen['description'], $locale)) ->setLinkAttribute('class', $item) - ->setCurrent($request->get('_route') === 'contao_backend' && $request->query->get('do') === $item); + ->setCurrent( + ($request->attributes->get('_route') === 'contao_backend') && ($request->query->get('do') === $item) + ); $sectionNode->addChild($node); } @@ -189,21 +192,20 @@ private function extractUserRights(TokenInterface $token): array default: } - return array_flip($allowedModules); + return \array_flip($allowedModules); } /** * Extract the language value. * * @param string[] $values The values. - * * @param string $locale The current locale. * * @return string */ - private function extractLanguageValue($values, $locale): string + private function extractLanguageValue(array $values, string $locale): string { - return html_entity_decode(($values[$locale] ?? $values[''])); + return \html_entity_decode(($values[$locale] ?? $values[''])); } /** diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/AbstractBreadcrumbListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/AbstractBreadcrumbListener.php index 1d18c6015..2dcc30a56 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/AbstractBreadcrumbListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/AbstractBreadcrumbListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +24,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; +use ContaoCommunityAlliance\DcGeneral\InputProviderInterface; /** * This class renders various breadcrumbs. @@ -34,14 +36,14 @@ abstract class AbstractBreadcrumbListener * * @var BreadcrumbStoreFactory */ - private $storeFactory; + private BreadcrumbStoreFactory $storeFactory; /** * The parent element renderer. * - * @var AbstractBreadcrumbListener + * @var AbstractBreadcrumbListener|null */ - private $parent; + private ?AbstractBreadcrumbListener $parent; /** * Create a new instance. @@ -90,7 +92,6 @@ abstract protected function wantToHandle(GetBreadcrumbEvent $event); * Perform the bread crumb generating. * * @param EnvironmentInterface $environment The environment in use. - * * @param BreadcrumbStore $elements The elements generated so far. * * @return void @@ -106,15 +107,17 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea * Extract the id value from the serialized parameter with the given name. * * @param EnvironmentInterface $environment The environment. - * * @param string $parameterName The parameter name containing the id. * - * @return int + * @return string */ protected function extractIdFrom(EnvironmentInterface $environment, $parameterName = 'pid') { - $parameter = $environment->getInputProvider()->getParameter($parameterName); + $inputProvider = $environment->getInputProvider(); + assert($inputProvider instanceof InputProviderInterface); + + $parameter = $inputProvider->getParameter($parameterName); - return ModelId::fromSerialized($parameter)->getId(); + return (string) ModelId::fromSerialized($parameter)->getId(); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbAttributeListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbAttributeListener.php index 13e789233..33a12e5c3 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbAttributeListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbAttributeListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,20 +13,25 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Breadcrumb; +use Contao\StringUtil; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; /** * Generate a breadcrumb for table tl_metamodel_attribute. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbAttributeListener extends AbstractBreadcrumbListener { @@ -37,7 +42,10 @@ class BreadcrumbAttributeListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel_attribute' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel_attribute' === $dataDefinition->getName(); } /** @@ -61,11 +69,12 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea ->unsetQueryParameter('act') ->unsetQueryParameter('id'); + $modelId = $elements->getId('tl_metamodel'); $elements->push( - ampersand($builder->getUrl()), - sprintf( + StringUtil::ampersand($builder->getUrl()), + \sprintf( $elements->getLabel('tl_metamodel_attribute'), - $this->getMetaModel($elements->getId('tl_metamodel'))->getName() + (null !== $modelId) ? $this->getMetaModel($modelId)->getName() : '' ), 'bundles/metamodelscore/images/icons/fields.png' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaCombineListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaCombineListener.php index 8d7cc11fe..6038beb91 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaCombineListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaCombineListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,20 +13,25 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Breadcrumb; +use Contao\StringUtil; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; /** * Generate a breadcrumb for table tl_metamodel_dcacombine. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbDcaCombineListener extends AbstractBreadcrumbListener { @@ -37,7 +42,10 @@ class BreadcrumbDcaCombineListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel_dca_combine' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel_dca_combine' === $dataDefinition->getName(); } /** @@ -61,11 +69,12 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea ->unsetQueryParameter('act') ->unsetQueryParameter('id'); + $modelId = $elements->getId('tl_metamodel'); $elements->push( - ampersand($builder->getUrl()), - sprintf( + StringUtil::ampersand($builder->getUrl()), + \sprintf( $elements->getLabel('tl_metamodel_dca_combine'), - $this->getMetaModel($elements->getId('tl_metamodel'))->getName() + (null !== $modelId) ? $this->getMetaModel($modelId)->getName() : '' ), 'bundles/metamodelscore/images/icons/dca_combine.png' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaListener.php index e87abbba3..9b6946407 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,20 +13,25 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Breadcrumb; +use Contao\StringUtil; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; /** * Generate a breadcrumb for table tl_metamodel_dca. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbDcaListener extends AbstractBreadcrumbListener { @@ -38,7 +43,10 @@ class BreadcrumbDcaListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel_dca' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel_dca' === $dataDefinition->getName(); } /** @@ -52,7 +60,7 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea } else { $elements->setId( 'tl_metamodel', - $this->getRow($elements->getId('tl_metamodel_dca'), 'tl_metamodel_dca')->pid + $this->getRow($elements->getId('tl_metamodel_dca') ?? '', 'tl_metamodel_dca')->pid ); } } @@ -69,11 +77,12 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea ->unsetQueryParameter('act') ->unsetQueryParameter('id'); + $modelId = $elements->getId('tl_metamodel'); $elements->push( - ampersand($builder->getUrl()), - sprintf( + StringUtil::ampersand($builder->getUrl()), + \sprintf( $elements->getLabel('tl_metamodel_dca'), - $this->getMetaModel($elements->getId('tl_metamodel'))->getName() + (null !== $modelId) ? $this->getMetaModel($modelId)->getName() : '' ), 'bundles/metamodelscore/images/icons/dca.png' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php index aa7ed8e29..bd38c2c46 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingConditionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,12 +24,16 @@ use Contao\StringUtil; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; use MetaModels\Helper\LocaleUtil; +use MetaModels\IMetaModel; /** * Generate a breadcrumb for table tl_metamodel_dcasetting_condition. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbDcaSettingConditionListener extends AbstractBreadcrumbListener { @@ -41,7 +45,10 @@ class BreadcrumbDcaSettingConditionListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel_dcasetting_condition' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel_dcasetting_condition' === $dataDefinition->getName(); } /** @@ -68,11 +75,12 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea ->unsetQueryParameter('act') ->unsetQueryParameter('id'); + $dcaSettingId = $elements->getId('tl_metamodel_dcasetting'); $elements->push( StringUtil::ampersand($builder->getUrl()), - sprintf( + \sprintf( $elements->getLabel('tl_metamodel_dcasetting_condition'), - $this->getConditionAttribute($elements->getId('tl_metamodel_dcasetting')) + (null !== $dcaSettingId) ? $this->getConditionAttribute($dcaSettingId) : '' ), 'bundles/metamodelscore/images/icons/dca_condition.png' ); @@ -92,10 +100,12 @@ private function getConditionAttribute($settingId) { $setting = $this->getRow($settingId, 'tl_metamodel_dcasetting'); - if ($setting->dcatype == 'attribute') { - $attribute = (object) $this->getRow($setting->attr_id, 'tl_metamodel_attribute'); + if ($setting->dcatype === 'attribute') { + $attribute = $this->getRow($setting->attr_id, 'tl_metamodel_attribute'); $metaModelName = $this->factory->translateIdToMetaModelName($attribute->pid); - $attribute = $this->factory->getMetaModel($metaModelName)->getAttributeById((int) $attribute->id); + $metaModel = $this->factory->getMetaModel($metaModelName); + assert($metaModel instanceof IMetaModel); + $attribute = $metaModel->getAttributeById((int) $attribute->id); if ($attribute) { return $attribute->getName(); } diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingListener.php index 7e88c2e57..b6ae9e430 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSettingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,20 +13,25 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Breadcrumb; +use Contao\StringUtil; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; /** * Generate a breadcrumb for table tl_metamodel_dcasetting. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbDcaSettingListener extends AbstractBreadcrumbListener { @@ -37,7 +42,10 @@ class BreadcrumbDcaSettingListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel_dcasetting' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel_dcasetting' === $dataDefinition->getName(); } /** @@ -51,7 +59,7 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea } else { $elements->setId( 'tl_metamodel_dca', - $this->getRow($elements->getId('tl_metamodel_dcasetting'), 'tl_metamodel_dcasetting')->pid + $this->getRow($elements->getId('tl_metamodel_dcasetting') ?? '', 'tl_metamodel_dcasetting')->pid ); } } @@ -69,11 +77,12 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea ->unsetQueryParameter('act') ->unsetQueryParameter('id'); + $dcaId = $elements->getId('tl_metamodel_dca'); $elements->push( - ampersand($builder->getUrl()), - sprintf( + StringUtil::ampersand($builder->getUrl()), + \sprintf( $elements->getLabel('tl_metamodel_dcasetting'), - $this->getRow($elements->getId('tl_metamodel_dca'), 'tl_metamodel_dca')->name + (null !== $dcaId) ? $this->getRow($dcaId, 'tl_metamodel_dca')->name : '' ), 'bundles/metamodelscore/images/icons/dca_setting.png' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSortGroupListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSortGroupListener.php index 6dd33b7df..90b2896c5 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSortGroupListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbDcaSortGroupListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,20 +13,25 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Breadcrumb; +use Contao\StringUtil; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; /** * Generate a breadcrumb for table tl_metamodel_dca_sortgroup. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbDcaSortGroupListener extends AbstractBreadcrumbListener { @@ -37,7 +42,10 @@ class BreadcrumbDcaSortGroupListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel_dca_sortgroup' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel_dca_sortgroup' === $dataDefinition->getName(); } /** @@ -62,11 +70,12 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea ->unsetQueryParameter('act') ->unsetQueryParameter('id'); + $dcaId = $elements->getId('tl_metamodel_dca'); $elements->push( - ampersand($builder->getUrl()), - sprintf( + StringUtil::ampersand($builder->getUrl()), + \sprintf( $elements->getLabel('tl_metamodel_dca_sortgroup'), - $this->getRow($elements->getId('tl_metamodel_dca'), 'tl_metamodel_dca')->name + (null !== $dcaId) ? $this->getRow($dcaId, 'tl_metamodel_dca')->name : '' ), 'bundles/metamodelscore/images/icons/dca_groupsortsettings.png' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbFilterListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbFilterListener.php index 2f5a8c96c..b52a93c5e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbFilterListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbFilterListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,20 +13,25 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Breadcrumb; +use Contao\StringUtil; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; /** * Generate a breadcrumb for table tl_metamodel_filter. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbFilterListener extends AbstractBreadcrumbListener { @@ -38,7 +43,10 @@ class BreadcrumbFilterListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel_filter' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel_filter' === $dataDefinition->getName(); } /** @@ -52,7 +60,7 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea } else { $elements->setId( 'tl_metamodel', - $this->getRow($elements->getId('tl_metamodel_filter'), 'tl_metamodel_filter')->pid + $this->getRow($elements->getId('tl_metamodel_filter') ?? '', 'tl_metamodel_filter')->pid ); } } @@ -69,11 +77,12 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea ->unsetQueryParameter('act') ->unsetQueryParameter('id'); + $modelId = $elements->getId('tl_metamodel'); $elements->push( - ampersand($builder->getUrl()), - sprintf( + StringUtil::ampersand($builder->getUrl()), + \sprintf( $elements->getLabel('tl_metamodel_filter'), - $this->getMetaModel($elements->getId('tl_metamodel'))->getName() + (null !== $modelId) ? $this->getMetaModel($modelId)->getName() : '' ), 'bundles/metamodelscore/images/icons/filter.png' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbFilterSettingListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbFilterSettingListener.php index 4ae117bcf..35cfcb1bb 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbFilterSettingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbFilterSettingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,20 +13,25 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Breadcrumb; +use Contao\StringUtil; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; /** * Generate a breadcrumb for table tl_metamodel_dcasetting. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbFilterSettingListener extends AbstractBreadcrumbListener { @@ -37,7 +42,10 @@ class BreadcrumbFilterSettingListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel_filtersetting' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel_filtersetting' === $dataDefinition->getName(); } /** @@ -51,7 +59,10 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea } else { $elements->setId( 'tl_metamodel_filter', - $this->getRow($elements->getId('tl_metamodel_filtersetting'), 'tl_metamodel_filtersetting')->pid + $this->getRow( + $elements->getId('tl_metamodel_filtersetting') ?? '', + 'tl_metamodel_filtersetting' + )->pid ); } } @@ -69,11 +80,12 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea ->unsetQueryParameter('act') ->unsetQueryParameter('id'); + $filterId = $elements->getId('tl_metamodel_filter'); $elements->push( - ampersand($builder->getUrl()), - sprintf( + StringUtil::ampersand($builder->getUrl()), + \sprintf( $elements->getLabel('tl_metamodel_filtersetting'), - $this->getRow($elements->getId('tl_metamodel_filter'), 'tl_metamodel_filter')->name + (null !== $filterId) ? $this->getRow($filterId, 'tl_metamodel_filter')->name : '' ), 'bundles/metamodelscore/images/icons/filter_setting.png' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbMetaModelListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbMetaModelListener.php index 75c356ec3..5cf1c42e7 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbMetaModelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbMetaModelListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,10 +22,13 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Breadcrumb; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; /** * Generate a breadcrumb for table tl_metamodel. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbMetaModelListener extends AbstractBreadcrumbListener { @@ -35,7 +39,10 @@ class BreadcrumbMetaModelListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel' === $dataDefinition->getName(); } /** diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbRenderSettingListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbRenderSettingListener.php index 3d2a6a105..27afffca9 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbRenderSettingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbRenderSettingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,20 +13,25 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Breadcrumb; +use Contao\StringUtil; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; /** * Generate a breadcrumb for table tl_metamodel_rendersetting. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbRenderSettingListener extends AbstractBreadcrumbListener { @@ -37,7 +42,10 @@ class BreadcrumbRenderSettingListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel_rendersetting' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel_rendersetting' === $dataDefinition->getName(); } /** @@ -64,11 +72,15 @@ public function getBreadcrumbElements(EnvironmentInterface $environment, Breadcr ->unsetQueryParameter('act') ->unsetQueryParameter('id'); + $renderSettingsId = $elements->getId('tl_metamodel_rendersettings'); $elements->push( - ampersand($builder->getUrl()), - sprintf( + StringUtil::ampersand($builder->getUrl()), + \sprintf( $elements->getLabel('tl_metamodel_rendersetting'), - $this->getRow($elements->getId('tl_metamodel_rendersettings'), 'tl_metamodel_rendersettings')->name + (null !== $renderSettingsId) ? $this->getRow( + $renderSettingsId, + 'tl_metamodel_rendersettings' + )->name : '' ), 'bundles/metamodelscore/images/icons/rendersetting.png' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbRenderSettingsListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbRenderSettingsListener.php index 91d70b43c..923f88508 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbRenderSettingsListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbRenderSettingsListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,20 +13,25 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Breadcrumb; +use Contao\StringUtil; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; /** * Generate a breadcrumb for table tl_metamodel_rendersettings. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbRenderSettingsListener extends AbstractBreadcrumbListener { @@ -38,7 +43,10 @@ class BreadcrumbRenderSettingsListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel_rendersettings' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel_rendersettings' === $dataDefinition->getName(); } /** @@ -52,7 +60,10 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea } else { $elements->setId( 'tl_metamodel', - $this->getRow($elements->getId('tl_metamodel_rendersettings'), 'tl_metamodel_rendersettings')->pid + $this->getRow( + $elements->getId('tl_metamodel_rendersettings') ?? '', + 'tl_metamodel_rendersettings' + )->pid ); } } @@ -69,11 +80,12 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea ->unsetQueryParameter('act') ->unsetQueryParameter('id'); + $modelId = $elements->getId('tl_metamodel'); $elements->push( - ampersand($builder->getUrl()), - sprintf( + StringUtil::ampersand($builder->getUrl()), + \sprintf( $elements->getLabel('tl_metamodel_rendersettings'), - $this->getMetaModel($elements->getId('tl_metamodel'))->getName() + (null !== $modelId) ? $this->getMetaModel($modelId)->getName() : '' ), 'bundles/metamodelscore/images/icons/rendersettings.png' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbSearchablePagesListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbSearchablePagesListener.php index 0b83e1d9c..4d5dd3784 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbSearchablePagesListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbSearchablePagesListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,20 +13,25 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Breadcrumb; +use Contao\StringUtil; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; /** * Generate a breadcrumb for table tl_metamodel_searchable_pages. + * + * @psalm-suppress PropertyNotSetInConstructor */ class BreadcrumbSearchablePagesListener extends AbstractBreadcrumbListener { @@ -38,7 +43,10 @@ class BreadcrumbSearchablePagesListener extends AbstractBreadcrumbListener */ protected function wantToHandle(GetBreadcrumbEvent $event) { - return 'tl_metamodel_searchable_pages' === $event->getEnvironment()->getDataDefinition()->getName(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return 'tl_metamodel_searchable_pages' === $dataDefinition->getName(); } /** @@ -53,7 +61,7 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea $elements->setId( 'tl_metamodel', $this->getRow( - $elements->getId('tl_metamodel_searchable_pages'), + $elements->getId('tl_metamodel_searchable_pages') ?? '', 'tl_metamodel_searchable_pages' )->pid ); @@ -75,11 +83,12 @@ protected function getBreadcrumbElements(EnvironmentInterface $environment, Brea ->unsetQueryParameter('act') ->unsetQueryParameter('id'); + $modelId = $elements->getId('tl_metamodel'); $elements->push( - ampersand($builder->getUrl()), - sprintf( + StringUtil::ampersand($builder->getUrl()), + \sprintf( $elements->getLabel('tl_metamodel_searchable_pages'), - $this->getMetaModel($elements->getId('tl_metamodel'))->getName() + (null !== $modelId) ? $this->getMetaModel($modelId)->getName() : '' ), 'bundles/metamodelscore/images/icons/searchable_pages.png' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/GetMetaModelTrait.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/GetMetaModelTrait.php index 4d7e52c5e..4ea5f68aa 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/GetMetaModelTrait.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/GetMetaModelTrait.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -33,7 +34,7 @@ trait GetMetaModelTrait * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Retrieve the MetaModel instance. @@ -46,12 +47,13 @@ trait GetMetaModelTrait */ protected function getMetaModel($metaModelId) { - if (null === $this->factory) { - throw new \RuntimeException('No factory set.'); - } - $metaModelName = $this->factory->translateIdToMetaModelName($metaModelId); - $metaModel = $this->factory->getMetaModel($metaModelName); + + $metaModel = $this->factory->getMetaModel($metaModelName); + + if (null === $metaModel) { + throw new \RuntimeException('MetaModel not found'); + } return $metaModel; } @@ -59,7 +61,7 @@ protected function getMetaModel($metaModelId) /** * {@inheritDoc} */ - public function setMetaModelFactory(IFactory $factory) + public function setMetaModelFactory(IFactory $factory): void { $this->factory = $factory; } diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/AbstractConditionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/AbstractConditionBuilder.php index 7052d33a2..6026d0fe1 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/AbstractConditionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/AbstractConditionBuilder.php @@ -32,6 +32,8 @@ /** * This class is the abstract base for the hierarchical/variant model condition builders. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ abstract class AbstractConditionBuilder { @@ -80,14 +82,25 @@ public static function calculateConditions(IMetaModelDataDefinition $container, throw new \InvalidArgumentException('Search element does not implement the correct interface.'); } - $instance = new static(); - - $instance->container = $container; - $instance->inputScreen = $inputScreen; - $instance->definition = $definition; + $instance = new static($container, $inputScreen, $definition); $instance->calculate(); } + /** + * @param IMetaModelDataDefinition $container + * @param array $inputScreen + * @param ModelRelationshipDefinitionInterface $definition + */ + final public function __construct( + IMetaModelDataDefinition $container, + array $inputScreen, + ModelRelationshipDefinitionInterface $definition + ) { + $this->container = $container; + $this->inputScreen = $inputScreen; + $this->definition = $definition; + } + /** * The real calculating function. * @@ -123,8 +136,8 @@ protected function addParentCondition(): void ->setDestinationName($this->container->getName()); $this->definition->addChildCondition($relationship); } else { - $setter = array_merge_recursive($setter, $relationship->getSetters()); - $inverse = array_merge_recursive($inverse, $relationship->getInverseFilterArray()); + $setter = \array_merge_recursive($setter, $relationship->getSetters()); + $inverse = \array_merge_recursive($inverse, $relationship->getInverseFilterArray()); } // For tl_ prefix, the only unique target can be the id? diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/BasicDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/BasicDefinitionBuilder.php index f210800e9..5390dcbfc 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/BasicDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/BasicDefinitionBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +25,7 @@ use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\DefaultBasicDefinition; use MetaModels\DcGeneral\DataDefinition\IMetaModelDataDefinition; use MetaModels\IFactory; +use MetaModels\IMetaModel; use MetaModels\ViewCombination\ViewCombination; /** @@ -39,14 +40,14 @@ class BasicDefinitionBuilder * * @var ViewCombination */ - private $viewCombination; + private ViewCombination $viewCombination; /** * The factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Create a new instance. @@ -70,7 +71,7 @@ public function __construct(ViewCombination $viewCombination, IFactory $factory) protected function build(IMetaModelDataDefinition $container) { $inputScreen = $this->viewCombination->getScreen($container->getName()); - if (!$inputScreen) { + if (null === $inputScreen) { return; } $meta = $inputScreen['meta']; @@ -80,6 +81,7 @@ protected function build(IMetaModelDataDefinition $container) $config->setDataProvider($container->getName()); $metaModel = $this->factory->getMetaModel($container->getName()); + assert($metaModel instanceof IMetaModel); // If we have variants, override all modes to tree mode. if ($metaModel->hasVariants()) { $config->setMode(BasicDefinitionInterface::MODE_HIERARCHICAL); @@ -113,7 +115,7 @@ protected function build(IMetaModelDataDefinition $container) * * @return BasicDefinitionInterface */ - private function getOrCreateBasicDefinition(IMetaModelDataDefinition $container) + private function getOrCreateBasicDefinition(IMetaModelDataDefinition $container): BasicDefinitionInterface { if ($container->hasBasicDefinition()) { return $container->getBasicDefinition(); diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php index a7f49b27b..e17c44f60 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -42,6 +42,8 @@ /** * This class builds the commands. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CommandBuilder { @@ -52,49 +54,42 @@ class CommandBuilder * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * The view combinations. * * @var ViewCombination */ - private $viewCombination; + private ViewCombination $viewCombination; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The container (only set during build phase). * - * @var IMetaModelDataDefinition + * @var IMetaModelDataDefinition|null */ - private $container; - - /** - * The input screen (only set during build phase). - * - * @var array - */ - private $inputScreen; + private IMetaModelDataDefinition|null $container = null; /** * The icon builder. * * @var IconBuilder */ - private $iconBuilder; + private IconBuilder $iconBuilder; /** * The translator. * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * Create a new instance. @@ -144,14 +139,13 @@ protected function build(IMetaModelDataDefinition $container) } $this->container = $container; - $this->inputScreen = $inputScreen = $this->viewCombination->getScreen($container->getName()); + $inputScreen = $this->viewCombination->getScreen($container->getName()); if (null === $inputScreen) { return; } $this->addEditMultipleCommand($view); $this->parseModelOperations($view); $this->container = null; - $this->inputScreen = null; if ($this->dispatcher->hasListeners(BuildMetaModelOperationsEvent::NAME)) { // @codingStandardsIgnoreStart @@ -160,11 +154,9 @@ protected function build(IMetaModelDataDefinition $container) E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - $event = new BuildMetaModelOperationsEvent( - $this->factory->getMetaModel($container->getName()), - $container, - $inputScreen - ); + $metaModel = $this->factory->getMetaModel($container->getName()); + assert($metaModel instanceof IMetaModel); + $event = new BuildMetaModelOperationsEvent($metaModel, $container, $inputScreen); $this->dispatcher->dispatch($event, $event::NAME); } } @@ -176,8 +168,9 @@ protected function build(IMetaModelDataDefinition $container) * * @return void */ - private function addEditMultipleCommand(Contao2BackendViewDefinitionInterface $view) + private function addEditMultipleCommand(Contao2BackendViewDefinitionInterface $view): void { + assert($this->container instanceof IMetaModelDataDefinition); $definition = $this->container->getBasicDefinition(); // No actions allowed. Don't add the select command button. if (!$definition->isEditable() && !$definition->isDeletable() && !$definition->isCreatable()) { @@ -206,8 +199,9 @@ private function addEditMultipleCommand(Contao2BackendViewDefinitionInterface $v * * @return void */ - private function parseModelOperations(Contao2BackendViewDefinitionInterface $view) + private function parseModelOperations(Contao2BackendViewDefinitionInterface $view): void { + assert($this->container instanceof IMetaModelDataDefinition); $collection = $view->getModelCommands(); $scrOffsetAttributes = ['attributes' => 'onclick="Backend.getScrollOffset();"']; @@ -228,7 +222,9 @@ private function parseModelOperations(Contao2BackendViewDefinitionInterface $vie ); $this->createCommand($collection, 'show', ['act' => 'show'], 'show.svg'); - if ($this->factory->getMetaModel($this->container->getName())->hasVariants()) { + $metaModel = $this->factory->getMetaModel($this->container->getName()); + assert($metaModel instanceof IMetaModel); + if ($metaModel->hasVariants()) { $this->createCommand( $collection, 'createvariant', @@ -240,7 +236,8 @@ private function parseModelOperations(Contao2BackendViewDefinitionInterface $vie // Check if we have some children. foreach ($this->viewCombination->getChildrenOf($this->container->getName()) as $tableName => $screen) { $metaModel = $this->factory->getMetaModel($tableName); - $caption = $this->getChildModelCaption($metaModel, $screen); + assert($metaModel instanceof IMetaModel); + $caption = $this->getChildModelCaption($metaModel, $screen); $this->createCommand( $collection, @@ -269,10 +266,10 @@ private function parseModelOperations(Contao2BackendViewDefinitionInterface $vie */ private function createCommand( CommandCollectionInterface $collection, - $operationName, - $queryParameters, - $icon, - $extraValues = [] + string $operationName, + array $queryParameters, + string $icon, + array $extraValues = [] ) { $command = $this->getCommandInstance($collection, $operationName); $parameters = $command->getParameters(); @@ -310,12 +307,11 @@ private function createCommand( * Retrieve or create a command instance of the given name. * * @param CommandCollectionInterface $collection The command collection. - * * @param string $operationName The name of the operation. * * @return CommandInterface */ - private function getCommandInstance(CommandCollectionInterface $collection, $operationName) + private function getCommandInstance(CommandCollectionInterface $collection, string $operationName) { if ($collection->hasCommandNamed($operationName)) { $command = $collection->getCommandNamed($operationName); @@ -351,11 +347,11 @@ private function getCommandInstance(CommandCollectionInterface $collection, $ope * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - private function getChildModelCaption($metaModel, $screen) + private function getChildModelCaption(IMetaModel $metaModel, array $screen): array { $caption = [ '', - sprintf( + \sprintf( $GLOBALS['TL_LANG']['MSC']['metamodel_edit_as_child']['label'], $metaModel->getName() ) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php index efec3a79e..df30a3f5e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithVariants.php @@ -66,7 +66,7 @@ protected function addVariantConditions(): void $relationship = $this->getRootCondition(); - $builder = FilterBuilder::fromArrayForRoot((array) $relationship->getFilterArray())->getFilter(); + $builder = FilterBuilder::fromArrayForRoot($relationship->getFilterArray())->getFilter(); $builder->andPropertyEquals('varbase', 1); @@ -78,7 +78,6 @@ protected function addVariantConditions(): void ]; $inverse = []; - /** @var ParentChildConditionInterface $relationship */ $relationship = $this->definition->getChildCondition($this->container->getName(), $this->container->getName()); if ($relationship === null) { @@ -100,7 +99,7 @@ protected function addVariantConditions(): void ->encapsulateOr() ->andRemotePropertyEquals('vargroup', 'vargroup') ->andRemotePropertyEquals('vargroup', 'id') - ->andRemotePropertyEquals('varbase', 0, true) + ->andRemotePropertyEquals('varbase', '0', true) ->getAllAsArray() ) ->setSetters($setter) diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithoutVariants.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithoutVariants.php index bd6a9c56d..8d871426f 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithoutVariants.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/ConditionBuilderWithoutVariants.php @@ -43,7 +43,7 @@ class ConditionBuilderWithoutVariants extends AbstractConditionBuilder protected function calculate(): void { if ($this->inputScreen['meta']['rendertype'] !== 'standalone') { - if ($this->container->getBasicDefinition()->getMode() == BasicDefinitionInterface::MODE_HIERARCHICAL) { + if ($this->container->getBasicDefinition()->getMode() === BasicDefinitionInterface::MODE_HIERARCHICAL) { throw new \RuntimeException('Hierarchical mode with parent table is not supported yet.'); } } @@ -78,7 +78,7 @@ protected function addHierarchicalConditions(): void ->setSetters([['property' => 'pid', 'value' => $parentValue]]); } - $builder = FilterBuilder::fromArrayForRoot((array) $relationship->getFilterArray())->getFilter(); + $builder = FilterBuilder::fromArrayForRoot($relationship->getFilterArray())->getFilter(); $builder->andPropertyEquals('pid', $parentValue); @@ -88,7 +88,6 @@ protected function addHierarchicalConditions(): void $setter = [['to_field' => 'pid', 'from_field' => 'id']]; $inverse = []; - /** @var ParentChildConditionInterface $relationship */ $relationship = $this->definition->getChildCondition($this->container->getName(), $this->container->getName()); if ($relationship === null) { $relationship = new ParentChildCondition(); diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php index 506cddd8e..2619ce470 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -37,6 +37,10 @@ /** * This class builds the Contao2 backend view definition. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * + * @psalm-suppress PropertyNotSetInConstructor */ class Contao2BackendViewDefinitionBuilder { @@ -47,56 +51,56 @@ class Contao2BackendViewDefinitionBuilder * * @var ViewCombination */ - private $viewCombination; + private ViewCombination $viewCombination; /** * The render setting factory. * * @var IRenderSettingFactory */ - private $renderSettingFactory; + private IRenderSettingFactory $renderSettingFactory; /** * The container being built (only set during build phase). * - * @var IMetaModelDataDefinition + * @var IMetaModelDataDefinition|null */ - private $container; + private IMetaModelDataDefinition|null $container; /** * The backend view definition (only set during build phase). * - * @var Contao2BackendViewDefinitionInterface + * @var Contao2BackendViewDefinitionInterface|null */ - private $definition; + private Contao2BackendViewDefinitionInterface|null $definition; /** * The input screen (only set during build phase). * - * @var array + * @var array|null */ - private $inputScreen; + private array|null $inputScreen; /** * The MetaModel that is the scope (only set during build phase). * - * @var IMetaModel + * @var IMetaModel|null */ - private $metaModel; + private IMetaModel|null $metaModel; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The icon builder. * * @var IconBuilder */ - private $iconBuilder; + private IconBuilder $iconBuilder; /** * Create a new instance. @@ -149,8 +153,9 @@ protected function build(IMetaModelDataDefinition $container) * * @throws DcGeneralInvalidArgumentException When the contained view definition is of invalid type. */ - private function getOrCreateDefinition() + private function getOrCreateDefinition(): Contao2BackendViewDefinitionInterface { + assert($this->container instanceof IMetaModelDataDefinition); if ($this->container->hasDefinition(Contao2BackendViewDefinitionInterface::NAME)) { $view = $this->container->getDefinition(Contao2BackendViewDefinitionInterface::NAME); if (!$view instanceof Contao2BackendViewDefinitionInterface) { @@ -158,8 +163,10 @@ private function getOrCreateDefinition() 'Configured BackendViewDefinition does not implement Contao2BackendViewDefinitionInterface.' ); } + return $view; } + $this->container->setDefinition( Contao2BackendViewDefinitionInterface::NAME, $view = new Contao2BackendViewDefinition() @@ -173,8 +180,11 @@ private function getOrCreateDefinition() * * @return void */ - private function parseListing() + private function parseListing(): void { + assert($this->definition instanceof Contao2BackendViewDefinitionInterface); + assert($this->metaModel instanceof IMetaModel); + assert(\is_array($this->inputScreen)); $listing = $this->definition->getListingConfig(); if (null === $listing->getRootLabel()) { @@ -182,7 +192,9 @@ private function parseListing() } if (null === $listing->getRootIcon()) { - $listing->setRootIcon($this->iconBuilder->getBackendIcon(($this->inputScreen['meta']['backendicon'] ?? ''))); + $listing->setRootIcon( + $this->iconBuilder->getBackendIcon(($this->inputScreen['meta']['backendicon'] ?? '')) + ); } $this->parseListSorting($listing); @@ -198,7 +210,7 @@ private function parseListing() * * @return void */ - private function parseListSorting(ListingConfigInterface $listing) + private function parseListSorting(ListingConfigInterface $listing): void { if (null === $this->inputScreen) { return; @@ -219,7 +231,8 @@ private function parseListSorting(ListingConfigInterface $listing) $this->handleSorting($information, $definition); $groupType = $this->convertRenderGroupType($information['rendergrouptype']); - if ($groupType !== GroupAndSortingInformationInterface::GROUP_NONE + if ( + $groupType !== GroupAndSortingInformationInterface::GROUP_NONE && !empty($information['col_name']) ) { $propertyInformation = $definition->add(0); @@ -241,9 +254,9 @@ private function parseListSorting(ListingConfigInterface $listing) * @return void */ private function handleSorting( - $information, + array $information, GroupAndSortingDefinitionInterface $definition - ) { + ): void { if (!empty($information['ismanualsort'])) { $definition ->add() @@ -267,7 +280,7 @@ private function handleSorting( * * @return string */ - private function convertRenderGroupType($type) + private function convertRenderGroupType(string $type): string { $lookup = [ 'char' => GroupAndSortingInformationInterface::GROUP_CHAR, @@ -278,7 +291,8 @@ private function convertRenderGroupType($type) 'month' => GroupAndSortingInformationInterface::GROUP_MONTH, 'year' => GroupAndSortingInformationInterface::GROUP_YEAR, ]; - if (array_key_exists($type, $lookup)) { + + if (\array_key_exists($type, $lookup)) { return $lookup[$type]; } @@ -292,9 +306,12 @@ private function convertRenderGroupType($type) * * @return void */ - private function parseListLabel(ListingConfigInterface $listing) + private function parseListLabel(ListingConfigInterface $listing): void { + assert($this->container instanceof IMetaModelDataDefinition); + assert($this->metaModel instanceof IMetaModel); $providerName = $this->container->getBasicDefinition()->getDataProvider(); + assert(\is_string($providerName)); if (!$listing->hasLabelFormatter($providerName)) { $formatter = new DefaultModelFormatterConfig(); $listing->setLabelFormatter($providerName, $formatter); @@ -308,9 +325,9 @@ private function parseListLabel(ListingConfigInterface $listing) ); $formatter->setPropertyNames( - array_merge($formatter->getPropertyNames(), $renderSetting->getSettingNames()) + \array_merge($formatter->getPropertyNames(), $renderSetting->getSettingNames()) ); - $formatter->setFormat(str_repeat('%s ', count($formatter->getPropertyNames()))); + $formatter->setFormat(\str_repeat('%s ', \count($formatter->getPropertyNames()))); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/DataProviderBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/DataProviderBuilder.php index fa3923742..8d819725a 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/DataProviderBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/DataProviderBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -41,14 +42,14 @@ class DataProviderBuilder * * @var ViewCombination */ - private $viewCombination; + private ViewCombination $viewCombination; /** * The factory to use. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Create a new instance. @@ -72,7 +73,7 @@ public function __construct(ViewCombination $viewCombination, IFactory $factory) protected function build(IMetaModelDataDefinition $container) { $inputScreen = $this->viewCombination->getScreen($container->getName()); - if (!$inputScreen) { + if (null === $inputScreen) { return; } $meta = $inputScreen['meta']; diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/MetaModelDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/MetaModelDefinitionBuilder.php index ec2285b3f..3a3c890dc 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/MetaModelDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/MetaModelDefinitionBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -37,7 +38,7 @@ class MetaModelDefinitionBuilder * * @var ViewCombination */ - private $viewCombination; + private ViewCombination $viewCombination; /** * Create a new instance. @@ -60,7 +61,7 @@ protected function build(IMetaModelDataDefinition $container) { $definition = $this->createOrGetDefinition($container); - if (empty($combination = $this->viewCombination->getCombination($container->getName()))) { + if (null === ($combination = $this->viewCombination->getCombination($container->getName()))) { return; } diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php index 9d1281a66..51cbf7de8 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +23,7 @@ use ContaoCommunityAlliance\DcGeneral\DataDefinition\ConditionInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\DefaultPalettesDefinition; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\DefinitionInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\PalettesDefinitionInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\Properties\PropertyInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Palette\DefaultPaletteCondition; @@ -40,6 +41,8 @@ /** * This class takes care of the palette building. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PaletteBuilder { @@ -50,21 +53,21 @@ class PaletteBuilder * * @var ViewCombination */ - private $viewCombination; + private ViewCombination $viewCombination; /** * The factory to use. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The property condition factory. * * @var PropertyConditionFactory */ - private $conditionFactory; + private PropertyConditionFactory $conditionFactory; /** * Create a new instance. @@ -95,7 +98,10 @@ protected function build(IMetaModelDataDefinition $container) if (null === ($inputScreen = $this->viewCombination->getScreen($container->getName()))) { return; } - $metaModel = $this->factory->getMetaModel($container->getName()); + + $metaModel = $this->factory->getMetaModel($container->getName()); + assert($metaModel instanceof IMetaModel); + $variantHandling = $metaModel->hasVariants(); $palettesDefinition = $this->getOrCreatePaletteDefinition($container); @@ -131,13 +137,17 @@ protected function build(IMetaModelDataDefinition $container) * * @param IMetaModelDataDefinition $container The container. * - * @return DefaultPalettesDefinition|\ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\DefinitionInterface + * @return PalettesDefinitionInterface */ - private function getOrCreatePaletteDefinition(IMetaModelDataDefinition $container) + private function getOrCreatePaletteDefinition(IMetaModelDataDefinition $container): PalettesDefinitionInterface { if ($container->hasDefinition(PalettesDefinitionInterface::NAME)) { - return $container->getDefinition(PalettesDefinitionInterface::NAME); + $definition = $container->getDefinition(PalettesDefinitionInterface::NAME); + assert($definition instanceof PalettesDefinitionInterface); + + return $definition; } + $container->setDefinition( PalettesDefinitionInterface::NAME, $palettesDefinition = new DefaultPalettesDefinition() @@ -201,14 +211,13 @@ private function createProperty( * Build the conditions for the passed condition array. * * @param array|null $condition The condition information. - * * @param IMetaModel $metaModel The MetaModel instance. * * @return null|ConditionInterface * * @throws \RuntimeException Throws if condition type not be transformed to an instance. */ - private function buildCondition($condition, $metaModel) + private function buildCondition(?array $condition, IMetaModel $metaModel): ?ConditionInterface { if (null === $condition) { return null; diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PanelBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PanelBuilder.php index 493bc64f9..6666361d6 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PanelBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PanelBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -37,6 +37,8 @@ /** * This class handles the panel building. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PanelBuilder { @@ -47,14 +49,14 @@ class PanelBuilder * * @var ViewCombination */ - private $viewCombination; + private ViewCombination $viewCombination; /** * The input screen to use (only set during build phase). * - * @var array + * @var array|null */ - private $inputScreen; + private ?array $inputScreen = null; /** * Create a new instance. @@ -89,7 +91,7 @@ protected function build(IMetaModelDataDefinition $container) $panelLayout = $this->inputScreen['meta']['panelLayout'] ?? null; // Check if we have a layout. - if (empty($panelLayout)) { + if (null === $panelLayout) { return; } @@ -102,7 +104,7 @@ protected function build(IMetaModelDataDefinition $container) foreach ($arrRows as $rowNo => $rowElements) { // Get the row, if we have one or create a new one. - if ($panelRows->getRowCount() < ($rowNo + 1)) { + if ($panelRows->getRowCount() < ((int) $rowNo + 1)) { $panelRow = $panelRows->addRow(); } else { $panelRow = $panelRows->getRow($rowNo); @@ -110,18 +112,18 @@ protected function build(IMetaModelDataDefinition $container) // Get the fields. $fields = StringUtil::trimsplit(',', $rowElements); - $fields = array_reverse($fields); + $fields = \array_reverse($fields); $this->parsePanelRow($fields, $panelRow); // If we have no entries for this row, remove it. - if ($panelRow->getCount() == 0) { + if ($panelRow->getCount() === 0) { $panelRows->deleteRow($rowNo); } } $this->ensureSubmitElement($panelRows); - $this->inputScreen = null; + $this->inputScreen = []; } /** @@ -133,7 +135,7 @@ protected function build(IMetaModelDataDefinition $container) * * @return void */ - private function ensureSubmitElement($panelRows) + private function ensureSubmitElement(PanelRowCollectionInterface $panelRows): void { // Check if we have a submit button. $hasSubmit = false; @@ -161,12 +163,11 @@ private function ensureSubmitElement($panelRows) * Parse a single row with all elements. * * @param array $fields A list of fields for adding to the row. - * * @param PanelRowInterface $panelRow The row container itself. * * @return void */ - private function parsePanelRow($fields, PanelRowInterface $panelRow) + private function parsePanelRow(array $fields, PanelRowInterface $panelRow): void { // Parse each type. foreach ($fields as $field) { @@ -204,9 +205,9 @@ private function parsePanelRow($fields, PanelRowInterface $panelRow) * * @return void */ - private function parsePanelFilter(PanelRowInterface $row) + private function parsePanelFilter(PanelRowInterface $row): void { - foreach ($this->inputScreen['properties'] as $value) { + foreach ($this->inputScreen['properties'] ?? [] as $value) { if (!empty($value['filter'])) { $element = new DefaultFilterElementInformation(); $element->setPropertyName($value['col_name']); @@ -224,7 +225,7 @@ private function parsePanelFilter(PanelRowInterface $row) * * @return void */ - private function parsePanelSort(PanelRowInterface $row) + private function parsePanelSort(PanelRowInterface $row): void { if (!$row->hasElement('sort')) { $element = new DefaultSortElementInformation(); @@ -241,7 +242,7 @@ private function parsePanelSort(PanelRowInterface $row) * * @throws \InvalidArgumentException When the search element does not implement the correct interface. */ - private function parsePanelSearch(PanelRowInterface $row) + private function parsePanelSearch(PanelRowInterface $row): void { if ($row->hasElement('search')) { $element = $row->getElement('search'); @@ -253,7 +254,7 @@ private function parsePanelSearch(PanelRowInterface $row) throw new \InvalidArgumentException('Search element does not implement the correct interface.'); } - foreach ($this->inputScreen['properties'] as $value) { + foreach ($this->inputScreen['properties'] ?? [] as $value) { if (!empty($value['search'])) { $element->addProperty($value['col_name']); } @@ -271,7 +272,7 @@ private function parsePanelSearch(PanelRowInterface $row) * * @return void */ - private function parsePanelLimit(PanelRowInterface $row) + private function parsePanelLimit(PanelRowInterface $row): void { if (!$row->hasElement('limit')) { $row->addElement(new DefaultLimitElementInformation()); @@ -285,7 +286,7 @@ private function parsePanelLimit(PanelRowInterface $row) * * @return void */ - private function parsePanelSubmit(PanelRowInterface $row) + private function parsePanelSubmit(PanelRowInterface $row): void { if (!$row->hasElement('submit')) { $row->addElement(new DefaultSubmitElementInformation()); diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php index 96d84a712..507b820a3 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php @@ -31,11 +31,14 @@ use MetaModels\DcGeneral\DataDefinition\IMetaModelDataDefinition; use MetaModels\DcGeneral\Events\MetaModel\BuildAttributeEvent; use MetaModels\IFactory; +use MetaModels\IMetaModel; use MetaModels\ViewCombination\ViewCombination; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * This class builds the property information. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PropertyDefinitionBuilder { @@ -46,21 +49,21 @@ class PropertyDefinitionBuilder * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * The view combinations. * * @var ViewCombination */ - private $viewCombination; + private ViewCombination $viewCombination; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Create a new instance. @@ -89,7 +92,7 @@ public function __construct( protected function build(IMetaModelDataDefinition $container) { $inputScreen = $this->viewCombination->getScreen($container->getName()); - if (!$inputScreen) { + if (null === $inputScreen) { return; } @@ -101,6 +104,7 @@ protected function build(IMetaModelDataDefinition $container) } $metaModel = $this->factory->getMetaModel($container->getName()); + assert($metaModel instanceof IMetaModel); // If the current metamodel has variants add the varbase and vargroup to the definition. if ($metaModel->hasVariants()) { @@ -141,12 +145,11 @@ protected function build(IMetaModelDataDefinition $container) * * @return void */ - private function buildProperty(PropertiesDefinitionInterface $definition, IAttribute $attribute, array $propInfo) - { - if (!$attribute) { - return; - } - + private function buildProperty( + PropertiesDefinitionInterface $definition, + IAttribute $attribute, + array $propInfo + ): void { $property = $this->getOrCreateProperty($definition, $attribute->getColName()); $this->setLabel($property, $propInfo, $attribute); $this->setDescription($property, $propInfo); @@ -169,11 +172,12 @@ private function buildProperty(PropertiesDefinitionInterface $definition, IAttri * * @return PropertyInterface */ - private function getOrCreateProperty(PropertiesDefinitionInterface $definition, $propName) + private function getOrCreateProperty(PropertiesDefinitionInterface $definition, string $propName): PropertyInterface { if ($definition->hasProperty($propName)) { return $definition->getProperty($propName); } + $property = new DefaultProperty($propName); $definition->addProperty($property); @@ -189,21 +193,24 @@ private function getOrCreateProperty(PropertiesDefinitionInterface $definition, * * @return void */ - private function setLabel(PropertyInterface $property, $propInfo, IAttribute $attribute) + private function setLabel(PropertyInterface $property, array $propInfo, IAttribute $attribute): void { if ($property->getLabel()) { return; } if (!isset($propInfo['label'])) { $property->setLabel($attribute->getName()); + return; } $lang = $propInfo['label']; - if (is_array($lang)) { + if (\is_array($lang)) { $property->setLabel(reset($lang)); $property->setDescription(next($lang)); + return; } + $property->setLabel($lang); } @@ -215,7 +222,7 @@ private function setLabel(PropertyInterface $property, $propInfo, IAttribute $at * * @return void */ - private function setDescription(PropertyInterface $property, $propInfo) + private function setDescription(PropertyInterface $property, array $propInfo): void { if ($property->getDescription() || !isset($propInfo['description'])) { return; @@ -232,7 +239,7 @@ private function setDescription(PropertyInterface $property, $propInfo) * * @return void */ - private function setDefaultValue(PropertyInterface $property, $propInfo) + private function setDefaultValue(PropertyInterface $property, array $propInfo): void { if (!isset($propInfo['default'])) { return; @@ -248,7 +255,7 @@ private function setDefaultValue(PropertyInterface $property, $propInfo) * * @return void */ - private function setExcluded(PropertyInterface $property, $propInfo) + private function setExcluded(PropertyInterface $property, array $propInfo): void { if (!isset($propInfo['exclude'])) { return; @@ -264,7 +271,7 @@ private function setExcluded(PropertyInterface $property, $propInfo) * * @return void */ - private function setSearchable(PropertyInterface $property, $propInfo) + private function setSearchable(PropertyInterface $property, array $propInfo): void { if (!isset($propInfo['search'])) { return; @@ -280,7 +287,7 @@ private function setSearchable(PropertyInterface $property, $propInfo) * * @return void */ - private function setFilterable(PropertyInterface $property, $propInfo) + private function setFilterable(PropertyInterface $property, array $propInfo): void { if (!isset($propInfo['filter'])) { return; @@ -296,10 +303,9 @@ private function setFilterable(PropertyInterface $property, $propInfo) * * @return void */ - private function setWidgetType(PropertyInterface $property, $propInfo) + private function setWidgetType(PropertyInterface $property, array $propInfo): void { - // FIXME: String cast for old DCG. - if ('' !== ((string) $property->getWidgetType()) || !isset($propInfo['inputType'])) { + if ('' !== ($property->getWidgetType()) || !isset($propInfo['inputType'])) { return; } @@ -314,7 +320,7 @@ private function setWidgetType(PropertyInterface $property, $propInfo) * * @return void */ - private function setOptions(PropertyInterface $property, $propInfo) + private function setOptions(PropertyInterface $property, array $propInfo): void { if (null !== $property->getOptions() || !isset($propInfo['options'])) { return; @@ -331,7 +337,7 @@ private function setOptions(PropertyInterface $property, $propInfo) * * @return void */ - private function setExplanation(PropertyInterface $property, $propInfo) + private function setExplanation(PropertyInterface $property, array $propInfo): void { if ($property->getExplanation() || !isset($propInfo['explanation'])) { return; @@ -349,14 +355,14 @@ private function setExplanation(PropertyInterface $property, $propInfo) * * @return void */ - private function setEval($property, $propInfo, $isTranslated) + private function setEval(PropertyInterface $property, array $propInfo, bool $isTranslated): void { - $extra = isset($propInfo['eval']) ? $propInfo['eval'] : []; + $extra = $propInfo['eval'] ?? []; if ($isTranslated) { $extra['tl_class'] = 'translat-attr' . (!empty($extra['tl_class']) ? ' ' . $extra['tl_class'] : ''); } - $property->setExtra(array_merge((array) $property->getExtra(), $extra)); + $property->setExtra(\array_merge($property->getExtra(), $extra)); } /** @@ -367,9 +373,9 @@ private function setEval($property, $propInfo, $isTranslated) * * @return void */ - private function setEmptyValue(PropertyInterface $property, array $propInfo) + private function setEmptyValue(PropertyInterface $property, array $propInfo): void { - if (!array_key_exists('empty_value', $propInfo) || !($property instanceof EmptyValueAwarePropertyInterface)) { + if (!\array_key_exists('empty_value', $propInfo) || !($property instanceof EmptyValueAwarePropertyInterface)) { return; } $property->setEmptyValue($propInfo['empty_value']); diff --git a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AssetPopulator.php b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AssetPopulator.php index 775b99cb3..521b311e5 100644 --- a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AssetPopulator.php +++ b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AssetPopulator.php @@ -39,6 +39,7 @@ class AssetPopulator * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function populate(EnvironmentInterface $environment) { diff --git a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AttributePopulator.php b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AttributePopulator.php index ad86e0023..abd9a7686 100644 --- a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AttributePopulator.php +++ b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/AttributePopulator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,16 +13,19 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2021 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\EnvironmentPopulator; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use MetaModels\DcGeneral\Events\MetaModel\PopulateAttributeEvent; use MetaModels\IFactory; +use MetaModels\IMetaModel; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** @@ -37,14 +40,14 @@ class AttributePopulator * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Create a new instance. @@ -67,7 +70,10 @@ public function __construct(EventDispatcherInterface $dispatcher, IFactory $fact */ public function populate(EnvironmentInterface $environment) { - $metaModel = $this->factory->getMetaModel($environment->getDataDefinition()->getName()); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + $metaModel = $this->factory->getMetaModel($dataDefinition->getName()); + assert($metaModel instanceof IMetaModel); foreach ($metaModel->getAttributes() as $attribute) { $event = new PopulateAttributeEvent($metaModel, $attribute, $environment); // Trigger BuildAttribute Event. diff --git a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/DataProviderPopulator.php b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/DataProviderPopulator.php index 5007852ec..c9e80a2d5 100644 --- a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/DataProviderPopulator.php +++ b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/DataProviderPopulator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,13 +13,15 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\EnvironmentPopulator; +use ContaoCommunityAlliance\DcGeneral\Contao\Dca\ContaoDataProviderInformation; use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\DataProviderDefinitionInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; @@ -40,21 +42,21 @@ class DataProviderPopulator * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The event dispatcher to pass to drivers. * - * @var EventDispatcherInterface + * @var EventDispatcherInterface|null */ - private $dispatcher = null; + private ?EventDispatcherInterface $dispatcher = null; /** * The database connection. * * @var Connection */ - private $connection; + private Connection $connection; /** * Create a new instance. @@ -79,11 +81,13 @@ public function __construct(IFactory $factory, EventDispatcherInterface $dispatc */ public function populate(EnvironmentInterface $environment) { - foreach ([ - $environment->getDataDefinition(), - $environment->getParentDataDefinition(), - $environment->getRootDataDefinition() - ] as $definition) { + foreach ( + [ + $environment->getDataDefinition(), + $environment->getParentDataDefinition(), + $environment->getRootDataDefinition() + ] as $definition + ) { if (!$definition instanceof ContainerInterface) { continue; } @@ -103,11 +107,11 @@ private function injectServiceContainerIntoDataDrivers($providerDefinitions, $en { foreach ($providerDefinitions as $provider) { $providerInstance = $environment->getDataProvider($provider->getName()); - if ($providerInstance instanceof Driver) { + if ($providerInstance instanceof Driver && $provider instanceof ContaoDataProviderInformation) { $initialization = $provider->getInitializationData(); $metaModel = $this->factory->getMetaModel($initialization['source']); $providerInstance->setBaseConfig( - array_merge($initialization, ['metaModel' => $metaModel]) + \array_merge($initialization, ['metaModel' => $metaModel]) ); $providerInstance->setDispatcher($this->dispatcher); $providerInstance->setConnection($this->connection); diff --git a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php index 2bb795429..776b7663e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php +++ b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,9 +23,11 @@ use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; use ContaoCommunityAlliance\Contao\Bindings\Events\System\LoadLanguageFileEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\Translator\StaticTranslator; use ContaoCommunityAlliance\Translator\TranslatorChain; +use ContaoCommunityAlliance\Translator\TranslatorInterface; use MetaModels\Helper\LocaleUtil; use MetaModels\ViewCombination\ViewCombination; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -42,14 +44,14 @@ class TranslatorPopulator * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * The view combination. * * @var ViewCombination */ - private $viewCombination; + private ViewCombination $viewCombination; /** * Create a new instance. @@ -76,6 +78,8 @@ public function __construct(EventDispatcherInterface $dispatcher, ViewCombinatio protected function populate(EnvironmentInterface $environment) { $translator = $environment->getTranslator(); + assert($translator instanceof TranslatorInterface); + if (!($translator instanceof TranslatorChain)) { $translatorChain = new TranslatorChain(); $translatorChain->add($translator); @@ -91,12 +95,16 @@ protected function populate(EnvironmentInterface $environment) ContaoEvents::SYSTEM_LOAD_LANGUAGE_FILE ); - $definitionName = $environment->getDataDefinition()->getName(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + $definitionName = $dataDefinition->getName(); $this->mapTranslations( $GLOBALS['TL_LANG']['tl_metamodel_item'], $definitionName, $translator ); + if (null === $inputScreen = $this->viewCombination->getScreen($definitionName)) { return; } @@ -122,7 +130,7 @@ private function mapTranslations($array, $domain, StaticTranslator $translator, { foreach ($array as $key => $value) { $newKey = ($baseKey ? $baseKey . '.' : '') . $key; - if (is_array($value)) { + if (\is_array($value)) { $this->mapTranslations($value, $domain, $translator, $newKey); } else { $translator->setValue($newKey, $value, $domain); @@ -148,8 +156,8 @@ private function addInputScreenTranslations(StaticTranslator $translator, $input // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. $currentLocale = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE']); // Either 2 char language code or null. - $shortLocale = (false !== strpos($currentLocale, '_')) - ? explode('_', $currentLocale, 2)[0] + $shortLocale = (\str_contains($currentLocale, '_')) + ? \explode('_', $currentLocale, 2)[0] : null; foreach ($inputScreen['legends'] as $legendName => $legendInfo) { @@ -161,21 +169,24 @@ private function addInputScreenTranslations(StaticTranslator $translator, $input ); $fallbackLocales = [$currentLocale]; - if ($shortLocale && !in_array($currentLocale, array_keys($legendInfo['label']), true)) { + if ((null !== $shortLocale) && !\array_key_exists($currentLocale, $legendInfo['label'])) { $fallbackLocales[] = $shortLocale; } + foreach ($legendInfo['label'] as $langCode => $label) { // Default is already handled above, do not overwrite! if ($langCode === 'default') { continue; } + $translator->setValue( $legendName . '_legend', $label, $containerName, $langCode ); - if (in_array($langCode, $fallbackLocales)) { + + if (\in_array($langCode, $fallbackLocales)) { $translator->setValue( $legendName . '_legend', $label, diff --git a/src/CoreBundle/EventListener/DcGeneral/ItemRendererListener.php b/src/CoreBundle/EventListener/DcGeneral/ItemRendererListener.php index 001a3c144..67ed36340 100644 --- a/src/CoreBundle/EventListener/DcGeneral/ItemRendererListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/ItemRendererListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author David Molineus * @author Alexander Menk * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -46,7 +46,7 @@ class ItemRendererListener * * @var IRenderSettingFactory */ - private $renderSettingFactory; + private IRenderSettingFactory $renderSettingFactory; /** * Create a new instance. @@ -82,35 +82,33 @@ public function render(ModelToLabelEvent $event) } $nativeItem = $model->getItem(); - $metaModel = $nativeItem->getMetaModel(); + assert($nativeItem instanceof IItem); + $metaModel = $nativeItem->getMetaModel(); $renderSetting = $this->renderSettingFactory ->createCollection($metaModel, $definition->getMetaModelDefinition()->getActiveRenderSetting()); - if (!$renderSetting) { - return; - } - - $data = array($nativeItem->parseValue('html5', $renderSetting)); + $data = [$nativeItem->parseValue('html5', $renderSetting)]; if ($listing->getShowColumns()) { $event->setArgs($data[0]['html5']); return; } - $template = new Template($renderSetting->get('template')); + $template = new Template($renderSetting->get('template') ?? ''); $renderSetting = self::removeInvariantAttributes($nativeItem, $renderSetting); $template->setData( - array( + [ 'settings' => $renderSetting, - 'items' => new Items(array($nativeItem)), + 'items' => new Items([$nativeItem]), 'view' => $renderSetting, 'data' => $data - ) + ] ); - $event->setLabel('%s')->setArgs(array($template->parse('html5'))); + /** @psalm-suppress InvalidArgument */ + $event->setLabel('%s')->setArgs([$template->parse('html5')]); } /** @@ -134,8 +132,10 @@ public function getReadableValue(RenderReadablePropertyValueEvent $event) } $nativeItem = $model->getItem(); - $metaModel = $nativeItem->getMetaModel(); - $propName = $event->getProperty()->getName(); + assert($nativeItem instanceof IItem); + $metaModel = $nativeItem->getMetaModel(); + $propName = $event->getProperty()->getName(); + if ($nativeItem->getAttribute($propName) instanceof IInternal) { return; } @@ -145,23 +145,20 @@ public function getReadableValue(RenderReadablePropertyValueEvent $event) $definition->getMetaModelDefinition()->getActiveRenderSetting() ); - if (!$renderSetting) { - return; - } - $result = $nativeItem->parseAttribute($propName, 'text', $renderSetting); if (!isset($result['text'])) { // If hide empty values active and the value IS empty, this is expected. See #1318. - if ($renderSetting->get('hideEmptyValues') && EmptyTest::isEmptyValue($nativeItem->get($propName))) { + if ((bool) $renderSetting->get('hideEmptyValues') && EmptyTest::isEmptyValue($nativeItem->get($propName))) { return; } $event->setRendered( - sprintf( + \sprintf( 'Unexpected behaviour, attribute %s text representation was not rendered.', $event->getProperty()->getName() ) ); + return; } @@ -182,26 +179,32 @@ public function addAdditionalParentHeaderFields(GetParentHeaderEvent $event) if (!$parentModel instanceof Model) { return; } + $environment = $event->getEnvironment(); /** @var IMetaModelDataDefinition $definition */ $definition = $environment->getDataDefinition(); $item = $parentModel->getItem(); + assert($item instanceof IItem); $metaModel = $item->getMetaModel(); $renderSetting = $this->renderSettingFactory->createCollection( $metaModel, $definition->getMetaModelDefinition()->getActiveRenderSetting() ); - $additional = array(); + $additional = []; foreach ($renderSetting->getSettingNames() as $name) { $parsed = $item->parseAttribute($name, 'text', $renderSetting); - $name = $item->getAttribute($name)->getName(); + $attribute = $item->getAttribute($name); + if (null === $attribute) { + continue; + } + $name = $attribute->getName(); $additional[$name] = $parsed['text']; } - $additional = array_merge( + $additional = \array_merge( $additional, $event->getAdditional() ); @@ -215,7 +218,6 @@ public function addAdditionalParentHeaderFields(GetParentHeaderEvent $event) * This is done by cloning the input collection of render settings and removing any invariant attribute. * * @param IItem $nativeItem The native item. - * * @param ICollection $renderSetting The render setting to be used. * * @return ICollection @@ -229,7 +231,7 @@ private function removeInvariantAttributes(IItem $nativeItem, ICollection $rende $renderSetting = clone $renderSetting; // Loop over all attributes and remove those from rendering that are not desired. - foreach (array_keys($model->getInVariantAttributes()) as $strAttrName) { + foreach (\array_keys($model->getInVariantAttributes()) as $strAttrName) { $renderSetting->setSetting($strAttrName, null); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/MetaModel/CreateVariantButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/MetaModel/CreateVariantButtonListener.php index a8c5220ac..2edd8d09b 100644 --- a/src/CoreBundle/EventListener/DcGeneral/MetaModel/CreateVariantButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/MetaModel/CreateVariantButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -30,17 +30,26 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\EditMask; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetOperationButtonEvent; +use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\View\CommandInterface; +use ContaoCommunityAlliance\DcGeneral\Data\DataProviderInterface; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\DcGeneral\Event\ActionEvent; use ContaoCommunityAlliance\DcGeneral\Event\PostCreateModelEvent; use ContaoCommunityAlliance\DcGeneral\Event\PreCreateModelEvent; use ContaoCommunityAlliance\DcGeneral\Event\PreEditModelEvent; +use ContaoCommunityAlliance\DcGeneral\InputProviderInterface; +use MetaModels\DcGeneral\Data\Driver; use MetaModels\DcGeneral\Data\Model; use MetaModels\IFactory; +use MetaModels\IItem; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Event handler class to manage the "create variant" button. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CreateVariantButtonListener { @@ -49,20 +58,19 @@ class CreateVariantButtonListener * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The request scope determinator. * * @var RequestScopeDeterminator */ - private $scopeMatcher; + private RequestScopeDeterminator $scopeMatcher; /** * Create a new instance. * * @param IFactory $factory The factory. - * * @param RequestScopeDeterminator $scopeMatcher The request scope determinator. */ public function __construct(IFactory $factory, RequestScopeDeterminator $scopeMatcher) @@ -80,12 +88,18 @@ public function __construct(IFactory $factory, RequestScopeDeterminator $scopeMa */ public function createButton(GetOperationButtonEvent $event) { - if ('createvariant' !== $event->getCommand()->getName()) { + $command = $event->getCommand(); + assert($command instanceof CommandInterface); + + if ('createvariant' !== $command->getName()) { return; } + /** @var Model $model */ - $model = $event->getModel(); - $metamodel = $model->getItem()->getMetaModel(); + $model = $event->getModel(); + $item = $model->getItem(); + assert($item instanceof IItem); + $metamodel = $item->getMetaModel(); if (!$metamodel->hasVariants() || $model->getProperty('varbase') === '0') { $event->setHtml(''); @@ -104,20 +118,27 @@ public function createButton(GetOperationButtonEvent $event) */ public function handleCreateVariantAction(ActionEvent $event) { - if (false === $this->scopeMatcher->currentScopeIsBackend() - || 'createvariant' !== $event->getAction()->getName()) { + if ( + false === $this->scopeMatcher->currentScopeIsBackend() + || 'createvariant' !== $event->getAction()->getName() + ) { return; } - $environment = $event->getEnvironment(); - $view = $environment->getView(); - $dataProvider = $environment->getDataProvider(); + $environment = $event->getEnvironment(); + $view = $environment->getView(); + $dataProvider = $environment->getDataProvider(); + assert($dataProvider instanceof Driver); $inputProvider = $environment->getInputProvider(); - $modelId = $inputProvider->hasParameter('id') + assert($inputProvider instanceof InputProviderInterface); + $modelId = $inputProvider->hasParameter('id') ? ModelId::fromSerialized($inputProvider->getParameter('id')) : null; - /** @var \MetaModels\DcGeneral\Data\Driver $dataProvider */ + if (null === $modelId) { + throw new \RuntimeException('No model id passed.'); + } + $model = $dataProvider ->createVariant( $dataProvider @@ -125,35 +146,41 @@ public function handleCreateVariantAction(ActionEvent $event) ->setId($modelId->getId()) ); - if ($model == null) { + if ($model === null) { throw new \RuntimeException(sprintf( 'Could not find model with id %s for creating a variant.', - $modelId + $modelId->getSerialized() )); } $metaModel = $this->factory->getMetaModel($model->getProviderName()); - if (!$metaModel || !$metaModel->hasVariants()) { + if ((null === $metaModel) || !$metaModel->hasVariants()) { return; } - $preFunction = function ($environment, $model) { - /** @var EnvironmentInterface $environment */ + $preFunction = function (EnvironmentInterface $environment, ModelInterface $model): void { + $dispatcher = $environment->getEventDispatcher(); + assert($dispatcher instanceof EventDispatcherInterface); + $copyEvent = new PreCreateModelEvent($environment, $model); - $environment->getEventDispatcher()->dispatch($copyEvent, $copyEvent::NAME); + $dispatcher->dispatch($copyEvent, $copyEvent::NAME); }; - $postFunction = function ($environment, $model) { - /** @var EnvironmentInterface $environment */ + $postFunction = function (EnvironmentInterface $environment, ModelInterface $model): void { + $dispatcher = $environment->getEventDispatcher(); + assert($dispatcher instanceof EventDispatcherInterface); + $copyEvent = new PostCreateModelEvent($environment, $model); - $environment->getEventDispatcher()->dispatch($copyEvent, $copyEvent::NAME); + $dispatcher->dispatch($copyEvent, $copyEvent::NAME); }; if (!$view instanceof BackendViewInterface) { throw new \InvalidArgumentException('Invalid view registered in environment.'); } - $editMask = new EditMask($view, $model, null, $preFunction, $postFunction, $this->breadcrumb($environment)); + $newModel = clone $model; + $editMask = + new EditMask($view, $newModel, $model, $preFunction, $postFunction, $this->breadcrumb($environment)); $event->setResponse($editMask->execute()); } @@ -176,7 +203,8 @@ public function presetVariantBase(PreEditModelEvent $event) // Get the item and check the context. $nativeItem = $model->getItem(); - $metaModel = $nativeItem->getMetaModel(); + assert($nativeItem instanceof IItem); + $metaModel = $nativeItem->getMetaModel(); if ($metaModel->hasVariants() && (!$nativeItem->get('vargroup'))) { $nativeItem->set('varbase', '1'); @@ -195,20 +223,21 @@ public function presetVariantBase(PreEditModelEvent $event) */ protected function breadcrumb(EnvironmentInterface $environment) { - $event = new GetBreadcrumbEvent($environment); - - $environment->getEventDispatcher()->dispatch($event, $event::NAME); + $event = new GetBreadcrumbEvent($environment); + $dispatcher = $environment->getEventDispatcher(); + assert($dispatcher instanceof EventDispatcherInterface); + $dispatcher->dispatch($event, $event::NAME); $arrReturn = $event->getElements(); - if (!is_array($arrReturn) || count($arrReturn) == 0) { - return null; + if ([] === $arrReturn) { + return ''; } $GLOBALS['TL_CSS'][] = 'bundles/ccadcgeneral/css/generalBreadcrumb.css'; $objTemplate = new ContaoBackendViewTemplate('dcbe_general_breadcrumb'); - $objTemplate->elements = $arrReturn; + $objTemplate->set('elements', $arrReturn); return $objTemplate->parse(); } diff --git a/src/CoreBundle/EventListener/DcGeneral/MetaModel/CutButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/MetaModel/CutButtonListener.php index 75ce260e9..047720b51 100644 --- a/src/CoreBundle/EventListener/DcGeneral/MetaModel/CutButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/MetaModel/CutButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @author David Molineus * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +24,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetOperationButtonEvent; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\ViewHelpers; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\View\CommandInterface; use MetaModels\DcGeneral\DataDefinition\IMetaModelDataDefinition; /** @@ -44,11 +46,12 @@ public function handle(GetOperationButtonEvent $event) } $command = $event->getCommand(); + assert($command instanceof CommandInterface); if ($command->getName() === 'cut') { $sortingProperty = ViewHelpers::getManualSortingProperty($event->getEnvironment()); - if (!$sortingProperty) { + if (null === $sortingProperty) { $event->setDisabled(true); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/MetaModel/PasteButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/MetaModel/PasteButtonListener.php index c28ad48bd..a936dad51 100644 --- a/src/CoreBundle/EventListener/DcGeneral/MetaModel/PasteButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/MetaModel/PasteButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author Stefan Heimes * @author David Molineus * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,16 +25,18 @@ use ContaoCommunityAlliance\DcGeneral\Clipboard\ClipboardInterface; use ContaoCommunityAlliance\DcGeneral\Clipboard\Filter; -use ContaoCommunityAlliance\DcGeneral\Clipboard\ItemInterface; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPasteButtonEvent; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPasteRootButtonEvent; use ContaoCommunityAlliance\DcGeneral\Data\DataProviderInterface; use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use MetaModels\IFactory; /** * This class handles the paste into and after button activation and deactivation for all MetaModels being edited. + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class PasteButtonListener { @@ -42,35 +45,35 @@ class PasteButtonListener * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The current environment. * - * @var EnvironmentInterface + * @var EnvironmentInterface|null */ - private $environment; + private EnvironmentInterface|null $environment = null; /** * The current data provider. * - * @var DataProviderInterface + * @var DataProviderInterface|null */ - private $provider; + private DataProviderInterface|null $provider = null; /** * The name of current data provider. * - * @var string + * @var string|null */ - private $providerName; + private string|null $providerName = null; /** * The model where we have to check if is it a paste into or paste after. * - * @var ModelInterface + * @var ModelInterface|null */ - private $currentModel; + private ModelInterface|null $currentModel = null; /** * Get determinator if there exists a circular reference. @@ -78,23 +81,23 @@ class PasteButtonListener * This flag determines if there exists a circular reference between the item currently in the clipboard and the * current model. A circular reference is of relevance when performing a cut and paste operation for example. * - * @var boolean + * @var boolean|null */ - private $circularReference; + private bool|null $circularReference = null; /** * Disable the paste after. * * @var bool */ - private $disablePA = true; + private bool $disablePA = true; /** * Disable the paste into. * * @var bool */ - private $disablePI = true; + private bool $disablePI = true; /** * Create a new instance. @@ -119,15 +122,21 @@ public function handle(GetPasteButtonEvent $event) { $this->circularReference = $event->isCircularReference(); $this->environment = $event->getEnvironment(); - $this->provider = $this->environment->getDataProvider(); - $this->providerName = $this->provider->getEmptyModel()->getProviderName(); - $clipboard = $this->environment->getClipboard(); - $this->currentModel = $event->getModel(); - $this->disablePI = true; - $this->disablePA = true; + $provider = $this->environment->getDataProvider(); + assert($provider instanceof DataProviderInterface); + $this->provider = $provider; + $this->providerName = $this->provider->getEmptyModel()->getProviderName(); + $clipboard = $this->environment->getClipboard(); + assert($clipboard instanceof ClipboardInterface); + $currentModel = $event->getModel(); + assert($currentModel instanceof ModelInterface); + $this->currentModel = $currentModel; + $this->disablePI = true; + $this->disablePA = true; // Only run for a MetaModels and if both values already disabled return here. - if ((substr($this->providerName, 0, 3) !== 'mm_') + if ( + (!\str_starts_with($this->providerName, 'mm_')) || ($event->isPasteIntoDisabled() && $event->isPasteAfterDisabled()) ) { return; @@ -153,15 +162,18 @@ public function handle(GetPasteButtonEvent $event) */ public function handleRoot(GetPasteRootButtonEvent $event) { - $this->environment = $event->getEnvironment(); - $this->provider = $this->environment->getDataProvider(); + $this->environment = $event->getEnvironment(); + $provider = $this->environment->getDataProvider(); + assert($provider instanceof DataProviderInterface); + $this->provider = $provider; $this->providerName = $this->provider->getEmptyModel()->getProviderName(); $clipboard = $this->environment->getClipboard(); + assert($clipboard instanceof ClipboardInterface); $this->currentModel = null; $this->disablePI = false; // Only run for a MetaModels. - if ((substr($this->providerName, 0, 3) !== 'mm_') || $event->isPasteDisabled()) { + if ((!\str_starts_with($this->providerName, 'mm_')) || $event->isPasteDisabled()) { return; } @@ -173,24 +185,26 @@ public function handleRoot(GetPasteRootButtonEvent $event) } /** - * Find a item by its id. + * Find an item by its id. * - * @param int $modelId The id to find. + * @param mixed $modelId The id to find. * - * @return ModelInterface + * @return ModelInterface|null */ - private function getModelById($modelId) + private function getModelById(mixed $modelId): ?ModelInterface { if ($modelId === null) { return null; } - $provider = $this->environment->getDataProvider(); - $config = $provider - ->getEmptyConfig() - ->setId($modelId); + $environment = $this->environment; + assert($environment instanceof EnvironmentInterface); + $dataProvider = $environment->getDataProvider(); + assert($dataProvider instanceof DataProviderInterface); - return $provider->fetch($config); + $config = $dataProvider->getEmptyConfig()->setId($modelId); + + return $dataProvider->fetch($config); } /** @@ -200,12 +214,15 @@ private function getModelById($modelId) * * @throws \RuntimeException When the MetaModel can not be loaded. */ - private function hasVariants() + private function hasVariants(): bool { + if ($this->providerName === null) { + throw new \RuntimeException('No MetaModel name given'); + } $metaModel = $this->factory->getMetaModel($this->providerName); if ($metaModel === null) { - throw new \RuntimeException(sprintf('Could not find a MetaModels with the name %s', $this->providerName)); + throw new \RuntimeException(\sprintf('Could not find a MetaModel with the name %s', $this->providerName)); } return $metaModel->hasVariants(); @@ -215,24 +232,17 @@ private function hasVariants() * Check the buttons based on the action. * * @param ClipboardInterface $clipboard The clipboard. - * * @param string $action The action to be checked. * * @return void */ - private function checkForAction($clipboard, $action) + private function checkForAction(ClipboardInterface $clipboard, string $action): void { // Make a filter for the given action. $filter = new Filter(); $filter->andActionIs($action); $items = $clipboard->fetch($filter); - // Check if there are items. - if ($items === null) { - return; - } - - /** @var ItemInterface[] $items */ foreach ($items as $item) { // Check the context. $itemProviderName = $item->getDataProviderName(); @@ -248,7 +258,7 @@ private function checkForAction($clipboard, $action) } $containedModel = $this->getModelById($modelId->getId()); - if ($this->currentModel == null) { + if ($this->currentModel === null) { $this->checkForRoot($containedModel, $action); } elseif ($containedModel) { $this->checkForModel($containedModel, $action); @@ -265,11 +275,11 @@ private function checkForAction($clipboard, $action) * * @return void */ - private function checkEmpty($action) + private function checkEmpty(string $action): void { if ($this->hasVariants() && $this->currentModel !== null) { $this->disablePA = false; - } elseif ($action == 'create') { + } elseif ($action === 'create') { $this->disablePA = false; $this->disablePI = false; } @@ -278,15 +288,19 @@ private function checkEmpty($action) /** * Check the PI for the root element. * - * @param ModelInterface $containedModel The model with all data. - * - * @param string $action The action to be checked. + * @param ModelInterface|null $containedModel The model with all data. + * @param string $action The action to be checked. * * @return void */ - private function checkForRoot($containedModel, $action) + private function checkForRoot(?ModelInterface $containedModel, string $action): void { - if ($this->hasVariants() && $action == 'cut' && $containedModel->getProperty('varbase') == 0) { + if ( + $action === 'cut' + && null !== $containedModel + && $this->hasVariants() + && $containedModel->getProperty('varbase') === '' + ) { $this->disablePI = true; } } @@ -295,29 +309,34 @@ private function checkForRoot($containedModel, $action) * Check the PA and PI with a model. * * @param ModelInterface $containedModel The model with all data. - * * @param string $action The action to be checked. * * @return void */ - private function checkForModel($containedModel, $action) + private function checkForModel(ModelInterface $containedModel, string $action): void { if (!$this->circularReference) { if ($this->hasVariants()) { $this->checkModelWithVariants($containedModel); } $this->checkModelWithoutVariants($containedModel); - } elseif ($this->currentModel == null && $containedModel->getProperty('varbase') == 0) { - $this->disablePA = true; - } else { - $this->disablePA = false; - // The following rules apply: - // 1. Variant bases must not get pasted into anything. - // 2. If we are not in create mode, disable the paste into for the item itself. - $this->disablePI = - ($this->hasVariants() && $containedModel->getProperty('varbase') == 1) - || ($action != 'create' && $containedModel->getId() == $this->currentModel->getId()); + return; } + + if ($this->currentModel === null) { + if ($containedModel->getProperty('varbase') === '') { + $this->disablePA = true; + } + + return; + } + $this->disablePA = false; + // The following rules apply: + // 1. Variant bases must not get pasted into anything. + // 2. If we are not in create mode, disable the paste into for the item itself. + $this->disablePI = + ($this->hasVariants() && $containedModel->getProperty('varbase') === '1') + || ($action !== 'create' && $containedModel->getId() === $this->currentModel->getId()); } /** @@ -327,19 +346,19 @@ private function checkForModel($containedModel, $action) * * @return void */ - private function checkModelWithVariants($containedModel) + private function checkModelWithVariants(ModelInterface $containedModel): void { // Item and variant support. $isVarbase = (bool) $containedModel->getProperty('varbase'); $vargroup = $containedModel->getProperty('vargroup'); - $isCurrentVarbase = (bool) $this->currentModel->getProperty('varbase'); - $currentVargroup = $this->currentModel->getProperty('vargroup'); + $isCurrentVarbase = (bool) $this->currentModel?->getProperty('varbase'); + $currentVargroup = $this->currentModel?->getProperty('vargroup'); if ($isVarbase && !$this->circularReference && $isCurrentVarbase) { // Insert new items only after bases. // Insert a varbase after any other varbase, for sorting. $this->disablePA = false; - } elseif (!$isVarbase && !$isCurrentVarbase && $vargroup == $currentVargroup) { + } elseif (!$isVarbase && !$isCurrentVarbase && $vargroup === $currentVargroup) { // Move items in their vargroup and only there. $this->disablePA = false; } @@ -354,14 +373,20 @@ private function checkModelWithVariants($containedModel) * * @return void */ - private function checkModelWithoutVariants($containedModel) + private function checkModelWithoutVariants(ModelInterface $containedModel): void { - $parentDefinition = $this->environment->getDataDefinition()->getBasicDefinition()->getParentDataProvider(); - - $this->disablePA = ($this->currentModel->getId() == $containedModel->getId()) - || ($parentDefinition && $this->currentModel->getProperty('pid') == $containedModel->getProperty('pid')); - $this->disablePI = ($this->circularReference) - || ($this->currentModel->getId() == $containedModel->getId()) - || ($parentDefinition && $this->currentModel->getProperty('pid') == $containedModel->getId()); + $environment = $this->environment; + assert($environment instanceof EnvironmentInterface); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + $parentDefinition = null !== $dataDefinition->getBasicDefinition()->getParentDataProvider(); + $currentModelId = $this->currentModel?->getId(); + $currentModelPid = $this->currentModel?->getProperty('pid'); + $this->disablePA = ($currentModelId === $containedModel->getId()) + || ($parentDefinition && $currentModelPid === $containedModel->getProperty('pid')); + $this->disablePI = ($this->circularReference) + || ($currentModelId === $containedModel->getId()) + || ($parentDefinition && $currentModelPid === $containedModel->getId()); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/AbstractPaletteRestrictionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/AbstractPaletteRestrictionListener.php index c424f18e0..7207eb2f3 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/AbstractPaletteRestrictionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/AbstractPaletteRestrictionListener.php @@ -34,7 +34,6 @@ */ class AbstractPaletteRestrictionListener { - /** * Retrieve the legend with the given name. * @@ -94,7 +93,8 @@ protected function getProperty($name, $legend) protected function addCondition($property, $condition) { $currentCondition = $property->getVisibleCondition(); - if ((!($currentCondition instanceof ConditionChainInterface)) + if ( + (!($currentCondition instanceof ConditionChainInterface)) || (ConditionChainInterface::OR_CONJUNCTION !== $currentCondition->getConjunction()) ) { if ($currentCondition === null) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeCreateListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeCreateListener.php index 59096a4ea..d19a262e4 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeCreateListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeCreateListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,7 @@ * * @package MetaModels/core * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,6 +22,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; use ContaoCommunityAlliance\DcGeneral\Event\PreEditModelEvent; +use ContaoCommunityAlliance\DcGeneral\InputProviderInterface; use Doctrine\DBAL\Connection; use MetaModels\Attribute\IAttributeFactory; use MetaModels\IFactory; @@ -69,9 +70,13 @@ public function handle(PreEditModelEvent $event): void return; } - if ('create' !== $event->getEnvironment()->getInputProvider()->getParameter('act') - || 'snc' !== $event->getEnvironment()->getInputProvider()->getParameter('btn') - || !($after = $event->getEnvironment()->getInputProvider()->getParameter('after')) + $inputProvider = $event->getEnvironment()->getInputProvider(); + assert($inputProvider instanceof InputProviderInterface); + + if ( + 'create' !== $inputProvider->getParameter('act') + || 'snc' !== $inputProvider->getParameter('btn') + || !($after = $inputProvider->getParameter('after')) ) { return; } @@ -87,7 +92,7 @@ public function handle(PreEditModelEvent $event): void ->where('t.id=:id') ->setParameter('id', $previousAttributeId) ->setMaxResults(1) - ->execute() + ->executeQuery() ->fetchFirstColumn(); if (empty($statement)) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php index 55e3b4e9e..b47145107 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,7 +22,10 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\Attribute; use Contao\StringUtil; +use Contao\System; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\ModelToLabelEvent; +use ContaoCommunityAlliance\Translator\TranslatorInterface; +use MetaModels\ITranslatedMetaModel; /** * This renders attribute information in the backend listing. @@ -49,10 +52,10 @@ public function modelToLabel(ModelToLabelEvent $event) $attribute = $this->attributeFactory->createAttribute($model->getPropertiesAsArray(), $metaModel); if (!$attribute) { - $translator = $event - ->getEnvironment() - ->getTranslator(); + $translator = $event->getEnvironment()->getTranslator(); + assert($translator instanceof TranslatorInterface); + /** @psalm-suppress InvalidArgument */ $event ->setLabel( '
    %s [%s]
    @@ -65,6 +68,7 @@ public function modelToLabel(ModelToLabelEvent $event) $type, $translator->translate('error_unknown_attribute.1', 'tl_metamodel_attribute', [$type]), ]); + return; } @@ -72,15 +76,24 @@ public function modelToLabel(ModelToLabelEvent $event) $colName = $attribute->getColName(); $name = $attribute->getName(); $arrDescription = StringUtil::deserialize($attribute->get('description')); - if (is_array($arrDescription)) { - $description = $arrDescription[$attribute->getMetaModel()->getActiveLanguage()] ?? null; - if (!$description) { - $description = $arrDescription[$attribute->getMetaModel()->getFallbackLanguage()]; + if (\is_array($arrDescription)) { + $locale = (string) System::getContainer()->get('request_stack')?->getCurrentRequest()?->getLocale(); + $description = $arrDescription[$locale] ?? null; + /** @psalm-suppress DeprecatedMethod */ + if (null === $description) { + if ($metaModel instanceof ITranslatedMetaModel) { + $description = $arrDescription[$metaModel->getMainLanguage()] ?? $attribute->getName(); + } else { + /** @psalm-suppress DeprecatedMethod */ + $description = $arrDescription[(string) $attribute->getMetaModel()->getFallbackLanguage()] + ?? $attribute->getName(); + } } } else { $description = $arrDescription ?: $attribute->getName(); } + /** @psalm-suppress InvalidArgument */ $event ->setLabel( '
    %s [%s%s]
    diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/BaseListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/BaseListener.php index 12c1b81b4..85a43ee20 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/BaseListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/BaseListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,6 +23,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; use ContaoCommunityAlliance\DcGeneral\Event\AbstractModelAwareEvent; use MetaModels\Attribute\IAttribute; @@ -39,7 +41,7 @@ class BaseListener * * @var RequestScopeDeterminator */ - private $scopeDeterminator; + private RequestScopeDeterminator $scopeDeterminator; /** * The attribute factory. @@ -130,13 +132,15 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) return false; } - $environment = $event->getEnvironment(); - if ('tl_metamodel_attribute' !== $environment->getDataDefinition()->getName()) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ('tl_metamodel_attribute' !== $dataDefinition->getName()) { return false; } if ($event instanceof AbstractModelAwareEvent) { - if ($event->getEnvironment()->getDataDefinition()->getName() !== $event->getModel()->getProviderName()) { + if ($dataDefinition->getName() !== $event->getModel()->getProviderName()) { return false; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php index b7e1e440b..5d3f3d274 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php @@ -23,6 +23,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\EncodePropertyValueFromWidgetEvent; +use ContaoCommunityAlliance\Translator\TranslatorInterface; use MetaModels\Attribute\IAttributeFactory; use MetaModels\Exceptions\Database\InvalidColumnNameException; use MetaModels\Helper\TableManipulator; @@ -76,6 +77,8 @@ public function handle(EncodePropertyValueFromWidgetEvent $event): void $oldColumnName = $event->getModel()->getProperty($event->getProperty()); $columnName = $event->getValue(); $metaModel = $this->getMetaModelByModelPid($event->getModel()); + $translator = $event->getEnvironment()->getTranslator(); + assert($translator instanceof TranslatorInterface); if ((!$columnName) || $oldColumnName !== $columnName) { try { @@ -83,7 +86,7 @@ public function handle(EncodePropertyValueFromWidgetEvent $event): void } catch (InvalidColumnNameException $exception) { throw new \RuntimeException( \sprintf( - $event->getEnvironment()->getTranslator()->translate( + $translator->translate( 'ERR.' . ($this->tableManipulator->isSystemColumn($columnName) ? 'systemColumn' : 'invalidColumnName') @@ -100,7 +103,7 @@ public function handle(EncodePropertyValueFromWidgetEvent $event): void if (\in_array($columnName, $colNames)) { throw new \RuntimeException( \sprintf( - $event->getEnvironment()->getTranslator()->translate('ERR.columnExists'), + $translator->translate('ERR.columnExists'), $columnName, $metaModel->getTableName() ) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/GetAttributeTypeListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/GetAttributeTypeListener.php index 85e37cfff..da072cb3b 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/GetAttributeTypeListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/GetAttributeTypeListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,8 +24,11 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; +use ContaoCommunityAlliance\Translator\TranslatorInterface; use MetaModels\Attribute\IAttributeFactory; +use MetaModels\Attribute\IAttributeTypeFactory; use MetaModels\IFactory; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; /** @@ -70,10 +74,13 @@ public function getOptions(GetPropertyOptionsEvent $event) return; } - $translator = $event->getEnvironment()->getTranslator(); + $translator = $event->getEnvironment()->getTranslator(); + assert($translator instanceof TranslatorInterface); + $objMetaModel = $this->getMetaModelByModelPid($event->getModel()); $flags = IAttributeFactory::FLAG_ALL_UNTRANSLATED; + /** @psalm-suppress DeprecatedMethod */ if ($objMetaModel->isTranslated()) { $flags |= IAttributeFactory::FLAG_INCLUDE_TRANSLATED; } @@ -82,7 +89,9 @@ public function getOptions(GetPropertyOptionsEvent $event) $optionsTrans = []; foreach ($this->attributeFactory->getTypeNames($flags) as $attributeType) { // Differentiate translated and simple. - if ($this->attributeFactory->getTypeFactory($attributeType)->isTranslatedType()) { + $typeFactory = $this->attributeFactory->getTypeFactory($attributeType); + assert($typeFactory instanceof IAttributeTypeFactory); + if ($typeFactory->isTranslatedType()) { $optionsTrans[$attributeType] = $translator->translate( 'typeOptions.' . $attributeType, 'tl_metamodel_attribute' @@ -94,12 +103,13 @@ public function getOptions(GetPropertyOptionsEvent $event) ); } } - asort($options); + \asort($options); // Add translated attributes. + /** @psalm-suppress DeprecatedMethod */ if ($objMetaModel->isTranslated()) { - asort($optionsTrans); - $options = array_merge($options, $optionsTrans); + \asort($optionsTrans); + $options = \array_merge($options, $optionsTrans); } $event->setOptions($options); @@ -123,6 +133,8 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) } $request = $this->requestStack->getCurrentRequest(); + assert($request instanceof Request); + if ($request->request->get('act', null) === 'select' && !$event->getModel()->getId()) { return false; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/BackendSectionOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/BackendSectionOptionListener.php index 86661c9ef..c6f8a60c9 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/BackendSectionOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/BackendSectionOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\Dca; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; /** * This provides the backend section options. @@ -39,11 +41,16 @@ class BackendSectionOptionListener */ public function handle(GetPropertyOptionsEvent $event) { - if (('tl_metamodel_dca' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('backendsection' !== $event->getPropertyName())) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_dca' !== $dataDefinition->getName()) + || ('backendsection' !== $event->getPropertyName()) + ) { return; } - $event->setOptions(array_keys($GLOBALS['BE_MOD'])); + $event->setOptions(\array_keys($GLOBALS['BE_MOD'])); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/ParentTableOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/ParentTableOptionListener.php index e99c47664..d3fdf6fc7 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/ParentTableOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/ParentTableOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +21,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\Dca; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use Doctrine\DBAL\Connection; use MetaModels\IFactory; @@ -34,14 +35,14 @@ class ParentTableOptionListener * * @var Connection */ - private $connection; + private Connection $connection; /** * The MetaModel factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Create a new instance. @@ -67,21 +68,26 @@ public function __construct(Connection $connection, IFactory $factory) */ public function handle(GetPropertyOptionsEvent $event) { - if (('tl_metamodel_dca' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('ptable' !== $event->getPropertyName())) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_dca' !== $dataDefinition->getName()) + || ('ptable' !== $event->getPropertyName()) + ) { return; } $tables = []; - foreach ($this->connection->getSchemaManager()->listTableNames() as $table) { + foreach ($this->connection->createSchemaManager()->listTableNames() as $table) { $tables[$table] = $table; } if ('ctable' === $event->getModel()->getProperty('rendertype')) { $currentTable = $this->factory->translateIdToMetaModelName($event->getModel()->getProperty('pid')); - $tables = array_filter( + $tables = \array_filter( $tables, - function ($table) use ($currentTable) { + static function ($table) use ($currentTable) { return ($currentTable !== $table); } ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/ParentTableVisibilityListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/ParentTableVisibilityListener.php index 8de2e2b26..8727c6c65 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/ParentTableVisibilityListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/ParentTableVisibilityListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -40,17 +41,19 @@ public function handle(BuildDataDefinitionEvent $event) { foreach ($event->getContainer()->getPalettesDefinition()->getPalettes() as $palette) { foreach ($palette->getProperties() as $property) { - if ($property->getName() != 'ptable') { + if ($property->getName() !== 'ptable') { continue; } $chain = $property->getVisibleCondition(); - if (!($chain + if ( + !($chain && ($chain instanceof PropertyConditionChain) && $chain->getConjunction() == PropertyConditionChain::AND_CONJUNCTION - )) { + ) + ) { $chain = new PropertyConditionChain( - array($property->getVisibleCondition()), + [$property->getVisibleCondition()], PropertyConditionChain::AND_CONJUNCTION ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php index c3191be5a..e2f5a8d41 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php @@ -22,6 +22,7 @@ use Contao\Message; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\BuildWidgetEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use Doctrine\DBAL\Connection; use MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting\AbstractListener; use MetaModels\IFactory; @@ -37,7 +38,7 @@ class RenderModeHintListener * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * Create a new instance. @@ -59,10 +60,14 @@ public function __construct( */ public function handle(BuildWidgetEvent $event) { - $environment = $event->getEnvironment(); - if (($environment->getDataDefinition()->getName() !== 'tl_metamodel_dca') + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ($dataDefinition->getName() !== 'tl_metamodel_dca') || ($event->getProperty()->getName() !== 'rendermode') - || (null === $event->getModel()->getId())) { + || (null === $event->getModel()->getId()) + ) { return; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeOptionListener.php index c30c138f6..40ff3b6bf 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,8 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\Dca; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\Translator\TranslatorInterface; /** * This provides the render mode options. @@ -39,13 +42,20 @@ class RenderModeOptionListener */ public function handle(GetPropertyOptionsEvent $event) { - if (('tl_metamodel_dca' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('rendermode' !== $event->getPropertyName())) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_dca' !== $dataDefinition->getName()) + || ('rendermode' !== $event->getPropertyName()) + ) { return; } $translator = $event->getEnvironment()->getTranslator(); - $options = [ + assert($translator instanceof TranslatorInterface); + + $options = [ 'flat' => $translator->translate('rendermodes.flat', 'tl_metamodel_dca'), 'hierarchical' => $translator->translate('rendermodes.hierarchical', 'tl_metamodel_dca'), ]; diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderTypeOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderTypeOptionListener.php index 1c9dde9e3..c03b46b78 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderTypeOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderTypeOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\Dca; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; /** * This provides the render type options. @@ -39,8 +41,13 @@ class RenderTypeOptionListener */ public function handle(GetPropertyOptionsEvent $event) { - if (('tl_metamodel_dca' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('rendertype' !== $event->getPropertyName())) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_dca' !== $dataDefinition->getName()) + || ('rendertype' !== $event->getPropertyName()) + ) { return; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/FixSortingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/FixSortingListener.php index 57e0c9e5d..e59c7f09f 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/FixSortingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/FixSortingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaCombine; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\EncodePropertyValueFromWidgetEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; /** * This class optimizes the sorting values. @@ -36,15 +38,20 @@ class FixSortingListener */ public function handle(EncodePropertyValueFromWidgetEvent $event) { - if (('tl_metamodel_dca_combine' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('rows' !== $event->getProperty())) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_dca_combine' !== $dataDefinition->getName()) + || ('rows' !== $event->getProperty()) + ) { return; } $values = $event->getValue(); $index = 0; - $time = time(); - foreach (array_keys($values) as $key) { + $time = \time(); + foreach (\array_keys($values) as $key) { $values[$key]['sorting'] = $index; $values[$key]['tstamp'] = $time; diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/FixTypeSafetyListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/FixTypeSafetyListener.php index 6b96f477b..4e79c0f96 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/FixTypeSafetyListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/FixTypeSafetyListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,8 @@ * * @package MetaModels/core * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -20,8 +21,10 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaCombine; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\EncodePropertyValueFromWidgetEvent; -use ContaoCommunityAlliance\DcGeneral\Data\DataProviderInterface; +use ContaoCommunityAlliance\DcGeneral\Data\DefaultDataProvider; use ContaoCommunityAlliance\DcGeneral\Data\ModelManipulator; +use ContaoCommunityAlliance\DcGeneral\Data\TableRowsAsRecordsDataProvider; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\PropertiesDefinitionInterface; /** @@ -38,14 +41,21 @@ class FixTypeSafetyListener */ public function handle(EncodePropertyValueFromWidgetEvent $event) { - if (('tl_metamodel_dca_combine' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('rows' !== $event->getProperty())) { + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_dca_combine' !== $dataDefinition->getName()) + || ('rows' !== $event->getProperty()) + ) { return; } - $environment = $event->getEnvironment(); + $dataProvider = $environment->getDataProvider(); - $properties = $environment->getDataDefinition()->getPropertiesDefinition(); + assert($dataProvider instanceof TableRowsAsRecordsDataProvider); + $properties = $dataDefinition->getPropertiesDefinition(); $values = (array) $event->getValue(); foreach ($values as $row => $current) { @@ -60,17 +70,18 @@ public function handle(EncodePropertyValueFromWidgetEvent $event) * * @param array $values The values for update. * @param PropertiesDefinitionInterface $properties The properties. - * @param DataProviderInterface $dataProvider The data provider. + * @param TableRowsAsRecordsDataProvider $dataProvider The data provider. * * @return array */ private function updateValues( array &$values, PropertiesDefinitionInterface $properties, - DataProviderInterface $dataProvider + TableRowsAsRecordsDataProvider $dataProvider ) { foreach ($values as $propertyName => $propertyValue) { - if (($dataProvider->getIdProperty() === $propertyName) + if ( + ($dataProvider->getIdProperty() === $propertyName) || ($dataProvider->getGroupColumnProperty() === $propertyName) || ($dataProvider->getSortingColumnProperty() === $propertyName) || ($dataProvider->getTimeStampProperty() === $propertyName) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/GroupOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/GroupOptionListener.php index 0ef7cb44a..7d5d9120a 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/GroupOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/GroupOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -14,13 +14,15 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaCombine; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\Translator\TranslatorInterface; use Doctrine\DBAL\Connection; use MenAtWork\MultiColumnWizardBundle\Event\GetOptionsEvent; @@ -34,7 +36,7 @@ class GroupOptionListener * * @var Connection */ - private $connection; + private Connection $connection; /** * Create a new instance. @@ -55,9 +57,14 @@ public function __construct(Connection $connection) */ public function handle(GetOptionsEvent $event) { - if (('tl_metamodel_dca_combine' !== $event->getEnvironment()->getDataDefinition()->getName()) + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_dca_combine' !== $dataDefinition->getName()) || ('rows' !== $event->getPropertyName()) - || !in_array($event->getSubPropertyName(), ['be_group', 'fe_group'])) { + || !\in_array($event->getSubPropertyName(), ['be_group', 'fe_group']) + ) { return; } @@ -71,8 +78,11 @@ public function handle(GetOptionsEvent $event) ->executeQuery() ->fetchAllAssociative(); + $translator = $event->getEnvironment()->getTranslator(); + assert($translator instanceof TranslatorInterface); + $result = []; - $result[-1] = $event->getEnvironment()->getTranslator()->translate( + $result[-1] = $translator->translate( $isBackend ? 'sysadmin' : 'anonymous', 'tl_metamodel_dca_combine' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/InputScreenOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/InputScreenOptionListener.php index 35a75c0dd..c633cdcae 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/InputScreenOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/InputScreenOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -14,13 +14,14 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaCombine; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use Doctrine\DBAL\Connection; use MenAtWork\MultiColumnWizardBundle\Event\GetOptionsEvent; @@ -34,7 +35,7 @@ class InputScreenOptionListener * * @var Connection */ - private $connection; + private Connection $connection; /** * Create a new instance. @@ -55,9 +56,14 @@ public function __construct(Connection $connection) */ public function handle(GetOptionsEvent $event) { - if (('tl_metamodel_dca_combine' !== $event->getEnvironment()->getDataDefinition()->getName()) + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_dca_combine' !== $dataDefinition->getName()) || ('rows' !== $event->getPropertyName()) - || ('dca_id' !== $event->getSubPropertyName())) { + || ('dca_id' !== $event->getSubPropertyName()) + ) { return; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/RenderSettingOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/RenderSettingOptionListener.php index 9bc98e182..1f0fe2d9d 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/RenderSettingOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaCombine/RenderSettingOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -14,13 +14,14 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaCombine; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use Doctrine\DBAL\Connection; use MenAtWork\MultiColumnWizardBundle\Event\GetOptionsEvent; @@ -34,7 +35,7 @@ class RenderSettingOptionListener * * @var Connection */ - private $connection; + private Connection $connection; /** * Create a new instance. @@ -55,9 +56,14 @@ public function __construct(Connection $connection) */ public function handle(GetOptionsEvent $event) { - if (('tl_metamodel_dca_combine' !== $event->getEnvironment()->getDataDefinition()->getName()) + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_dca_combine' !== $dataDefinition->getName()) || ('rows' !== $event->getPropertyName()) - || 'view_id' !== $event->getSubPropertyName()) { + || 'view_id' !== $event->getSubPropertyName() + ) { return; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractAbstainingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractAbstainingListener.php index 4d4f1d27a..59b478bef 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractAbstainingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractAbstainingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; use ContaoCommunityAlliance\DcGeneral\Event\AbstractModelAwareEvent; @@ -34,7 +36,7 @@ abstract class AbstractAbstainingListener * * @var RequestScopeDeterminator */ - private $scopeDeterminator; + private RequestScopeDeterminator $scopeDeterminator; /** * Create a new instance. @@ -60,13 +62,15 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) return false; } - $environment = $event->getEnvironment(); - if ('tl_metamodel_dcasetting' !== $environment->getDataDefinition()->getName()) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ('tl_metamodel_dcasetting' !== $dataDefinition->getName()) { return false; } if ($event instanceof AbstractModelAwareEvent) { - if ($event->getEnvironment()->getDataDefinition()->getName() !== $event->getModel()->getProviderName()) { + if ($dataDefinition->getName() !== $event->getModel()->getProviderName()) { return false; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractListener.php index e2d5fd476..820970ec7 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AbstractListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -69,16 +69,16 @@ public function __construct( * * @param ModelInterface $model The input screen model for which to retrieve the MetaModel. * - * @return IMetaModel + * @return IMetaModel|null * * @throws DcGeneralInvalidArgumentException When an invalid model has been passed or the model does not have an id. * @throws \Doctrine\DBAL\Exception */ protected function getMetaModelFromModel(ModelInterface $model) { - if (!(($model->getProviderName() == 'tl_metamodel_dcasetting') && $model->getProperty('pid'))) { + if (!(($model->getProviderName() === 'tl_metamodel_dcasetting') && $model->getProperty('pid'))) { throw new DcGeneralInvalidArgumentException( - sprintf( + \sprintf( 'Model must originate from tl_metamodel_dcasetting and be saved, this one originates from %s and ' . 'has pid %s', $model->getProviderName(), @@ -96,6 +96,10 @@ protected function getMetaModelFromModel(ModelInterface $model) ->executeQuery() ->fetchOne(); + if (false === $metaModelId) { + return null; + } + $tableName = $this->factory->translateIdToMetaModelName($metaModelId); return $this->factory->getMetaModel($tableName); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php index 927e2109b..ede039e7e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AddAllButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +23,8 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetGlobalButtonEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\DcGeneral\InputProviderInterface; use Doctrine\DBAL\Connection; use MetaModels\IFactory; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; @@ -37,21 +39,21 @@ class AddAllButtonListener * * @var Connection */ - private $connection; + private Connection $connection; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The URL generator. * * @var UrlGeneratorInterface */ - private $urlGenerator; + private UrlGeneratorInterface $urlGenerator; /** * Create a new instance. @@ -78,13 +80,21 @@ public function __construct(Connection $connection, IFactory $factory, UrlGenera */ public function getGlobalButton(GetGlobalButtonEvent $event) { - $environment = $event->getEnvironment(); - if ('addall' !== $event->getKey() - || 'tl_metamodel_dcasetting' !== $environment->getDataDefinition()->getName()) { + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + 'addall' !== $event->getKey() + || 'tl_metamodel_dcasetting' !== $dataDefinition->getName() + ) { return; } - $inputScreen = ModelId::fromSerialized($environment->getInputProvider()->getParameter('pid'))->getId(); + $inputProvider = $environment->getInputProvider(); + assert($inputProvider instanceof InputProviderInterface); + + $inputScreen = ModelId::fromSerialized($inputProvider->getParameter('pid'))->getId(); $modelId = $this->connection->createQueryBuilder() ->select('d.pid') @@ -94,6 +104,10 @@ public function getGlobalButton(GetGlobalButtonEvent $event) ->executeQuery() ->fetchOne(); + if (false === $modelId) { + return; + } + $name = $this->factory->translateIdToMetaModelName($modelId); $event->setHref( diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AttributeOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AttributeOptionListener.php index ac30decbe..cea6a5956 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AttributeOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/AttributeOptionListener.php @@ -38,7 +38,7 @@ class AttributeOptionListener extends AbstractListener * * @var SelectAttributeOptionLabelFormatter */ - private $attributeLabelFormatter; + private SelectAttributeOptionLabelFormatter $labelFormatter; /** * {@inheritDoc} @@ -47,10 +47,10 @@ public function __construct( RequestScopeDeterminator $scopeDeterminator, IFactory $factory, Connection $connection, - SelectAttributeOptionLabelFormatter $attributeLabelFormatter + SelectAttributeOptionLabelFormatter $labelFormatter ) { parent::__construct($scopeDeterminator, $factory, $connection); - $this->attributeLabelFormatter = $attributeLabelFormatter; + $this->labelFormatter = $labelFormatter; } /** @@ -69,7 +69,7 @@ public function getAttributeOptions(GetPropertyOptionsEvent $event) $model = $event->getModel(); $metaModel = $this->getMetaModelFromModel($model); - if (!$metaModel) { + if (null === $metaModel) { return; } @@ -96,7 +96,7 @@ public function getAttributeOptions(GetPropertyOptionsEvent $event) if ($attribute instanceof IInternal || in_array($attribute->get('id'), $alreadyTaken)) { continue; } - $options[$attribute->get('id')] = $this->attributeLabelFormatter->formatLabel($attribute); + $options[$attribute->get('id')] = $this->labelFormatter->formatLabel($attribute); } $event->setOptions($options); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php index 9005fb25d..3cca5a750 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Ingolf Steinhardt * @author Richard Henkenjohann * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,8 +25,10 @@ use Contao\Message; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\BuildWidgetEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use Doctrine\DBAL\Connection; use MetaModels\IFactory; +use MetaModels\IMetaModel; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -68,15 +70,20 @@ public function __construct( */ public function handle(BuildWidgetEvent $event) { - $environment = $event->getEnvironment(); - if (($environment->getDataDefinition()->getName() !== 'tl_metamodel_dcasetting') + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + if ( + ($dataDefinition->getName() !== 'tl_metamodel_dcasetting') || ($event->getProperty()->getName() !== 'mandatory') - || (null === $event->getModel()->getId())) { + || (null === $event->getModel()->getId()) + ) { return; } - $model = $event->getModel(); + $model = $event->getModel(); + assert($model instanceof IMetaModel); $metaModel = $this->getMetaModelFromModel($model); + assert($metaModel instanceof IMetaModel); $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); if (null === $attribute) { return; diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php index b6a1cccde..8742e3c22 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,8 +24,11 @@ use Contao\Message; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\BuildWidgetEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use Doctrine\DBAL\Connection; +use MetaModels\Attribute\IAttribute; use MetaModels\IFactory; +use MetaModels\IMetaModel; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -38,7 +41,7 @@ class DisableReadOnlyListener extends AbstractListener * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * Create a new instance. @@ -68,16 +71,27 @@ public function __construct( public function handle(BuildWidgetEvent $event) { $environment = $event->getEnvironment(); - if (($environment->getDataDefinition()->getName() !== 'tl_metamodel_dcasetting') + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ($dataDefinition->getName() !== 'tl_metamodel_dcasetting') || ($event->getProperty()->getName() !== 'readonly') - || (null === $event->getModel()->getId())) { + || (null === $event->getModel()->getId()) + ) { return; } $model = $event->getModel(); + assert($model instanceof IMetaModel); $metaModel = $this->getMetaModelFromModel($model); + assert($metaModel instanceof IMetaModel); + $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); + if (null === $attribute) { + return; + } - if ($metaModel->getAttributeById((int) $model->getProperty('attr_id'))->get('force_alias')) { + if ($attribute->get('force_alias')) { Message::addInfo( $this->translator->trans( 'tl_metamodel_dcasetting.readonly_for_force_alias', diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php index 7e57d6735..488551d61 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,7 @@ * * @package MetaModels/core * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +21,8 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetEditMaskSubHeadlineEvent; use Contao\CoreBundle\String\SimpleTokenParser; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\DcGeneral\InputProviderInterface; use MetaModels\DcGeneral\DataDefinition\Definition\IMetaModelDefinition; use MetaModels\ViewCombination\InputScreenInformationBuilder; use Symfony\Contracts\Translation\TranslatorInterface; @@ -75,25 +77,29 @@ public function __construct( */ public function __invoke(GetEditMaskSubHeadlineEvent $event): void { - if (!\str_starts_with($event->getEnvironment()->getDataDefinition()->getName(), 'mm_')) { + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if (!\str_starts_with($dataDefinition->getName(), 'mm_')) { return; } // Nothing to do on create item. - $environment = $event->getEnvironment(); - if ('create' === $environment->getInputProvider()->getParameter('act')) { + $inputProvider = $environment->getInputProvider(); + assert($inputProvider instanceof InputProviderInterface); + if ('create' === $inputProvider->getParameter('act')) { return; } // Retrieve the settings of the input mask for item attribute. - $dataDefinition = $environment->getDataDefinition(); - /** @var IMetaModelDefinition $metaModels */ - $metaModel = $dataDefinition->getDefinition(IMetaModelDefinition::NAME); + $metaModel = $dataDefinition->getDefinition(IMetaModelDefinition::NAME); + assert($metaModel instanceof IMetaModelDefinition); $metaModelName = $dataDefinition->getName(); $screen = $this->inputScreens->fetchInputScreens([$metaModelName => $metaModel->getActiveInputScreen()]); $screenMeta = $screen[$metaModelName]['meta'] ?? null; - if (empty($screenMeta) || empty($headline = ($screenMeta['subheadline'] ?? null))) { + if (null === $screenMeta || null === ($headline = ($screenMeta['subheadline'] ?? null))) { return; } @@ -123,8 +129,10 @@ public function __invoke(GetEditMaskSubHeadlineEvent $event): void */ private function replaceSimpleTokensAtHeadline(string $headline, array $tokenData): string { - if (\str_contains($headline, '##') - || \str_contains($headline, '##')) { + if ( + \str_contains($headline, '##') + || \str_contains($headline, '##') + ) { $headline = $this->tokenParser->parse( \str_replace('#', '#', $headline), diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/LegendTitleListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/LegendTitleListener.php index 8fad10876..81320f09c 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/LegendTitleListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/LegendTitleListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,7 +27,9 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\EncodePropertyValueFromWidgetEvent; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\Properties\PropertyInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; +use ContaoCommunityAlliance\Translator\TranslatorInterface; use MetaModels\Dca\Helper; +use MetaModels\IMetaModel; /** * This handles the serialization and deserialization as well as the building of the title widget. @@ -47,10 +50,11 @@ public function decodeValue(DecodePropertyValueForWidgetEvent $event) } $metaModel = $this->getMetaModelFromModel($event->getModel()); + assert($metaModel instanceof IMetaModel); $values = Helper::decodeLangArray($event->getValue(), $metaModel); - $event->setValue(unserialize($values)); + $event->setValue(\unserialize($values)); } /** @@ -67,6 +71,7 @@ public function encodeValue(EncodePropertyValueFromWidgetEvent $event) } $metaModel = $this->getMetaModelFromModel($event->getModel()); + assert($metaModel instanceof IMetaModel); $values = Helper::encodeLangArray($event->getValue(), $metaModel); @@ -87,13 +92,16 @@ public function buildWidget(BuildWidgetEvent $event) } $metaModel = $this->getMetaModelFromModel($event->getModel()); + assert($metaModel instanceof IMetaModel); + $translator = $event->getEnvironment()->getTranslator(); + assert($translator instanceof TranslatorInterface); Helper::prepareLanguageAwareWidget( $event->getEnvironment(), $event->getProperty(), $metaModel, - $event->getEnvironment()->getTranslator()->translate('name_langcode', 'tl_metamodel_dcasetting'), - $event->getEnvironment()->getTranslator()->translate('name_value', 'tl_metamodel_dcasetting'), + $translator->translate('name_langcode', 'tl_metamodel_dcasetting'), + $translator->translate('name_value', 'tl_metamodel_dcasetting'), false, StringUtil::deserialize($event->getModel()->getProperty('legendtitle'), true) ); @@ -107,10 +115,10 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) if (!parent::wantToHandle($event)) { return false; } - if (method_exists($event, 'getPropertyName') && ('legendtitle' !== $event->getPropertyName())) { + if (\method_exists($event, 'getPropertyName') && ('legendtitle' !== $event->getPropertyName())) { return false; } - if (method_exists($event, 'getProperty')) { + if (\method_exists($event, 'getProperty')) { $property = $event->getProperty(); if ($property instanceof PropertyInterface) { $property = $property->getName(); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ManipulateWidgetListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ManipulateWidgetListener.php index 9bf3d4999..ca04f4432 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ManipulateWidgetListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ManipulateWidgetListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,7 @@ * * @package MetaModels/core * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,9 +21,11 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\ManipulateWidgetEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; use MetaModels\Attribute\IInternal; use MetaModels\DcGeneral\Data\Model; +use MetaModels\IItem; final class ManipulateWidgetListener { @@ -47,7 +49,7 @@ public function __construct( /** * Change the widget template with your own choice. * - * @param BuildWidgetEvent $event The event. + * @param ManipulateWidgetEvent $event The event. * * @return void */ @@ -63,7 +65,9 @@ public function handle(ManipulateWidgetEvent $event) } $property = $event->getProperty(); - if (null === $attribute = $model->getItem()->getMetaModel()->getAttribute($property->getName())) { + $item = $model->getItem(); + assert($item instanceof IItem); + if (null === $attribute = $item->getMetaModel()->getAttribute($property->getName())) { return; } @@ -96,9 +100,10 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event): bool return false; } - $environment = $event->getEnvironment(); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); - if ('mm_' !== \substr($environment->getDataDefinition()->getName(), 0, 3)) { + if (!\str_starts_with($dataDefinition->getName(), 'mm_')) { return false; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php index f8dc0f06d..8aea94cfd 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -28,6 +28,7 @@ use MetaModels\Attribute\IAttributeFactory; use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\IFactory; +use MetaModels\IMetaModel; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -40,21 +41,21 @@ class ModelToLabelListener extends AbstractListener * * @var IAttributeFactory */ - private $attributeFactory; + private IAttributeFactory $attributeFactory; /** * The icon builder. * * @var IconBuilder */ - private $iconBuilder; + private IconBuilder $iconBuilder; /** * The translator. * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * Create a new instance. @@ -120,6 +121,7 @@ private function drawAttribute(ModelToLabelEvent $event) { $model = $event->getModel(); $metaModel = $this->getMetaModelFromModel($model); + assert($metaModel instanceof IMetaModel); $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); if ($attribute) { @@ -133,7 +135,7 @@ private function drawAttribute(ModelToLabelEvent $event) $variant = ($metaModel->hasVariants() && $attribute->get('isvariant')) ? ', variant' : ''; $name = $attribute->getName(); $colName = $attribute->getColName(); - $isUnique = $attribute->get('isunique'); + $isUnique = (bool) $attribute->get('isunique'); } else { $type = 'unknown ID: ' . $model->getProperty('attr_id'); $image = $this->iconBuilder->getBackendIconImageTag('bundles/metamodelscore/images/icons/fields.png'); @@ -143,6 +145,7 @@ private function drawAttribute(ModelToLabelEvent $event) $isUnique = false; } + /** @psalm-suppress InvalidArgument */ $event ->setLabel('
    %s [%s%s]
    @@ -155,11 +158,11 @@ private function drawAttribute(ModelToLabelEvent $event) $variant, $image, $name, - // unique attributes are automatically mandatory - $model->getProperty('mandatory') || $isUnique - ? ' ['. $this->trans('mandatory.0') . ']' + // unique attributes are automatically mandatory. + (bool) $model->getProperty('mandatory') || $isUnique + ? ' [' . $this->trans('mandatory.0') . ']' : '', - $model->getProperty('tl_class') ? sprintf('[%s]', $model->getProperty('tl_class')) : '' + $model->getProperty('tl_class') ? \sprintf('[%s]', $model->getProperty('tl_class')) : '' ]); } @@ -174,18 +177,21 @@ private function drawLegend(ModelToLabelEvent $event) { $model = $event->getModel(); $metaModel = $this->getMetaModelFromModel($model); - if (is_array($legend = StringUtil::deserialize($model->getProperty('legendtitle')))) { + assert($metaModel instanceof IMetaModel); + if (\is_array($legend = StringUtil::deserialize($model->getProperty('legendtitle')))) { + /** @psalm-suppress DeprecatedMethod */ foreach ([$metaModel->getActiveLanguage(), $metaModel->getFallbackLanguage()] as $language) { - if (array_key_exists($language, $legend) && !empty($legend[$language])) { + if (\array_key_exists($language ?? '', $legend) && !empty($legend[$language])) { $legend = $legend[$language]; break; } } } - if (empty($legend)) { + if (null === $legend) { $legend = 'legend'; } + /** @psalm-suppress InvalidArgument */ $event ->setLabel('
    %s
    %s%s
    ') diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/RemoveOverrideButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/RemoveOverrideButtonListener.php index 88ebabe59..41104d444 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/RemoveOverrideButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/RemoveOverrideButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,8 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -20,6 +21,8 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSetting; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetSelectModeButtonsEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\DcGeneral\InputProviderInterface; /** * This class takes care of removing the override button when select mode is active. @@ -35,8 +38,14 @@ class RemoveOverrideButtonListener */ public function removeButton(GetSelectModeButtonsEvent $event) { - if (('tl_metamodel_dcasetting' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('select' !== $event->getEnvironment()->getInputProvider()->getParameter('act')) + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + $inputProvider = $environment->getInputProvider(); + assert($inputProvider instanceof InputProviderInterface); + if ( + ('tl_metamodel_dcasetting' !== $dataDefinition->getName()) + || ('select' !== $inputProvider->getParameter('act')) ) { return; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/SetVisibilityConditionIconListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/SetVisibilityConditionIconListener.php index bb4e9caf9..21f1a8c6c 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/SetVisibilityConditionIconListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/SetVisibilityConditionIconListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,7 @@ * * @package MetaModels/core * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,12 +21,14 @@ use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; use ContaoCommunityAlliance\Contao\Bindings\Events\Image\GenerateHtmlEvent; -use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetOperationButtonEvent; +use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\View\CommandInterface; use Contao\Image; use Contao\StringUtil; -use Doctrine\DBAL\Connection; -use MetaModels\IFactory; +use MetaModels\IMetaModel; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * This handles the icon as status of visibility condition. @@ -42,24 +44,29 @@ class SetVisibilityConditionIconListener extends AbstractListener */ public function handle(GetOperationButtonEvent $event): void { - $environment = $event->getEnvironment(); - if ('tl_metamodel_dcasetting' !== $environment->getDataDefinition()->getName() - || 'conditions' !== $event->getCommand()->getName()) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + $command = $event->getCommand(); + assert($command instanceof CommandInterface); + if ( + 'tl_metamodel_dcasetting' !== $dataDefinition->getName() + || 'conditions' !== $command->getName() + ) { return; } - + $model = $event->getModel(); + assert($model instanceof ModelInterface); $statement = $this->connection->createQueryBuilder() ->select('count(*) as count') ->from('tl_metamodel_dcasetting_condition', 't') ->where('settingId=:settingId') - ->setParameter('settingId', $event->getModel()->getId()) + ->setParameter('settingId', $model->getId()) ->setMaxResults(1) - ->execute() + ->executeQuery() ->fetchFirstColumn(); - $command = $event->getCommand(); $extra = (array) $command->getExtra(); - $icon = $extra['icon']; + $icon = (string) $extra['icon']; if (empty($statement[0])) { $iconDisabledSuffix = '_1'; @@ -67,15 +74,15 @@ public function handle(GetOperationButtonEvent $event): void if ($icon !== Image::getPath($icon)) { $iconDisabledSuffix = '_'; } - $icon = \substr_replace($icon, $iconDisabledSuffix, \strrpos($icon, '.'), 0); + $icon = \substr_replace($icon, $iconDisabledSuffix, (int) \strrpos($icon, '.'), 0); } $button = \sprintf( ' %s', $command->getName(), - $event->getHref(), + $event->getHref() ?? '', StringUtil::specialchars( - \sprintf((string) $command->getDescription(), $event->getModel()->getID()) + \sprintf($command->getDescription(), $model->getID()) ), $this->renderImageAsHtml($event, $icon, $command->getLabel()) ); @@ -94,12 +101,14 @@ public function handle(GetOperationButtonEvent $event): void */ private function renderImageAsHtml(GetOperationButtonEvent $event, string $src, string $alt): string { + $dispatcher = $event->getEnvironment()->getEventDispatcher(); + assert($dispatcher instanceof EventDispatcherInterface); /** @var GenerateHtmlEvent $imageEvent */ - $imageEvent = $event->getEnvironment()->getEventDispatcher()->dispatch( + $imageEvent = $dispatcher->dispatch( new GenerateHtmlEvent($src, $alt), ContaoEvents::IMAGE_GET_HTML ); - return $imageEvent->getHtml(); + return $imageEvent->getHtml() ?? ''; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/TemplateOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/TemplateOptionListener.php index b45a6edcd..c0c4a4649 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/TemplateOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/TemplateOptionListener.php @@ -21,6 +21,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; use MetaModels\BackendIntegration\TemplateList; @@ -86,8 +87,10 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event): bool return false; } - $environment = $event->getEnvironment(); - if ('tl_metamodel_dcasetting' !== $environment->getDataDefinition()->getName()) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ('tl_metamodel_dcasetting' !== $dataDefinition->getName()) { return false; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AbstractListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AbstractListener.php index 27dc2926f..c8340df46 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AbstractListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AbstractListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,11 +23,15 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; use ContaoCommunityAlliance\DcGeneral\Event\AbstractModelAwareEvent; +use ContaoCommunityAlliance\DcGeneral\InputProviderInterface; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use MetaModels\IFactory; +use MetaModels\IMetaModel; /** * This provides a way to obtain a MetaModel. @@ -39,7 +43,7 @@ abstract class AbstractListener * * @var RequestScopeDeterminator */ - private $scopeDeterminator; + private RequestScopeDeterminator $scopeDeterminator; /** * The MetaModel factory. @@ -53,7 +57,7 @@ abstract class AbstractListener * * @var Connection */ - private $connection; + private Connection $connection; /** * Create a new instance. @@ -77,24 +81,31 @@ public function __construct( * * @param EnvironmentInterface $interface The environment. * - * @return \MetaModels\IMetaModel + * @return IMetaModel * * @throws \RuntimeException Throws if you could not retrieve metamodel. - * @throws \Doctrine\DBAL\Exception + * @throws Exception */ public function getMetaModel(EnvironmentInterface $interface) { + $inputProvider = $interface->getInputProvider(); + assert($inputProvider instanceof InputProviderInterface); + $metaModelId = $this->connection ->createQueryBuilder() ->select('d.pid') ->from('tl_metamodel_dca', 'd') ->leftJoin('d', 'tl_metamodel_dcasetting', 's', 'd.id=s.pid') ->where('s.id=:id') - ->setParameter('id', ModelId::fromSerialized($interface->getInputProvider()->getParameter('pid'))->getId()) + ->setParameter('id', ModelId::fromSerialized($inputProvider->getParameter('pid'))->getId()) ->executeQuery(); - if ($tableName = $this->factory->translateIdToMetaModelName($metaModelId = $metaModelId->fetchOne())) { - return $this->factory->getMetaModel($tableName); + if ( + false !== ($metaModelId = $metaModelId->fetchOne()) + && ($tableName = $this->factory->translateIdToMetaModelName($metaModelId)) + && null !== ($metaModel = $this->factory->getMetaModel($tableName)) + ) { + return $metaModel; } throw new \RuntimeException('Could not retrieve MetaModel ' . $metaModelId); @@ -113,13 +124,15 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) return false; } - $environment = $event->getEnvironment(); - if ('tl_metamodel_dcasetting_condition' !== $environment->getDataDefinition()->getName()) { + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + if ('tl_metamodel_dcasetting_condition' !== $dataDefinition->getName()) { return false; } if ($event instanceof AbstractModelAwareEvent) { - if ($event->getEnvironment()->getDataDefinition()->getName() !== $event->getModel()->getProviderName()) { + if ($dataDefinition->getName() !== $event->getModel()->getProviderName()) { return false; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AttributeIdListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AttributeIdListener.php index 1786a93ed..2a554b924 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AttributeIdListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/AttributeIdListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -27,6 +27,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; use Doctrine\DBAL\Connection; +use MetaModels\Attribute\IAttribute; use MetaModels\CoreBundle\DcGeneral\PropertyConditionFactory; use MetaModels\CoreBundle\Formatter\SelectAttributeOptionLabelFormatter; use MetaModels\IFactory; @@ -41,7 +42,7 @@ class AttributeIdListener extends AbstractConditionFactoryUsingListener * * @var SelectAttributeOptionLabelFormatter */ - private $attributeLabelFormatter; + private SelectAttributeOptionLabelFormatter $labelFormatter; /** * {@inheritDoc} @@ -51,10 +52,10 @@ public function __construct( IFactory $factory, Connection $connection, PropertyConditionFactory $conditionFactory, - SelectAttributeOptionLabelFormatter $attributeLabelFormatter + SelectAttributeOptionLabelFormatter $labelFormatter ) { parent::__construct($scopeDeterminator, $factory, $connection, $conditionFactory); - $this->attributeLabelFormatter = $attributeLabelFormatter; + $this->labelFormatter = $labelFormatter; } /** @@ -81,8 +82,8 @@ public function getAttributeOptions(GetPropertyOptionsEvent $event) } $colName = $attribute->getColName(); - $strSelectVal = $metaModel->getTableName() .'_' . $colName; - $result[$strSelectVal] = $this->attributeLabelFormatter->formatLabel($attribute); + $strSelectVal = $metaModel->getTableName() . '_' . $colName; + $result[$strSelectVal] = $this->labelFormatter->formatLabel($attribute); } $event->setOptions($result); @@ -104,19 +105,19 @@ public function decodeAttributeValue(DecodePropertyValueForWidgetEvent $event) $metaModel = $this->getMetaModel($event->getEnvironment()); $value = $event->getValue(); - if (!($metaModel && $value)) { + if (!$value) { $event->setValue(null); return; } $attribute = $metaModel->getAttributeById((int) $value); if ($attribute) { - $event->setValue($metaModel->getTableName() .'_' . $attribute->getColName()); + $event->setValue($metaModel->getTableName() . '_' . $attribute->getColName()); } } /** - * Translates an generated alias to the corresponding attribute id. + * Translates a generated alias to the corresponding attribute id. * * @param EncodePropertyValueFromWidgetEvent $event The event. * @@ -131,18 +132,17 @@ public function encodeAttributeValue(EncodePropertyValueFromWidgetEvent $event) $metaModel = $this->getMetaModel($event->getEnvironment()); $value = $event->getValue(); - if (!($metaModel && $value)) { + if (!$value) { return; } // Cut off the 'mm_xyz_' prefix. - $value = substr($value, \strlen($metaModel->getTableName() . '_')); + $value = \substr($value, \strlen($metaModel->getTableName() . '_')); $attribute = $metaModel->getAttribute($value); + assert($attribute instanceof IAttribute); - if ($attribute) { - $event->setValue($attribute->get('id')); - } + $event->setValue($attribute->get('id')); } /** @@ -153,10 +153,10 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) if (!parent::wantToHandle($event)) { return false; } - if (method_exists($event, 'getPropertyName') && ('attr_id' !== $event->getPropertyName())) { + if (\method_exists($event, 'getPropertyName') && ('attr_id' !== $event->getPropertyName())) { return false; } - if (method_exists($event, 'getProperty') && ('attr_id' !== $event->getProperty())) { + if (\method_exists($event, 'getProperty') && ('attr_id' !== $event->getProperty())) { return false; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php index 5122c9711..913f3840e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,6 +24,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\ModelToLabelEvent; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; +use ContaoCommunityAlliance\DcGeneral\InputProviderInterface; use Doctrine\DBAL\Connection; use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\IFactory; @@ -39,14 +40,14 @@ class ModelToLabelListener extends AbstractListener * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * The icon builder. * * @var IconBuilder */ - private $iconBuilder; + private IconBuilder $iconBuilder; /** * Create a new instance. @@ -91,7 +92,7 @@ public function handle(ModelToLabelEvent $event) $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); $type = $model->getProperty('type'); $parameterValue = (\is_array($model->getProperty('value')) - ? implode(', ', $model->getProperty('value')) + ? \implode(', ', $model->getProperty('value')) : $model->getProperty('value')); $name = $this->translator->trans( @@ -100,6 +101,7 @@ public function handle(ModelToLabelEvent $event) 'contao_tl_metamodel_dcasetting_condition' ); + /** @psalm-suppress InvalidArgument */ $event ->setLabel($this->getLabelText($type)) ->setArgs([ @@ -120,9 +122,12 @@ public function handle(ModelToLabelEvent $event) */ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) { - return $event->getEnvironment()->getInputProvider()->hasParameter('mode') + $inputProvider = $event->getEnvironment()->getInputProvider(); + assert($inputProvider instanceof InputProviderInterface); + + return $inputProvider->hasParameter('mode') ? parent::wantToHandle($event) - && ('select' === $event->getEnvironment()->getInputProvider()->getParameter('act')) + && ('select' === $inputProvider->getParameter('act')) : parent::wantToHandle( $event ); @@ -142,6 +147,7 @@ private function getLabelText($type) [], 'contao_tl_metamodel_dcasetting_condition' ); + if ($label === 'tl_metamodel_dcasetting_condition.typedesc.' . $type) { $label = $this->translator->trans( 'tl_metamodel_dcasetting_condition.typedesc._default_', @@ -152,6 +158,7 @@ private function getLabelText($type) return $type; } } + return $label; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/PasteButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/PasteButtonListener.php index 3868c9229..6866bea99 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/PasteButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/PasteButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -14,13 +14,14 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSettingCondition; +use ContaoCommunityAlliance\DcGeneral\Clipboard\ClipboardInterface; use ContaoCommunityAlliance\DcGeneral\Clipboard\Filter; use ContaoCommunityAlliance\DcGeneral\Clipboard\ItemInterface; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPasteButtonEvent; @@ -28,7 +29,8 @@ use ContaoCommunityAlliance\DcGeneral\Controller\RelationshipManager; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; -use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\BasicDefinitionInterface; /** * This handles the type options for conditions. @@ -50,11 +52,15 @@ public function handle(GetPasteButtonEvent $event) $environment = $event->getEnvironment(); $model = $event->getModel(); - $clipboard = $environment->getClipboard(); + assert($model instanceof ModelInterface); + $clipboard = $environment->getClipboard(); + assert($clipboard instanceof ClipboardInterface); // Disable all buttons if there is a circular reference. - if ($clipboard->fetch( - Filter::create()->andActionIs(ItemInterface::CUT)->andModelIs(ModelId::fromModel($model)) - )) { + if ( + $clipboard->fetch( + Filter::create()->andActionIs(ItemInterface::CUT)->andModelIs(ModelId::fromModel($model)) + ) + ) { $event ->setPasteAfterDisabled(true) ->setPasteIntoDisabled(true); @@ -87,15 +93,19 @@ public function handle(GetPasteButtonEvent $event) */ private function testParent(ModelInterface $model, GetPasteButtonEvent $event): void { - $environment = $event->getEnvironment(); - $definition = $environment->getDataDefinition(); - $mode = $definition->getBasicDefinition()->getMode(); + $environment = $event->getEnvironment(); + $definition = $environment->getDataDefinition(); + assert($definition instanceof ContainerInterface); + + $mode = $definition->getBasicDefinition()->getMode() ?? BasicDefinitionInterface::MODE_FLAT; $relationships = new RelationshipManager($definition->getModelRelationshipDefinition(), $mode); $collector = new ModelCollector($environment); - if (!$relationships->isRoot($model) + if ( + !$relationships->isRoot($model) && ($parent = $collector->searchParentOf($model)) - && !$this->acceptsAnotherChild($parent, $collector)) { + && !$this->acceptsAnotherChild($parent, $collector) + ) { $event->setPasteAfterDisabled(true); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php index 2cf8461ef..3ddc2a5d5 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ValueListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author Stefan Heimes - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +26,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\EncodePropertyValueFromWidgetEvent; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\ManipulateWidgetEvent; +use ContaoCommunityAlliance\DcGeneral\Data\DataProviderInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\Properties\PropertyInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; @@ -34,9 +35,12 @@ use MetaModels\Attribute\IAttribute; use MetaModels\IMetaModel; use MetaModels\ITranslatedMetaModel; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * This handles the rendering of models to labels. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ValueListener extends AbstractListener { @@ -66,7 +70,7 @@ public function getValueOptions(GetPropertyOptionsEvent $event) if ($attribute) { $options = $this->getOptionsViaDcGeneral($metaModel, $event->getEnvironment(), $attribute); $mangled = []; - foreach ((array) $options as $key => $option) { + foreach ($options as $key => $option) { $mangled['value_' . $key] = $option; } @@ -93,10 +97,14 @@ public function decodeValue(DecodePropertyValueForWidgetEvent $event) if (null === $attributeId = $model->getProperty('attr_id')) { return; } - $attribute = $metaModel->getAttributeById((int) $attributeId); + + if (null === $attribute = $metaModel->getAttributeById((int) $attributeId)) { + return; + } + $currentLanguage = $this->extractCurrentLanguageContext($metaModel); - if (is_array($event->getValue())) { + if (\is_array($event->getValue())) { $values = []; foreach ($event->getValue() as $value) { @@ -128,10 +136,14 @@ public function encodeValue(EncodePropertyValueFromWidgetEvent $event) if (null === $attributeId = $model->getPropertyValue('attr_id')) { return; } - $attribute = $metaModel->getAttributeById((int) $attributeId); + + if (null === $attribute = $metaModel->getAttributeById((int) $attributeId)) { + return; + } + $currentLanguage = $this->extractCurrentLanguageContext($metaModel); - if (is_array($event->getValue())) { + if (\is_array($event->getValue())) { $values = []; foreach ($event->getValue() as $value) { @@ -164,7 +176,7 @@ public function setValueOptionsMultiple(ManipulateWidgetEvent $event) $metaModel = $this->getMetaModel($event->getEnvironment()); $attribute = $metaModel->getAttributeById((int) $event->getModel()->getProperty('attr_id')); - if (!($attribute && ($attribute->get('type') == 'tags'))) { + if (!($attribute && ($attribute->get('type') === 'tags'))) { return; } @@ -179,14 +191,16 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) if (!parent::wantToHandle($event)) { return false; } - if (method_exists($event, 'getPropertyName') && ('value' !== $event->getPropertyName())) { + if (\method_exists($event, 'getPropertyName') && ('value' !== $event->getPropertyName())) { return false; } - if (method_exists($event, 'getProperty')) { + + if (\method_exists($event, 'getProperty')) { $property = $event->getProperty(); if ($property instanceof PropertyInterface) { $property = $property->getName(); } + if ('value' !== $property) { return false; } @@ -210,12 +224,16 @@ private function getOptionsViaDcGeneral($metaModel, $environment, $attribute) ->setContainerName($metaModel->getTableName()); $dcGeneral = $factory->createDcGeneral(); - $subEnv = $dcGeneral->getEnvironment(); - $optEv = new GetPropertyOptionsEvent($subEnv, $subEnv->getDataProvider()->getEmptyModel()); + $subEnv = $dcGeneral->getEnvironment(); + $dataProvider = $subEnv->getDataProvider(); + assert($dataProvider instanceof DataProviderInterface); + $optEv = new GetPropertyOptionsEvent($subEnv, $dataProvider->getEmptyModel()); $optEv->setPropertyName($attribute->getColName()); - $subEnv->getEventDispatcher()->dispatch($optEv, GetPropertyOptionsEvent::NAME); + $dispatcher = $subEnv->getEventDispatcher(); + assert($dispatcher instanceof EventDispatcherInterface); + $dispatcher->dispatch($optEv, GetPropertyOptionsEvent::NAME); - return $optEv->getOptions(); + return $optEv->getOptions() ?? []; } /** @@ -231,13 +249,13 @@ private function getOptionsViaDcGeneral($metaModel, $environment, $attribute) private function aliasToId(string $alias, IAttribute $attribute, string $language): string { if ($attribute instanceof IAliasConverter) { - $idForAlias = $attribute->getIdForAlias(substr($alias, 6), $language); + $idForAlias = $attribute->getIdForAlias(\substr($alias, 6), $language); if ($idForAlias !== null) { return $idForAlias; } } - return substr($alias, 6); + return \substr($alias, 6); } /** @@ -252,8 +270,8 @@ private function aliasToId(string $alias, IAttribute $attribute, string $languag */ private function idToAlias(string $idValue, IAttribute $attribute, string $language): string { - if (substr($idValue, 0, 6) == 'value_') { - $idValue = substr($idValue, 6); + if (\str_starts_with($idValue, 'value_')) { + $idValue = \substr($idValue, 6); } if ($attribute instanceof IAliasConverter) { @@ -269,7 +287,7 @@ private function idToAlias(string $idValue, IAttribute $attribute, string $langu /** * Try to find the right language context. * - * @param \MetaModels\IMetaModel $metaModel The current metamodel for the context. + * @param IMetaModel $metaModel The current metamodel for the context. * * @return string * @@ -281,10 +299,16 @@ private function extractCurrentLanguageContext(IMetaModel $metaModel): string return $metaModel->getLanguage(); } // Legacy compatibility fallback for translated metamodels not implementing the interface. + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ if ($metaModel->isTranslated(false)) { + /** @psalm-suppress DeprecatedMethod */ return $metaModel->getActiveLanguage(); } + // Use the current backend language then. - return \str_replace('-', '_', $GLOBALS['TL_LANGUAGE']); + return \str_replace('-', '_', (string) $GLOBALS['TL_LANGUAGE']); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractAbstainingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractAbstainingListener.php index 86d63ae50..b3196517c 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractAbstainingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractAbstainingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSortGroup; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; use ContaoCommunityAlliance\DcGeneral\Event\AbstractModelAwareEvent; @@ -34,7 +36,7 @@ abstract class AbstractAbstainingListener * * @var RequestScopeDeterminator */ - private $scopeDeterminator; + private RequestScopeDeterminator $scopeDeterminator; /** * Create a new instance. @@ -59,13 +61,15 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) return false; } - $environment = $event->getEnvironment(); - if ('tl_metamodel_dca_sortgroup' !== $environment->getDataDefinition()->getName()) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ('tl_metamodel_dca_sortgroup' !== $dataDefinition->getName()) { return false; } if ($event instanceof AbstractModelAwareEvent) { - if ($event->getEnvironment()->getDataDefinition()->getName() !== $event->getModel()->getProviderName()) { + if ($dataDefinition->getName() !== $event->getModel()->getProviderName()) { return false; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractListener.php index 3fe8d5983..7665fec8c 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AbstractListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +25,7 @@ use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; use ContaoCommunityAlliance\DcGeneral\Exception\DcGeneralInvalidArgumentException; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use MetaModels\IFactory; use MetaModels\IMetaModel; @@ -69,16 +70,16 @@ public function __construct( * * @param ModelInterface $model The input screen model for which to retrieve the MetaModel. * - * @return IMetaModel + * @return IMetaModel|null * * @throws DcGeneralInvalidArgumentException When an invalid model has been passed or the model does not have an id. - * @throws \Doctrine\DBAL\Exception + * @throws Exception */ protected function getMetaModelFromModel(ModelInterface $model) { - if (!(($model->getProviderName() == 'tl_metamodel_dca_sortgroup') && $model->getProperty('pid'))) { + if (!(($model->getProviderName() === 'tl_metamodel_dca_sortgroup') && $model->getProperty('pid'))) { throw new DcGeneralInvalidArgumentException( - sprintf( + \sprintf( 'Model must originate from tl_metamodel_dca_sortgroup and be saved, this one originates from %s ' . 'and has pid %s', $model->getProviderName(), @@ -96,6 +97,10 @@ protected function getMetaModelFromModel(ModelInterface $model) ->executeQuery() ->fetchOne(); + if (false === $metaModelId) { + return null; + } + $tableName = $this->factory->translateIdToMetaModelName($metaModelId); return $this->factory->getMetaModel($tableName); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AttributeOptionsListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AttributeOptionsListener.php index bc534f9d8..443fa685c 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AttributeOptionsListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/AttributeOptionsListener.php @@ -29,6 +29,7 @@ use MetaModels\CoreBundle\Formatter\SelectAttributeOptionLabelFormatter; use MetaModels\CoreBundle\Sorter\AttributeSorter; use MetaModels\IFactory; +use MetaModels\IMetaModel; /** * This provides the attribute name options. @@ -40,7 +41,7 @@ class AttributeOptionsListener extends AbstractListener * * @var SelectAttributeOptionLabelFormatter */ - private SelectAttributeOptionLabelFormatter $attributeLabelFormatter; + private SelectAttributeOptionLabelFormatter $labelFormatter; /** * The attribute sorter. @@ -52,19 +53,19 @@ class AttributeOptionsListener extends AbstractListener /** * {@inheritDoc} * - * @param SelectAttributeOptionLabelFormatter $attributeLabelFormatter The attribute select option label formatter. - * @param AttributeSorter $attributeSorter The attribute sorter. + * @param SelectAttributeOptionLabelFormatter $labelFormatter The attribute select option label formatter. + * @param AttributeSorter $attributeSorter The attribute sorter. */ public function __construct( RequestScopeDeterminator $scopeDeterminator, IFactory $factory, Connection $connection, - SelectAttributeOptionLabelFormatter $attributeLabelFormatter, + SelectAttributeOptionLabelFormatter $labelFormatter, AttributeSorter $attributeSorter ) { parent::__construct($scopeDeterminator, $factory, $connection); - $this->attributeLabelFormatter = $attributeLabelFormatter; - $this->attributeSorter = $attributeSorter; + $this->labelFormatter = $labelFormatter; + $this->attributeSorter = $attributeSorter; } /** @@ -82,6 +83,7 @@ public function handle(GetPropertyOptionsEvent $event) $result = []; $metaModel = $this->getMetaModelFromModel($event->getModel()); + assert($metaModel instanceof IMetaModel); $attributes = $metaModel->getAttributes(); $attributes = $this->attributeSorter->sortByName($attributes); @@ -89,7 +91,7 @@ public function handle(GetPropertyOptionsEvent $event) if ($attribute instanceof IInternal) { continue; } - $result[$attribute->get('id')] = $this->attributeLabelFormatter->formatLabel($attribute); + $result[$attribute->get('id')] = $this->labelFormatter->formatLabel($attribute); } $event->setOptions($result); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/SortGroupCreateListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/SortGroupCreateListener.php index 12d12819b..745eddd41 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/SortGroupCreateListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/SortGroupCreateListener.php @@ -20,7 +20,9 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\DcaSortGroup; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\Event\PreEditModelEvent; +use ContaoCommunityAlliance\DcGeneral\InputProviderInterface; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Exception; @@ -58,12 +60,18 @@ public function __construct( */ public function handle(PreEditModelEvent $event): void { - if ('tl_metamodel_dca_sortgroup' !== $event->getEnvironment()->getDataDefinition()->getName()) { + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ('tl_metamodel_dca_sortgroup' !== $dataDefinition->getName()) { return; } - if ('paste' !== $event->getEnvironment()->getInputProvider()->getParameter('act') - || !($pid = $event->getEnvironment()->getInputProvider()->getParameter('pid'))) { + $inputProvider = $environment->getInputProvider(); + assert($inputProvider instanceof InputProviderInterface); + + if ('paste' !== $inputProvider->getParameter('act') || !($pid = $inputProvider->getParameter('pid'))) { return; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/VisibilityConditionBuildingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/VisibilityConditionBuildingListener.php index 694e3c44c..61a5a4ec2 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/VisibilityConditionBuildingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/VisibilityConditionBuildingListener.php @@ -97,10 +97,11 @@ public function handle(BuildDataDefinitionEvent $event) private function addCondition(PropertyInterface $property, ConditionInterface $condition) { $chain = $property->getVisibleCondition(); - if (!($chain + if ( + !($chain && ($chain instanceof PropertyConditionChain) && $chain->getConjunction() == PropertyConditionChain::AND_CONJUNCTION - ) + ) ) { if ($property->getVisibleCondition()) { $previous = array($property->getVisibleCondition()); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php index edd0b039b..fe7897979 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -31,11 +31,14 @@ use ContaoCommunityAlliance\Translator\TranslatorInterface; use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\Filter\Setting\IFilterSettingFactory; +use MetaModels\Filter\Setting\IFilterSettingTypeFactory; use MetaModels\IMetaModel; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Handles rendering of model from tl_metamodel_filtersetting. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ abstract class AbstractFilterSettingTypeRenderer { @@ -44,28 +47,28 @@ abstract class AbstractFilterSettingTypeRenderer * * @var IFilterSettingFactory */ - private $factory; + private IFilterSettingFactory $factory; /** * The event dispatcher. * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * The icon builder. * * @var IconBuilder */ - private $iconBuilder; + private IconBuilder $iconBuilder; /** * Request scope determinator. * * @var RequestScopeDeterminator */ - private $scopeMatcher; + private RequestScopeDeterminator $scopeMatcher; /** * Create a new instance. @@ -102,8 +105,9 @@ public function modelToLabel(ModelToLabelEvent $event) } $model = $event->getModel(); - if (($model->getProviderName() !== 'tl_metamodel_filtersetting') - || !in_array($event->getModel()->getProperty('type'), $this->getTypes()) + if ( + ($model->getProviderName() !== 'tl_metamodel_filtersetting') + || !\in_array($event->getModel()->getProperty('type'), $this->getTypes()) ) { return; } @@ -148,7 +152,7 @@ abstract protected function getTypes(); protected function getLabelComment(ModelInterface $model, TranslatorInterface $translator) { if ($model->getProperty('comment')) { - return sprintf( + return \sprintf( $translator->translate('typedesc._comment_', 'tl_metamodel_filtersetting'), StringUtil::specialchars($model->getProperty('comment')) ); @@ -166,6 +170,7 @@ protected function getLabelComment(ModelInterface $model, TranslatorInterface $t protected function getLabelImage(ModelInterface $model) { $typeFactory = $this->factory->getTypeFactory($model->getProperty('type')); + assert($typeFactory instanceof IFilterSettingTypeFactory); $image = $this->iconBuilder->getBackendIconImageTag( $this->updateImageWithDisabled($model, $typeFactory->getTypeIcon()), @@ -180,7 +185,7 @@ protected function getLabelImage(ModelInterface $model) ContaoEvents::BACKEND_ADD_TO_URL ); - return sprintf( + return \sprintf( '%s', $urlEvent->getUrl(), $image @@ -199,7 +204,7 @@ protected function getLabelText(TranslatorInterface $translator, ModelInterface { $type = $model->getProperty('type'); $label = $translator->translate('typenames.' . $type, 'tl_metamodel_filtersetting'); - if ($label == 'typenames.' . $type) { + if ($label === 'typenames.' . $type) { return $type; } return $label; @@ -216,10 +221,12 @@ protected function getLabelText(TranslatorInterface $translator, ModelInterface protected function getLabelPattern(EnvironmentInterface $environment, ModelInterface $model) { $translator = $environment->getTranslator(); - $type = $model->getProperty('type'); - $combined = 'typedesc.' . $type; + assert($translator instanceof TranslatorInterface); + + $type = $model->getProperty('type'); + $combined = 'typedesc.' . $type; - if (($resultPattern = $translator->translate($combined, 'tl_metamodel_filtersetting')) == $combined) { + if (($resultPattern = $translator->translate($combined, 'tl_metamodel_filtersetting')) === $combined) { $resultPattern = $translator->translate('typedesc._default_', 'tl_metamodel_filtersetting'); } @@ -239,8 +246,10 @@ protected function getLabelParametersWithAttributeAndUrlParam( ModelInterface $model ) { $translator = $environment->getTranslator(); - $metamodel = $this->getMetaModel($model); - $attribute = $metamodel->getAttributeById((int) $model->getProperty('attr_id')); + assert($translator instanceof TranslatorInterface); + + $metamodel = $this->getMetaModel($model); + $attribute = $metamodel->getAttributeById((int) $model->getProperty('attr_id')); if ($attribute) { $attributeColumnName = $attribute->getColName(); @@ -277,6 +286,7 @@ protected function getLabelParametersWithAttributeAndUrlParam( protected function getLabelParametersNormal(EnvironmentInterface $environment, ModelInterface $model) { $translator = $environment->getTranslator(); + assert($translator instanceof TranslatorInterface); return [ $this->getLabelImage($model), diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AttributeListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AttributeListener.php index 294758d2c..13712e9ea 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AttributeListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AttributeListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2023 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +24,8 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\DecodePropertyValueForWidgetEvent; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\EncodePropertyValueFromWidgetEvent; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use MetaModels\Attribute\IAttribute; use MetaModels\CoreBundle\Formatter\SelectAttributeOptionLabelFormatter; use MetaModels\Filter\Setting\IFilterSettingFactory; @@ -43,20 +46,20 @@ class AttributeListener * * @var SelectAttributeOptionLabelFormatter */ - private SelectAttributeOptionLabelFormatter $attributeLabelFormatter; + private SelectAttributeOptionLabelFormatter $labelFormatter; /** * Create a new instance. * - * @param IFilterSettingFactory $filterFactory The filter setting factory. - * @param SelectAttributeOptionLabelFormatter $attributeLabelFormatter The attribute select option label formatter. + * @param IFilterSettingFactory $filterFactory The filter setting factory. + * @param SelectAttributeOptionLabelFormatter $labelFormatter The attribute select option label formatter. */ public function __construct( IFilterSettingFactory $filterFactory, - SelectAttributeOptionLabelFormatter $attributeLabelFormatter + SelectAttributeOptionLabelFormatter $labelFormatter ) { - $this->filterFactory = $filterFactory; - $this->attributeLabelFormatter = $attributeLabelFormatter; + $this->filterFactory = $filterFactory; + $this->labelFormatter = $labelFormatter; } /** @@ -68,9 +71,14 @@ public function __construct( */ public function getOptions(GetPropertyOptionsEvent $event): void { - if (('tl_metamodel_filtersetting' !== $event->getEnvironment()->getDataDefinition()->getName()) + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_filtersetting' !== $dataDefinition->getName()) || ('attr_id' !== $event->getPropertyName()) - || null !== $event->getOptions()) { + || null !== $event->getOptions() + ) { return; } @@ -85,12 +93,12 @@ public function getOptions(GetPropertyOptionsEvent $event): void } foreach ($metaModel->getAttributes() as $attribute) { - if ($typeFilter && (!in_array($attribute->get('type'), $typeFilter))) { + if (null !== $typeFilter && (!\in_array((string) $attribute->get('type'), $typeFilter))) { continue; } - $strSelectVal = $metaModel->getTableName() .'_' . $attribute->getColName(); - $result[$strSelectVal] = $this->attributeLabelFormatter->formatLabel($attribute); + $strSelectVal = $metaModel->getTableName() . '_' . $attribute->getColName(); + $result[$strSelectVal] = $this->labelFormatter->formatLabel($attribute); } $event->setOptions($result); @@ -105,8 +113,13 @@ public function getOptions(GetPropertyOptionsEvent $event): void */ public function decodeValue(DecodePropertyValueForWidgetEvent $event): void { - if (('tl_metamodel_filtersetting' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('attr_id' !== $event->getProperty())) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_filtersetting' !== $dataDefinition->getName()) + || ('attr_id' !== $event->getProperty()) + ) { return; } @@ -114,13 +127,13 @@ public function decodeValue(DecodePropertyValueForWidgetEvent $event): void $metaModel = $this->filterFactory->createCollection($model->getProperty('fid'))->getMetaModel(); $value = $event->getValue(); - if (!($metaModel && $value)) { + if (!$value) { return; } $attribute = $metaModel->getAttributeById((int) $value); if ($attribute) { - $event->setValue($metaModel->getTableName() .'_' . $attribute->getColName()); + $event->setValue($metaModel->getTableName() . '_' . $attribute->getColName()); } } @@ -133,8 +146,13 @@ public function decodeValue(DecodePropertyValueForWidgetEvent $event): void */ public function encodeValue(EncodePropertyValueFromWidgetEvent $event): void { - if (('tl_metamodel_filtersetting' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('attr_id' !== $event->getProperty())) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_filtersetting' !== $dataDefinition->getName()) + || ('attr_id' !== $event->getProperty()) + ) { return; } @@ -142,16 +160,14 @@ public function encodeValue(EncodePropertyValueFromWidgetEvent $event): void $metaModel = $this->filterFactory->createCollection($model->getProperty('fid'))->getMetaModel(); $value = $event->getValue(); - if (!($metaModel && $value)) { + if (!$value) { return; } - $value = substr($value, strlen($metaModel->getTableName() . '_')); + $value = \substr($value, \strlen($metaModel->getTableName() . '_')); $attribute = $metaModel->getAttribute($value); - - if ($attribute) { - $event->setValue($attribute->get('id')); - } + assert($attribute instanceof IAttribute); + $event->setValue($attribute->get('id')); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/DefaultOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/DefaultOptionListener.php index f897c50ac..b3ee4690a 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/DefaultOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/DefaultOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,6 +22,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\FilterSetting; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use MetaModels\Attribute\IAttribute; use MetaModels\Filter\Setting\IFilterSettingFactory; @@ -35,7 +36,7 @@ class DefaultOptionListener * * @var IFilterSettingFactory */ - private $filterFactory; + private IFilterSettingFactory $filterFactory; /** * Create a new instance. @@ -56,8 +57,13 @@ public function __construct(IFilterSettingFactory $filterFactory) */ public function handle(GetPropertyOptionsEvent $event) { - if (('tl_metamodel_filtersetting' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('defaultid' !== $event->getPropertyName())) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_filtersetting' !== $dataDefinition->getName()) + || ('defaultid' !== $event->getPropertyName()) + ) { return; } @@ -65,22 +71,20 @@ public function handle(GetPropertyOptionsEvent $event) if (!($attributeId = $model->getProperty('attr_id'))) { return; } - if (null === $metaModel = $this->filterFactory->createCollection($model->getProperty('fid'))->getMetaModel()) { - return; - } + + $metaModel = $this->filterFactory->createCollection($model->getProperty('fid'))->getMetaModel(); if (null === $attribute = $metaModel->getAttributeById((int) $attributeId)) { return; } - $event->setOptions($this->getOptions($attribute, $model->getProperty('onlyused') ? true : false)); + $event->setOptions($this->getOptions($attribute, (bool) $model->getProperty('onlyused'))); } /** * Ensure that all options have a value. * * @param IAttribute $attribute The options to be cleaned. - * * @param bool $onlyUsed Determines if only "used" values shall be returned. * * @return array @@ -91,7 +95,7 @@ private function getOptions($attribute, $onlyUsed) $options = []; foreach ($attribute->getFilterOptions(null, $onlyUsed) as $key => $value) { // Remove html/php tags. - $value = trim(strip_tags($value)); + $value = \trim(\strip_tags($value)); if (!empty($value)) { $options[$key] = $value; diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/FilterSettingTypeRendererCore.php b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/FilterSettingTypeRendererCore.php index 68b2175ac..8ee714241 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/FilterSettingTypeRendererCore.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/FilterSettingTypeRendererCore.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -31,7 +32,7 @@ class FilterSettingTypeRendererCore extends AbstractFilterSettingTypeRenderer /** * Retrieve the types this renderer is valid for. * - * @return array + * @return list */ protected function getTypes() { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/PasteButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/PasteButtonListener.php index 7aee7fb1d..4aa148d2e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/PasteButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/PasteButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,17 +13,20 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\FilterSetting; +use ContaoCommunityAlliance\DcGeneral\Clipboard\ClipboardInterface; use ContaoCommunityAlliance\DcGeneral\Clipboard\Filter; use ContaoCommunityAlliance\DcGeneral\Clipboard\ItemInterface; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPasteButtonEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; use MetaModels\Filter\Setting\IFilterSettingFactory; /** @@ -36,7 +39,7 @@ class PasteButtonListener * * @var IFilterSettingFactory */ - private $filterFactory; + private IFilterSettingFactory $filterFactory; /** * Create a new instance. @@ -58,13 +61,14 @@ public function __construct(IFilterSettingFactory $filterFactory) public function handle(GetPasteButtonEvent $event) { $model = $event->getModel(); + assert($model instanceof ModelInterface); + if (('tl_metamodel_filtersetting' !== $model->getProviderName())) { return; } - $environment = $event->getEnvironment(); - $model = $event->getModel(); - $clipboard = $environment->getClipboard(); + $clipboard = $event->getEnvironment()->getClipboard(); + assert($clipboard instanceof ClipboardInterface); $filter = Filter::create()->andModelIs(ModelId::fromModel($model))->andActionIs(ItemInterface::CUT); // Disable all buttons if there is a circular reference. diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/TemplateOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/TemplateOptionListener.php index 33ffcd049..671ac1bb2 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/TemplateOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/TemplateOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\FilterSetting; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use MetaModels\BackendIntegration\TemplateList; /** @@ -33,7 +35,7 @@ class TemplateOptionListener * * @var TemplateList */ - private $templateList; + private TemplateList $templateList; /** * Create a new instance. @@ -54,8 +56,13 @@ public function __construct(TemplateList $templateList) */ public function handle(GetPropertyOptionsEvent $event) { - if (('tl_metamodel_filtersetting' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('template' !== $event->getPropertyName())) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_filtersetting' !== $dataDefinition->getName()) + || ('template' !== $event->getPropertyName()) + ) { return; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/TypeOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/TypeOptionListener.php index 8994173d5..2a95fd3ac 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/TypeOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/TypeOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,8 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\FilterSetting; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\Translator\TranslatorInterface; use MetaModels\Filter\Setting\IFilterSettingFactory; /** @@ -33,7 +36,7 @@ class TypeOptionListener * * @var IFilterSettingFactory */ - private $filterFactory; + private IFilterSettingFactory $filterFactory; /** * Create a new instance. @@ -54,13 +57,20 @@ public function __construct(IFilterSettingFactory $filterFactory) */ public function handle(GetPropertyOptionsEvent $event) { - if (('tl_metamodel_filtersetting' !== $event->getEnvironment()->getDataDefinition()->getName()) - || ('type' !== $event->getPropertyName())) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ('tl_metamodel_filtersetting' !== $dataDefinition->getName()) + || ('type' !== $event->getPropertyName()) + ) { return; } $translator = $event->getEnvironment()->getTranslator(); - $options = []; + assert($translator instanceof TranslatorInterface); + + $options = []; foreach ($this->filterFactory->getTypeNames() as $filter) { $options[$filter] = $translator->translate('typenames.' . $filter, 'tl_metamodel_filtersetting'); } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/AbstractAbstainingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/AbstractAbstainingListener.php index b2faa1ac2..984440359 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/AbstractAbstainingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/AbstractAbstainingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\MetaModel; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; use ContaoCommunityAlliance\DcGeneral\Event\AbstractModelAwareEvent; @@ -34,7 +36,7 @@ abstract class AbstractAbstainingListener * * @var RequestScopeDeterminator */ - private $scopeDeterminator; + private RequestScopeDeterminator $scopeDeterminator; /** * Create a new instance. @@ -59,13 +61,16 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) return false; } - $environment = $event->getEnvironment(); - if ('tl_metamodel' !== $environment->getDataDefinition()->getName()) { + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ('tl_metamodel' !== $dataDefinition->getName()) { return false; } if ($event instanceof AbstractModelAwareEvent) { - if ($event->getEnvironment()->getDataDefinition()->getName() !== $event->getModel()->getProviderName()) { + if ($dataDefinition->getName() !== $event->getModel()->getProviderName()) { return false; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/DcaCombineButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/DcaCombineButtonListener.php index 319a20dc7..cdf02fee8 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/DcaCombineButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/DcaCombineButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 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,8 @@ * @author Christian Schiffler * @author David Molineus * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +24,8 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetOperationButtonEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\View\CommandInterface; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; /** @@ -44,12 +47,17 @@ public function handle(GetOperationButtonEvent $event) } $command = $event->getCommand(); - if ($command->getName() == 'dca_combine') { + assert($command instanceof CommandInterface); + + $model = $event->getModel(); + assert($model instanceof ModelInterface); + + if ($command->getName() === 'dca_combine') { $event->setHref( - UrlBuilder::fromUrl($event->getHref()) + UrlBuilder::fromUrl($event->getHref() ?? '') ->setQueryParameter( 'id', - ModelId::fromValues('tl_metamodel_dca_combine', $event->getModel()->getId())->getSerialized() + ModelId::fromValues('tl_metamodel_dca_combine', $model->getId())->getSerialized() ) ->getUrl() ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/LanguageOptionsListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/LanguageOptionsListener.php index 2a2a6d021..9a7060f75 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/LanguageOptionsListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/LanguageOptionsListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +23,7 @@ use Contao\System; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use MenAtWork\MultiColumnWizardBundle\Event\GetOptionsEvent; /** @@ -60,6 +61,7 @@ public function handle(GetOptionsEvent $event): void return; } + /** @psalm-suppress DeprecatedMethod */ $languages = System::getLanguages(); $hasTerritorySupport = (bool) $event->getModel()->getProperty('localeterritorysupport'); $languageOptions = []; @@ -97,12 +99,13 @@ protected function wantToHandle(GetOptionsEvent $event): bool return false; } - $environment = $event->getEnvironment(); - if ('tl_metamodel' !== $environment->getDataDefinition()->getName()) { + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + if ('tl_metamodel' !== $dataDefinition->getName()) { return false; } - if ($event->getEnvironment()->getDataDefinition()->getName() !== $event->getModel()->getProviderName()) { + if ($dataDefinition->getName() !== $event->getModel()->getProviderName()) { return false; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php index 0cc914598..91411b630 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php @@ -36,14 +36,14 @@ class ModelToLabelListener extends AbstractAbstainingListener * * @var Connection */ - private $connection; + private Connection $connection; /** * The translator. * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * Create a new instance. @@ -83,7 +83,7 @@ public function handle(ModelToLabelEvent $event): void $count = '?'; $transId = 'tl_metamodel.itemFormatCount.0'; - if ($model && !empty($tableName) && $this->connection->createSchemaManager()->tablesExist([$tableName])) { + if (!empty($tableName) && $this->connection->createSchemaManager()->tablesExist([$tableName])) { $count = $this->connection ->createQueryBuilder() ->select('COUNT(t.id) AS itemCount') @@ -107,6 +107,7 @@ public function handle(ModelToLabelEvent $event): void $label = \vsprintf($event->getLabel(), $event->getArgs()); $image = ((bool) $model->getProperty('translated')) ? 'locale.png' : 'locale_1.png'; + /** @psalm-suppress InvalidArgument */ $event ->setLabel(' diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php index 0edebbbdb..75c5d3c00 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +23,8 @@ use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\EncodePropertyValueFromWidgetEvent; +use ContaoCommunityAlliance\DcGeneral\Data\DataProviderInterface; +use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; use ContaoCommunityAlliance\Translator\TranslatorInterface; use MetaModels\Exceptions\Database\InvalidTableNameException; use MetaModels\Helper\TableManipulator; @@ -94,15 +96,21 @@ public function handle(EncodePropertyValueFromWidgetEvent $event): void $tableName = 'mm_' . $tableName; } + $translator = $event->getEnvironment()->getTranslator(); + assert($translator instanceof TranslatorInterface); + // New model, ensure the table does not exist. if (!$event->getModel()->getId()) { - $this->checkTableName($tableName, $event->getEnvironment()->getTranslator()); + $this->checkTableName($tableName, $translator); } else { $dataProvider = $event->getEnvironment()->getDataProvider('tl_metamodel'); + assert($dataProvider instanceof DataProviderInterface); + // Edited model, ensure the value is unique and then that the table does not exist. $oldVersion = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($event->getModel()->getId())); + assert($oldVersion instanceof ModelInterface); if ($oldVersion->getProperty('tableName') !== $event->getModel()->getProperty('tableName')) { - $this->checkTableName($tableName, $event->getEnvironment()->getTranslator()); + $this->checkTableName($tableName, $translator); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractAbstainingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractAbstainingListener.php index f5527adf2..6b7b2b5fc 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractAbstainingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractAbstainingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\RenderSetting; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; use ContaoCommunityAlliance\DcGeneral\Event\AbstractModelAwareEvent; @@ -34,7 +36,7 @@ abstract class AbstractAbstainingListener * * @var RequestScopeDeterminator */ - private $scopeDeterminator; + private RequestScopeDeterminator $scopeDeterminator; /** * Create a new instance. @@ -59,13 +61,16 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) return false; } - $environment = $event->getEnvironment(); - if ('tl_metamodel_rendersetting' !== $environment->getDataDefinition()->getName()) { + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ('tl_metamodel_rendersetting' !== $dataDefinition->getName()) { return false; } if ($event instanceof AbstractModelAwareEvent) { - if ($event->getEnvironment()->getDataDefinition()->getName() !== $event->getModel()->getProviderName()) { + if ($dataDefinition->getName() !== $event->getModel()->getProviderName()) { return false; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractListener.php index 1c99d883e..4bba34eab 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AbstractListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +25,7 @@ use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; use ContaoCommunityAlliance\DcGeneral\Exception\DcGeneralInvalidArgumentException; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use MetaModels\IFactory; use MetaModels\IMetaModel; @@ -69,16 +70,16 @@ public function __construct( * * @param ModelInterface $model The input screen model for which to retrieve the MetaModel. * - * @return IMetaModel + * @return IMetaModel|NULL * * @throws DcGeneralInvalidArgumentException When an invalid model has been passed or the model does not have an id. - * @throws \Doctrine\DBAL\Exception + * @throws Exception */ protected function getMetaModelFromModel(ModelInterface $model) { - if (!(($model->getProviderName() == 'tl_metamodel_rendersetting') && $model->getProperty('pid'))) { + if (!(($model->getProviderName() === 'tl_metamodel_rendersetting') && $model->getProperty('pid'))) { throw new DcGeneralInvalidArgumentException( - sprintf( + \sprintf( 'Model must originate from tl_metamodel_rendersetting and be saved, this one originates from ' . '%s and has pid %s', $model->getProviderName(), @@ -96,6 +97,10 @@ protected function getMetaModelFromModel(ModelInterface $model) ->executeQuery() ->fetchOne(); + if (false === $metaModelId) { + return null; + } + $tableName = $this->factory->translateIdToMetaModelName($metaModelId); return $this->factory->getMetaModel($tableName); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AddAllButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AddAllButtonListener.php index 4ae6c644d..0d17b4ecb 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AddAllButtonListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AddAllButtonListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +23,8 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetGlobalButtonEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelId; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\DcGeneral\InputProviderInterface; use Doctrine\DBAL\Connection; use MetaModels\IFactory; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; @@ -37,21 +39,21 @@ class AddAllButtonListener * * @var Connection */ - private $connection; + private Connection $connection; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The URL generator. * * @var UrlGeneratorInterface */ - private $urlGenerator; + private UrlGeneratorInterface $urlGenerator; /** * Create a new instance. @@ -78,13 +80,21 @@ public function __construct(Connection $connection, IFactory $factory, UrlGenera */ public function getGlobalButton(GetGlobalButtonEvent $event) { - $environment = $event->getEnvironment(); - if ('addall' !== $event->getKey() - || 'tl_metamodel_rendersetting' !== $environment->getDataDefinition()->getName()) { + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + 'addall' !== $event->getKey() + || 'tl_metamodel_rendersetting' !== $dataDefinition->getName() + ) { return; } - $renderSetting = ModelId::fromSerialized($environment->getInputProvider()->getParameter('pid'))->getId(); + $inputProvider = $environment->getInputProvider(); + assert($inputProvider instanceof InputProviderInterface); + + $renderSetting = ModelId::fromSerialized($inputProvider->getParameter('pid'))->getId(); $modelId = $this->connection->createQueryBuilder() ->select('r.pid') @@ -94,6 +104,10 @@ public function getGlobalButton(GetGlobalButtonEvent $event) ->executeQuery() ->fetchOne(); + if (false === $modelId) { + return; + } + $name = $this->factory->translateIdToMetaModelName($modelId); $event->setHref( diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AttributeOptionsListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AttributeOptionsListener.php index ab3dc3c5d..7361050a1 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AttributeOptionsListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/AttributeOptionsListener.php @@ -38,21 +38,21 @@ class AttributeOptionsListener extends AbstractListener * * @var SelectAttributeOptionLabelFormatter */ - private $attributeLabelFormatter; + private SelectAttributeOptionLabelFormatter $labelFormatter; /** * {@inheritDoc} * - * @param SelectAttributeOptionLabelFormatter $attributeLabelFormatter The attribute select option label formatter. + * @param SelectAttributeOptionLabelFormatter $labelFormatter The attribute select option label formatter. */ public function __construct( RequestScopeDeterminator $scopeDeterminator, IFactory $factory, Connection $connection, - SelectAttributeOptionLabelFormatter $attributeLabelFormatter + SelectAttributeOptionLabelFormatter $labelFormatter ) { parent::__construct($scopeDeterminator, $factory, $connection); - $this->attributeLabelFormatter = $attributeLabelFormatter; + $this->labelFormatter = $labelFormatter; } /** @@ -71,7 +71,7 @@ public function handle(GetPropertyOptionsEvent $event) $model = $event->getModel(); $metaModel = $this->getMetaModelFromModel($model); - if (!$metaModel) { + if (null === $metaModel) { return; } @@ -92,12 +92,13 @@ public function handle(GetPropertyOptionsEvent $event) $options = []; foreach ($metaModel->getAttributes() as $attribute) { - if ($attribute instanceof IInternal + if ( + $attribute instanceof IInternal || in_array($attribute->get('id'), $alreadyTaken) ) { continue; } - $options[$attribute->get('id')] = $this->attributeLabelFormatter->formatLabel($attribute); + $options[$attribute->get('id')] = $this->labelFormatter->formatLabel($attribute); } $event->setOptions($options); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php index ef44c4b82..11a5bc032 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php @@ -27,6 +27,7 @@ use MetaModels\Attribute\IAttributeFactory; use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\IFactory; +use MetaModels\IMetaModel; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -94,6 +95,7 @@ public function handle(ModelToLabelEvent $event) $model = $event->getModel(); $metaModel = $this->getMetaModelFromModel($model); + assert($metaModel instanceof IMetaModel); $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); if ($attribute) { @@ -115,6 +117,7 @@ public function handle(ModelToLabelEvent $event) $colName = $this->trans('error_unknown_column'); } + /** @psalm-suppress InvalidArgument */ $event ->setLabel('
    %s [%s%s]
    diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/PaletteRestrictionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/PaletteRestrictionListener.php index 8031aee09..67892d9ed 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/PaletteRestrictionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/PaletteRestrictionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 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,8 @@ * @author Christian Schiffler * @author Sven Baumann * @author David Molineus - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -40,7 +41,7 @@ class PaletteRestrictionListener extends AbstractPaletteRestrictionListener * * @var Connection */ - private $connection; + private Connection $connection; /** * PaletteRestrictionListener constructor. @@ -73,11 +74,12 @@ public function handle(BuildDataDefinitionEvent $event) foreach ($palettes->getPalettes() as $palette) { if ($palette->getName() !== 'default') { $paletteCondition = $palette->getCondition(); - if (!($paletteCondition instanceof ConditionChainInterface) + if ( + !($paletteCondition instanceof ConditionChainInterface) || ($paletteCondition->getConjunction() !== PaletteConditionChain::OR_CONJUNCTION) ) { $paletteCondition = new PaletteConditionChain( - $paletteCondition ? array($paletteCondition) : array(), + null !== $paletteCondition ? [$paletteCondition] : [], PaletteConditionChain::OR_CONJUNCTION ); $palette->setCondition($paletteCondition); @@ -107,7 +109,7 @@ private function buildMetaPaletteConditions($palette, $metaPalettes) continue; } - if (preg_match('#^(\w+) extends (\w+)$#', $typeName, $matches)) { + if (\preg_match('#^(\w+) extends (\w+)$#', $typeName, $matches)) { $typeName = $matches[1]; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/TemplateOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/TemplateOptionListener.php index 461544bf4..92d770919 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/TemplateOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/TemplateOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +26,7 @@ use Doctrine\DBAL\Connection; use MetaModels\BackendIntegration\TemplateList; use MetaModels\IFactory; +use MetaModels\IMetaModel; /** * This handles the providing of available templates. @@ -72,6 +73,7 @@ public function handle(GetPropertyOptionsEvent $event) $model = $event->getModel(); $metaModel = $this->getMetaModelFromModel($model); + assert($metaModel instanceof IMetaModel); $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); if (!$attribute) { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AbstractAbstainingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AbstractAbstainingListener.php index b670b021a..3784e39f1 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AbstractAbstainingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AbstractAbstainingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\RenderSettings; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; use ContaoCommunityAlliance\DcGeneral\Event\AbstractModelAwareEvent; @@ -34,7 +36,7 @@ abstract class AbstractAbstainingListener * * @var RequestScopeDeterminator */ - private $scopeDeterminator; + private RequestScopeDeterminator $scopeDeterminator; /** * Create a new instance. @@ -59,13 +61,16 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) return false; } - $environment = $event->getEnvironment(); - if ('tl_metamodel_rendersettings' !== $environment->getDataDefinition()->getName()) { + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ('tl_metamodel_rendersettings' !== $dataDefinition->getName()) { return false; } if ($event instanceof AbstractModelAwareEvent) { - if ($event->getEnvironment()->getDataDefinition()->getName() !== $event->getModel()->getProviderName()) { + if ($dataDefinition->getName() !== $event->getModel()->getProviderName()) { return false; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AddAssetListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AddAssetListener.php index 476b7d615..e7f9e8382 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AddAssetListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/AddAssetListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Richard Henkenjohann * @author Andreas Fischer * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,6 +24,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\RenderSettings; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use MenAtWork\MultiColumnWizardBundle\Event\GetOptionsEvent; use Symfony\Component\Filesystem\Path; use Symfony\Component\Finder\Finder; @@ -38,14 +39,14 @@ class AddAssetListener * * @var RequestScopeDeterminator */ - private $scopeDeterminator; + private RequestScopeDeterminator $scopeDeterminator; /** * The upload path to scan within. * * @var string */ - private $uploadPath; + private string $uploadPath; /** * Create a new instance. @@ -68,9 +69,11 @@ public function __construct(RequestScopeDeterminator $scopeDeterminator, $upload */ public function getStylesheets(GetOptionsEvent $event) { - if (!$this->wantToHandle($event) + if ( + !$this->wantToHandle($event) || ($event->getPropertyName() !== 'additionalCss') - || ($event->getSubPropertyName() !== 'file')) { + || ($event->getSubPropertyName() !== 'file') + ) { return; } @@ -86,9 +89,14 @@ public function getStylesheets(GetOptionsEvent $event) */ public function getJavascripts(GetOptionsEvent $event) { - if (($event->getEnvironment()->getDataDefinition()->getName() !== 'tl_metamodel_rendersettings') + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ( + ($dataDefinition->getName() !== 'tl_metamodel_rendersettings') || ($event->getPropertyName() !== 'additionalJs') - || ($event->getSubPropertyName() !== 'file')) { + || ($event->getSubPropertyName() !== 'file') + ) { return; } @@ -105,7 +113,8 @@ public function getJavascripts(GetOptionsEvent $event) private function scanFiles($extension) { $files = []; - foreach (Finder::create() + foreach ( + Finder::create() ->followLinks() ->in($this->uploadPath) ->name('*.' . $extension) @@ -130,12 +139,15 @@ private function wantToHandle(GetOptionsEvent $event) return false; } - $environment = $event->getEnvironment(); - if ('tl_metamodel_rendersettings' !== $environment->getDataDefinition()->getName()) { + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + if ('tl_metamodel_rendersettings' !== $dataDefinition->getName()) { return false; } - if ($event->getEnvironment()->getDataDefinition()->getName() !== $event->getModel()->getProviderName()) { + if ($dataDefinition->getName() !== $event->getModel()->getProviderName()) { return false; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php index 144fd5d1f..dfe0708c3 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php @@ -27,8 +27,10 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\DecodePropertyValueForWidgetEvent; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\EncodePropertyValueFromWidgetEvent; use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use Doctrine\DBAL\Connection; use MetaModels\IFactory; +use MetaModels\IMetaModel; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -41,21 +43,21 @@ class JumpToListener extends AbstractAbstainingListener * * @var IFactory */ - private $factory; + private IFactory $factory; /** * The connection. * * @var Connection */ - private $connection; + private Connection $connection; /** * The translator. * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * Create a new instance. @@ -90,23 +92,27 @@ public function decodeValue(DecodePropertyValueForWidgetEvent $event) return; } - $propInfo = $event->getEnvironment()->getDataDefinition()->getPropertiesDefinition()->getProperty('jumpTo'); + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + $propInfo = $dataDefinition->getPropertiesDefinition()->getProperty('jumpTo'); $value = StringUtil::deserialize($event->getValue(), true); $extra = $propInfo->getExtra(); $newValues = []; + /** @var array $languages */ $languages = $extra['columnFields']['langcode']['options'] ?? []; - foreach (array_keys($languages) as $key) { + foreach (\array_keys($languages) as $key) { $newValue = ''; $filter = 0; if ($value) { foreach ($value as $arr) { - if (!is_array($arr)) { + if (!\is_array($arr)) { break; } // Set the new value and exit the loop. - if (array_search($key, $arr) !== false) { + if (\in_array($key, $arr, true)) { $newValue = '{{link_url::' . $arr['value'] . '}}'; $filter = $arr['filter']; break; @@ -141,10 +147,10 @@ public function encodeValue(EncodePropertyValueFromWidgetEvent $event) $value = StringUtil::deserialize($event->getValue(), true); foreach ($value as $k => $v) { - $value[$k]['value'] = str_replace(['{{link_url::', '}}'], ['', ''], $v['value']); + $value[$k]['value'] = \str_replace(['{{link_url::', '}}'], ['', ''], $v['value']); } - $event->setValue(serialize($value)); + $event->setValue(\serialize($value)); } /** @@ -166,19 +172,22 @@ public function buildWidget(BuildWidgetEvent $event) $model = $event->getModel(); $metaModel = $this->factory->getMetaModel($this->factory->translateIdToMetaModelName($model->getProperty('pid'))); + assert($metaModel instanceof IMetaModel); $extra = $event->getProperty()->getExtra(); + /** @psalm-suppress DeprecatedMethod */ if ($metaModel->isTranslated()) { $arrLanguages = []; + /** @psalm-suppress DeprecatedMethod */ foreach ((array) $metaModel->getAvailableLanguages() as $strLangCode) { $arrLanguages[$strLangCode] = $this->translator - ->trans('LNG.'. $strLangCode, [], 'contao_languages'); + ->trans('LNG.' . $strLangCode, [], 'contao_languages'); } asort($arrLanguages); - $extra['minCount'] = count($arrLanguages); - $extra['maxCount'] = count($arrLanguages); + $extra['minCount'] = \count($arrLanguages); + $extra['maxCount'] = \count($arrLanguages); $extra['columnFields']['langcode']['options'] = $arrLanguages; } else { diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/LanguageCodeWizardListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/LanguageCodeWizardListener.php index c31a4e06d..04ca987f5 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/LanguageCodeWizardListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/LanguageCodeWizardListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author David Maack * @author Stefan Heimes * @author Sven Baumann - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -27,23 +27,30 @@ use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; use ContaoCommunityAlliance\Contao\Bindings\Events\Image\GenerateHtmlEvent; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; -use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminatorAwareTrait; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\ContaoBackendViewTemplate; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\ManipulateWidgetEvent; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\Translator\TranslatorInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** - * This handles the wizard button for the language code jump to field in the multicolumn wizard. + * This handles the wizard button for the language code jump to field in the multi-column wizard. */ class LanguageCodeWizardListener { - use RequestScopeDeterminatorAwareTrait; + /** + * The request mode determinator. + * + * @var RequestScopeDeterminator + */ + private RequestScopeDeterminator $scopeDeterminator; /** * The picker builder. * * @var PickerBuilderInterface */ - private $pickerBuilder; + private PickerBuilderInterface $pickerBuilder; /** * LanguageCodeWizardListener constructor. @@ -66,31 +73,39 @@ public function __construct(RequestScopeDeterminator $scopeDeterminator, PickerB */ public function pagePicker(ManipulateWidgetEvent $event) { - if (!$this->scopeDeterminator->currentScopeIsBackend() - || !('tl_metamodel_rendersettings' === $event->getEnvironment()->getDataDefinition()->getName()) - || !((0 === strpos($event->getProperty()->getName(), 'jumpTo')) - && ('[value]' === substr($event->getProperty()->getName(), -\strlen('[value]')))) + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + if ( + !$this->scopeDeterminator->currentScopeIsBackend() + || !('tl_metamodel_rendersettings' === $dataDefinition->getName()) + || !((\str_starts_with($event->getProperty()->getName(), 'jumpTo')) + && (\str_ends_with($event->getProperty()->getName(), '[value]'))) ) { return; } - $environment = $event->getEnvironment(); - $pickerUrl = $this->pickerBuilder->getUrl('cca_link'); + $translator = $environment->getTranslator(); + assert($translator instanceof TranslatorInterface); + $urlEvent = new GenerateHtmlEvent( 'pickpage.svg', - $environment->getTranslator()->translate('MSC.pagepicker'), + $translator->translate('MSC.pagepicker'), 'style="vertical-middle:top;cursor:pointer"' ); - $environment->getEventDispatcher()->dispatch($urlEvent, ContaoEvents::IMAGE_GET_HTML); + $dispatcher = $environment->getEventDispatcher(); + assert($dispatcher instanceof EventDispatcherInterface); + + $dispatcher->dispatch($urlEvent, ContaoEvents::IMAGE_GET_HTML); $template = new ContaoBackendViewTemplate('dc_general_wizard_link_url_picker'); $template ->set('name', $event->getWidget()->name) ->set('popupUrl', $pickerUrl) - ->set('html', ' ' . $urlEvent->getHtml()) + ->set('html', ' ' . (string) $urlEvent->getHtml()) ->set('label', $event->getProperty()->getLabel()[1]) ->set('id', $event->getWidget()->id); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/AbstractAbstainingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/AbstractAbstainingListener.php index 7e2b3e2e6..1911f70b2 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/AbstractAbstainingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/AbstractAbstainingListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +21,7 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\SearchablePages; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; use ContaoCommunityAlliance\DcGeneral\Event\AbstractModelAwareEvent; @@ -34,7 +35,7 @@ abstract class AbstractAbstainingListener * * @var RequestScopeDeterminator */ - private $scopeDeterminator; + private RequestScopeDeterminator $scopeDeterminator; /** * Create a new instance. @@ -59,13 +60,15 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) return false; } - $environment = $event->getEnvironment(); - if ('tl_metamodel_searchable_pages' !== $environment->getDataDefinition()->getName()) { + $environment = $event->getEnvironment(); + $dataDefinition = $environment->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + if ('tl_metamodel_searchable_pages' !== $dataDefinition->getName()) { return false; } if ($event instanceof AbstractModelAwareEvent) { - if ($event->getEnvironment()->getDataDefinition()->getName() !== $event->getModel()->getProviderName()) { + if ($dataDefinition->getName() !== $event->getModel()->getProviderName()) { return false; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/FilterOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/FilterOptionListener.php index ca4f8dd2a..3c20a9d78 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/FilterOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/FilterOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,7 +35,7 @@ class FilterOptionListener extends AbstractAbstainingListener * * @var Connection */ - private $connection; + private Connection $connection; /** * Create a new instance. diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/PaletteRestrictionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/PaletteRestrictionListener.php index 687c8473c..716d8551e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/PaletteRestrictionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/PaletteRestrictionListener.php @@ -50,10 +50,11 @@ public function handle(BuildDataDefinitionEvent $event) } $chain = $property->getVisibleCondition(); - if (!($chain + if ( + !($chain && ($chain instanceof PropertyConditionChain) && $chain->getConjunction() == PropertyConditionChain::AND_CONJUNCTION - ) + ) ) { $chain = new PropertyConditionChain( $chain ?: array(), diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/RenderSettingOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/RenderSettingOptionListener.php index 6f4e26b5a..c7b30aca4 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/RenderSettingOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/SearchablePages/RenderSettingOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,7 +35,7 @@ class RenderSettingOptionListener extends AbstractAbstainingListener * * @var Connection */ - private $connection; + private Connection $connection; /** * Create a new instance. @@ -68,9 +68,9 @@ public function handle(GetPropertyOptionsEvent $event) } $filters = $this->connection ->createQueryBuilder() - ->select('id', 'name') - ->from('tl_metamodel_rendersettings') - ->where('pid=:id') + ->select('t.id', 't.name') + ->from('tl_metamodel_rendersettings', 't') + ->where('t.pid=:id') ->setParameter('id', $model->getProperty('pid')) ->executeQuery() ->fetchAllAssociative(); diff --git a/src/CoreBundle/EventListener/DoctrineSchemaListener.php b/src/CoreBundle/EventListener/DoctrineSchemaListener.php index f6c04a720..a9ae20f7f 100644 --- a/src/CoreBundle/EventListener/DoctrineSchemaListener.php +++ b/src/CoreBundle/EventListener/DoctrineSchemaListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,8 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2022 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -21,6 +22,7 @@ use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Types\Type; use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs; use LogicException; use MetaModels\InformationProvider\MetaModelInformationCollector; @@ -50,12 +52,11 @@ public function postGenerateSchema(GenerateSchemaEventArgs $event): void $this->generator->generate($information = new SchemaInformation(), $this->collector->getCollection()); $contaoSchema = $event->getSchema(); - if ($schema = $information->get(DoctrineSchemaInformation::class)) { - if (!$schema instanceof DoctrineSchemaInformation) { - throw new LogicException('Invalid schema information obtained.'); - } - $this->mergeSchema($schema, $contaoSchema); + $schema = $information->get(DoctrineSchemaInformation::class); + if (!$schema instanceof DoctrineSchemaInformation) { + throw new LogicException('Invalid schema information obtained.'); } + $this->mergeSchema($schema, $contaoSchema); } private function mergeSchema(DoctrineSchemaInformation $source, Schema $target): void @@ -85,8 +86,9 @@ private function mergeTable(Table $sourceTable, Table $targetTable): void private function mergeColumns(Table $sourceTable, Table $targetTable): void { + $registry = Type::getTypeRegistry(); foreach ($sourceTable->getColumns() as $sourceColumn) { - $name = $sourceColumn->getName(); + $name = $sourceColumn->getName(); $options = [ 'default' => $sourceColumn->getDefault(), 'notnull' => $sourceColumn->getNotnull(), @@ -99,20 +101,15 @@ private function mergeColumns(Table $sourceTable, Table $targetTable): void 'columnDefinition' => $sourceColumn->getColumnDefinition(), 'comment' => $sourceColumn->getComment(), ]; - $platformOptions = $sourceColumn->getPlatformOptions(); - $customSchemaOptions = $sourceColumn->getCustomSchemaOptions(); + $platformOptions = $sourceColumn->getPlatformOptions(); if ($targetTable->hasColumn($name)) { - $tmpColumn = $targetTable->getColumn($name); - $platformOptions = array_merge($tmpColumn->getPlatformOptions(), $platformOptions); - $customSchemaOptions = array_merge($tmpColumn->getCustomSchemaOptions(), $customSchemaOptions); + $platformOptions = \array_merge($targetTable->getColumn($name)->getPlatformOptions(), $platformOptions); } $targetTable - ->addColumn($name, $sourceColumn->getType()->getName(), $options) - ->setPlatformOptions($platformOptions) - ->setCustomSchemaOptions($customSchemaOptions); - + ->addColumn($name, $registry->lookupName($sourceColumn->getType()), $options) + ->setPlatformOptions($platformOptions); } } @@ -128,9 +125,9 @@ private function mergeIndexes(Table $sourceTable, Table $targetTable): void if ($targetTable->hasIndex($name)) { $tmpIndex = $targetTable->getIndex($name); $targetTable->dropIndex($name); - $columns = array_merge($tmpIndex->getColumns(), $columns); - $flags = array_merge($tmpIndex->getFlags(), $flags); - $options = array_merge($tmpIndex->getOptions(), $options); + $columns = \array_merge($tmpIndex->getColumns(), $columns); + $flags = \array_merge($tmpIndex->getFlags(), $flags); + $options = \array_merge($tmpIndex->getOptions(), $options); $unique = $unique || $source->isUnique(); $primary = $primary || $source->isPrimary(); } @@ -149,16 +146,16 @@ private function mergeIndexes(Table $sourceTable, Table $targetTable): void private function mergeUniqueConstraints(Table $sourceTable, Table $targetTable): void { foreach ($sourceTable->getUniqueConstraints() as $uniqueConstraint) { - $name = $uniqueConstraint->getName(); + $name = $uniqueConstraint->getName(); $columns = $uniqueConstraint->getColumns(); - $flags = $uniqueConstraint->getFlags(); + $flags = $uniqueConstraint->getFlags(); $options = $uniqueConstraint->getOptions(); if ($targetTable->hasUniqueConstraint($name)) { $tmpUniqueConstraint = $targetTable->getUniqueConstraint($name); $targetTable->removeUniqueConstraint($name); - $columns = array_merge($tmpUniqueConstraint->getColumns(), $columns); - $flags = array_merge($tmpUniqueConstraint->getFlags(), $flags); - $options = array_merge($tmpUniqueConstraint->getOptions(), $options); + $columns = \array_merge($tmpUniqueConstraint->getColumns(), $columns); + $flags = \array_merge($tmpUniqueConstraint->getFlags(), $flags); + $options = \array_merge($tmpUniqueConstraint->getOptions(), $options); } $targetTable->addUniqueConstraint($columns, $name, $flags, $options); @@ -168,17 +165,17 @@ private function mergeUniqueConstraints(Table $sourceTable, Table $targetTable): private function mergeForeignKeyConstraints(Table $sourceTable, Table $targetTable): void { foreach ($sourceTable->getForeignKeys() as $foreignKey) { - $name = $foreignKey->getName(); - $foreignTable = $foreignKey->getForeignTableName(); - $localColumns = $foreignKey->getLocalColumns(); + $name = $foreignKey->getName(); + $foreignTable = $foreignKey->getForeignTableName(); + $localColumns = $foreignKey->getLocalColumns(); $foreignColumns = $foreignKey->getForeignColumns(); - $options = $foreignKey->getOptions(); + $options = $foreignKey->getOptions(); if ($targetTable->hasForeignKey($name)) { $tmpUniqueConstraint = $targetTable->getForeignKey($name); $targetTable->removeUniqueConstraint($name); - $localColumns = array_merge($tmpUniqueConstraint->getLocalColumns(), $localColumns); - $foreignColumns = array_merge($tmpUniqueConstraint->getForeignColumns(), $foreignColumns); - $options = array_merge($tmpUniqueConstraint->getOptions(), $options); + $localColumns = \array_merge($tmpUniqueConstraint->getLocalColumns(), $localColumns); + $foreignColumns = \array_merge($tmpUniqueConstraint->getForeignColumns(), $foreignColumns); + $options = \array_merge($tmpUniqueConstraint->getOptions(), $options); } $targetTable->addForeignKeyConstraint($foreignTable, $localColumns, $foreignColumns, $options, $name); } diff --git a/src/CoreBundle/EventListener/GetSearchablePagesListener.php b/src/CoreBundle/EventListener/GetSearchablePagesListener.php index 5eb018354..86cbe20cb 100644 --- a/src/CoreBundle/EventListener/GetSearchablePagesListener.php +++ b/src/CoreBundle/EventListener/GetSearchablePagesListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Ingolf Steinhardt * @author David Molineus * @author Richard Henkenjohann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -29,27 +29,30 @@ use ContaoCommunityAlliance\Contao\Bindings\Events\Controller\GetPageDetailsEvent; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; use Contao\CoreBundle\Event\SitemapEvent; +use Contao\Environment; use Contao\StringUtil; use DOMElement; use DOMException; use DOMNode; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Exception; -use Environment; use Generator; use MetaModels\Filter\IFilter; use MetaModels\Filter\Setting\IFilterSettingFactory; use MetaModels\IFactory; -use MetaModels\IItem; use MetaModels\IItems; use MetaModels\IMetaModel; +use MetaModels\Item; use MetaModels\ITranslatedMetaModel; use MetaModels\Render\Setting\ICollection as IRenderSettingCollection; use MetaModels\Render\Setting\IRenderSettingFactory; use RuntimeException; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use function array_merge; +use function array_values; use function in_array; +use function trim; /** * Class SearchablePages. @@ -64,6 +67,9 @@ * rendersetting: int, * published: string * } + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ class GetSearchablePagesListener { @@ -132,17 +138,20 @@ public function __construct( */ public function __invoke(SitemapEvent $event): void { - $rootPageIds = $event->getRootPageIds(); - $sitemap = $event->getDocument(); - $urlSet = $sitemap->childNodes[0]; + $rootPageIds = $event->getRootPageIds(); + $sitemap = $event->getDocument(); + $urlSet = $sitemap->childNodes[0]; + assert($urlSet instanceof DOMElement); // Run each entry in the published config array and search detail pages. foreach ($this->getPublishedConfigs() as $config) { - $metaModelId = $config['pid']; - $metaModel = $this->getMetaModel($metaModelId); + $metaModelId = (string) $config['pid']; + $metaModel = $this->getMetaModel($metaModelId); + assert($metaModel instanceof IMetaModel); $filterParams = StringUtil::deserialize($config['filterparams'], true); - $listFilter = $this->getListFilter($metaModel, (string)$config['filter'], $filterParams); - $renderSetting = $this->renderSettingFactory->createCollection($metaModel, $config['rendersetting']); + $listFilter = $this->getListFilter($metaModel, (string) $config['filter'], $filterParams); + $renderSetting = + $this->renderSettingFactory->createCollection($metaModel, (string) $config['rendersetting']); // Now loop over all detail pages... foreach ((array) $renderSetting->get('jumpTo') as $jumpTo) { @@ -195,6 +204,8 @@ public function __invoke(SitemapEvent $event): void * @param IFilter $listFilter The list filter. * * @return Generator + * + * @SuppressWarnings(PHPMD.Superglobals) */ private function generateUrlsFor( IMetaModel $metaModel, @@ -220,7 +231,7 @@ private function generateUrlsFor( 0, 0, 'ASC', - array_merge($renderSetting->getSettingNames(), $filterAttributes) + array_values(array_merge($renderSetting->getSettingNames(), $filterAttributes)) ); foreach ($this->buildUrlsForItems($items, $renderSetting, $pageDetails) as $url) { @@ -251,6 +262,7 @@ private function getPublishedConfigs(): Generator ->where('t.published=1') ->executeQuery(); + /** @var TSearchablePageConfig $config */ foreach ($statement->fetchAllAssociative() as $config) { yield $config; } @@ -288,24 +300,18 @@ private function getListFilter(IMetaModel $metaModel, string $filterId, array $p /** * Get a MetaModels by name or id. * - * @param string $identifier The Name or ID of a MetaModels. + * @param string $identifier The Name/ID of a MetaModels. * - * @return IMetaModel + * @return IMetaModel|null * * @throws RuntimeException When the MetaModels is missing. */ - private function getMetaModel(string $identifier): IMetaModel + private function getMetaModel(string $identifier): ?IMetaModel { // Translate id to name. $identifier = $this->factory->translateIdToMetaModelName($identifier); - $metaModel = $this->factory->getMetaModel($identifier); - - // If we have no mm throw a new exception. - if (null === $metaModel) { - throw new RuntimeException('Could not find the MetaModels with the name ' . $identifier); - } - return $metaModel; + return $this->factory->getMetaModel($identifier); } /** @@ -323,7 +329,7 @@ private function buildUrlsForItems( array $pageDetails ): Generator { foreach ($items as $item) { - assert($item instanceof IItem); + assert($item instanceof Item); $jumpTo = $item->buildJumpToLink($renderSetting); $url = UrlBuilder::fromUrl($jumpTo['url']); if (null === $url->getScheme()) { @@ -338,8 +344,8 @@ private function buildUrlsForItems( /** * Get the base URL. * - * @param string[] $pageDetails The page details. - * @param string|null $path Additional path settings. + * @param array $pageDetails The page details. + * @param string|null $path Additional path settings. * * @return UrlBuilder */ @@ -355,7 +361,7 @@ private function getBaseUrl(array $pageDetails, string $path = null): UrlBuilder // Add dummy parameter, because non legacy mode parameter must not be null. $event = new GenerateFrontendUrlEvent( $pageDetails, - ($pageDetails['requireItem'] ?? false) ? '/foo/bar' : null, + ((bool) ($pageDetails['requireItem'] ?? false)) ? '/foo/bar' : null, $pageDetails['language'], true ); @@ -385,9 +391,10 @@ public function removePlainDetailsUrl(array $pageDetails, DOMElement $urlSet): v } foreach ($childNode->childNodes as $childNode2) { - if (!$this->isDomElement($childNode2, 'loc') || trim($childNode2->nodeValue) !== $removeUrl) { + if (!$this->isDomElement($childNode2, 'loc') || trim((string) $childNode2->nodeValue) !== $removeUrl) { continue; } + assert($childNode->parentNode instanceof \DOMNode); $childNode->parentNode->removeChild($childNode); return; diff --git a/src/CoreBundle/EventListener/InsertTagsListener.php b/src/CoreBundle/EventListener/InsertTagsListener.php index 83854d918..5ecbacd5a 100644 --- a/src/CoreBundle/EventListener/InsertTagsListener.php +++ b/src/CoreBundle/EventListener/InsertTagsListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author David Molineus * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -28,6 +28,7 @@ use Contao\Input; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Exception; +use MetaModels\Attribute\IAttribute; use MetaModels\Filter\Rules\StaticIdList; use MetaModels\Filter\Setting\IFilterSettingFactory; use MetaModels\IFactory; @@ -58,6 +59,10 @@ * mm::jumpTo::[MM Table-Name|ID]::[Item ID]::[ID render setting](::[Parameter (Default:url)|label|page|params.attname]) * * @codingStandardsIgnoreEnd + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ final class InsertTagsListener { @@ -141,13 +146,19 @@ public function __invoke(string $insertTag): bool|int|string // Count for mod or ce elements. case 'total': return $this->checkMinExpectElements(4, $elements) - ? $this->getCount($elements[2], $elements[3], ($elements[4] ?? null)) + ? $this->getCount($elements[2], $elements[3], (isset($elements[4]) ? (int) $elements[4] : null)) : false; // Get value from an attribute. case 'attribute': return $this->checkMinExpectElements(6, $elements) - ? $this->getAttribute($elements[2], $elements[3], $elements[4], $elements[5], ($elements[6] ?? null)) + ? $this->getAttribute( + $elements[2], + $elements[3], + $elements[4], + $elements[5], + ($elements[6] ?? null) + ) : false; // Get item. @@ -176,35 +187,29 @@ public function __invoke(string $insertTag): bool|int|string /** * Get the jumpTo for a chosen value. * - * @param int|string $mixMetaModel ID or column name of MetaModels. - * @param int $mixDataId ID of the data row. - * @param int $viewId ID of render setting. + * @param string $mixMetaModel ID or column name of MetaModels. + * @param string $mixDataId ID of the data row. + * @param string $viewId ID of render setting. * @param string|null $strParam Name of parameter - (Default:url)|label|page|params.[attrname]. * * @return bool|string Return false when nothing was found for the requested value. */ private function jumpTo( - int|string $mixMetaModel, - int $mixDataId, - int $viewId, + string $mixMetaModel, + string $mixDataId, + string $viewId, ?string $strParam - ): bool|string - { + ): bool|string { // Set the param to url if empty. - if (empty($strParam)) { + if (null === $strParam || '' === $strParam) { $strParam = 'url'; } // Get the MetaModel. Return if we can not find one. $metaModel = $this->loadMetaModel($mixMetaModel); - if (null === $metaModel) { - return false; - } // Get the render setting. - if (null === $renderSetting = $this->renderSettingFactory->createCollection($metaModel, (int) $viewId)) { - return false; - } + $renderSetting = $this->renderSettingFactory->createCollection($metaModel, $viewId); // Get the data row. $item = $metaModel->findById($mixDataId); @@ -239,41 +244,38 @@ private function jumpTo( * Get an item. * * @param int|string $metaModelIdOrName ID or column name of MetaModels. - * @param int|string $mixDataId ID of the data row. - * @param int|string $viewId ID of render setting. + * @param string $mixDataId ID or list of IDs of the data row. + * @param string $viewId ID of render setting. * @param string|null $outputFormat Name of output format- (Default:text)|html5. * * @return bool|string Return false when nothing was found or return the value. */ private function getItem( int|string $metaModelIdOrName, - int|string $mixDataId, - int|string $viewId, + string $mixDataId, + string $viewId, ?string $outputFormat - ): bool|string - { + ): bool|string { // Get the MetaModel. Return if we can not find one. $metaModel = $this->loadMetaModel($metaModelIdOrName); - if (null === $metaModel) { - return false; - } // Set output format to default if not set. - if (empty($outputFormat)) { + if (null === $outputFormat || '' === $outputFormat) { $outputFormat = 'text'; } $objMetaModelList = new ItemList(); $objMetaModelList - ->setMetaModel((int) $metaModel->get('id'), (int) $viewId) + ->setMetaModel((string) $metaModel->get('id'), $viewId) ->overrideOutputFormat($outputFormat); // Handle a set of ids. + /** @var list $arrIds */ $arrIds = StringUtil::trimsplit(',', $mixDataId); // Render an empty insert tag rather than displaying a list with an empty // result information - do not return false here because the insert tag itself is correct. - if (count($arrIds) < 1) { + if (\count($arrIds) < 1) { return ''; } @@ -285,28 +287,24 @@ private function getItem( /** * Get from MM X the item with the id Y and parse the attribute Z and return it. * - * @param int|string $metaModelIdOrName ID or column name of MetaModel. - * @param int $intDataId ID of the data row. - * @param int|string $viewId ID of render setting. - * @param int|string $attributeIdentifier ID or column name of the attribute. + * @param string $metaModelIdOrName ID or column name of MetaModel. + * @param string $intDataId ID of the data row. + * @param string $viewId ID of render setting. + * @param string $attributeIdentifier ID or column name of the attribute. * @param string|null $outputFormat Type of output format - (Default:text)|html5|raw. * * @return bool|string Return false when nothing was found or return the value. * */ private function getAttribute( - int|string $metaModelIdOrName, - int $intDataId, - int|string $viewId, - int|string $attributeIdentifier, + string $metaModelIdOrName, + string $intDataId, + string $viewId, + string $attributeIdentifier, ?string $outputFormat - ): bool|string - { + ): bool|string { // Get the MM. $metaModel = $this->loadMetaModel($metaModelIdOrName); - if (null === $metaModel) { - return false; - } // Get item. $item = $metaModel->findById($intDataId); @@ -315,19 +313,19 @@ private function getAttribute( } if (\is_numeric($attributeIdentifier)) { - $attributeIdentifier = $metaModel->getAttributeById((int) $attributeIdentifier)->getColName(); + $attribute = $metaModel->getAttributeById((int) $attributeIdentifier); + assert($attribute instanceof IAttribute); + $attributeIdentifier = $attribute->getColName(); } $originalOutputFormat = $outputFormat; // Set output format to default if not set or raw. - if (empty($outputFormat) || 'raw' === $outputFormat) { + if (null === $outputFormat || '' === $outputFormat || 'raw' === $outputFormat) { $outputFormat = 'text'; } // Get render setting. - if (null === ($renderSetting = $this->renderSettingFactory->createCollection($metaModel, (int) $viewId))) { - $outputFormat = 'text'; - } + $renderSetting = $this->renderSettingFactory->createCollection($metaModel, $viewId); // Parse attribute. $arrAttr = $item->parseAttribute($attributeIdentifier, $outputFormat, $renderSetting); @@ -350,26 +348,26 @@ private function getAttribute( * @return int Return the count value. * @throws Exception */ - private function getCount(string $type, int|string $identifier, int $filterId = null): int + private function getCount(string $type, int|string $identifier, ?int $filterId = null): int { switch ($type) { // From module, can be a MetaModel list or filter. case 'mod': - if (($result = $this->getMetaModelDataFrom('tl_module', $identifier))) { + if (false !== ($result = $this->getMetaModelDataFrom('tl_module', (int) $identifier))) { return $this->getCountFor($result['metamodel'], $result['metamodel_filtering']); } break; // From content element, can be a MetaModel list or filter. case 'ce': - if (($result = $this->getMetaModelDataFrom('tl_content', $identifier))) { + if (false !== ($result = $this->getMetaModelDataFrom('tl_content', (int) $identifier))) { return $this->getCountFor($result['metamodel'], $result['metamodel_filtering']); } break; // From MetaModel with filter. case 'mm': - return $this->getCountFor($identifier, $filterId); + return $this->getCountFor((string) $identifier, $filterId); break; // Unknown element type. @@ -385,24 +383,24 @@ private function getCount(string $type, int|string $identifier, int $filterId = * * @param int|string $nameOrId Name or id of the MetaModel. * - * @return IMetaModel|null + * @return IMetaModel */ - private function loadMetaModel(int|string $nameOrId): ?IMetaModel + private function loadMetaModel(int|string $nameOrId): IMetaModel { + // Name. + $tableName = $nameOrId; if (\is_numeric($nameOrId)) { // ID. - $tableName = $this->factory->translateIdToMetaModelName($nameOrId); - } elseif (\is_string($nameOrId)) { - // Name. - $tableName = $nameOrId; + $tableName = $this->factory->translateIdToMetaModelName((string) $nameOrId); } - if (isset($tableName)) { - return $this->factory->getMetaModel($tableName); + $metaModel = $this->factory->getMetaModel((string) $tableName); + + if (null === $metaModel) { + throw new \RuntimeException('MetaModel not found: ' . $nameOrId); } - // Unknown. - return null; + return $metaModel; } /** @@ -413,7 +411,6 @@ private function loadMetaModel(int|string $nameOrId): ?IMetaModel * * @return false|array Returns null when nothing was found or a \Database\Result with the chosen information. * - * @throws \Doctrine\DBAL\DBALException When an database error occur. * @throws Exception */ private function getMetaModelDataFrom(string $strTable, int $intID): bool|array @@ -426,7 +423,7 @@ private function getMetaModelDataFrom(string $strTable, int $intID): bool|array // Get all information form table or return null if we have no data. $statement = $this->connection ->createQueryBuilder() - ->select('t.metamodel, t.metamodel_filtering') + ->select('t.metamodel', 't.metamodel_filtering') ->from($strTable, 't') ->where('t.id=:id') ->setParameter('id', $intID) @@ -448,16 +445,13 @@ private function getMetaModelDataFrom(string $strTable, int $intID): bool|array * * @return int The count result. */ - private function getCountFor(string $metaModelNameOrId, int $intFilterId = null): int + private function getCountFor(string $metaModelNameOrId, ?int $intFilterId = null): int { $metaModel = $this->loadMetaModel($metaModelNameOrId); - if (null === $metaModel) { - return 0; - } $objFilter = $metaModel->getEmptyFilter(); - if ($intFilterId) { - $collection = $this->filterSettingFactory->createCollection($intFilterId); + if (null !== $intFilterId) { + $collection = $this->filterSettingFactory->createCollection((string) $intFilterId); $values = []; foreach ($collection->getParameters() as $key) { @@ -489,8 +483,6 @@ private function checkMinExpectElements(int $expectCount, array $elements): bool * * @return bool True => Published | False => Not published * - * @throws \Doctrine\DBAL\DBALException When a database error occur. - * * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @deprecated * diff --git a/src/CoreBundle/EventListener/PurgeListener.php b/src/CoreBundle/EventListener/PurgeListener.php index e30776177..b32ce81cb 100644 --- a/src/CoreBundle/EventListener/PurgeListener.php +++ b/src/CoreBundle/EventListener/PurgeListener.php @@ -59,7 +59,8 @@ public function __construct(PurgeCache $purger) public function checkPurge(AbstractModelAwareEvent $event) { $table = $event->getModel()->getProviderName(); - if (($table == 'tl_metamodel') || + if ( + ($table == 'tl_metamodel') || ($table == 'tl_metamodel_dca') || ($table == 'tl_metamodel_dca_sortgroup') || ($table == 'tl_metamodel_dcasetting') || diff --git a/src/CoreBundle/EventListener/SubSystemBootListener.php b/src/CoreBundle/EventListener/SubSystemBootListener.php index c2c476afa..5b8487dd2 100644 --- a/src/CoreBundle/EventListener/SubSystemBootListener.php +++ b/src/CoreBundle/EventListener/SubSystemBootListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author David Molineus * @author Sven Baumann * @author Richard Henkenjohann - * @copyright 2012-2021 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -36,41 +37,40 @@ */ class SubSystemBootListener { - /** * The Contao framework. * * @var ContaoFramework */ - private $contaoFramework; + private ContaoFramework $contaoFramework; /** * The database connection. * * @var Connection */ - private $connection; + private Connection $connection; /** * The logger. * * @var LoggerInterface */ - private $logger; + private LoggerInterface $logger; /** * The scope matcher. * * @var RequestScopeDeterminator */ - private $scopeMatcher; + private RequestScopeDeterminator $scopeMatcher; /** * The event dispatcher. * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * SubSystemBoot constructor. @@ -102,7 +102,7 @@ public function __construct( */ public function boot(): void { - /** @var Environment $environment */ + /** @psalm-suppress InternalMethod - the ContaoFramework class is internal, not the method usage. */ $environment = $this->contaoFramework->getAdapter(Environment::class); $script = explode('?', $environment->get('relativeRequest'), 2)[0]; @@ -112,21 +112,23 @@ public function boot(): void } try { - if (!$this->connection->getSchemaManager()->tablesExist( - [ - 'tl_metamodel', - 'tl_metamodel_dca', - 'tl_metamodel_dca_sortgroup', - 'tl_metamodel_dcasetting', - 'tl_metamodel_dcasetting_condition', - 'tl_metamodel_attribute', - 'tl_metamodel_filter', - 'tl_metamodel_filtersetting', - 'tl_metamodel_rendersettings', - 'tl_metamodel_rendersetting', - 'tl_metamodel_dca_combine', - ] - )) { + if ( + !$this->connection->createSchemaManager()->tablesExist( + [ + 'tl_metamodel', + 'tl_metamodel_dca', + 'tl_metamodel_dca_sortgroup', + 'tl_metamodel_dcasetting', + 'tl_metamodel_dcasetting_condition', + 'tl_metamodel_attribute', + 'tl_metamodel_filter', + 'tl_metamodel_filtersetting', + 'tl_metamodel_rendersettings', + 'tl_metamodel_rendersetting', + 'tl_metamodel_dca_combine', + ] + ) + ) { $this->logger->error('MetaModels startup interrupted. Not all MetaModels tables have been created.'); return; } diff --git a/src/CoreBundle/EventListener/UserListener.php b/src/CoreBundle/EventListener/UserListener.php index 041427ed7..61970ad3a 100644 --- a/src/CoreBundle/EventListener/UserListener.php +++ b/src/CoreBundle/EventListener/UserListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -38,47 +38,47 @@ class UserListener * * @var TokenStorageInterface */ - private $tokenStorage; + private TokenStorageInterface $tokenStorage; /** * The authentication resolver. * * @var AuthenticationTrustResolverInterface */ - private $authenticationTrustResolver; + private AuthenticationTrustResolverInterface $trustResolver; /** * The scope matcher. * * @var ScopeMatcher */ - private $scopeMatcher; + private ScopeMatcher $scopeMatcher; /** * The view combination. * * @var ViewCombination */ - private $viewCombination; + private ViewCombination $viewCombination; /** * Constructor. * - * @param TokenStorageInterface $tokenStorage The token storage. - * @param AuthenticationTrustResolverInterface $authenticationTrustResolver The authentication resolver. - * @param ScopeMatcher $scopeMatcher The scope matche. - * @param ViewCombination $viewCombination The view combination. + * @param TokenStorageInterface $tokenStorage The token storage. + * @param AuthenticationTrustResolverInterface $trustResolver The authentication resolver. + * @param ScopeMatcher $scopeMatcher The scope matche. + * @param ViewCombination $viewCombination The view combination. */ public function __construct( TokenStorageInterface $tokenStorage, - AuthenticationTrustResolverInterface $authenticationTrustResolver, + AuthenticationTrustResolverInterface $trustResolver, ScopeMatcher $scopeMatcher, ViewCombination $viewCombination ) { - $this->tokenStorage = $tokenStorage; - $this->authenticationTrustResolver = $authenticationTrustResolver; - $this->scopeMatcher = $scopeMatcher; - $this->viewCombination = $viewCombination; + $this->tokenStorage = $tokenStorage; + $this->trustResolver = $trustResolver; + $this->scopeMatcher = $scopeMatcher; + $this->viewCombination = $viewCombination; } /** @@ -93,13 +93,13 @@ public function __construct( */ public function onKernelRequest(RequestEvent $event) { - if (!$this->scopeMatcher->isBackendMasterRequest($event)) { + if (!$this->scopeMatcher->isBackendMainRequest($event)) { return; } $token = $this->tokenStorage->getToken(); - if (null === $token || $this->authenticationTrustResolver->isAnonymous($token)) { + if (null === $token || !$this->trustResolver->isAuthenticated($token)) { return; } @@ -128,7 +128,7 @@ private function buildBackendModules(&$localMenu) $localMenu[$section]['metamodel_' . $metaModelName] = ['tables' => []]; } $localMenu[$section]['metamodel_' . $metaModelName]['callback'] = Module::class; - array_unshift($localMenu[$section]['metamodel_' . $metaModelName]['tables'], $metaModelName); + \array_unshift($localMenu[$section]['metamodel_' . $metaModelName]['tables'], $metaModelName); $GLOBALS['TL_LANG']['MOD']['metamodel_' . $metaModelName] = [ ($screen['label'][$GLOBALS['TL_LANGUAGE']] ?? ($screen['label'][''] ?? '')) ]; @@ -145,12 +145,12 @@ private function buildBackendModules(&$localMenu) private function injectChildTables(&$localMenu) { $parented = $this->viewCombination->getParented(); - $lastCount = count($parented); + $lastCount = \count($parented); while ($parented) { foreach ($parented as $metaModelName => $child) { foreach ($localMenu as $groupName => $modules) { foreach ($modules as $moduleName => $module) { - if (isset($module['tables']) && in_array($child['meta']['ptable'], $module['tables'])) { + if (isset($module['tables']) && \in_array($child['meta']['ptable'], $module['tables'])) { $localMenu[$groupName][$moduleName]['tables'][] = $metaModelName; unset($parented[$metaModelName]); break; @@ -159,10 +159,10 @@ private function injectChildTables(&$localMenu) } } // If the dependencies can not be resolved any further, we give up here to prevent an endless loop. - if (count($parented) == $lastCount) { + if (\count($parented) === $lastCount) { break; } - $lastCount = count($parented); + $lastCount = \count($parented); } } } diff --git a/src/CoreBundle/LegacyCompat/ServiceContainerInitializer.php b/src/CoreBundle/LegacyCompat/ServiceContainerInitializer.php index 52d5dc4ae..b464aa833 100644 --- a/src/CoreBundle/LegacyCompat/ServiceContainerInitializer.php +++ b/src/CoreBundle/LegacyCompat/ServiceContainerInitializer.php @@ -35,7 +35,7 @@ class ServiceContainerInitializer * * @var ContainerInterface */ - private $container; + private ContainerInterface $container; /** * Create a new instance. @@ -53,6 +53,8 @@ public function __construct(ContainerInterface $container) * @param MetaModelsServiceContainer $serviceContainer The container to configure. * * @return MetaModelsServiceContainer + * + * @psalm-suppress DeprecatedClass */ public function configure(MetaModelsServiceContainer $serviceContainer) { diff --git a/src/CoreBundle/MetaModelsCoreBundle.php b/src/CoreBundle/MetaModelsCoreBundle.php index 355b99c8f..6a1bb7069 100644 --- a/src/CoreBundle/MetaModelsCoreBundle.php +++ b/src/CoreBundle/MetaModelsCoreBundle.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,7 +36,7 @@ class MetaModelsCoreBundle extends Bundle /** * {@inheritDoc} */ - public function build(ContainerBuilder $container) + public function build(ContainerBuilder $container): void { parent::build($container); diff --git a/src/CoreBundle/Migration/FindClearAllTemplateMigration.php b/src/CoreBundle/Migration/FindClearAllTemplateMigration.php index 7cc96b153..066ae4cbf 100644 --- a/src/CoreBundle/Migration/FindClearAllTemplateMigration.php +++ b/src/CoreBundle/Migration/FindClearAllTemplateMigration.php @@ -18,7 +18,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\CoreBundle\Migration; diff --git a/src/CoreBundle/Migration/FindXhtmlTemplateMigration.php b/src/CoreBundle/Migration/FindXhtmlTemplateMigration.php index 2141de61b..e8824bf44 100644 --- a/src/CoreBundle/Migration/FindXhtmlTemplateMigration.php +++ b/src/CoreBundle/Migration/FindXhtmlTemplateMigration.php @@ -18,7 +18,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\CoreBundle\Migration; diff --git a/src/CoreBundle/Migration/SetDefaultZeroMigration.php b/src/CoreBundle/Migration/SetDefaultZeroMigration.php index 0b9c5aa55..f7b159790 100644 --- a/src/CoreBundle/Migration/SetDefaultZeroMigration.php +++ b/src/CoreBundle/Migration/SetDefaultZeroMigration.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,7 @@ * @package MetaModels/core * @author Ingolf Steinhardt * @author Christian Schiffler - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +25,7 @@ use Contao\CoreBundle\Migration\AbstractMigration; use Contao\CoreBundle\Migration\MigrationResult; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use Doctrine\DBAL\Schema\Table; /** @@ -94,6 +95,7 @@ public function getName(): string * - default zero values for system columns values not set. * * @return bool + * @throws Exception */ public function shouldRun(): bool { @@ -109,6 +111,7 @@ public function shouldRun(): bool * Collect the columns to be updated and update them. * * @return MigrationResult + * @throws Exception */ public function run(): MigrationResult { @@ -121,13 +124,14 @@ public function run(): MigrationResult } } - return new MigrationResult(true, 'Adjusted column(s): ' . implode(', ', $message)); + return new MigrationResult(true, 'Adjusted column(s): ' . \implode(', ', $message)); } /** * Fetch all columns that are not nullable yet. * * @return array> + * @throws Exception */ private function fetchNonDefaultZeroColumns(): array { @@ -135,14 +139,14 @@ private function fetchNonDefaultZeroColumns(): array if (empty($tables)) { return []; } - $schemaManager = $this->connection->getSchemaManager(); + $schemaManager = $this->connection->createSchemaManager(); $result = []; foreach ($tables as $tableName) { $columns = $schemaManager->listTableColumns($tableName); foreach ($columns as $column) { $columnName = $column->getName(); - if (!array_key_exists($columnName, self::COLUMN_NAMES)) { + if (!\array_key_exists($columnName, self::COLUMN_NAMES)) { continue; } $default = self::COLUMN_NAMES[$columnName]['default']; @@ -162,26 +166,23 @@ private function fetchNonDefaultZeroColumns(): array * Obtain the names of table columns. * * @return list + * @throws Exception */ private function fetchTableNames(): array { - return array_map( - function (Table $table): string { - return $table->getName(); - }, - array_filter( - $this - ->connection - ->getSchemaManager() - ->listTables(), - function (Table $table): bool { - return 'mm_' === substr($table->getName(), 0, 3); - } + return \array_values( + \array_map( + static fn (Table $table): string => $table->getName(), + \array_filter( + $this->connection->createSchemaManager()->listTables(), + static fn (Table $table): bool => \str_starts_with($table->getName(), 'mm_') + ) ) ); } // @codingStandardsIgnoreStart + /** * Fix a table column. * @@ -190,16 +191,17 @@ function (Table $table): bool { * @param TColumnInformation $information The column information. * * @return void + * @throws Exception */ private function fixColumn(string $tableName, string $columnName, array $information): void { $this->connection->executeQuery( - sprintf( + \sprintf( 'ALTER TABLE `%1$s` CHANGE COLUMN `%2$s` `%2$s` %3$s NOT NULL DEFAULT %4$s', $tableName, $columnName, $information['type'], - var_export($information['default'], true), + \var_export($information['default'], true), ) ); } diff --git a/src/CoreBundle/Migration/TableCollationMigration.php b/src/CoreBundle/Migration/TableCollationMigration.php index 0b7932c2f..09305be63 100644 --- a/src/CoreBundle/Migration/TableCollationMigration.php +++ b/src/CoreBundle/Migration/TableCollationMigration.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,7 @@ * @package MetaModels/core * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +25,7 @@ use Contao\CoreBundle\Migration\AbstractMigration; use Contao\CoreBundle\Migration\MigrationResult; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; /** * This migration changes collation of all mm_* databases to the collation from the default table options @@ -37,14 +38,14 @@ class TableCollationMigration extends AbstractMigration * * @var Connection */ - private $connection; + private Connection $connection; /** * The default table options. * * @var array */ - private $defaultTableOptions; + private array $defaultTableOptions; /** * Create a new instance. @@ -79,7 +80,7 @@ public function getName(): string * - the engine is not InnoDB. * * @return bool - * @throws \Doctrine\DBAL\Exception + * @throws Exception */ public function shouldRun(): bool { @@ -95,7 +96,7 @@ public function shouldRun(): bool * Collect the tables to be updated and update them. * * @return MigrationResult - * @throws \Doctrine\DBAL\Exception + * @throws Exception */ public function run(): MigrationResult { @@ -106,24 +107,24 @@ public function run(): MigrationResult $message[] = $table; } - return new MigrationResult(true, 'Adjusted table(s): ' . implode(', ', $message)); + return new MigrationResult(true, 'Adjusted table(s): ' . \implode(', ', $message)); } /** * Fetch all tables that are not right collection or DB engine yet. * * @return array - * @throws \Doctrine\DBAL\Exception + * @throws Exception */ private function fetchPendingTables(): array { - $schemaManager = $this->connection->getSchemaManager(); + $schemaManager = $this->connection->createSchemaManager(); $tableNames = $schemaManager->listTableNames(); $results = []; foreach ($tableNames as $tableName) { // Only MM model tables. - if ('mm_' !== \substr($tableName, 0, 3)) { + if (!\str_starts_with($tableName, 'mm_')) { continue; } @@ -131,9 +132,13 @@ private function fetchPendingTables(): array $result = $this->connection ->executeQuery(sprintf('SHOW TABLE STATUS LIKE \'%1$s\'', $tableName)) ->fetchAssociative(); + if (false === $result) { + continue; + } // Check collation and DB engine and collect tables with false data. - if (($this->defaultTableOptions['collation'] !== $result['Collation']) + if ( + ($this->defaultTableOptions['collation'] !== $result['Collation']) || ($this->defaultTableOptions['engine'] !== $result['Engine']) ) { $results[] = $tableName; @@ -149,7 +154,7 @@ private function fetchPendingTables(): array * @param string $tableName The name of the table. * * @return void - * @throws \Doctrine\DBAL\Exception + * @throws Exception */ private function fixTable(string $tableName): void { diff --git a/src/CoreBundle/Resources/config/listeners.yml b/src/CoreBundle/Resources/config/listeners.yml index fe7851234..ded769c9f 100644 --- a/src/CoreBundle/Resources/config/listeners.yml +++ b/src/CoreBundle/Resources/config/listeners.yml @@ -74,9 +74,6 @@ services: event: dc-general.model.post-persist method: checkPurge - - - MetaModels\CoreBundle\EventListener\BackendNavigationListener: arguments: - '@contao.translation.translator' @@ -87,18 +84,6 @@ services: tags: - { name: kernel.event_listener } - - - - - - - - - - - - MetaModels\CoreBundle\EventListener\DoctrineSchemaListener: arguments: $generator: '@MetaModels\Schema\SchemaGenerator' @@ -118,8 +103,6 @@ services: event: kernel.request priority: -500 - - # metamodels.listener.table.tl_metamodel_rendersettings: # class: MetaModels\DcGeneral\Events\Table\RenderSettings\Subscriber # arguments: diff --git a/src/CoreBundle/Resources/contao/config/config.php b/src/CoreBundle/Resources/contao/config/config.php index 5b95638f7..268f55429 100644 --- a/src/CoreBundle/Resources/contao/config/config.php +++ b/src/CoreBundle/Resources/contao/config/config.php @@ -29,7 +29,7 @@ // Preserve values by extensions but insert as first entry after 'system'. $arrOld = isset($GLOBALS['BE_MOD']['metamodels']) ? $GLOBALS['BE_MOD']['metamodels'] : array(); unset($GLOBALS['BE_MOD']['metamodels']); -array_insert( +\Contao\ArrayUtil::arrayInsert( $GLOBALS['BE_MOD'], (array_search('accounts', array_keys($GLOBALS['BE_MOD'])) + 1), array @@ -114,7 +114,7 @@ $GLOBALS['METAMODELS']['metainformation']['allowedDescription'][] = 'translatedlongtext'; $GLOBALS['METAMODELS']['metainformation']['allowedDescription'][] = 'combinedvalues'; -array_insert($GLOBALS['BE_FFL'], 15, array +\Contao\ArrayUtil::arrayInsert($GLOBALS['BE_FFL'], 15, array ( 'mm_subdca' => 'MetaModels\Widgets\SubDcaWidget' )); diff --git a/src/CoreBundle/Resources/contao/config/services.php b/src/CoreBundle/Resources/contao/config/services.php index 10940c67f..1ed87e5c2 100644 --- a/src/CoreBundle/Resources/contao/config/services.php +++ b/src/CoreBundle/Resources/contao/config/services.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author Sven Baumann * @author Oliver Willmes * @author Richard Henkenjohann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ diff --git a/src/CoreBundle/Resources/contao/dca/tl_content.php b/src/CoreBundle/Resources/contao/dca/tl_content.php index 84dea8ed5..a02e260b4 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_content.php +++ b/src/CoreBundle/Resources/contao/dca/tl_content.php @@ -64,7 +64,7 @@ $GLOBALS['TL_DCA']['tl_content']['palettes']['__selector__'][] = 'metamodel_use_parameters'; // Insert new Subpalettes after position 1. -\array_insert( +\Contao\ArrayUtil::arrayInsert( $GLOBALS['TL_DCA']['tl_content']['subpalettes'], 1, [ @@ -75,7 +75,7 @@ ); // Fields. -\array_insert( +\Contao\ArrayUtil::arrayInsert( $GLOBALS['TL_DCA']['tl_content']['fields'], 1, [ diff --git a/src/CoreBundle/Resources/contao/dca/tl_module.php b/src/CoreBundle/Resources/contao/dca/tl_module.php index c882f7a77..e2cade3e1 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_module.php +++ b/src/CoreBundle/Resources/contao/dca/tl_module.php @@ -60,7 +60,7 @@ $GLOBALS['TL_DCA']['tl_module']['palettes']['__selector__'][] = 'metamodel_use_parameters'; // Insert new Subpalettes after position 1. -\array_insert( +\Contao\ArrayUtil::arrayInsert( $GLOBALS['TL_DCA']['tl_module']['subpalettes'], 1, [ @@ -71,7 +71,7 @@ ); // Fields. -\array_insert( +\Contao\ArrayUtil::arrayInsert( $GLOBALS['TL_DCA']['tl_module']['fields'], 1, [ diff --git a/src/CoreBundle/Sorter/AttributeSorter.php b/src/CoreBundle/Sorter/AttributeSorter.php index d385769c7..74fdf7bf2 100644 --- a/src/CoreBundle/Sorter/AttributeSorter.php +++ b/src/CoreBundle/Sorter/AttributeSorter.php @@ -33,6 +33,8 @@ final class AttributeSorter * @param string $dir The sort direction. * * @return array + * + * @SuppressWarnings(PHPMD.ShortVariable) */ public function sortByName(array $attributes, string $dir = 'ASC'): array { @@ -54,6 +56,8 @@ public function sortByName(array $attributes, string $dir = 'ASC'): array * @param string $dir The sort direction. * * @return array + * + * @SuppressWarnings(PHPMD.ShortVariable) */ public function sortByColumnName(array $attributes, string $dir = 'ASC'): array { diff --git a/src/DcGeneral/Data/Driver.php b/src/DcGeneral/Data/Driver.php index da7978495..aad9d9cb0 100644 --- a/src/DcGeneral/Data/Driver.php +++ b/src/DcGeneral/Data/Driver.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -28,6 +28,7 @@ use ContaoCommunityAlliance\DcGeneral\Data\CollectionInterface; use ContaoCommunityAlliance\DcGeneral\Data\ConfigInterface; +use ContaoCommunityAlliance\DcGeneral\Data\DataProviderInterface; use ContaoCommunityAlliance\DcGeneral\Data\DCGE; use ContaoCommunityAlliance\DcGeneral\Data\DefaultCollection; use ContaoCommunityAlliance\DcGeneral\Data\DefaultConfig; @@ -54,45 +55,50 @@ * Data driver class for DC_General. * * @SuppressWarnings(PHPMD.TooManyPublicMethods) - The interface is too complex, maybe split into traits. + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * + * @psalm-suppress DeprecatedTrait */ class Driver implements MultiLanguageDataProviderInterface { + /** @psalm-suppress DeprecatedTrait */ use DriverBcLayerTrait; /** * Name of current table. * - * @var null|string + * @var string|null */ - protected ?string $strTable = null; + protected string|null $strTable = null; /** * The MetaModel this DataContainer is working on. * - * @var null|IMetaModel + * @var IMetaModel|null */ - protected ?IMetaModel $metaModel = null; + protected IMetaModel|null $metaModel = null; /** * The event dispatcher to pass to items. * - * @var null|EventDispatcherInterface + * @var EventDispatcherInterface|null */ - private ?EventDispatcherInterface $dispatcher = null; + private EventDispatcherInterface|null $dispatcher = null; /** * The current active language. * * @var string */ - protected string $strCurrentLanguage; + protected string $strCurrentLanguage = ''; /** * The database connection. * * @var Connection|null */ - private ?Connection $connection; + private Connection|null $connection = null; /** * Set dispatcher. @@ -127,31 +133,33 @@ public function setConnection(Connection $connection) * * The given value may be either integer, string or an instance of Model * - * @param mixed $varItem Id or the model itself, to delete. + * @param mixed $item Id or the model itself, to delete. * * @return void * * @throws \RuntimeException When an unusable object has been passed. */ - public function delete($varItem) + public function delete($item) { + $metaModel = $this->getMetaModel(); + assert($metaModel instanceof IMetaModel); + // Determine the id. - if (is_object($varItem) && ($varItem instanceof Model)) { - $objModelItem = $varItem->getItem(); + if (\is_object($item) && ($item instanceof Model)) { + $objModelItem = $item->getItem(); } else { - $objModelItem = $this->getMetaModel()->findById($varItem); + $objModelItem = $metaModel->findById($item); } if ($objModelItem) { - $this->getMetaModel()->delete($objModelItem); + $metaModel->delete($objModelItem); } } /** * Save a new Version of a record. * - * @param ModelInterface $objModel The model to be saved. - * - * @param string $strUsername The username that creates the new version. + * @param ModelInterface $model The model to be saved. + * @param string $username The username that creates the new version. * * @return void * @@ -159,7 +167,7 @@ public function delete($varItem) * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function saveVersion(ModelInterface $objModel, $strUsername) + public function saveVersion(ModelInterface $model, $username) { throw new \RuntimeException('Versioning not supported in MetaModels so far.'); } @@ -168,10 +176,9 @@ public function saveVersion(ModelInterface $objModel, $strUsername) * Return a model based of the version information. * * @param mixed $mixID The ID of record. - * * @param mixed $mixVersion The ID of the version. * - * @return void + * @return never-return * * @throws \RuntimeException As this is currently unimplemented, an Exception is thrown. * @@ -186,7 +193,6 @@ public function getVersion($mixID, $mixVersion) * Set a version as active. * * @param mixed $mixID The ID of record. - * * @param mixed $mixVersion The ID of the version. * * @return void @@ -205,7 +211,7 @@ public function setVersionActive($mixID, $mixVersion) * * @param mixed $mixID The ID of the record. * - * @return void + * @return mixed * * @throws \RuntimeException As this is currently unimplemented, an Exception is thrown. * @@ -262,9 +268,10 @@ protected function getMetaModel() { if (!$this->metaModel) { if ($this->metaModel === null) { - throw new \RuntimeException('No MetaModel instance set for ' . $this->strTable); + throw new \RuntimeException('No MetaModel instance set for ' . (string) $this->strTable); } } + return $this->metaModel; } @@ -275,23 +282,23 @@ protected function getMetaModel() * * If the model shall be retrieved by filter, use $objConfig->setFilter() to populate the config with a filter. * - * @param ConfigInterface $objConfig The config to use. + * @param ConfigInterface $config The config to use. * * @return null|ModelInterface */ - public function fetch(ConfigInterface $objConfig) + public function fetch(ConfigInterface $config) { $backupLanguage = $this->setLanguage($currentLanguage = $this->getCurrentLanguage()); - if ($objConfig->getId() !== null) { - $modelId = $objConfig->getId(); + if ($config->getId() !== null) { + $modelId = $config->getId(); } else { - $filter = $this->prepareFilter($objConfig); - $ids = $this->getIdsFromFilter($filter, $objConfig); - $modelId = reset($ids); + $filter = $this->prepareFilter($config); + $ids = $this->getIdsFromFilter($filter, $config); + $modelId = \reset($ids); } - $objItem = $modelId ? $this->getMetaModel()->findById($modelId, $objConfig->getFields() ?: array()) : null; + $objItem = (null !== $modelId) ? $this->getMetaModel()->findById($modelId, $config->getFields() ?? []) : null; $this->setLanguage($backupLanguage); @@ -305,20 +312,20 @@ public function fetch(ConfigInterface $objConfig) /** * Set base config with source and other necessary parameter. * - * @param array $arrConfig The configuration to use. + * @param array $config The configuration to use. * * @return void * * @throws \RuntimeException When no source has been defined. */ - public function setBaseConfig(array $arrConfig) + public function setBaseConfig(array $config) { - if (!$arrConfig['source']) { + if (!$config['source']) { throw new \RuntimeException('Missing table name.'); } - $this->strTable = $arrConfig['source']; - $this->metaModel = $arrConfig['metaModel'] ?? null; + $this->strTable = $config['source']; + $this->metaModel = $config['metaModel'] ?? null; } /** @@ -381,6 +388,7 @@ protected function prepareFilter(ConfigInterface $configuration) // @codingStandardsIgnoreEnd } $builder = new FilterBuilder($this->getMetaModel(), $configuration, $this->connection); + return $builder->build(); } @@ -389,26 +397,27 @@ protected function prepareFilter(ConfigInterface $configuration) * * @param ConfigInterface $config The configuration to be applied. * - * @return array + * @return array{string, string}|null */ protected function extractSorting($config) { $sorting = $config->getSorting(); + $sortBy = \key($sorting); + if (null === $sortBy) { + return null; + } + $sortDir = $sorting[$sortBy] ?? DCGE::MODEL_SORTING_ASC; - $sortBy = key($sorting); - $sortDir = current($sorting) ?: DCGE::MODEL_SORTING_ASC; - - return array($sortBy, $sortDir); + return [$sortBy, \strtoupper($sortDir)]; } /** * Fetch the ids via the given filter. * * @param IFilter $filter The filter. - * * @param ConfigInterface $config The configuration to be applied. * - * @return string[] + * @return list */ protected function getIdsFromFilter($filter, $config) { @@ -416,10 +425,10 @@ protected function getIdsFromFilter($filter, $config) return $this->getMetaModel()->getIdsFromFilter( $filter, - $sorting[0], + $sorting[0] ?? '', $config->getStart(), $config->getAmount(), - strtoupper($sorting[1]) + $sorting[1] ?? DCGE::MODEL_SORTING_ASC, ); } @@ -427,10 +436,9 @@ protected function getIdsFromFilter($filter, $config) * Fetch the items via the given filter. * * @param IFilter $filter The filter. - * * @param ConfigInterface $config The configuration to be applied. * - * @return IItems|IItem[] The collection of IItem instances that match the given filter. + * @return IItems The collection of IItem instances that match the given filter. */ protected function getItemsFromFilter($filter, $config) { @@ -438,33 +446,33 @@ protected function getItemsFromFilter($filter, $config) return $this->getMetaModel()->findByFilter( $filter, - $sorting[0], + $sorting[0] ?? '', $config->getStart(), $config->getAmount(), - strtoupper($sorting[1]), - $config->getFields() ?: array() + $sorting[1] ?? DCGE::MODEL_SORTING_ASC, + $config->getFields() ?? [] ); } /** * Fetch all records (optional filtered, sorted and limited). * - * @param ConfigInterface $objConfig The configuration to be applied. + * @param ConfigInterface $config The configuration to be applied. * - * @return CollectionInterface|ModelInterface[]|string[] + * @return CollectionInterface|list */ - public function fetchAll(ConfigInterface $objConfig) + public function fetchAll(ConfigInterface $config) { $backupLanguage = $this->setLanguage($this->getCurrentLanguage()); - $filter = $this->prepareFilter($objConfig); - if ($objConfig->getIdOnly()) { + $filter = $this->prepareFilter($config); + if ($config->getIdOnly()) { $this->setLanguage($backupLanguage); - return $this->getIdsFromFilter($filter, $objConfig); + return $this->getIdsFromFilter($filter, $config); } - $items = $this->getItemsFromFilter($filter, $objConfig); + $items = $this->getItemsFromFilter($filter, $config); $collection = $this->getEmptyCollection(); foreach ($items as $objItem) { $collection->push(new Model($objItem)); @@ -485,24 +493,26 @@ public function fetchAll(ConfigInterface $objConfig) * The only information being interpreted from the passed config object is the first property to fetch and the * filter definition. * - * @param ConfigInterface $objConfig The filter config options. + * @param ConfigInterface $config The filter config options. * * @return FilterOptionCollectionInterface * * @throws \RuntimeException If improper values have been passed (i.e. not exactly one field requested). */ - public function getFilterOptions(ConfigInterface $objConfig) + public function getFilterOptions(ConfigInterface $config) { - $arrProperties = $objConfig->getFields(); - if (count($arrProperties) <> 1) { + $arrProperties = $config->getFields(); + if (\count($arrProperties ?? []) <> 1) { throw new \RuntimeException('objConfig must contain exactly one property to be retrieved.'); } - $objFilter = $this->prepareFilter($objConfig); + $objFilter = $this->prepareFilter($config); $metaModel = $this->getMetaModel(); + assert($metaModel instanceof IMetaModel); + $arrValues = $metaModel - ->getAttributeOptions($arrProperties[0], $objFilter); + ->getAttributeOptions($arrProperties[0] ?? '', $objFilter); $objCollection = new DefaultFilterOptionCollection(); foreach ($arrValues as $strKey => $strValue) { @@ -515,63 +525,64 @@ public function getFilterOptions(ConfigInterface $objConfig) /** * Return the amount of total items (filtering may be used in the config). * - * @param ConfigInterface $objConfig The filter config options. + * @param ConfigInterface $config The filter config options. * * @return int */ - public function getCount(ConfigInterface $objConfig) + public function getCount(ConfigInterface $config) { - $objFilter = $this->prepareFilter($objConfig); - return $this->getMetaModel()->getCount($objFilter); + $objFilter = $this->prepareFilter($config); + $metaModel = $this->getMetaModel(); + assert($metaModel instanceof IMetaModel); + + return $metaModel->getCount($objFilter); } /** * Return a list with all versions for the model with the given Id. * - * @param mixed $mixID The ID of the row. - * - * @param boolean $blnOnlyActive If true, only active versions will get returned, if false all version will get - * returned. + * @param mixed $mixID The ID of the row. + * @param boolean $onlyActive If true, only active versions will get returned, if false all version will get + * returned. * * @return CollectionInterface * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function getVersions($mixID, $blnOnlyActive = false) + public function getVersions($mixID, $onlyActive = false) { // No version support on MetaModels so far, sorry. - return null; + return new DefaultCollection(); } /** * Determine if a given value is unique within the metamodel. * - * @param string $strField The attribute name. - * - * @param mixed $varNew The value that shall be checked. - * - * @param int $intId The (optional) id of the item currently in scope - pass null for new items. + * @param string $field The attribute name. + * @param mixed $new The value that shall be checked. + * @param mixed $primaryId The (optional) id of the item currently in scope - pass null for new items. * * @return bool True if the values is not yet contained within the table, false otherwise. */ - public function isUniqueValue($strField, $varNew, $intId = null) + public function isUniqueValue($field, $new, $primaryId = null) { - $attribute = $this->getMetaModel()->getAttribute($strField); + $attribute = $this->getMetaModel()->getAttribute($field); if ($attribute) { $matchingIds = $this ->prepareFilter( $this->getEmptyConfig()->setFilter( - array( - array( + [ + [ 'operation' => '=', - 'property' => $attribute->getColName(), - 'value' => $varNew - ) - ) + 'property' => $attribute->getColName(), + 'value' => $new + ] + ] ) ) ->getMatchingIds(); - return (count($matchingIds) == 0) || ($matchingIds == array($intId)); + + return ([] === $matchingIds) || ([(string) $primaryId] === $matchingIds); } return false; @@ -582,20 +593,22 @@ public function isUniqueValue($strField, $varNew, $intId = null) * * This clears the given property in all items in the data provider to an empty value. * - * @param string $strField The field to reset. + * @param string $field The field to reset. * - * @return void + * @return never * * @throws \RuntimeException For invalid ids. */ - public function resetFallback($strField) + public function resetFallback($field) { // @codingStandardsIgnoreStart @trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated - handle resetting manually', E_USER_DEPRECATED); // @codingStandardsIgnoreEnd $metaModel = $this->getMetaModel(); - $attribute = $metaModel->getAttribute($strField); + assert($metaModel instanceof IMetaModel); + + $attribute = $metaModel->getAttribute($field); $ids = $metaModel->getIdsFromFilter(null); if ($attribute instanceof IComplex) { @@ -605,14 +618,14 @@ public function resetFallback($strField) $attribute->unsetValueFor($ids, $this->getCurrentLanguage()); } if ($attribute instanceof IAttribute) { - $data = array(); + $data = []; foreach ($ids as $id) { $data[$id] = null; } $attribute->setDataFor($data); } - throw new \RuntimeException('Unknown attribute or type ' . $strField); + throw new \RuntimeException('Unknown attribute or type ' . $field); } /** @@ -621,15 +634,14 @@ public function resetFallback($strField) * If the item does not have an Id yet, the save operation will add it as a new row to the database and * populate the Id of the model accordingly. * - * @param ModelInterface $objItem The model to save back. - * - * @param int|null $timestamp Optional the timestamp. + * @param ModelInterface $item The model to save back. + * @param int|null $timestamp Optional the timestamp. * * @return ModelInterface The passed model. * * @throws \RuntimeException When an incompatible item was passed, an Exception is being thrown. */ - public function save(ModelInterface $objItem, $timestamp = null) + public function save(ModelInterface $item, $timestamp = null) { if (null === $timestamp) { // @codingStandardsIgnoreStart @@ -640,14 +652,16 @@ public function save(ModelInterface $objItem, $timestamp = null) // @codingStandardsIgnoreEnd } - if ($objItem instanceof Model) { + if ($item instanceof Model) { $backupLanguage = $this->setLanguage($this->getCurrentLanguage()); - $objItem->getItem()->save($timestamp); + $mmItem = $item->getItem(); + assert($mmItem instanceof IItem); + $mmItem->save($timestamp); $this->setLanguage($backupLanguage); - return $objItem; + return $item; } throw new \RuntimeException('ERROR: incompatible object passed to GeneralDataMetaModel::save()'); @@ -656,15 +670,14 @@ public function save(ModelInterface $objItem, $timestamp = null) /** * Save a collection of items to the data provider. * - * @param CollectionInterface $objItems The collection containing all items to be saved. - * - * @param int $timestamp Optional the timestamp. + * @param CollectionInterface $items The collection containing all items to be saved. + * @param int|null $timestamp Optional the timestamp. * * @return void * * @throws \RuntimeException When an incompatible item was passed. */ - public function saveEach(CollectionInterface $objItems, $timestamp = 0) + public function saveEach(CollectionInterface $items, $timestamp = 0) { if (null === $timestamp) { // @codingStandardsIgnoreStart @@ -675,7 +688,7 @@ public function saveEach(CollectionInterface $objItems, $timestamp = 0) // @codingStandardsIgnoreEnd } - foreach ($objItems as $objItem) { + foreach ($items as $objItem) { $this->save($objItem, $timestamp); } } @@ -683,45 +696,47 @@ public function saveEach(CollectionInterface $objItems, $timestamp = 0) /** * Check if the attribute exists in the table and holds a value. * - * @param string $strField The name of the attribute that shall be tested. + * @param string $columnName The name of the attribute that shall be tested. * * @return boolean */ - public function fieldExists($strField) + public function fieldExists($columnName) { return !!( - in_array($strField, array('id', 'pid', 'tstamp', 'sorting')) - || $this->getMetaModel()->getAttribute($strField) + \in_array($columnName, ['id', 'pid', 'tstamp', 'sorting']) + || $this->getMetaModel()->getAttribute($columnName) ); } /** * Check if two models have the same values in all properties. * - * @param ModelInterface $objModel1 The first model to compare. - * - * @param ModelInterface $objModel2 The second model to compare. + * @param ModelInterface $firstModel The first model to compare. + * @param ModelInterface $secondModel The second model to compare. * * @return boolean True - If both models are same, false if not. * * @throws \InvalidArgumentException If not both models are compatible with this data provider. */ - public function sameModels($objModel1, $objModel2) + public function sameModels($firstModel, $secondModel) { - if (!($objModel1 instanceof Model && $objModel2 instanceof Model)) { + if (!($firstModel instanceof Model && $secondModel instanceof Model)) { throw new \InvalidArgumentException('Passed models are not valid.'); } - $objNative1 = $objModel1->getItem(); - $objNative2 = $objModel2->getItem(); + $objNative1 = $firstModel->getItem(); + assert($objNative1 instanceof IItem); + $objNative2 = $secondModel->getItem(); + assert($objNative2 instanceof IItem); if ($objNative1->getMetaModel() === $objNative2->getMetaModel()) { return true; } foreach ($objNative1->getMetaModel()->getAttributes() as $objAttribute) { - if ($objNative1->get($objAttribute->getColName()) != $objNative2->get($objAttribute->getColName())) { + if ($objNative1->get($objAttribute->getColName()) !== $objNative2->get($objAttribute->getColName())) { return false; } } + return true; } @@ -734,11 +749,9 @@ public function sameModels($objModel1, $objModel2) */ public function createVariant(ConfigInterface $objConfig) { - $objItem = $this->getMetaModel()->findById($objConfig->getId())->varCopy(); - - if (!$objItem) { - return null; - } + $item = $this->getMetaModel()->findById($objConfig->getId()); + assert($item instanceof IItem); + $objItem = $item->varCopy(); $model = new Model($objItem); $model->setMeta($model::IS_CHANGED, true); @@ -757,16 +770,20 @@ public function getLanguages($mixID) if ($metaModel instanceof ITranslatedMetaModel) { $collection = new DefaultLanguageInformationCollection(); foreach ($metaModel->getLanguages() as $langCode) { - [$langCode, $locale] = explode('_', $langCode, 2) + [null, null]; + [$langCode, $locale] = \explode('_', $langCode, 2) + [null, null]; $collection->add(new DefaultLanguageInformation($langCode, $locale)); } - if (count($collection) > 0) { + if (\count($collection) > 0) { return $collection; } return null; } + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { return null; } @@ -785,10 +802,14 @@ public function getFallbackLanguage($mixID) { $metaModel = $this->getMetaModel(); if ($metaModel instanceof ITranslatedMetaModel) { - [$langCode, $locale] = explode('_', $metaModel->getMainLanguage(), 2) + [null, null]; + [$langCode, $locale] = \explode('_', $metaModel->getMainLanguage(), 2) + [null, null]; return new DefaultLanguageInformation($langCode, $locale); } + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { return null; } @@ -801,13 +822,15 @@ public function getFallbackLanguage($mixID) /** * Set the current working language for the whole data provider. * - * @param string $strLanguage The new language, use short tag "2 chars like de, fr etc.". + * @param string $language The new language, use short tag "2 chars like de, fr etc.". * - * @return void + * @return DataProviderInterface */ - public function setCurrentLanguage($strLanguage) + public function setCurrentLanguage($language) { - $this->strCurrentLanguage = $strLanguage; + $this->strCurrentLanguage = $language; + + return $this; } /** @@ -817,6 +840,6 @@ public function setCurrentLanguage($strLanguage) */ public function getCurrentLanguage() { - return $this->strCurrentLanguage ?? 'en'; + return '' === $this->strCurrentLanguage ? 'en' : $this->strCurrentLanguage; } } diff --git a/src/DcGeneral/Data/DriverBcLayerTrait.php b/src/DcGeneral/Data/DriverBcLayerTrait.php index 7599980da..951e01e47 100644 --- a/src/DcGeneral/Data/DriverBcLayerTrait.php +++ b/src/DcGeneral/Data/DriverBcLayerTrait.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Andreas Fischer - * @copyright 2012-2021 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -51,12 +52,13 @@ private function getLanguagesBcLayer($metaModel): ?DefaultLanguageInformationCol ); // @codingStandardsIgnoreEnd $collection = new DefaultLanguageInformationCollection(); - foreach ($metaModel->getAvailableLanguages() as $langCode) { - [$langCode, $country] = explode('_', $langCode, 2); - $collection->add(new DefaultLanguageInformation($langCode, $country ?: null)); + /** @psalm-suppress DeprecatedMethod */ + foreach ($metaModel->getAvailableLanguages() ?? [] as $langCode) { + [$langCode, $country] = \explode('_', $langCode ?: '', 2) + ['', null]; + $collection->add(new DefaultLanguageInformation($langCode, $country ?? null)); } - if (count($collection) > 0) { + if (\count($collection) > 0) { return $collection; } @@ -81,11 +83,12 @@ private function getFallbackLanguageBcLayer(IMetaModel $metaModel): DefaultLangu E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + /** @psalm-suppress DeprecatedMethod */ $langCode = $metaModel->getFallbackLanguage(); - [$langCode, $country] = explode('_', $langCode, 2); + [$langCode, $country] = \explode('_', $langCode ?? '', 2) + ['', null]; - return new DefaultLanguageInformation($langCode, $country ?: null); + return new DefaultLanguageInformation($langCode, $country ?? null); // @coverageIgnoreEnd } } diff --git a/src/DcGeneral/Data/FilterBuilder.php b/src/DcGeneral/Data/FilterBuilder.php index ef0f9cda4..9ce788f5f 100644 --- a/src/DcGeneral/Data/FilterBuilder.php +++ b/src/DcGeneral/Data/FilterBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author David Molineus * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -36,9 +36,19 @@ use MetaModels\Filter\Rules\SimpleQuery; use MetaModels\IMetaModel; use MetaModels\IMetaModelsServiceContainer; +use MetaModels\ITranslatedMetaModel; /** * Class to generate a MetaModels filter from a data configuration. + * + * @psalm-type TFilterANDOR=array{operation: 'AND'|'OR', children: list>} + * @psalm-type TFilterCMP=array{operation: "="|">"|"<", property: string, value: string} + * @psalm-type TFilterIN=array{operation: 'IN', property: string, values: list} + * @psalm-type TFilterLIKE=array{operation: 'LIKE', property: string, value: string} + * @psalm-type TFilterForProperty=TFilterCMP|TFilterIN|TFilterLIKE + * @psalm-type TFilter=TFilterANDOR|TFilterForProperty + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class FilterBuilder { @@ -67,9 +77,7 @@ class FilterBuilder * Generate a filter from a passed configuration. * * @param IMetaModel $metaModel The MetaModel. - * * @param ConfigInterface $configuration The data configuration. - * * @param Connection|null $connection The database connection. */ public function __construct(IMetaModel $metaModel, ConfigInterface $configuration, Connection $connection = null) @@ -77,18 +85,16 @@ public function __construct(IMetaModel $metaModel, ConfigInterface $configuratio $this->metaModel = $metaModel; $this->configuration = $configuration; - // @codingStandardsIgnoreStart - // @codeCoverageIgnoreStart if (null === $connection) { + // @codingStandardsIgnoreStart @trigger_error( 'Connection is missing. It has to be passed in the constructor. Fallback will be dropped.', E_USER_DEPRECATED ); + // @codingStandardsIgnoreEnd $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); } - // @codeCoverageIgnoreEnd - // @codingStandardsIgnoreEnd - $this->connection = $connection; } @@ -106,9 +112,12 @@ protected function getMetaModel() * Retrieve the service container. * * @return IMetaModelsServiceContainer + * + * @psalm-suppress DeprecatedInterface */ protected function getServiceContainer() { + /** @psalm-suppress DeprecatedMethod */ return $this->getMetaModel()->getServiceContainer(); } @@ -119,6 +128,7 @@ protected function getServiceContainer() */ protected function getDatabase() { + /** @psalm-suppress DeprecatedMethod */ return $this->getServiceContainer()->getDatabase(); } @@ -126,10 +136,8 @@ protected function getDatabase() * Build the sub query for a comparing operator like =,<,>. * * @param IAttribute $attribute The attribute. - * * @param IFilter $filter The filter to add the operations to. - * - * @param array $operation The operation to convert. + * @param TFilterCMP $operation The operation to convert. * * @return void * @@ -137,69 +145,39 @@ protected function getDatabase() */ private function getFilterForComparingOperator($attribute, IFilter $filter, $operation) { - if ($attribute) { - switch ($operation['operation']) { - case '=': - $filter->addFilterRule(new SearchAttribute( - $attribute, - $operation['value'], - $this->getMetaModel()->getAvailableLanguages() ?: array() - )); - return; - - case '>': - $filter->addFilterRule(new GreaterThan( - $attribute, - $operation['value'] - )); - return; - - case '<': - $filter->addFilterRule(new LessThan( - $attribute, - $operation['value'] - )); - return; - - default: - throw new \RuntimeException( - 'Error processing filter array - unknown operation ' . - var_export($operation['operation'], true), - 1 - ); - } - } + switch ($operation['operation']) { + case '=': + $filter->addFilterRule($this->buildSearchAttributeFilterRule($attribute, $operation['value'])); + return; - $columns = $this->connection->getSchemaManager()->listTableColumns($this->getMetaModel()->getTableName()); - if ($columns[$operation['property']]) { - // System column? - $filter->addFilterRule(new SimpleQuery( - sprintf( - 'SELECT t.id FROM %s AS t WHERE t.%s %s?', - $this->getMetaModel()->getTableName(), - $operation['property'], - $operation['operation'] - ), - array($operation['value']), - 'id', - $this->connection - )); + case '>': + $filter->addFilterRule(new GreaterThan( + $attribute, + $operation['value'] + )); + return; - return; - } + case '<': + $filter->addFilterRule(new LessThan( + $attribute, + $operation['value'] + )); + return; - throw new \RuntimeException( - 'Error processing filter array - unknown property ' . var_export($operation['property'], true), - 1 - ); + default: + throw new \RuntimeException( + 'Error processing filter array - unknown operation ' . + \var_export($operation['operation'], true), + 1 + ); + } } /** * Return the filter query for a "foo IN ('a', 'b')" filter. * - * @param IFilter $filter The filter to add the operations to. - * - * @param array $operation The operation to convert. + * @param IFilter $filter The filter to add the operations to. + * @param TFilterIN $operation The operation to convert. * * @return void * @@ -208,18 +186,16 @@ private function getFilterForComparingOperator($attribute, IFilter $filter, $ope private function getFilterForInList(IFilter $filter, $operation) { // Rewrite the IN operation to a rephrased term: "(x=a) OR (x=b) OR ...". - $subRules = array(); + $subRules = []; foreach ($operation['values'] as $varValue) { - $subRules[] = array( + $subRules[] = [ 'property' => $operation['property'], 'operation' => '=', 'value' => $varValue - ); + ]; } - $this->calculateSubfilter(array( - 'operation' => 'OR', - 'children' => $subRules - ), $filter); + + $this->getAndOrFilter($filter, ['operation' => 'OR', 'children' => $subRules]); } /** @@ -227,11 +203,9 @@ private function getFilterForInList(IFilter $filter, $operation) * * The searched value may contain the wildcards '*' and '?' which will get converted to proper SQL. * - * @param IAttribute $attribute The attribute. - * - * @param IFilter $filter The filter to add the operations to. - * - * @param array $operation The operation to convert. + * @param IAttribute $attribute The attribute. + * @param IFilter $filter The filter to add the operations to. + * @param TFilterLIKE $operation The operation to convert. * * @return void * @@ -239,37 +213,7 @@ private function getFilterForInList(IFilter $filter, $operation) */ private function getFilterForLike($attribute, IFilter $filter, $operation) { - if ($attribute) { - $filter->addFilterRule(new SearchAttribute( - $attribute, - $operation['value'], - $this->getMetaModel()->getAvailableLanguages() ?: array() - )); - - return; - } - - $columns = $this->connection->getSchemaManager()->listTableColumns($this->getMetaModel()->getTableName()); - if ($columns[$operation['property']]) { - // System column? - $filter->addFilterRule(new SimpleQuery( - sprintf( - 'SELECT t.id FROM %s AS t WHERE t.%s LIKE ?', - $this->getMetaModel()->getTableName(), - $operation['property'] - ), - array($operation['value']), - 'id', - $this->connection - )); - - return; - } - - throw new \RuntimeException( - 'Error processing filter array - unknown property ' . var_export($operation['property'], true), - 1 - ); + $filter->addFilterRule($this->buildSearchAttributeFilterRule($attribute, $operation['value'])); } /** @@ -286,6 +230,7 @@ protected function buildNativeSqlProcedure(FilterBuilderSql $procedure, $childre $metaModel = $this->getMetaModel(); $tableName = $metaModel->getTableName(); foreach ($children as $child) { + assert(\is_array($child)); // If there is an attribute contained within this rule, skip it. if (isset($child['property']) && $metaModel->hasAttribute($child['property'])) { $skipped[] = $child; @@ -302,7 +247,7 @@ protected function buildNativeSqlProcedure(FilterBuilderSql $procedure, $childre $subProcedure = new FilterBuilderSql($tableName, $child['operation'], $this->connection, 't.'); $subSkipped = $this->buildNativeSqlProcedure($subProcedure, $child['children']); - if (count($subSkipped) !== count($child['children'])) { + if (\count($subSkipped) !== \count($child['children'])) { $procedure->addSubProcedure($subProcedure); } @@ -323,9 +268,7 @@ protected function buildNativeSqlProcedure(FilterBuilderSql $procedure, $childre * Method to optimize as many system column lookup filters as possible into a combined filter rule. * * @param ConditionAnd|ConditionOr $filterRule The filter to which the optimized rule shall be added to. - * * @param array $children The children to parse. - * * @param string $operation The operation to parse (AND or OR). * * @return array @@ -335,8 +278,8 @@ protected function optimizedFilter($filterRule, $children, $operation) $procedure = new FilterBuilderSql($this->getMetaModel()->getTableName(), $operation, $this->connection, 't.'); $skipped = $this->buildNativeSqlProcedure($procedure, $children); - if (!$procedure->isEmpty()) { - $filterRule->addChild($this->getMetaModel()->getEmptyFilter()->addFilterRule($procedure->build())); + if (null !== ($rule = $procedure->build())) { + $filterRule->addChild($this->getMetaModel()->getEmptyFilter()->addFilterRule($rule)); } return $skipped; @@ -345,19 +288,18 @@ protected function optimizedFilter($filterRule, $children, $operation) /** * Build an AND or OR query. * - * @param IFilter $filter The filter to add the operations to. - * - * @param array $operation The operation to convert. + * @param IFilter $filter The filter to add the operations to. + * @param TFilterANDOR $operation The operation to convert. * * @return void */ protected function getAndOrFilter(IFilter $filter, $operation) { - if (!$operation['children']) { + if ([] === $operation['children']) { return; } - if ($operation['operation'] == 'AND') { + if ($operation['operation'] === 'AND') { $filterRule = new ConditionAnd(); } else { $filterRule = new ConditionOr(); @@ -376,7 +318,7 @@ protected function getAndOrFilter(IFilter $filter, $operation) /** * Retrieve the attribute for a filter operation. * - * @param array $operation The operation to retrieve the attribute for. + * @param TFilter $operation The operation to retrieve the attribute for. * * @return IAttribute * @@ -384,13 +326,13 @@ protected function getAndOrFilter(IFilter $filter, $operation) */ protected function getAttributeFromFilterOperation($operation) { - $attribute = null; - if (!empty($operation['property'])) { - $attribute = $this->getMetaModel()->getAttribute($operation['property']); + if (null === ($property = $operation['property'] ?? null)) { + throw new \InvalidArgumentException('Missing key "property" in ' . var_export($operation, true)); } + $attribute = $this->getMetaModel()->getAttribute($property); if ($attribute === null) { - throw new \InvalidArgumentException('Attribute ' . $operation['property'] . ' not found.'); + throw new \InvalidArgumentException('Attribute ' . $property . ' not found.'); } return $attribute; @@ -418,29 +360,26 @@ protected function getAttributeFromFilterOperation($operation) * 'property' string (the name of a property) * 'values' array of literal * - * @param array $operation The filter to be combined into the passed filter object. - * + * @param TFilter $operation The filter to be combined into the passed filter object. * @param IFilter $filter The filter object where the rules shall get appended to. * * @return void * * @throws \RuntimeException When an improper filter condition is encountered, an exception is thrown. */ - private function calculateSubfilter($operation, IFilter $filter) + private function calculateSubfilter(array $operation, IFilter $filter): void { - if (!is_array($operation)) { - throw new \RuntimeException('Error Processing subfilter: ' . var_export($operation, true), 1); - } - switch ($operation['operation']) { case 'AND': case 'OR': + $this->assertValidAndOr($operation); $this->getAndOrFilter($filter, $operation); break; case '=': case '>': case '<': + $this->assertValidCompareOperation($operation); $this->getFilterForComparingOperator( $this->getAttributeFromFilterOperation($operation), $filter, @@ -449,10 +388,12 @@ private function calculateSubfilter($operation, IFilter $filter) break; case 'IN': + $this->assertValidInList($operation); $this->getFilterForInList($filter, $operation); break; case 'LIKE': + $this->assertValidLike($operation); $this->getFilterForLike( $this->getAttributeFromFilterOperation($operation), $filter, @@ -462,7 +403,7 @@ private function calculateSubfilter($operation, IFilter $filter) default: throw new \RuntimeException( - 'Error processing filter array - unknown operation ' . var_export($operation, true), + 'Error processing filter array - unknown operation ' . \var_export($operation, true), 1 ); } @@ -477,17 +418,60 @@ public function build() { $filter = $this->getMetaModel()->getEmptyFilter(); - if ($this->configuration->getFilter()) { - $this->calculateSubfilter( - array - ( - 'operation' => 'AND', - 'children' => $this->configuration->getFilter() - ), - $filter - ); + /** @var null|list $filterRules */ + $filterRules = $this->configuration->getFilter(); + if (null !== $filterRules) { + $this->calculateSubfilter(['operation' => 'AND', 'children' => $filterRules], $filter); } return $filter; } + + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ + private function buildSearchAttributeFilterRule(IAttribute $attribute, string $value): SearchAttribute + { + $languages = []; + $metaModel = $attribute->getMetaModel(); + if ($metaModel instanceof ITranslatedMetaModel) { + $languages = $metaModel->getLanguages(); + } elseif ($metaModel->isTranslated(false)) { + $languages = $this->getMetaModel()->getAvailableLanguages() ?? []; + } + + return new SearchAttribute($attribute, $value, \array_values(\array_filter($languages))); + } + + /** @psalm-assert TFilterANDOR $filter */ + private function assertValidAndOr(array $filter): void + { + assert(\is_array($filter['children'] ?? null)); + assert(\in_array($filter['operation'], ['AND', 'OR'], true)); + } + + /** @psalm-assert TFilterCMP $filter */ + private function assertValidCompareOperation(array $filter): void + { + assert(\is_string($filter['property'] ?? null)); + assert(\is_string($filter['value'] ?? null)); + assert(\in_array($filter['operation'], ['<', '=', '>'], true)); + } + + /** @psalm-assert TFilterIN $filter */ + private function assertValidInList(array $filter): void + { + assert(\is_string($filter['property'] ?? null)); + assert(\is_string($filter['value'] ?? null)); + assert($filter['operation'] === 'IN'); + } + + /** @psalm-assert TFilterLIKE $filter */ + private function assertValidLike(array $filter): void + { + assert(\is_string($filter['property'] ?? null)); + assert(\is_string($filter['value'] ?? null)); + assert($filter['operation'] === 'LIKE'); + } } diff --git a/src/DcGeneral/Data/FilterBuilderSql.php b/src/DcGeneral/Data/FilterBuilderSql.php index 8c9817b4f..05f67cfb5 100644 --- a/src/DcGeneral/Data/FilterBuilderSql.php +++ b/src/DcGeneral/Data/FilterBuilderSql.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author David Molineus * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -44,51 +44,49 @@ class FilterBuilderSql * * @var string */ - private $combiner; + private string $combiner; /** * The SQL procedure. * - * @var string + * @var array */ - private $procedures = []; + private array $procedures = []; /** * The SQL query parameters. * * @var array */ - private $parameter = []; + private array $parameter = []; /** * The database instance. * * @var Connection */ - private $connection; + private Connection $connection; /** * The table alias to use. * * @var string */ - private $tableAlias; + private string $tableAlias; /** * Create a new instance. * * @param string $tableName The table name. - * * @param string $combiner The combiner (AND or OR). - * * @param Connection $connection The database connection. - * * @param string $tableAlias The table alias prefix (defaults to 't.'). */ public function __construct($tableName, $combiner, $connection, string $tableAlias = 't.') { $this->tableName = $tableName; $this->combiner = strtoupper($combiner); + /** @psalm-suppress DeprecatedMethod */ $this->connection = $this->sanitizeConnection($connection); $this->tableAlias = $tableAlias; } @@ -110,7 +108,7 @@ public function isEmpty() */ public function getProcedure() { - return '(' . implode(' ' . $this->combiner . ' ', $this->procedures) . ')'; + return '(' . \implode(' ' . $this->combiner . ' ', $this->procedures) . ')'; } /** @@ -132,7 +130,7 @@ public function build() { if (!$this->isEmpty()) { return new SimpleQuery( - sprintf('SELECT t.id FROM %s AS t WHERE %s', $this->tableName, $this->getProcedure()), + \sprintf('SELECT t.id FROM %s AS t WHERE %s', $this->tableName, $this->getProcedure()), $this->getParameters(), 'id', $this->connection @@ -152,7 +150,7 @@ public function build() protected function getFilterForComparingOperator($operation) { $this->parameter[] = $operation['value']; - $this->procedures[] = sprintf( + $this->procedures[] = \sprintf( '(%s%s %s ?)', $this->tableAlias, $operation['property'], @@ -171,12 +169,12 @@ protected function getFilterForComparingOperator($operation) */ protected function getFilterForInList($operation) { - $this->parameter = array_merge($this->parameter, array_values($operation['values'])); - $this->procedures[] = sprintf( + $this->parameter = \array_merge($this->parameter, \array_values($operation['values'])); + $this->procedures[] = \sprintf( '(%s%s IN (%s))', $this->tableAlias, $operation['property'], - rtrim(str_repeat('?,', \count($operation['values'])), ',') + \rtrim(\str_repeat('?,', \count($operation['values'])), ',') ); return $this; @@ -193,8 +191,8 @@ protected function getFilterForInList($operation) */ protected function getFilterForLike($operation) { - $this->parameter[] = str_replace(array('*', '?'), array('%', '_'), $operation['value']); - $this->procedures[] = sprintf('(%s%s LIKE ?)', $this->tableAlias, $operation['property']); + $this->parameter[] = \str_replace(array('*', '?'), array('%', '_'), $operation['value']); + $this->procedures[] = \sprintf('(%s%s LIKE ?)', $this->tableAlias, $operation['property']); return $this; } @@ -210,11 +208,7 @@ protected function getFilterForLike($operation) */ public function addChild($child) { - if (!\is_array($child)) { - throw new \RuntimeException('Error Processing sub filter: ' . var_export($child, true), 1); - } - - switch (strtoupper($child['operation'])) { + switch (\strtoupper($child['operation'])) { case '=': case '>': case '<': @@ -229,7 +223,7 @@ public function addChild($child) default: } - throw new \RuntimeException('Error processing filter array ' . var_export($child, true), 1); + throw new \RuntimeException('Error processing filter array ' . \var_export($child, true), 1); } /** @@ -242,7 +236,7 @@ public function addChild($child) public function addSubProcedure(FilterBuilderSql $subProcedure) { $this->procedures[] = $subProcedure->getProcedure(); - $this->parameter = array_merge($this->parameter, $subProcedure->getParameters()); + $this->parameter = \array_merge($this->parameter, $subProcedure->getParameters()); return $this; } @@ -250,7 +244,7 @@ public function addSubProcedure(FilterBuilderSql $subProcedure) /** * Sanitize the connection value * - * @param Connection|\Contao\Database $connection The connection value. + * @param \Contao\Database|Connection|null $connection The connection value. * * @return Connection * @@ -258,7 +252,7 @@ public function addSubProcedure(FilterBuilderSql $subProcedure) * * @deprecated To be removed in 3.0 - you should ALWAYS pass the proper connection. */ - private function sanitizeConnection($connection) + private function sanitizeConnection(Connection|Database|null $connection): Connection { if ($connection instanceof Connection) { return $connection; @@ -275,8 +269,10 @@ private function sanitizeConnection($connection) ); $reflection = new \ReflectionProperty(Database::class, 'resConnection'); $reflection->setAccessible(true); + return $reflection->getValue($connection); } + if (null === $connection) { @trigger_error( 'You should pass a doctrine database connection to "' . __METHOD__ . '".', diff --git a/src/DcGeneral/Data/Model.php b/src/DcGeneral/Data/Model.php index 87c96eb7c..1b267cd30 100644 --- a/src/DcGeneral/Data/Model.php +++ b/src/DcGeneral/Data/Model.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @author Christian Schiffler * @author Stefan Heimes * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +26,7 @@ use ContaoCommunityAlliance\DcGeneral\Data\PropertyValueBagInterface; use ContaoCommunityAlliance\DcGeneral\Exception\DcGeneralInvalidArgumentException; use ContaoCommunityAlliance\DcGeneral\Exception\DcGeneralInvalidPropertyValueException; +use MetaModels\Attribute\IAttribute; use MetaModels\Exceptions\DifferentValuesException; use MetaModels\IItem; use MetaModels\ITranslatedMetaModel; @@ -34,11 +36,10 @@ */ class Model implements ModelInterface { - /** * The MetaModel item accessible via this instance. * - * @var IItem + * @var IItem|null */ protected $objItem = null; @@ -47,7 +48,7 @@ class Model implements ModelInterface * * @var array */ - protected $arrMetaInformation = array(); + protected $arrMetaInformation = []; /** * The language of the contained data. @@ -63,20 +64,23 @@ class Model implements ModelInterface */ protected function getPropertyNames() { - $propertyNames = array('id', 'pid', 'tstamp', 'sorting'); + $propertyNames = ['id', 'pid', 'tstamp', 'sorting']; + + $item = $this->getItem(); + assert($item instanceof IItem); - if ($this->getItem()->getMetaModel()->hasVariants()) { + if ($item->getMetaModel()->hasVariants()) { $propertyNames[] = 'varbase'; $propertyNames[] = 'vargroup'; } - return array_merge($propertyNames, array_keys($this->getItem()->getMetaModel()->getAttributes())); + return \array_merge($propertyNames, \array_keys($item->getMetaModel()->getAttributes())); } /** * Returns the native IMetaModelItem instance encapsulated within this abstraction. * - * @return IItem + * @return IItem|null */ public function getItem() { @@ -99,7 +103,9 @@ public function __construct($objItem, ?string $language = null) */ public function __clone() { - $this->objItem = $this->getItem()->copy(); + $item = $this->getItem(); + assert($item instanceof IItem); + $this->objItem = $item->copy(); } /** @@ -107,24 +113,28 @@ public function __clone() */ public function getId() { - return $this->getItem()->get('id'); + $item = $this->getItem(); + assert($item instanceof IItem); + + return $item->get('id'); } /** * {@inheritDoc} */ - public function getProperty($strPropertyName) + public function getProperty($propertyName) { - if ($this->getItem()) { - $varValue = $this->getItem()->get($strPropertyName); + if (null !== ($item = $this->getItem())) { + $varValue = $item->get($propertyName); // Test if it is an attribute, if so, let it transform the data for the widget. - $objAttribute = $this->getItem()->getAttribute($strPropertyName); + $objAttribute = $item->getAttribute($propertyName); if ($objAttribute) { $varValue = $objAttribute->valueToWidget($varValue); } return $varValue; } + return null; } @@ -133,11 +143,12 @@ public function getProperty($strPropertyName) */ public function getPropertiesAsArray() { - $arrResult = array(); + $arrResult = []; foreach ($this->getPropertyNames() as $strKey) { $arrResult[$strKey] = $this->getProperty($strKey); } + return $arrResult; } @@ -146,19 +157,22 @@ public function getPropertiesAsArray() */ public function getMeta($strMetaName) { - if (array_key_exists($strMetaName, $this->arrMetaInformation)) { + if (\array_key_exists($strMetaName, $this->arrMetaInformation)) { return $this->arrMetaInformation[$strMetaName]; } + return null; } /** * {@inheritDoc} */ - public function setId($mixID) + public function setId($mixId) { - if ($this->getId() == null) { - $this->getItem()->set('id', $mixID); + if ($this->getId() === null) { + $item = $this->getItem(); + assert($item instanceof IItem); + $item->set('id', $mixId); $this->setMeta(static::IS_CHANGED, true); } } @@ -173,38 +187,40 @@ public function setId($mixID) */ public function setProperty($strPropertyName, $varValue) { - if ($this->getItem()) { + if (null !== ($item = $this->getItem())) { $varInternalValue = $varValue; // Test if it is an attribute, if so, let it transform the data for the widget. - $objAttribute = $this->getItem()->getAttribute($strPropertyName); + $objAttribute = $item->getAttribute($strPropertyName); - if ($objAttribute) { + if (null !== $objAttribute) { $model = $objAttribute->getMetaModel(); $originalLanguage = null; + /** @psalm-suppress DeprecatedMethod */ if (null !== $this->language) { if ($model instanceof ITranslatedMetaModel) { $originalLanguage = $model->selectLanguage($this->language); + /** @psalm-suppress DeprecatedMethod */ } elseif ($model->isTranslated()) { $originalLanguage = $GLOBALS['TL_LANGUAGE']; $GLOBALS['TL_LANGUAGE'] = $this->language; } } - $varInternalValue = $objAttribute->widgetToValue($varValue, $this->getItem()->get('id')); + $varInternalValue = $objAttribute->widgetToValue($varValue, $item->get('id')); } try { if ($varValue !== $this->getProperty($strPropertyName)) { $this->setMeta(static::IS_CHANGED, true); - $this->getItem()->set($strPropertyName, $varInternalValue); + $item->set($strPropertyName, $varInternalValue); try { DifferentValuesException::compare($varValue, $this->getProperty($strPropertyName), false); } catch (DifferentValuesException $exception) { throw new DcGeneralInvalidPropertyValueException( - sprintf( + \sprintf( 'Property %s (%s) did not accept the value (%s).', $strPropertyName, - $objAttribute->get('type'), + $objAttribute ? ((string) $objAttribute->get('type')) : '?', $exception->getLongMessage() ), 1, @@ -227,9 +243,9 @@ public function setProperty($strPropertyName, $varValue) /** * {@inheritDoc} */ - public function setPropertiesAsArray($arrProperties) + public function setPropertiesAsArray($properties) { - foreach ($arrProperties as $strKey => $varValue) { + foreach ($properties as $strKey => $varValue) { $this->setProperty($strKey, $varValue); } } @@ -247,12 +263,15 @@ public function setMeta($strMetaName, $varValue) */ public function hasProperties() { - return ($this->getItem()) ? true : false; + return (bool) $this->getItem(); } /** * {@inheritDoc} + * + * @return \Traversable */ + #[\ReturnTypeWillChange] public function getIterator() { return new ModelIterator($this); @@ -263,7 +282,10 @@ public function getIterator() */ public function getProviderName() { - return $this->getItem()->getMetaModel()->getTableName(); + $item = $this->getItem(); + assert($item instanceof IItem); + + return $item->getMetaModel()->getTableName(); } /** @@ -284,6 +306,8 @@ public function readFromPropertyValueBag(PropertyValueBagInterface $valueBag) $this->setProperty($property, $valueBag->getPropertyValue($property)); } + + return $this; } /** @@ -298,5 +322,7 @@ public function writeToPropertyValueBag(PropertyValueBagInterface $valueBag) $valueBag->setPropertyValue($property, $this->getProperty($property)); } + + return $this; } } diff --git a/src/DcGeneral/Data/ModelIterator.php b/src/DcGeneral/Data/ModelIterator.php index 7d4b0b86f..dcb10bf1e 100644 --- a/src/DcGeneral/Data/ModelIterator.php +++ b/src/DcGeneral/Data/ModelIterator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,23 +13,28 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\DcGeneral\Data; +use MetaModels\IItem; + /** * Iterator class for allowing usage of MetaModels\DcGeneral\Data\Model * in foreach constructs. + * + * @implements \Iterator */ class ModelIterator implements \Iterator { /** * The model to iterate over. * - * @var Model + * @var Model|null */ protected $objModel = null; @@ -38,14 +43,14 @@ class ModelIterator implements \Iterator * * @var int */ - private $intPosition = 0; + private int $intPosition = 0; /** * All property names. * * @var string[] */ - protected $arrKeys = array(); + protected $arrKeys = []; /** * Returns an array containing all property names. @@ -66,14 +71,16 @@ public function __construct(Model $objModel) { $this->intPosition = 0; $this->objModel = $objModel; - $objMetaModel = $this->objModel->getItem()->getMetaModel(); + $item = $this->objModel->getItem(); + assert($item instanceof IItem); + $objMetaModel = $item->getMetaModel(); - $arrKeys = array(); + $arrKeys = []; if ($objMetaModel->hasVariants()) { $arrKeys[] = 'varbase'; $arrKeys[] = 'vargroup'; } - $this->arrKeys = array_merge($arrKeys, array_keys($objMetaModel->getAttributes())); + $this->arrKeys = \array_merge($arrKeys, \array_keys($objMetaModel->getAttributes())); } /** @@ -81,7 +88,7 @@ public function __construct(Model $objModel) * * @return void */ - public function rewind() + public function rewind(): void { $this->intPosition = 0; } @@ -91,9 +98,12 @@ public function rewind() * * @return mixed */ - public function current() + public function current(): mixed { - return $this->objModel->getProperty($this->key()); + $model = $this->objModel; + assert($model instanceof Model); + + return $model->getProperty($this->key()); } /** @@ -101,9 +111,10 @@ public function current() * * @return string */ - public function key() + public function key(): string { $arrKeys = $this->getKeys(); + return $arrKeys[$this->intPosition]; } @@ -112,7 +123,7 @@ public function key() * * @return void */ - public function next() + public function next(): void { ++$this->intPosition; } @@ -122,8 +133,8 @@ public function next() * * @return bool */ - public function valid() + public function valid(): bool { - return strlen($this->key()) > 0; + return \strlen($this->key()) > 0; } } diff --git a/src/DcGeneral/DataDefinition/Definition/IMetaModelDefinition.php b/src/DcGeneral/DataDefinition/Definition/IMetaModelDefinition.php index f28d19ac7..2cd7d27b5 100644 --- a/src/DcGeneral/DataDefinition/Definition/IMetaModelDefinition.php +++ b/src/DcGeneral/DataDefinition/Definition/IMetaModelDefinition.php @@ -30,7 +30,7 @@ interface IMetaModelDefinition extends DefinitionInterface /** * The name of the definition. */ - const NAME = 'metamodels'; + public const NAME = 'metamodels'; /** * Set the id of the active render setting for the MetaModel. diff --git a/src/DcGeneral/DataDefinition/Definition/MetaModelDefinition.php b/src/DcGeneral/DataDefinition/Definition/MetaModelDefinition.php index a1506f765..78f3f29ee 100644 --- a/src/DcGeneral/DataDefinition/Definition/MetaModelDefinition.php +++ b/src/DcGeneral/DataDefinition/Definition/MetaModelDefinition.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,6 +23,8 @@ /** * Default implementation of IMetaModelDefinition. + * + * @psalm-suppress MissingConstructor */ class MetaModelDefinition implements IMetaModelDefinition { diff --git a/src/DcGeneral/DataDefinition/MetaModelDataDefinition.php b/src/DcGeneral/DataDefinition/MetaModelDataDefinition.php index f1330f716..dd23bdb13 100644 --- a/src/DcGeneral/DataDefinition/MetaModelDataDefinition.php +++ b/src/DcGeneral/DataDefinition/MetaModelDataDefinition.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -51,6 +52,9 @@ public function hasMetaModelDefinition() */ public function getMetaModelDefinition() { - return $this->getDefinition(IMetaModelDefinition::NAME); + $definition = $this->getDefinition(IMetaModelDefinition::NAME); + assert($definition instanceof IMetaModelDefinition); + + return $definition; } } diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php b/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php index b5eb05d05..9d36ed815 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Palette/RenderSettingAttributeIs.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author David Molineus * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -29,6 +29,7 @@ use ContaoCommunityAlliance\DcGeneral\Data\PropertyValueBag; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Palette\AbstractWeightAwarePaletteCondition; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use MetaModels\IMetaModelsServiceContainer; use MetaModels\MetaModelsServiceContainer; @@ -49,20 +50,19 @@ class RenderSettingAttributeIs extends AbstractWeightAwarePaletteCondition * * @var array */ - protected static $attributeTypes = array(); + protected static $attributeTypes = []; /** * Database connection. * * @var Connection */ - private $connection; + private Connection $connection; /** * Create a new instance. * * @param string $attributeType The attribute type name. - * * @param int $weight The weight of this condition to apply. * * @param Connection|null $connection Database connection. @@ -80,8 +80,8 @@ public function __construct($attributeType, $weight = 1, Connection $connection ); // @codingStandardsIgnoreEnd $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); } - $this->connection = $connection; } @@ -116,7 +116,7 @@ public function getAttributeType() * * @return string * - * @throws \Doctrine\DBAL\DBALException When an database error occurs. + * @throws Exception When an database error occurs. */ public function getTypeOfAttribute($value) { @@ -131,7 +131,11 @@ public function getTypeOfAttribute($value) ->setMaxResults(1) ->executeQuery(); - self::$attributeTypes[$value] = $statement->fetchAssociative()['type']; + if (false === ($result = $statement->fetchAssociative())) { + return new Exception('Failed to load attribute for render setting.'); + } + + self::$attributeTypes[$value] = $result['type']; } return self::$attributeTypes[$value]; @@ -171,9 +175,15 @@ public function __clone() * @return IMetaModelsServiceContainer * * @deprecated + * + * @psalm-suppress DeprecatedInterface + * @psalm-suppress DeprecatedClass */ protected function getServiceContainer(): IMetaModelsServiceContainer { - return System::getContainer()->get(MetaModelsServiceContainer::class); + $serviceContainer = System::getContainer()->get(MetaModelsServiceContainer::class); + assert($serviceContainer instanceof IMetaModelsServiceContainer); + + return $serviceContainer; } } diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php index 9d8a5c13a..5c2828bce 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/AttributeByIdIsOfType.php @@ -120,9 +120,9 @@ public function getTypeOfAttribute($value) ->executeQuery(); $result = $statement->fetchFirstColumn(); - if(count($result) > 0){ + if (count($result) > 0) { self::$attributeTypes[$value] = \current($result); - }else { + } else { self::$attributeTypes[$value] = null; } } diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/ConditionTableNameIsMetaModel.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/ConditionTableNameIsMetaModel.php index 0f89d8fdb..c98c8ef48 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/ConditionTableNameIsMetaModel.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/ConditionTableNameIsMetaModel.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,7 +33,7 @@ class ConditionTableNameIsMetaModel implements PropertyConditionInterface { /** - * The name of the property in the passed model which contains the table name. + * The name of the property in the past model which contains the table name. * * @var string */ @@ -48,9 +49,8 @@ class ConditionTableNameIsMetaModel implements PropertyConditionInterface /** * Create a new instance. * - * @param string $tableProperty The name of the property in the passed model which contains the table name. - * - * @param string $desiredValue The desired value, true if the table shall be a MetaModel, false otherwise. + * @param string $tableProperty The name of the property in the past model which contains the table name. + * @param bool $desiredValue The desired value, true if the table shall be a MetaModel, false otherwise. */ public function __construct($tableProperty, $desiredValue) { @@ -97,7 +97,7 @@ public function setTablePropertyName($tablePropertyName) } /** - * Retrieve the name of the property in the passed model which contains the table name. + * Retrieve the name of the property in the past model which contains the table name. * * @return string */ @@ -124,7 +124,7 @@ public function match( return false; } - return $this->desiredValue == (substr($value, 0, 3) === 'mm_'); + return $this->desiredValue == (\str_starts_with($value, 'mm_')); } /** diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenAttributeIs.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenAttributeIs.php index 82f0c7e22..f5c18fab7 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenAttributeIs.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenAttributeIs.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,8 @@ * @author Cliff Parnitzky * @author David Molineus * @author Richard Henkenjohann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -58,6 +59,7 @@ public function __construct($attributeType, Connection $connection = null) ); // @codingStandardsIgnoreEnd $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); } parent::__construct($attributeType, $connection, 'attr_id'); @@ -69,9 +71,15 @@ public function __construct($attributeType, Connection $connection = null) * @return IMetaModelsServiceContainer * * @deprecated + * + * @psalm-suppress DeprecatedInterface */ protected function getServiceContainer(): IMetaModelsServiceContainer { - return System::getContainer()->get(MetaModelsServiceContainer::class); + /** @psalm-suppress DeprecatedClass */ + $serviceContainer = System::getContainer()->get(MetaModelsServiceContainer::class); + assert($serviceContainer instanceof IMetaModelsServiceContainer); + + return $serviceContainer; } } diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenRenderModeIs.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenRenderModeIs.php index 4af54864d..ca107c733 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenRenderModeIs.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/InputScreenRenderModeIs.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author David Molineus * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -31,11 +31,14 @@ use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\LegendInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\PropertyInterface; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use MetaModels\IMetaModelsServiceContainer; use MetaModels\MetaModelsServiceContainer; /** * Condition for the default palette. + * + * @psalm-suppress PropertyNotSetInConstructor */ class InputScreenRenderModeIs implements PropertyConditionInterface { @@ -58,13 +61,12 @@ class InputScreenRenderModeIs implements PropertyConditionInterface * * @var Connection */ - private $connection; + private Connection $connection; /** * Create a new instance. * * @param string $desiredState The desired state. - * * @param Connection|null $connection Database connection. */ public function __construct($desiredState, Connection $connection = null) @@ -79,8 +81,8 @@ public function __construct($desiredState, Connection $connection = null) ); // @codingStandardsIgnoreEnd $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); } - $this->connection = $connection; } @@ -115,12 +117,12 @@ public function getRenderMode() * * @return string * - * @throws \Doctrine\DBAL\Exception + * @throws Exception */ public function getInputScreenRenderMode($value) { if (!isset(self::$stateBuffer[$value])) { - $statement =$this->connection + $statement = $this->connection ->createQueryBuilder() ->select('t.rendermode') ->from('tl_metamodel_dca', 't') @@ -129,7 +131,11 @@ public function getInputScreenRenderMode($value) ->setMaxResults(1) ->executeQuery(); - self::$stateBuffer[$value] = $statement->fetchAssociative()['rendermode']; + if (false === ($result = $statement->fetchAssociative())) { + return new Exception('Failed to load attribute for input screen setting.'); + } + + self::$stateBuffer[$value] = $result['rendermode']; } return self::$stateBuffer[$value]; @@ -168,9 +174,15 @@ public function __clone() * @return IMetaModelsServiceContainer * * @deprecated + * + * @psalm-suppress DeprecatedInterface */ protected function getServiceContainer(): IMetaModelsServiceContainer { - return System::getContainer()->get(MetaModelsServiceContainer::class); + /** @psalm-suppress DeprecatedClass */ + $serviceContainer = System::getContainer()->get(MetaModelsServiceContainer::class); + assert($serviceContainer instanceof IMetaModelsServiceContainer); + + return $serviceContainer; } } diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/IsVariantAttribute.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/IsVariantAttribute.php index 91894aaed..dabcfa60f 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/IsVariantAttribute.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/IsVariantAttribute.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Stefan Heimes * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -27,9 +27,11 @@ use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Condition\Property\PropertyConditionInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\LegendInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\PropertyInterface; +use MetaModels\DcGeneral\Data\Model; +use MetaModels\IItem; /** - * This condition matches as soon as all of the following apply: + * This condition matches as soon as all the following apply: * 1. the MetaModel supports variants. * 2. the current item is not a variant base. * 3. the attribute is not an invariant attribute. @@ -45,17 +47,15 @@ public function match( PropertyInterface $property = null, LegendInterface $legend = null ) { - if ($property === null || $model === null) { + if ($property === null || !($model instanceof Model)) { return false; } - - /** @var $model \MetaModels\DcGeneral\Data\Model */ - $nativeItem = $model->getItem(); - $metaModel = $nativeItem->getMetaModel(); + assert($nativeItem instanceof IItem); + $metaModel = $nativeItem->getMetaModel(); if ($metaModel->hasVariants() && !$nativeItem->isVariantBase()) { - return !in_array($property->getName(), array_keys($metaModel->getInVariantAttributes())); + return !\in_array($property->getName(), \array_keys($metaModel->getInVariantAttributes())); } return true; diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/PropertyContainAnyOfCondition.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/PropertyContainAnyOfCondition.php index b8e8b36ff..10c21b6b9 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/PropertyContainAnyOfCondition.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/PropertyContainAnyOfCondition.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Sven Baumann * @author Stefan Heimes * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -75,9 +75,9 @@ class PropertyContainAnyOfCondition implements PropertyConditionInterface */ public function __construct($propertyName = '', $propertyValue = null, $strict = false) { - $this->propertyName = (string) $propertyName; + $this->propertyName = $propertyName; $this->propertyValue = $propertyValue; - $this->strict = (bool) $strict; + $this->strict = $strict; $this->metaModel = null; } @@ -110,7 +110,7 @@ public function setMetaModel(IMetaModel $metaModel): void */ public function setPropertyName($propertyName) { - $this->propertyName = (string) $propertyName; + $this->propertyName = $propertyName; return $this; } @@ -156,7 +156,7 @@ public function getPropertyValue() */ public function setStrict($strict) { - $this->strict = (bool) $strict; + $this->strict = $strict; return $this; } @@ -184,12 +184,15 @@ public function match( PropertyInterface $property = null, LegendInterface $legend = null ) { - $attribute = $this->metaModel->getAttribute($this->propertyName); - + assert($this->metaModel instanceof IMetaModel); if ($this->metaModel instanceof ITranslatedMetaModel) { $currentLanguage = $this->metaModel->getLanguage(); } else { - $currentLanguage = $this->metaModel->getActiveLanguage(); + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ + $currentLanguage = $this->metaModel->isTranslated(false) ? $this->metaModel->getActiveLanguage() : ''; } if ($input && $input->hasPropertyValue($this->propertyName)) { @@ -211,6 +214,7 @@ public function match( return false; } + $attribute = $this->metaModel->getAttribute($this->propertyName); foreach ($values as $value) { if ($value && $attribute instanceof IAliasConverter) { $value = ($attribute->getIdForAlias($value, $currentLanguage) ?? $value); diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/PropertyValueCondition.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/PropertyValueCondition.php index 529e4143c..06538caa8 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/PropertyValueCondition.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/PropertyValueCondition.php @@ -140,6 +140,7 @@ public function match( if ($this->metaModel instanceof ITranslatedMetaModel) { $currentLanguage = $this->metaModel->getLanguage(); } else { + /** @psalm-suppress DeprecatedMethod */ $currentLanguage = $this->metaModel->getActiveLanguage(); } diff --git a/src/DcGeneral/DataDefinition/Palette/Condition/Property/RenderSettingAttributeIs.php b/src/DcGeneral/DataDefinition/Palette/Condition/Property/RenderSettingAttributeIs.php index 5e267c54d..520f2b194 100644 --- a/src/DcGeneral/DataDefinition/Palette/Condition/Property/RenderSettingAttributeIs.php +++ b/src/DcGeneral/DataDefinition/Palette/Condition/Property/RenderSettingAttributeIs.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,8 @@ * @author Cliff Parnitzky * @author David Molineus * @author Richard Henkenjohann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -58,6 +59,7 @@ public function __construct($attributeType, Connection $connection = null) ); // @codingStandardsIgnoreEnd $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); } parent::__construct($attributeType, $connection, 'attr_id'); @@ -69,9 +71,15 @@ public function __construct($attributeType, Connection $connection = null) * @return IMetaModelsServiceContainer * * @deprecated + * + * @psalm-suppress DeprecatedInterface */ protected function getServiceContainer(): IMetaModelsServiceContainer { - return System::getContainer()->get(MetaModelsServiceContainer::class); + /** @psalm-suppress DeprecatedClass */ + $serviceContainer = System::getContainer()->get(MetaModelsServiceContainer::class); + assert($serviceContainer instanceof IMetaModelsServiceContainer); + + return $serviceContainer; } } diff --git a/src/DcGeneral/Events/BaseSubscriber.php b/src/DcGeneral/Events/BaseSubscriber.php index 2799efc96..86e313fa2 100644 --- a/src/DcGeneral/Events/BaseSubscriber.php +++ b/src/DcGeneral/Events/BaseSubscriber.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -34,6 +35,8 @@ class BaseSubscriber * The MetaModel service container. * * @var IMetaModelsServiceContainer + * + * @psalm-suppress DeprecatedInterface */ protected $serviceContainer; @@ -41,6 +44,8 @@ class BaseSubscriber * Create a new instance. * * @param IMetaModelsServiceContainer $serviceContainer The MetaModel service container. + * + * @psalm-suppress DeprecatedInterface */ public function __construct(IMetaModelsServiceContainer $serviceContainer) { @@ -53,6 +58,8 @@ public function __construct(IMetaModelsServiceContainer $serviceContainer) * Retrieve the service container. * * @return IMetaModelsServiceContainer + * + * @psalm-suppress DeprecatedInterface */ protected function getServiceContainer() { @@ -66,6 +73,7 @@ protected function getServiceContainer() */ protected function getDatabase() { + /** @psalm-suppress DeprecatedMethod */ return $this->getServiceContainer()->getDatabase(); } @@ -83,15 +91,14 @@ protected function registerEventsInDispatcher() * Register multiple event listeners. * * @param string $eventName The event name to register. - * * @param callable $listener The listener to register. - * * @param int $priority The priority. * * @return BaseSubscriber */ public function addListener($eventName, $listener, $priority = 200) { + /** @psalm-suppress DeprecatedMethod */ $dispatcher = $this->getServiceContainer()->getEventDispatcher(); $dispatcher->addListener($eventName, $listener, $priority); @@ -101,13 +108,14 @@ public function addListener($eventName, $listener, $priority = 200) /** * Retrieve the MetaModel with the given id. * - * @param int $modelId The model being processed. + * @param string $modelId The model being processed. * - * @return IMetaModel + * @return IMetaModel|null */ protected function getMetaModelById($modelId) { - $services = $this->getServiceContainer(); + $services = $this->getServiceContainer(); + /** @psalm-suppress DeprecatedMethod */ $modelFactory = $services->getFactory(); $name = $modelFactory->translateIdToMetaModelName($modelId); diff --git a/src/DcGeneral/Events/MetaModel/BuildAttributeEvent.php b/src/DcGeneral/Events/MetaModel/BuildAttributeEvent.php index 541587e96..96e2a7392 100644 --- a/src/DcGeneral/Events/MetaModel/BuildAttributeEvent.php +++ b/src/DcGeneral/Events/MetaModel/BuildAttributeEvent.php @@ -33,7 +33,7 @@ class BuildAttributeEvent extends AbstractContainerAwareEvent /** * The event name. */ - const NAME = 'metamodels.dc-general.events.metamodel.build.attribute'; + public const NAME = 'metamodels.dc-general.events.metamodel.build.attribute'; /** * The Attribute. diff --git a/src/DcGeneral/Events/MetaModel/BuildMetaModelOperationsEvent.php b/src/DcGeneral/Events/MetaModel/BuildMetaModelOperationsEvent.php index 6757c104d..dc37767e7 100644 --- a/src/DcGeneral/Events/MetaModel/BuildMetaModelOperationsEvent.php +++ b/src/DcGeneral/Events/MetaModel/BuildMetaModelOperationsEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,18 +13,21 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\DcGeneral\Events\MetaModel; +use Contao\System; use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\Event\AbstractContainerAwareEvent; use MetaModels\BackendIntegration\InputScreen\IInputScreen; use MetaModels\BackendIntegration\InputScreen\InputScreen; use MetaModels\IMetaModel; +use MetaModels\IMetaModelsServiceContainer; /** * This event is triggered to allow adding of model operations for MetaModels when the data container is being built. @@ -34,7 +37,7 @@ class BuildMetaModelOperationsEvent extends AbstractContainerAwareEvent /** * The event name. */ - const NAME = 'metamodels.dc-general.events.metamodel.build.metamodel.operations'; + public const NAME = 'metamodels.dc-general.events.metamodel.build.metamodel.operations'; /** * The MetaModel instance. @@ -54,9 +57,7 @@ class BuildMetaModelOperationsEvent extends AbstractContainerAwareEvent * Create a new container aware event. * * @param IMetaModel $metaModel The MetaModel. - * * @param ContainerInterface $dataContainer The data container information. - * * @param array $inputScreen The input screen in use. */ public function __construct( @@ -96,11 +97,17 @@ public function getScreen() * @return IInputScreen * * @deprecated The InputScreen class will get removed. + * + * @psalm-suppress DeprecatedInterface + * @psalm-suppress DeprecatedClass */ public function getInputScreen() { + $serviceContainer = System::getContainer()->get('cca.legacy_dic')?->getService('metamodels-service-container'); + assert($serviceContainer instanceof IMetaModelsServiceContainer); + return new InputScreen( - \System::getContainer()->get('cca.legacy_dic')->getService('metamodels-service-container'), + $serviceContainer, $this->inputScreen['meta'], $this->inputScreen['properties'], $this->inputScreen['conditions'], diff --git a/src/DcGeneral/Events/MetaModel/DuplicateModel.php b/src/DcGeneral/Events/MetaModel/DuplicateModel.php index 60bb8cba7..501c9d6e3 100644 --- a/src/DcGeneral/Events/MetaModel/DuplicateModel.php +++ b/src/DcGeneral/Events/MetaModel/DuplicateModel.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author Stefan Heimes * @author Christopher Boelter * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,6 +25,7 @@ use ContaoCommunityAlliance\DcGeneral\Event\PreDuplicateModelEvent; use MetaModels\IFactory; +use MetaModels\IMetaModel; /** * This class handles the paste into or after handling for variants. @@ -35,7 +37,7 @@ class DuplicateModel * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Create a new instance. @@ -59,8 +61,9 @@ public function handle(PreDuplicateModelEvent $event) $model = $event->getModel(); $metaModel = $this->factory->getMetaModel($model->getProviderName()); + assert($metaModel instanceof IMetaModel); - if (!$metaModel || !$metaModel->hasVariants()) { + if (!$metaModel->hasVariants()) { return; } diff --git a/src/DcGeneral/Events/MetaModel/PopulateAttributeEvent.php b/src/DcGeneral/Events/MetaModel/PopulateAttributeEvent.php index fe833f5fe..96bd13718 100644 --- a/src/DcGeneral/Events/MetaModel/PopulateAttributeEvent.php +++ b/src/DcGeneral/Events/MetaModel/PopulateAttributeEvent.php @@ -33,7 +33,7 @@ class PopulateAttributeEvent extends AbstractEnvironmentAwareEvent /** * The event name. */ - const NAME = 'metamodels.dc-general.events.metamodel.populate.attribute'; + public const NAME = 'metamodels.dc-general.events.metamodel.populate.attribute'; /** * The Attribute. diff --git a/src/DcGeneral/Events/MetaModel/PropertyOptionsProvider.php b/src/DcGeneral/Events/MetaModel/PropertyOptionsProvider.php index 57b73331a..1e5dbf53b 100644 --- a/src/DcGeneral/Events/MetaModel/PropertyOptionsProvider.php +++ b/src/DcGeneral/Events/MetaModel/PropertyOptionsProvider.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +24,7 @@ use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; use MetaModels\Attribute\IAttribute; use MetaModels\DcGeneral\Data\Model; +use MetaModels\IItem; /** * This class retrieves the options of an attribute within a MetaModel unless someone else already provided them. @@ -45,7 +47,14 @@ public static function getPropertyOptions(GetPropertyOptionsEvent $event) if (!($model instanceof Model)) { return; } - $attribute = $model->getItem()->getAttribute($event->getPropertyName()); + + $propertyName = $event->getPropertyName(); + assert(\is_string($propertyName)); + + $item = $model->getItem(); + assert($item instanceof IItem); + + $attribute = $item->getAttribute($propertyName); if (!($attribute instanceof IAttribute)) { return; } @@ -53,7 +62,7 @@ public static function getPropertyOptions(GetPropertyOptionsEvent $event) try { $options = $attribute->getFilterOptions(null, false); } catch (\Exception $exception) { - $options = array('Error: ' . $exception->getMessage()); + $options = ['Error: ' . $exception->getMessage()]; } $event->setOptions($options); diff --git a/src/DcGeneral/Events/Table/FilterSetting/FilterSettingTypeRenderer.php b/src/DcGeneral/Events/Table/FilterSetting/FilterSettingTypeRenderer.php index 1f098c49e..f8d92fc75 100644 --- a/src/DcGeneral/Events/Table/FilterSetting/FilterSettingTypeRenderer.php +++ b/src/DcGeneral/Events/Table/FilterSetting/FilterSettingTypeRenderer.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,14 +13,18 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\DcGeneral\Events\Table\FilterSetting; +use Contao\System; +use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\ModelToLabelEvent; +use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\CoreBundle\EventListener\DcGeneral\Table\FilterSetting\AbstractFilterSettingTypeRenderer; use MetaModels\IMetaModelsServiceContainer; @@ -36,27 +40,37 @@ abstract class FilterSettingTypeRenderer extends AbstractFilterSettingTypeRender * The MetaModel service container. * * @var IMetaModelsServiceContainer + * + * @psalm-suppress DeprecatedInterface */ - private $serviceContainer; + private IMetaModelsServiceContainer $serviceContainer; /** * Create a new instance. * * @param IMetaModelsServiceContainer $serviceContainer The MetaModel service container. + * + * @psalm-suppress DeprecatedInterface + * @psalm-suppress DeprecatedMethod */ public function __construct(IMetaModelsServiceContainer $serviceContainer) { $this->serviceContainer = $serviceContainer; + $iconBuilder = System::getContainer()->get('metamodels.assets.icon_builder'); + assert($iconBuilder instanceof IconBuilder); + $scopeMatcher = System::getContainer()->get('cca.dc-general.scope-matcher'); + assert($scopeMatcher instanceof RequestScopeDeterminator); + parent::__construct( $serviceContainer->getFilterFactory(), $serviceContainer->getEventDispatcher(), - \System::getContainer()->get('metamodels.assets.icon_builder'), - \System::getContainer()->get('cca.dc-general.scope-matcher') + $iconBuilder, + $scopeMatcher ); $this->getServiceContainer()->getEventDispatcher()->addListener( ModelToLabelEvent::NAME, - array($this, 'modelToLabel') + [$this, 'modelToLabel'] ); } @@ -64,6 +78,8 @@ public function __construct(IMetaModelsServiceContainer $serviceContainer) * Retrieve the service container. * * @return IMetaModelsServiceContainer + * + * @psalm-suppress DeprecatedInterface */ protected function getServiceContainer() { diff --git a/src/Dca/Helper.php b/src/Dca/Helper.php index 6473610dc..e4ff6551a 100644 --- a/src/Dca/Helper.php +++ b/src/Dca/Helper.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -19,14 +19,16 @@ * @author Cliff Parnitzky * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\Dca; +use Contao\Folder; use Contao\StringUtil; +use Contao\System; use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\Properties\PropertyInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\Translator\TranslatorInterface; @@ -49,6 +51,10 @@ class Helper public static function decodeLangArray($varValue, IMetaModel $metaModel) { $arrLangValues = StringUtil::deserialize($varValue); + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { // If we have an array, return the first value and exit, if not an array, return the value itself. return \is_array($arrLangValues) @@ -57,10 +63,11 @@ public static function decodeLangArray($varValue, IMetaModel $metaModel) } // Sort like in MetaModel definition. + /** @psalm-suppress DeprecatedMethod */ $arrLanguages = $metaModel->getAvailableLanguages(); $arrOutput = []; - if ($arrLanguages) { + if (null !== $arrLanguages) { foreach ($arrLanguages as $strLangCode) { if (\is_array($arrLangValues)) { $varSubValue = $arrLangValues[$strLangCode] ?? ''; @@ -75,6 +82,7 @@ public static function decodeLangArray($varValue, IMetaModel $metaModel) } } } + return \serialize($arrOutput); } @@ -84,34 +92,39 @@ public static function decodeLangArray($varValue, IMetaModel $metaModel) * @param array|string $varValue The value to decode. * @param IMetaModel $metaModel The MetaModel holding the languages. * - * @return string + * @return string|array */ public static function encodeLangArray($varValue, IMetaModel $metaModel) { // Not translated, make it a plain string. + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { return $varValue; } + $arrLangValues = StringUtil::deserialize($varValue); $arrOutput = []; foreach ($arrLangValues as $varSubValue) { $strLangCode = $varSubValue['langcode']; unset($varSubValue['langcode']); - if (count($varSubValue) > 1) { + if (\count($varSubValue) > 1) { $arrOutput[$strLangCode] = $varSubValue; } else { - $arrKeys = array_keys($varSubValue); + $arrKeys = \array_keys($varSubValue); $arrOutput[$strLangCode] = $varSubValue[$arrKeys[0]]; } } - return serialize($arrOutput); + + return \serialize($arrOutput); } /** * Extract all languages from the MetaModel and return them as array. * * @param IMetaModel $metaModel The MetaModel to extract the languages from. - * * @param TranslatorInterface $translator The translator to use. * * @return \string[] @@ -119,6 +132,7 @@ public static function encodeLangArray($varValue, IMetaModel $metaModel) private static function buildLanguageArray(IMetaModel $metaModel, TranslatorInterface $translator) { $languages = []; + /** @psalm-suppress DeprecatedMethod */ foreach ((array) $metaModel->getAvailableLanguages() as $langCode) { $languages[$langCode] = $translator->translate('LNG.' . $langCode, 'languages'); } @@ -148,6 +162,10 @@ public static function prepareLanguageAwareWidget( $isTextArea, $arrValues ) { + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ if (!($metaModel instanceof ITranslatedMetaModel) && !$metaModel->isTranslated(false)) { $extra = $property->getExtra(); @@ -160,25 +178,30 @@ public static function prepareLanguageAwareWidget( return; } - $fallback = $metaModel->getFallbackLanguage(); - $languages = self::buildLanguageArray($metaModel, $environment->getTranslator()); + /** @psalm-suppress DeprecatedMethod */ + $fallback = $metaModel->getFallbackLanguage(); + + $translator = $environment->getTranslator(); + assert($translator instanceof TranslatorInterface); + + $languages = self::buildLanguageArray($metaModel, $translator); // Ensure we have values for all languages present. - if (array_diff_key($languages, $arrValues)) { - foreach (array_keys($languages) as $langCode) { + if (\array_diff_key($languages, $arrValues)) { + foreach (\array_keys($languages) as $langCode) { $arrValues[$langCode] = ''; } } $rowClasses = []; - foreach (array_keys($arrValues) as $langCode) { + foreach (\array_keys($arrValues) as $langCode) { $rowClasses[] = ($langCode == $fallback) ? 'fallback_language' : 'normal_language'; } $extra = $property->getExtra(); $extra['minCount'] = - $extra['maxCount'] = count($languages); + $extra['maxCount'] = \count($languages); $extra['disableSorting'] = true; $extra['tl_class'] = 'clr w50'; $extra['columnFields'] = [ @@ -214,7 +237,6 @@ public static function prepareLanguageAwareWidget( * Search all files with the given file extension below the given path. * * @param string $folder The folder to scan. - * * @param string $extension The file extension. * * @return array @@ -223,17 +245,19 @@ public static function searchFiles($folder, $extension) { $scanResult = []; $result = []; + $rootDir = System::getContainer()->getParameter('kernel.project_dir'); + assert(\is_string($rootDir)); // Check if we have a file or folder. - if (is_dir(TL_ROOT . '/' . $folder)) { - $scanResult = scan(TL_ROOT . '/' . $folder); + if (\is_dir($rootDir . '/' . $folder)) { + $scanResult = Folder::scan($rootDir . '/' . $folder); } // Run each value. foreach ($scanResult as $value) { - if (!is_file(TL_ROOT . '/' . $folder . '/' . $value)) { + if (!\is_file($rootDir . '/' . $folder . '/' . $value)) { $result += self::searchFiles($folder . '/' . $value, $extension); } else { - if (preg_match('/' . $extension . '$/i', $value)) { + if (\preg_match('/' . $extension . '$/i', $value)) { $result[$folder][$folder . '/' . $value] = $value; } } diff --git a/src/Events/CollectMetaModelTableNamesEvent.php b/src/Events/CollectMetaModelTableNamesEvent.php index 0d442d351..78db11195 100644 --- a/src/Events/CollectMetaModelTableNamesEvent.php +++ b/src/Events/CollectMetaModelTableNamesEvent.php @@ -31,7 +31,7 @@ class CollectMetaModelTableNamesEvent extends Event /** * The event name. */ - const NAME = 'metamodels.metamodel.collect-table-names'; + public const NAME = 'metamodels.metamodel.collect-table-names'; /** * The factory calling the event. diff --git a/src/Events/CreateMetaModelEvent.php b/src/Events/CreateMetaModelEvent.php index 6c134213d..31c56f441 100644 --- a/src/Events/CreateMetaModelEvent.php +++ b/src/Events/CreateMetaModelEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,13 +27,15 @@ /** * This event is triggered for every metamodel when a factory wants to create an instance. + * + * @psalm-suppress PropertyNotSetInConstructor */ class CreateMetaModelEvent extends Event { /** * The event name. */ - const NAME = 'metamodels.metamodel.create'; + public const NAME = 'metamodels.metamodel.create'; /** * The factory calling the event. @@ -51,7 +54,7 @@ class CreateMetaModelEvent extends Event /** * The MetaModel instance being created. * - * @var IMetaModel + * @var IMetaModel|null */ protected $metaModel; @@ -59,7 +62,6 @@ class CreateMetaModelEvent extends Event * Create a new instance. * * @param IFactory $factory The MetaModel factory dispatching this event. - * * @param string $metaModelName The name of the MetaModel to be created. */ public function __construct($factory, $metaModelName) @@ -91,7 +93,7 @@ public function getMetaModelName() /** * Retrieve the MetaModel instance. * - * @return IMetaModel + * @return IMetaModel|null */ public function getMetaModel() { diff --git a/src/Events/CreatePropertyConditionEvent.php b/src/Events/CreatePropertyConditionEvent.php index 1d67df5fa..d33aba011 100644 --- a/src/Events/CreatePropertyConditionEvent.php +++ b/src/Events/CreatePropertyConditionEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -28,10 +29,12 @@ * This event is dispatched, whenever a MetaModels property condition shall be transformed into an object instance. * * @deprecated Implement proper factories and create conditions within there. + * + * @psalm-suppress PropertyNotSetInConstructor */ class CreatePropertyConditionEvent extends Event { - const NAME = 'metamodels.events.create-property-condition-event'; + public const NAME = 'metamodels.events.create-property-condition-event'; /** * The array containing the meta information for the instance. @@ -50,15 +53,14 @@ class CreatePropertyConditionEvent extends Event /** * The instance to be returned. * - * @var PropertyConditionInterface + * @var PropertyConditionInterface|null */ - protected $instance; + protected $instance = null; /** * Create a new instance. * * @param array $data The meta information for the instance. - * * @param IMetaModel $metaModel The MetaModel instance the condition applies to. */ public function __construct($data, IMetaModel $metaModel) @@ -90,7 +92,7 @@ public function getMetaModel() /** * Retrieve the instance. * - * @return PropertyConditionInterface + * @return PropertyConditionInterface|null */ public function getInstance() { diff --git a/src/Events/DatabaseBackedListener.php b/src/Events/DatabaseBackedListener.php index 8d21f091f..2435dc76d 100644 --- a/src/Events/DatabaseBackedListener.php +++ b/src/Events/DatabaseBackedListener.php @@ -37,6 +37,8 @@ /** * This is the information retriever database backend. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class DatabaseBackedListener { @@ -45,14 +47,14 @@ class DatabaseBackedListener * * @var Connection */ - private $database; + private Connection $database; /** * The event dispatcher. * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * All MetaModel instances created via this listener. @@ -61,7 +63,7 @@ class DatabaseBackedListener * * @var IMetaModel[] */ - private $instancesById = []; + private array $instancesById = []; /** * All MetaModel instances. @@ -70,35 +72,35 @@ class DatabaseBackedListener * * @var IMetaModel[] */ - private $instancesByTable = []; + private array $instancesByTable = []; /** * The table names. * * @var string[] */ - private $tableNames = []; + private array $tableNames = []; /** * Flag if the table names have already been collected. * * @var bool */ - private $tableNamesCollected = false; + private bool $tableNamesCollected = false; /** * All attribute information. * * @var array[] */ - private $attributeInformation = []; + private array $attributeInformation = []; /** * The system columns of MetaModels. * * @var string[] */ - private $systemColumns; + private array $systemColumns; /** * Create a new instance. @@ -120,10 +122,16 @@ public function __construct(Connection $database, EventDispatcherInterface $disp * @return IMetaModelsServiceContainer * * @deprecated The service container is deprecated and should not be used anymore. + * + * @psalm-suppress DeprecatedInterface */ public function getServiceContainer() { - return System::getContainer()->get(MetaModelsServiceContainer::class); + /** @psalm-suppress DeprecatedClass */ + $serviceContainer = System::getContainer()->get(MetaModelsServiceContainer::class); + assert($serviceContainer instanceof IMetaModelsServiceContainer); + + return $serviceContainer; } /** @@ -136,7 +144,7 @@ public function getServiceContainer() public function getMetaModelNameFromId(GetMetaModelNameFromIdEvent $event) { $metaModelId = $event->getMetaModelId(); - if (array_key_exists($metaModelId, $this->instancesById)) { + if (\array_key_exists($metaModelId, $this->instancesById)) { $event->setMetaModelName($this->instancesById[$metaModelId]->getTableName()); return; @@ -160,7 +168,7 @@ public function getMetaModelNameFromId(GetMetaModelNameFromIdEvent $event) ->executeQuery() ->fetchAssociative(); - if ($table) { + if (false !== $table) { $this->tableNames[$metaModelId] = $table['tableName']; $event->setMetaModelName($this->tableNames[$metaModelId]); } @@ -171,7 +179,6 @@ public function getMetaModelNameFromId(GetMetaModelNameFromIdEvent $event) * Determines the correct factory from a metamodel table name and creates an instance using the factory. * * @param CreateMetaModelEvent $event The event. - * * @param array $arrData The meta information for the MetaModel. * * @return bool @@ -191,16 +198,15 @@ protected function createInstanceViaLegacyFactory(CreateMetaModelEvent $event, $ // @codingStandardsIgnoreEnd $factoryClass = $GLOBALS['METAMODELS']['factories'][$name]; - $event->setMetaModel(call_user_func_array(array($factoryClass, 'createInstance'), array($arrData))); + $event->setMetaModel(\call_user_func_array([$factoryClass, 'createInstance'], [$arrData])); - return $event->getMetaModel() !== null; + return (bool) $event->getMetaModel(); } /** * Create a MetaModel instance with the given information. * * @param CreateMetaModelEvent $event The event. - * * @param array $arrData The meta information for the MetaModel. * * @return void @@ -210,15 +216,18 @@ protected function createInstanceViaLegacyFactory(CreateMetaModelEvent $event, $ */ protected function createInstance(CreateMetaModelEvent $event, $arrData) { - if (!$this->createInstanceViaLegacyFactory($event, $arrData)) { + if (false === $this->createInstanceViaLegacyFactory($event, $arrData)) { if ($arrData['translated']) { $metaModel = new TranslatedMetaModel($arrData, $this->dispatcher, $this->database); // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. - $metaModel->selectLanguage(LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])); + $metaModel->selectLanguage(LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'] ?? 'en')); } else { $metaModel = new MetaModel($arrData, $this->dispatcher, $this->database); } + + /** @psalm-suppress DeprecatedMethod */ $metaModel->setServiceContainer(function () { + /** @psalm-suppress DeprecatedMethod */ return $this->getServiceContainer(); }, false); $event->setMetaModel($metaModel); @@ -240,6 +249,7 @@ protected function createInstance(CreateMetaModelEvent $event, $arrData) public function createMetaModel(CreateMetaModelEvent $event) { if ($event->getMetaModel() !== null) { + /** @psalm-suppress DeprecatedMethod */ if (($metaModel = $event->getMetaModel()) instanceof ITranslatedMetaModel && $metaModel->isTranslated()) { // @codingStandardsIgnoreStart @\trigger_error( @@ -269,7 +279,7 @@ public function createMetaModel(CreateMetaModelEvent $event) ->executeQuery() ->fetchAssociative(); - if ($table) { + if (false !== $table) { $table['system_columns'] = $this->systemColumns; $this->createInstance($event, $table); @@ -318,7 +328,7 @@ public function collectMetaModelTableNames(CollectMetaModelTableNamesEvent $even public function collectMetaModelAttributeInformation(CollectMetaModelAttributeInformationEvent $event) { $metaModelName = $event->getMetaModel()->getTableName(); - if (!array_key_exists($metaModelName, $this->attributeInformation)) { + if (!\array_key_exists($metaModelName, $this->attributeInformation)) { $attributes = $this ->database ->createQueryBuilder() diff --git a/src/Events/GetMetaModelNameFromIdEvent.php b/src/Events/GetMetaModelNameFromIdEvent.php index 125d2888d..4788dcd6f 100644 --- a/src/Events/GetMetaModelNameFromIdEvent.php +++ b/src/Events/GetMetaModelNameFromIdEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,13 +25,15 @@ /** * This event is triggered when a MetaModel id must get translated to a MetaModel name. + * + * @psalm-suppress PropertyNotSetInConstructor */ class GetMetaModelNameFromIdEvent extends Event { /** * The event name. */ - const NAME = 'metamodels.metamodel.get-metamodel-name-from-id'; + public const NAME = 'metamodels.metamodel.get-metamodel-name-from-id'; /** * The MetaModel id to be translated. @@ -42,9 +45,9 @@ class GetMetaModelNameFromIdEvent extends Event /** * The name of the MetaModel. * - * @var string + * @var string|null */ - protected $metaModelName; + protected $metaModelName = null; /** * Create a new instance. @@ -69,7 +72,7 @@ public function getMetaModelId() /** * Retrieve the MetaModel name. * - * @return string + * @return string|null */ public function getMetaModelName() { diff --git a/src/Events/MetaModelsBootEvent.php b/src/Events/MetaModelsBootEvent.php index abd2222be..f23cf7613 100644 --- a/src/Events/MetaModelsBootEvent.php +++ b/src/Events/MetaModelsBootEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @author Christian Schiffler * @author Sven Baumann * @author Richard Henkenjohann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -43,6 +44,8 @@ class MetaModelsBootEvent extends Event * @return IMetaModelsServiceContainer * * @deprecated + * + * @psalm-suppress DeprecatedInterface */ public function getServiceContainer(): IMetaModelsServiceContainer { @@ -52,6 +55,11 @@ public function getServiceContainer(): IMetaModelsServiceContainer E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - return System::getContainer()->get(MetaModelsServiceContainer::class); + + /** @psalm-suppress DeprecatedClass */ + $serviceContainer = System::getContainer()->get(MetaModelsServiceContainer::class); + assert($serviceContainer instanceof IMetaModelsServiceContainer); + + return $serviceContainer; } } diff --git a/src/Events/RenderItemListEvent.php b/src/Events/RenderItemListEvent.php index 33b05fa36..62e87a668 100644 --- a/src/Events/RenderItemListEvent.php +++ b/src/Events/RenderItemListEvent.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,35 +35,33 @@ class RenderItemListEvent extends Event * * @var ItemList */ - private $list; + private ItemList $list; /** * The list template being rendered. * * @var Template */ - private $template; + private Template $template; /** * The calling object (most likely a Module or ContentElement). * - * @var object + * @var object|null */ - private $caller; + private object|null $caller; /** * Create a new instance. * - * @param ItemList $list The item list getting rendered. - * - * @param Template $template The list template. - * - * @param object $caller The calling object (most likely a Module or ContentElement). + * @param ItemList $list The item list getting rendered. + * @param Template $template The list template. + * @param object|null $caller The calling object (most likely a Module or ContentElement). */ public function __construct(ItemList $list, Template $template, $caller = null) { - $this->template = $template; $this->list = $list; + $this->template = $template; $this->caller = $caller; } diff --git a/src/Exceptions/Database/ColumnDoesNotExistException.php b/src/Exceptions/Database/ColumnDoesNotExistException.php index 1e276662b..6a92e9cda 100644 --- a/src/Exceptions/Database/ColumnDoesNotExistException.php +++ b/src/Exceptions/Database/ColumnDoesNotExistException.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,12 +13,12 @@ * @package MetaModels/core * @author David Molineus * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ - namespace MetaModels\Exceptions\Database; /** @@ -27,19 +27,19 @@ class ColumnDoesNotExistException extends \RuntimeException { /** - * Create a new exception for a non existing table. + * Create a new exception for a non-existing table. * * @param string $columnName Column name. * @param string $tableName The table name. * @param int $code The optional Exception code. * @param \Exception $previous The optional previous throwable used for the exception chaining. * - * @return static + * @return self */ public static function withName($columnName, $tableName, $code = 0, $previous = null) { - return new static( - sprintf('Column "%s" does not exist on table "%s".', $columnName, $tableName), + return new self( + \sprintf('Column "%s" does not exist on table "%s".', $columnName, $tableName), $code, $previous ); diff --git a/src/Exceptions/Database/ColumnExistsException.php b/src/Exceptions/Database/ColumnExistsException.php index 37392f38d..d13184e5b 100644 --- a/src/Exceptions/Database/ColumnExistsException.php +++ b/src/Exceptions/Database/ColumnExistsException.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,12 +13,12 @@ * @package MetaModels/core * @author David Molineus * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ - namespace MetaModels\Exceptions\Database; /** @@ -34,12 +34,12 @@ class ColumnExistsException extends \RuntimeException * @param int $code The optional Exception code. * @param \Exception $previous The optional previous throwable used for the exception chaining. * - * @return static + * @return self */ public static function withName($columnName, $tableName, $code = 0, $previous = null) { - return new static( - sprintf('Column "%s" already exists on table "%s', $columnName, $tableName), + return new self( + \sprintf('Column "%s" already exists on table "%s', $columnName, $tableName), $code, $previous ); diff --git a/src/Exceptions/Database/InvalidColumnNameException.php b/src/Exceptions/Database/InvalidColumnNameException.php index e0dc73bb3..a7d933cee 100644 --- a/src/Exceptions/Database/InvalidColumnNameException.php +++ b/src/Exceptions/Database/InvalidColumnNameException.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author David Molineus * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,11 +33,11 @@ class InvalidColumnNameException extends \RuntimeException * @param int $code The optional Exception code. * @param \Exception $previous The optional previous throwable used for the exception chaining. * - * @return static + * @return self */ public static function invalidCharacters($columnName, $code = 0, $previous = null) { - return new static(sprintf('The column name "%s" is invalid.', $columnName), $code, $previous); + return new self(\sprintf('The column name "%s" is invalid.', $columnName), $code, $previous); } /** @@ -46,10 +47,10 @@ public static function invalidCharacters($columnName, $code = 0, $previous = nul * @param int $code The optional Exception code. * @param \Exception $previous The optional previous throwable used for the exception chaining. * - * @return static + * @return self */ public static function systemColumn($columnName, $code = 0, $previous = null) { - return new static(sprintf('The column name "%s" is reserved for system use.', $columnName), $code, $previous); + return new self(\sprintf('The column name "%s" is reserved for system use.', $columnName), $code, $previous); } } diff --git a/src/Exceptions/Database/InvalidTableNameException.php b/src/Exceptions/Database/InvalidTableNameException.php index 6ca8c4b70..d582fbb8b 100644 --- a/src/Exceptions/Database/InvalidTableNameException.php +++ b/src/Exceptions/Database/InvalidTableNameException.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author David Molineus * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,10 +33,10 @@ class InvalidTableNameException extends \RuntimeException * @param int $code The optional Exception code. * @param \Exception $previous The optional previous throwable used for the exception chaining. * - * @return static + * @return self */ public static function invalidCharacters($tableName, $code = 0, $previous = null) { - return new static(sprintf('The table name "%s" is invalid.', $tableName), $code, $previous); + return new self(\sprintf('The table name "%s" is invalid.', $tableName), $code, $previous); } } diff --git a/src/Exceptions/Database/TableDoesNotExistException.php b/src/Exceptions/Database/TableDoesNotExistException.php index a8e475b79..ad01f6adc 100644 --- a/src/Exceptions/Database/TableDoesNotExistException.php +++ b/src/Exceptions/Database/TableDoesNotExistException.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,12 +13,12 @@ * @package MetaModels/core * @author David Molineus * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ - namespace MetaModels\Exceptions\Database; /** @@ -33,10 +33,10 @@ class TableDoesNotExistException extends \RuntimeException * @param int $code The optional Exception code. * @param \Exception $previous The optional previous throwable used for the exception chaining. * - * @return static + * @return self */ public static function withName($tableName, $code = 0, $previous = null) { - return new static(sprintf('Table "%s" does not exist.', $tableName), $code, $previous); + return new self(\sprintf('Table "%s" does not exist.', $tableName), $code, $previous); } } diff --git a/src/Exceptions/Database/TableExistsException.php b/src/Exceptions/Database/TableExistsException.php index b604175ca..e29b573d6 100644 --- a/src/Exceptions/Database/TableExistsException.php +++ b/src/Exceptions/Database/TableExistsException.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,12 +13,12 @@ * @package MetaModels/core * @author David Molineus * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ - namespace MetaModels\Exceptions\Database; /** @@ -33,10 +33,10 @@ class TableExistsException extends \RuntimeException * @param int $code The optional Exception code. * @param \Exception $previous The optional previous throwable used for the exception chaining. * - * @return static + * @return self */ public static function withName($tableName, $code = 0, $previous = null) { - return new static(sprintf('Table "%s" already exists.', $tableName), $code, $previous); + return new self(\sprintf('Table "%s" already exists.', $tableName), $code, $previous); } } diff --git a/src/Exceptions/DifferentValuesException.php b/src/Exceptions/DifferentValuesException.php index d44dee875..9ec1dc620 100644 --- a/src/Exceptions/DifferentValuesException.php +++ b/src/Exceptions/DifferentValuesException.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -28,27 +29,27 @@ class DifferentValuesException extends \Exception /** * Two values are an array but differ in count. */ - const ARRAY_COUNT_MISMATCH = 1; + public const ARRAY_COUNT_MISMATCH = 1; /** * Two values are an array but differ in keys. */ - const ARRAY_KEY_MISMATCH = 1; + public const ARRAY_KEY_MISMATCH = 1; /** * Two values are an array but have a different value at a certain key. */ - const ARRAY_VALUE_MISMATCH = 1; + public const ARRAY_VALUE_MISMATCH = 1; /** * Two values differ in type. */ - const TYPE_MISMATCH = 1; + public const TYPE_MISMATCH = 1; /** * Two values are different. */ - const VALUE_MISMATCH = 1; + public const VALUE_MISMATCH = 1; /** * The expected value. @@ -75,13 +76,9 @@ class DifferentValuesException extends \Exception * Create a new instance. * * @param mixed $expected The expected value. - * * @param mixed $actual The actual value. - * * @param bool $strict Compared in strict mode. - * * @param string $message The Exception message to throw. - * * @param int $code The Exception code. * * @param \Exception $previous The previous exception used for the exception chaining. @@ -103,9 +100,7 @@ public function __construct($expected, $actual, $strict, $message = '', $code = * Check if the actual argument is the same as the expected. * * @param mixed $expected The expected value. - * * @param mixed $actual The actual value. - * * @param bool $strict Run in strict mode. * * @return void @@ -168,65 +163,59 @@ public function isStrict() */ public function getLongMessage($glue = ' ') { - $messages = array(); + $messages = []; $exception = $this; do { $messages[] = $exception->getMessage(); } while (null !== ($exception = $exception->getPrevious())); - return implode($glue, $messages); + return \implode($glue, $messages); } /** * Check if the actual argument is of type array and empty and the expected value is of type string and also empty. * * @param mixed $expected The expected value. - * * @param mixed $actual The actual value. * * @return bool */ - private static function isEmptyArrayEquivalent($expected, $actual) + private static function isEmptyArrayEquivalent(mixed $expected, mixed $actual): bool { - return (gettype($expected) == 'string') - && ((gettype($actual) == 'array') || (gettype($actual) == 'NULL')) - && empty($actual) - && empty($expected); + return ('' === $expected) && ([] === $actual || null === $actual); } /** * Check for differences in arrays. * * @param array $expected The expected value. - * * @param array $actual The actual value. - * * @param bool $strict Run in strict mode. * * @return void * * @throws \LogicException When the values differ. */ - private static function calculateArrayDiff($expected, $actual, $strict) + private static function calculateArrayDiff(array $expected, array $actual, bool $strict): void { - if (count($expected) !== count($actual)) { + if (\count($expected) !== count($actual)) { throw new \LogicException( - sprintf( + \sprintf( 'Array element count mismatch. Found %s, expected %s.', - count($actual), - count($expected) + \count($actual), + \count($expected) ), self::ARRAY_COUNT_MISMATCH ); } - reset($actual); + \reset($actual); foreach ($expected as $key => $value) { if ($key !== key($actual)) { throw new \LogicException( - sprintf( + \sprintf( 'Array key mismatch. Found %s, expected %s.', - key($actual), + \key($actual), $key ), self::ARRAY_KEY_MISMATCH @@ -237,15 +226,15 @@ private static function calculateArrayDiff($expected, $actual, $strict) self::calculateDiff($value, current($actual), $strict); } catch (\Exception $exception) { throw new \LogicException( - sprintf( + \sprintf( 'Array value mismatch for key %s.', - key($actual) + \key($actual) ), self::ARRAY_VALUE_MISMATCH, $exception ); } - next($actual); + \next($actual); } } @@ -253,48 +242,46 @@ private static function calculateArrayDiff($expected, $actual, $strict) * Helper to determine if two values are the same. * * @param mixed $expected The expected value. - * * @param mixed $actual The actual value. - * * @param bool $strict Run in strict mode. * * @return void * * @throws \LogicException When the values differ. */ - private static function calculateDiff($expected, $actual, $strict) + private static function calculateDiff(mixed $expected, mixed $actual, bool $strict): void { if ($expected === $actual) { return; } - if (gettype($expected) !== gettype($actual)) { - // Only exception of the rule: array values are transported as empty string. + if (\gettype($expected) !== \gettype($actual)) { + // Only exception to the rule: array values are transported as empty string. if (!$strict && self::isEmptyArrayEquivalent($expected, $actual)) { return; } throw new \LogicException( - sprintf( + \sprintf( 'Encountered type %s expected %s (Found %s, expected %s)', - gettype($actual), - gettype($expected), - var_export($actual, true), - var_export($expected, true) + \gettype($actual), + \gettype($expected), + \var_export($actual, true), + \var_export($expected, true) ), self::TYPE_MISMATCH ); } - if (is_array($expected)) { + if (\is_array($expected)) { self::calculateArrayDiff($expected, $actual, $strict); } throw new \LogicException( - sprintf( + \sprintf( 'Found %s expected %s', - var_export($actual, true), - var_export($expected, true) + \var_export($actual, true), + \var_export($expected, true) ), self::VALUE_MISMATCH ); diff --git a/src/Factory.php b/src/Factory.php index 3f537d597..70e02d654 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2023 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,8 @@ * @author Christian Schiffler * @author David Maack * @author Sven Baumann - * @copyright 2012-2021 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -30,6 +31,8 @@ * This is the MetaModel factory interface. * * To create a MetaModel instance, call @link{MetaModelFactory::getMetaModel()} + * + * @psalm-suppress DeprecatedInterface */ class Factory implements IFactory { @@ -38,21 +41,23 @@ class Factory implements IFactory * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * The service container. * - * @var IMetaModelsServiceContainer + * @var IMetaModelsServiceContainer|null + * + * @psalm-suppress DeprecatedInterface */ - private $serviceContainer; + private IMetaModelsServiceContainer|null $serviceContainer = null; /** * The already translated MetaModel names. * * @var string[] */ - private $lookupMap = array(); + private array $lookupMap = []; /** * Create a new instance. @@ -67,11 +72,14 @@ public function __construct(EventDispatcherInterface $dispatcher) /** * Set the service container. * - * @param IMetaModelsServiceContainer $serviceContainer The service container to use. + * @param IMetaModelsServiceContainer $serviceContainer The service container to use. + * @param bool $deprecationNotice The flag to trigger error. * * @return Factory * * @deprecated The service container will get removed, use the symfony service container instead. + * + * @psalm-suppress DeprecatedInterface */ public function setServiceContainer(IMetaModelsServiceContainer $serviceContainer, $deprecationNotice = true) { @@ -95,9 +103,15 @@ public function setServiceContainer(IMetaModelsServiceContainer $serviceContaine * @return IMetaModelsServiceContainer * * @deprecated The service container will get removed, use the symfony service container instead. + * + * @psalm-suppress DeprecatedInterface */ public function getServiceContainer() { + if (null === $this->serviceContainer) { + throw new \RuntimeException('Deprecated service container is not set anymore by default.'); + } + // @codingStandardsIgnoreStart @trigger_error( '"' .__METHOD__ . '" is deprecated - use the services from the service container.', @@ -116,8 +130,12 @@ public function translateIdToMetaModelName($metaModelId) $event = new GetMetaModelNameFromIdEvent($metaModelId); $this->dispatcher->dispatch($event, $event::NAME); + $translated = $event->getMetaModelName(); + if (null === $translated) { + throw new \RuntimeException('Failed to convert id ' . $metaModelId . ' to table name.'); + } - $this->lookupMap[$metaModelId] = $event->getMetaModelName(); + $this->lookupMap[$metaModelId] = $translated; } return $this->lookupMap[$metaModelId]; @@ -132,9 +150,7 @@ public function getMetaModel($metaModelName) $this->dispatcher->dispatch($event, $event::NAME); - $metaModel = $event->getMetaModel(); - - return $metaModel; + return $event->getMetaModel(); } /** diff --git a/src/Filter/Filter.php b/src/Filter/Filter.php index 98d7568ec..f1fa25d94 100644 --- a/src/Filter/Filter.php +++ b/src/Filter/Filter.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @author Christian Schiffler * @author David Maack * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -38,14 +39,14 @@ class Filter implements IFilter /** * The contained filter rules. * - * @var array + * @var list */ - protected $arrFilterRules = array(); + protected $arrFilterRules = []; /** * The cached result after this filter has been evaluated. * - * @var string[]|null + * @var list|null */ protected $arrMatches = null; @@ -56,9 +57,7 @@ class Filter implements IFilter */ public function __construct(IMetaModel $objMetaModel) { - if ($objMetaModel) { - $this->strMetaModel = $objMetaModel->getTableName(); - } + $this->strMetaModel = $objMetaModel->getTableName(); } /** @@ -70,7 +69,7 @@ public function __clone() { $this->arrMatches = null; $arrOld = $this->arrFilterRules; - $this->arrFilterRules = array(); + $this->arrFilterRules = []; foreach ($arrOld as $objFilterRule) { $this->addFilterRule(clone $objFilterRule); } @@ -83,9 +82,7 @@ public function __clone() */ public function createCopy() { - $objCopy = clone $this; - - return $objCopy; + return clone $this; } /** @@ -112,7 +109,6 @@ public function getMatchingIds() $arrIds = null; foreach ($this->arrFilterRules as $objFilterRule) { - /** @var IFilterRule $objFilterRule */ $arrRuleIds = $objFilterRule->getMatchingIds(); if ($arrRuleIds === null) { continue; @@ -122,13 +118,15 @@ public function getMatchingIds() $arrIds = $arrRuleIds; } else { // NOTE: all rules are implicitely "AND"-ed together. - $arrIds = array_intersect($arrIds, $arrRuleIds); - // When no ids are left any more, the result will stay empty, do not evaluate any further rules. - if (count($arrIds) == 0) { + $arrIds = \array_intersect($arrIds, $arrRuleIds); + // When no ids are left anymore, the result will stay empty, do not evaluate any further rules. + if (\count($arrIds) === 0) { break; } } } + $arrIds = (null !== $arrIds) ? \array_values($arrIds) : null; + $this->arrMatches = $arrIds; return $arrIds; diff --git a/src/Filter/FilterUrl.php b/src/Filter/FilterUrl.php index 7110a7f92..2f4782a9e 100644 --- a/src/Filter/FilterUrl.php +++ b/src/Filter/FilterUrl.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -28,30 +28,30 @@ class FilterUrl /** * The page array. * - * @var string[] + * @var array */ - private $page = []; + private array $page = []; /** * All parameters to be used as GET parameters. * - * @var string[] + * @var array> */ - private $getParameters = []; + private array $getParameters = []; /** * All parameters to be used as slug. * - * @var string[] + * @var array */ - private $slugParameters = []; + private array $slugParameters = []; /** * Create a new instance. * - * @param string[] $page The page. - * @param string[] $getParameters The get parameters. - * @param string[] $slugParameters The slug parameters. + * @param array $page The page. + * @param array $getParameters The get parameters. + * @param array $slugParameters The slug parameters. */ public function __construct( array $page = [], @@ -60,10 +60,9 @@ public function __construct( ) { if (static::class !== __CLASS__) { // @codingStandardsIgnoreStart - @\trigger_deprecation( - 'metamodels/core', - '2.2', - static::class . ' should not extend ' . __CLASS__ . ' as it will become final in 3.0.' + @trigger_error( + static::class . ' should not extend ' . __CLASS__ . ' as it will become final in 3.0.', + E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd } @@ -94,7 +93,7 @@ public function clone(): self /** * Set the target page. * - * @param array $page The page. + * @param array $page The page. * * @return self */ @@ -108,7 +107,7 @@ public function setPage(array $page): self /** * Obtain the target page. * - * @return array + * @return array */ public function getPage(): array { @@ -148,7 +147,7 @@ public function getPageValue(string $name) } /** - * Add a slug parameter. + * Add a GET parameter. * * @param string $name The slug name. * @param string|list $value The slug value. @@ -157,8 +156,9 @@ public function getPageValue(string $name) */ public function setGet(string $name, $value): self { - if (empty($value)) { + if ([] === $value || '' === $value) { unset($this->getParameters[$name]); + return $this; } @@ -188,7 +188,7 @@ public function getGet(string $name) */ public function hasGet(string $name): bool { - return array_key_exists($name, $this->getParameters); + return \array_key_exists($name, $this->getParameters); } /** @@ -225,7 +225,7 @@ public function setSlug(string $name, string $value): self * * @param string $name The slug name. * - * @return string + * @return string|null */ public function getSlug(string $name): ?string { @@ -241,13 +241,13 @@ public function getSlug(string $name): ?string */ public function hasSlug(string $name): bool { - return array_key_exists($name, $this->slugParameters); + return \array_key_exists($name, $this->slugParameters); } /** * Obtain the slug parameters. * - * @return array + * @return array */ public function getSlugParameters(): array { diff --git a/src/Filter/FilterUrlBuilder.php b/src/Filter/FilterUrlBuilder.php index d92069644..2b4573bd5 100644 --- a/src/Filter/FilterUrlBuilder.php +++ b/src/Filter/FilterUrlBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Ingolf Steinhardt * @author Stefan Heimes * @author Andreas Fischer - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +26,7 @@ use Contao\ArrayUtil; use Contao\Config; use Contao\CoreBundle\Framework\Adapter; +use Contao\Model\Collection; use Contao\PageModel; use Contao\System; use Symfony\Component\HttpFoundation\Request; @@ -35,6 +36,18 @@ /** * This class builds filter URLs. + * + * @psalm-type TFilterUrlOptions=array{ + * postAsSlug?: list, + * postAsGet?: list, + * preserveGet?: bool, + * removeGetOnSlug?: bool + * } + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class FilterUrlBuilder { @@ -69,9 +82,9 @@ class FilterUrlBuilder /** * The page model adapter. * - * @var Adapter|PageModel + * @var Adapter */ - private Adapter|PageModel $pageModelAdapter; + private Adapter $pageModelAdapter; /** * Flag if legacy routing is active. @@ -87,7 +100,7 @@ class FilterUrlBuilder * @param RequestStack $requestStack The request stack. * @param bool $isLocalePrepended Flag if the locale is prepended to the URL. * @param string $urlSuffix The URL suffix. - * @param Adapter $pageModelAdapter The page model adapter. + * @param Adapter $pageModelAdapter The page model adapter. * @param bool $hasLegacyRouting Flag if legacy routing is active. */ public function __construct( @@ -130,8 +143,8 @@ public function generate(FilterUrl $filterUrl): string $parameters = $filterUrl->getGetParameters(); $url = ''; - if ($filterUrl->hasSlug('auto_item')) { - $url .= '/' . $this->encodeForAllowEncodedSlashes($filterUrl->getSlug('auto_item')); + if ($filterUrl->hasSlug('auto_item') && '' !== ($slug = (string) $filterUrl->getSlug('auto_item'))) { + $url .= '/' . $this->encodeForAllowEncodedSlashes($slug); } if ($this->hasLegacyRouting) { @@ -147,7 +160,7 @@ public function generate(FilterUrl $filterUrl): string $parameters['_locale'] = $locale; } foreach ($filterUrl->getSlugParameters() as $name => $value) { - if (\in_array($name, ['auto_item'])) { + if ($name === 'auto_item') { continue; } @@ -169,7 +182,8 @@ public function generate(FilterUrl $filterUrl): string /** * Generate a filter URL from the current request. * - * @param array|null $options The options for updating - for details see FilterUrlBuilder::addFromCurrentRequest(). + * @param TFilterUrlOptions|null $options The options for updating - for details + * see FilterUrlBuilder::addFromCurrentRequest(). * * @return FilterUrl */ @@ -196,7 +210,7 @@ public function getCurrentFilterUrl(array $options = null): FilterUrl * default: true * * @param FilterUrl $filterUrl The filter URL to update. - * @param array|null $options The options for updating. + * @param TFilterUrlOptions|null $options The options for updating. * * @return void */ @@ -232,7 +246,7 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = nul } else { $routeName = $this->determineRouteName($request); - $filterUrl->setPageValue('id', substr($routeName, 8)); + $filterUrl->setPageValue('id', \substr($routeName, 8)); $requestUri = \rawurldecode(\substr($request->getPathInfo(), 1)); if (null === ($route = $request->attributes->get('_route_object'))) { @@ -249,9 +263,9 @@ public function addFromCurrentRequest(FilterUrl $filterUrl, array $options = nul $fragments = \explode('/', \substr($requestUri, $start, $length)); if (1 === \count($fragments) % 2) { - array_unshift($fragments, 'auto_item'); + \array_unshift($fragments, 'auto_item'); } - array_unshift($fragments, $pageModel->alias); + \array_unshift($fragments, $pageModel->alias); } // If alias part is empty, this means we have the 'index' page. @@ -327,7 +341,7 @@ private function determineFragments(Request $request): ?array $fragments = null; // Use folder-style URLs - if (Config::get('folderUrl') && false !== \strpos($requestUri, '/')) { + if (Config::get('folderUrl') && \str_contains($requestUri, '/')) { $fragments = $this->getFolderUrlFragments( $requestUri, $request->getHttpHost(), @@ -345,7 +359,7 @@ private function determineFragments(Request $request): ?array // Add the second fragment as auto_item if the number of fragments is even if (Config::get('useAutoItem') && 0 === (\count($fragments) % 2)) { - ArrayUtil::arrayInsert($fragments, 1, ['auto_item']); + \array_splice($fragments, 1, 0, 'auto_item'); } $fragments = $this->getPageIdFromUrlHook($fragments); @@ -368,7 +382,7 @@ private function determineFragments(Request $request): ?array private function strippedUri(Request $request): ?string { // Strip leading slash. - if (null === $request || '' === $requestUri = \rawurldecode(substr($request->getPathInfo(), 1))) { + if ('' === $requestUri = \rawurldecode(\substr($request->getPathInfo(), 1))) { return null; } if ($this->isLocalePrepended) { @@ -380,9 +394,11 @@ private function strippedUri(Request $request): ?string } // Remove the URL suffix if not just a language root (e.g. en/) is requested - if ('' !== $this->urlSuffix && '' !== $requestUri && ( + if ( + '' !== $this->urlSuffix && '' !== $requestUri && ( !$this->isLocalePrepended || !\preg_match('@^[a-z]{2}(-[A-Z]{2})?/$@', $requestUri) - )) { + ) + ) { $requestUri = \substr($requestUri, 0, -\strlen($this->urlSuffix)); } @@ -404,30 +420,30 @@ private function getFolderUrlFragments(string $alias, string $host, string $loca { // Check if there are pages with a matching alias $pages = $this->getPageCandidates($alias); - if (null === $pages) { + if ([] === $pages) { return null; } // Look for a root page whose domain name matches the host name - if (isset($pages[$host])) { - $languages = $pages[$host]; - } else { + $languages = $pages[$host] // empty domain - $languages = $pages['*'] ?: []; - } + ?? ($pages['*'] ?: []); unset($pages); $pages = []; if (!$this->isLocalePrepended) { - // Use the first result (see #4872) + // Use the first result (see #4872). $pages = \current($languages); - } elseif ($locale && isset($languages[$locale])) { + if (false === $pages) { + $pages = []; + } + } elseif (null !== $locale && isset($languages[$locale])) { // Try to find a page matching the language parameter $pages = $languages[$locale]; } - // Return if there are no matches + // Return if there are no matches. if (empty($pages)) { return null; } @@ -436,11 +452,11 @@ private function getFolderUrlFragments(string $alias, string $host, string $loca $page = $pages[0]; // The request consists of the alias only - if ($alias == $page->alias) { + if ($alias === $page->alias) { $arrFragments = [$alias]; } else { // Remove the alias from the request string, explode it and then re-insert it at the beginning. - $arrFragments = explode('/', \substr($alias, (\strlen($page->alias) + 1))); + $arrFragments = \explode('/', \substr($alias, (\strlen($page->alias) + 1))); \array_unshift($arrFragments, $page->alias); } @@ -452,13 +468,13 @@ private function getFolderUrlFragments(string $alias, string $host, string $loca * * @param string $alias The requested alias. * - * @return array|null + * @return array>> */ - private function getPageCandidates(string $alias): ?array + private function getPageCandidates(string $alias): array { $aliases = [$alias]; // Compile all possible aliases by applying dirname() to the request. - while ('/' !== $alias && false !== strpos($alias, '/')) { + while ('/' !== $alias && \str_contains($alias, '/')) { $alias = \dirname($alias); $aliases[] = $alias; } @@ -466,14 +482,12 @@ private function getPageCandidates(string $alias): ?array // Check if there are pages with a matching alias - sort by priority desc and alias* desc. // *: You can assume that if folderurl is enabled, the lower hierarchy pages will have a // longer alias string - hence descending sorting. + /** @psalm-suppress InternalMethod */ $pages = $this->pageModelAdapter->findByAliases( $aliases, ['order' => 'tl_page.routePriority DESC, tl_page.alias DESC'] ); - - if (null === $pages) { - return null; - } + assert($pages instanceof Collection); $arrPages = []; // Order by domain and language. @@ -536,7 +550,7 @@ private function extractPostData(FilterUrl $filterUrl, array $options, Request $ foreach ($request->request->all() as $name => $value) { if (\is_array($value)) { - $value = implode(',', $value); + $value = \implode(',', $value); } if (\in_array($name, $options['postAsSlug'])) { $filterUrl->setSlug($name, $value); @@ -559,10 +573,10 @@ public function determineRouteName(Request $request): string $pageModel = $request->attributes->get('pageModel'); return 'tl_page.' . match (true) { - ($pageModel instanceof PageModel) => $pageModel->id, - is_int($pageModel) => (string) $pageModel, - default => - throw new \RuntimeException('Unknown page model encountered: ' . get_debug_type($pageModel)), - }; + ($pageModel instanceof PageModel) => $pageModel->id, + \is_int($pageModel) => (string) $pageModel, + default => + throw new \RuntimeException('Unknown page model encountered: ' . \get_debug_type($pageModel)), + }; } } diff --git a/src/Filter/IFilter.php b/src/Filter/IFilter.php index 37f0c1d36..40589e07b 100644 --- a/src/Filter/IFilter.php +++ b/src/Filter/IFilter.php @@ -45,7 +45,7 @@ public function addFilterRule(IFilterRule $objFilterRule); /** * Narrow down the list of Ids that match the given filter. * - * @return string[]|null all matching Ids or null if all ids did match. + * @return list|null all matching Ids or null if all ids did match. */ public function getMatchingIds(); } diff --git a/src/Filter/IFilterRule.php b/src/Filter/IFilterRule.php index ee9475e9d..1c041d843 100644 --- a/src/Filter/IFilterRule.php +++ b/src/Filter/IFilterRule.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,7 +33,7 @@ interface IFilterRule * If no filtering was applied and therefore all ids shall be reported as valid, the return value of NULL is * allowed. * - * @return string[]|null + * @return list|null */ public function getMatchingIds(); } diff --git a/src/Filter/Rules/Comparing/GreaterThan.php b/src/Filter/Rules/Comparing/GreaterThan.php index 926a77cdf..82d4203f1 100644 --- a/src/Filter/Rules/Comparing/GreaterThan.php +++ b/src/Filter/Rules/Comparing/GreaterThan.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -33,7 +34,7 @@ class GreaterThan implements IFilterRule * * @var IAttribute */ - protected $objAttribute = null; + protected $objAttribute; /** * The value to compare with. @@ -53,9 +54,7 @@ class GreaterThan implements IFilterRule * Creates an instance of this class. * * @param IAttribute $objAttribute The attribute that shall be searched. - * * @param mixed $varValue The value to compare against. - * * @param bool $blnInclusive If true, the passed value will be included in the check * and therefore make the check an equal-or-greater test. */ @@ -71,7 +70,7 @@ public function __construct(IAttribute $objAttribute, $varValue, $blnInclusive = * * If no entries have been found, the result is an empty array. * - * @return string[]|null + * @return list|null */ public function getMatchingIds() { diff --git a/src/Filter/Rules/Comparing/LessThan.php b/src/Filter/Rules/Comparing/LessThan.php index 09678fd32..536c29fac 100644 --- a/src/Filter/Rules/Comparing/LessThan.php +++ b/src/Filter/Rules/Comparing/LessThan.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -33,7 +34,7 @@ class LessThan implements IFilterRule * * @var IAttribute */ - protected $objAttribute = null; + protected $objAttribute; /** * The value to compare with. @@ -53,9 +54,7 @@ class LessThan implements IFilterRule * Creates an instance of this class. * * @param IAttribute $objAttribute The attribute that shall be searched. - * * @param mixed $varValue The value to compare against. - * * @param bool $blnInclusive If true, the passed value will be included in the check * and therefore make the check an less-or-equal test. */ @@ -71,7 +70,7 @@ public function __construct(IAttribute $objAttribute, $varValue, $blnInclusive = * * If no entries have been found, the result is an empty array. * - * @return string[]|null + * @return list|null */ public function getMatchingIds() { diff --git a/src/Filter/Rules/Comparing/NotEqual.php b/src/Filter/Rules/Comparing/NotEqual.php index 7bf21ccb5..82b655a5c 100644 --- a/src/Filter/Rules/Comparing/NotEqual.php +++ b/src/Filter/Rules/Comparing/NotEqual.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -33,7 +34,7 @@ class NotEqual implements IFilterRule * * @var IAttribute */ - protected $objAttribute = null; + protected $objAttribute; /** * The value to compare with. @@ -46,7 +47,6 @@ class NotEqual implements IFilterRule * Creates an instance of this class. * * @param IAttribute $objAttribute The query that shall be executed. - * * @param mixed $varValue The value to compare against. */ public function __construct(IAttribute $objAttribute, $varValue) @@ -60,7 +60,7 @@ public function __construct(IAttribute $objAttribute, $varValue) * * If no entries have been found, the result is an empty array. * - * @return string[]|null + * @return list|null */ public function getMatchingIds() { diff --git a/src/Filter/Rules/Condition/ConditionAnd.php b/src/Filter/Rules/Condition/ConditionAnd.php index 2d9c68fc3..a65841986 100644 --- a/src/Filter/Rules/Condition/ConditionAnd.php +++ b/src/Filter/Rules/Condition/ConditionAnd.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -34,7 +34,7 @@ class ConditionAnd extends FilterRule * * @var IFilter[] */ - protected $arrChildFilters = array(); + protected $arrChildFilters = []; /** * Adds a child filter to this rule that will get evaluated when this rule is evaluated. @@ -56,15 +56,15 @@ public function addChild(IFilter $objFilter) public function getMatchingIds() { if (0 === count($this->arrChildFilters)) { - return array(); + return []; } $ids = null; foreach ($this->arrChildFilters as $objChildFilter) { $matchingIds = $objChildFilter->getMatchingIds(); - if (array() === $matchingIds) { + if ([] === $matchingIds) { // Empty array, no items allowed by this rule, break out. - return array(); + return []; } // If null => all items allowed by this rule => ignore it. @@ -77,9 +77,9 @@ public function getMatchingIds() continue; } - $ids = array_intersect($ids, $matchingIds); + $ids = \array_intersect($ids, $matchingIds); } - return is_array($ids) ? array_values($ids) : null; + return \is_array($ids) ? \array_values($ids) : null; } } diff --git a/src/Filter/Rules/Condition/ConditionOr.php b/src/Filter/Rules/Condition/ConditionOr.php index 558065726..e777da848 100644 --- a/src/Filter/Rules/Condition/ConditionOr.php +++ b/src/Filter/Rules/Condition/ConditionOr.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @author Christian Schiffler * @author David Maack * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,9 +33,9 @@ class ConditionOr extends FilterRule /** * The list of child filters that shall be evaluated. * - * @var IFilter[] + * @var list */ - protected $arrChildFilters = array(); + protected $arrChildFilters = []; /** * Flag determining if filtering shall return the first non-empty match. @@ -42,7 +43,7 @@ class ConditionOr extends FilterRule * This flag determines if the rule shall return the result of the first * child that returns at least one element (a return value of NULL from a * rule counts as "all ids" in this context and therefore is considered - * non empty per definition). + * non-empty per definition). * * @var boolean */ @@ -86,17 +87,17 @@ public function addChild(IFilter $objFilter) * evaluated, as the result set can not expand any further. * * Note: when "stopAfterMatch" has been set, the rule will stop processing - * also when the first rule returns a non empty result and return that + * also when the first rule returns a non-empty result and return that * result. * - * @return string[]|null + * @return list|null */ public function getMatchingIds() { - $arrIds = array(); + $arrIds = []; foreach ($this->arrChildFilters as $objChildFilter) { $arrChildMatches = $objChildFilter->getMatchingIds(); - // NULL => all items - for OR conditions, this can never be more than all so we are already satisfied here. + // NULL => all items - for OR conditions, this can never be more than all, so we are already satisfied here. if ($arrChildMatches === null) { return null; } @@ -106,10 +107,10 @@ public function getMatchingIds() } if ($arrChildMatches) { - $arrIds = array_merge($arrIds, $arrChildMatches); + $arrIds = \array_merge($arrIds, $arrChildMatches); } } - return array_unique($arrIds); + return \array_values(\array_unique($arrIds)); } } diff --git a/src/Filter/Rules/SearchAttribute.php b/src/Filter/Rules/SearchAttribute.php index 1daf83d04..18134e113 100644 --- a/src/Filter/Rules/SearchAttribute.php +++ b/src/Filter/Rules/SearchAttribute.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,32 +36,30 @@ class SearchAttribute extends FilterRule * * @var IAttribute|ITranslated|IComplex */ - protected $objAttribute = null; + protected $objAttribute; /** * The value to search for. * * @var string */ - protected $strValue = null; + protected $strValue = ''; /** * The valid languages to match (only used when searching a translated attribute). * - * @var array + * @var list */ - protected $arrValidLanguages = null; + protected $arrValidLanguages = []; /** * Creates an instance of a simple query filter rule. * - * @param IAttribute $objAttribute The attribute to be searched. - * - * @param string $strValue The value to be searched for. Wildcards (* and ? allowed). - * - * @param array $arrValidLanguages The list of valid languages to be searched in. + * @param IAttribute $objAttribute The attribute to be searched. + * @param string $strValue The value to be searched for. Wildcards (* and ? allowed). + * @param list $arrValidLanguages The list of valid languages to be searched in. */ - public function __construct($objAttribute, $strValue = '', $arrValidLanguages = array()) + public function __construct($objAttribute, $strValue = '', $arrValidLanguages = []) { parent::__construct(); $this->objAttribute = $objAttribute; diff --git a/src/Filter/Rules/SimpleQuery.php b/src/Filter/Rules/SimpleQuery.php index 6a4545375..434ae9b0d 100644 --- a/src/Filter/Rules/SimpleQuery.php +++ b/src/Filter/Rules/SimpleQuery.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Cliff Parnitzky * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -38,47 +38,47 @@ class SimpleQuery extends FilterRule * * @var string */ - private $queryString; + private string $queryString; /** * The query parameters. * * @var array */ - private $params; + private array $params; /** * The name of the id column in the query. * * @var string */ - private $idColumn; + private string $idColumn; /** * The database instance to use. * * @var Connection */ - private $connection; + private Connection $connection; /** * The parameter types. * * @var array */ - private $types; + private array $types; /** * Create a rule instance from the passed query builder. * * @param QueryBuilder $builder The builder to extract query information from. - * * @param string $columnName The column to retrieve. * * @return SimpleQuery */ public static function createFromQueryBuilder(QueryBuilder $builder, $columnName = 'id') { + /** @psalm-suppress DeprecatedMethod */ return new self( $builder->getSQL(), $builder->getParameters(), @@ -109,9 +109,10 @@ public function __construct($queryString, $params = [], $idColumn = 'id', $conne $this->queryString = $queryString; $this->params = $params; - $this->idColumn = (string) $idColumn; - $this->connection = $this->sanitizeConnection($connection); - $this->types = $types; + $this->idColumn = $idColumn; + /** @psalm-suppress DeprecatedMethod */ + $this->connection = $this->sanitizeConnection($connection); + $this->types = $types; } /** @@ -131,7 +132,7 @@ public function getMatchingIds() /** * Sanitize the connection value * - * @param Connection|\Contao\Database $connection The connection value. + * @param Connection|\Contao\Database|null $connection The connection value. * * @return Connection * @@ -145,9 +146,10 @@ private function sanitizeConnection($connection) return $connection; } + // @codingStandardsIgnoreStart + // @codeCoverageIgnoreStart // BC layer - we used to accept a Contao database instance here. if ($connection instanceof Database) { - // @codingStandardsIgnoreStart @trigger_error( '"' . __METHOD__ . '" now accepts doctrine instances - ' . 'passing Contao database instances is deprecated.', @@ -156,8 +158,10 @@ private function sanitizeConnection($connection) // @codingStandardsIgnoreEnd $reflection = new \ReflectionProperty(Database::class, 'resConnection'); $reflection->setAccessible(true); + return $reflection->getValue($connection); } + if (null === $connection) { // @codingStandardsIgnoreStart @trigger_error( @@ -173,5 +177,7 @@ private function sanitizeConnection($connection) } return $connection; + // @codeCoverageIgnoreEnd + // @codingStandardsIgnoreEnd } } diff --git a/src/Filter/Rules/StaticIdList.php b/src/Filter/Rules/StaticIdList.php index 5d72de835..fe4955c18 100644 --- a/src/Filter/Rules/StaticIdList.php +++ b/src/Filter/Rules/StaticIdList.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @author Christian Schiffler * @author David Maack * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -31,14 +32,14 @@ class StaticIdList extends FilterRule /** * The static id list that shall be applied. * - * @var string[]|null + * @var list */ - protected $arrIds = array(); + protected $arrIds = []; /** * Create a new FilterRule instance. * - * @param string[]|null $arrIds Static list of ids that shall be returned as matches. + * @param list $arrIds Static list of ids that shall be returned as matches. */ public function __construct($arrIds) { diff --git a/src/Filter/Setting/AbstractFilterSettingTypeFactory.php b/src/Filter/Setting/AbstractFilterSettingTypeFactory.php index 5b6d0969d..211b127a7 100644 --- a/src/Filter/Setting/AbstractFilterSettingTypeFactory.php +++ b/src/Filter/Setting/AbstractFilterSettingTypeFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -14,18 +14,23 @@ * @author Christian Schiffler * @author Sven Baumann * @author David Molineus - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\Filter\Setting; +use MetaModels\Filter\Setting\IWithChildren; + /** * This is an abstract factory to query instances of attributes. * * Extend your own attribute factories from this class and register them when the create attribute factory event is * triggered. + * + * @psalm-suppress PropertyNotSetInConstructor */ abstract class AbstractFilterSettingTypeFactory implements IFilterSettingTypeFactory { @@ -34,21 +39,21 @@ abstract class AbstractFilterSettingTypeFactory implements IFilterSettingTypeFac * * @var string */ - private $typeName; + private string $typeName; /** * The name of the attribute class of this type. * - * @var string + * @var class-string */ - private $typeClass; + private string $typeClass; /** * The icon representing this filter setting type. * * @var string */ - private $typeIcon; + private string $typeIcon; /** * The maximum amount of children allowed. @@ -57,21 +62,21 @@ abstract class AbstractFilterSettingTypeFactory implements IFilterSettingTypeFac * * @var int|null */ - private $maxChildren; + private ?int $maxChildren = null; /** * List of valid attribute types that can be filtered with this filter. * - * @var string[] + * @var list|null */ - private $attributeTypes; + private ?array $attributeTypes = null; /** * Cache lookup variable. * * @var bool */ - private $isNestedType; + private ?bool $isNestedType = null; /** * Create a new instance. @@ -84,7 +89,7 @@ protected function __construct() /** * Set the type class. * - * @param string $typeClass The name of the class. + * @param class-string $typeClass The name of the class. * * @return AbstractFilterSettingTypeFactory */ @@ -98,7 +103,7 @@ protected function setTypeClass($typeClass) /** * Get the type class. * - * @return string|null + * @return class-string|null */ protected function getTypeClass(): ?string { @@ -164,11 +169,8 @@ public function createInstance($information, $filterSettings) */ public function isNestedType() { - if (!isset($this->isNestedType)) { - $this->isNestedType = in_array( - 'MetaModels\Filter\Setting\IWithChildren', - class_implements($this->typeClass, true) - ); + if (null === $this->isNestedType) { + $this->isNestedType = \in_array(IWithChildren::class, \class_implements($this->typeClass, true), true); } return $this->isNestedType; @@ -203,7 +205,7 @@ public function getMaxChildren() } /** - * Setup the allowance of attribute types to be added to this factory. + * Set up the allowance of attribute types to be added to this factory. * * This must be called before any calls to addKnownAttributeType() is allowed. * @@ -211,7 +213,8 @@ public function getMaxChildren() * * Either pass one parameter as array of string or pass 1 to n parameters as string. * - * @param string|string[] $initialType1toN One or more attribute type names to be available initially (optional). + * @param string|list $initialType1toN One or more attribute type names to be available + * initially (optional). * * @return AbstractFilterSettingTypeFactory * @@ -219,11 +222,12 @@ public function getMaxChildren() */ protected function allowAttributeTypes($initialType1toN = null) { - if (is_array($initialType1toN)) { + if (\is_array($initialType1toN)) { $this->attributeTypes = $initialType1toN; } else { - $this->attributeTypes = func_get_args(); + $this->attributeTypes = \func_get_args(); } + $this->attributeTypes = \array_values(\array_unique($this->attributeTypes)); return $this; } @@ -231,7 +235,7 @@ protected function allowAttributeTypes($initialType1toN = null) /** * Retrieve the list of known attribute types. * - * @return string[] The list of attribute names or null if no attributes are allowed. + * @return list|null The list of attribute names or null if no attributes are allowed. */ public function getKnownAttributeTypes() { @@ -249,11 +253,13 @@ public function getKnownAttributeTypes() */ public function addKnownAttributeType($typeName) { - if (!is_array($this->attributeTypes)) { + if (!\is_array($this->attributeTypes)) { throw new \LogicException('Filter setting ' . $this->typeClass . ' can not handle attributes.'); } - $this->attributeTypes[$typeName] = $typeName; + $this->attributeTypes[] = $typeName; + + $this->attributeTypes = \array_values(\array_unique($this->attributeTypes)); return $this; } diff --git a/src/Filter/Setting/Collection.php b/src/Filter/Setting/Collection.php index 9280ff160..d854d3ea7 100644 --- a/src/Filter/Setting/Collection.php +++ b/src/Filter/Setting/Collection.php @@ -32,11 +32,13 @@ /** * This is the ICollection reference implementation. + * + * @psalm-suppress PropertyNotSetInConstructor */ class Collection implements ICollection { /** - * The additional meta data for this filter setting collection. + * The additional meta-data for this filter setting collection. * * @var array */ @@ -97,13 +99,7 @@ public function setMetaModel($metaModel): self */ public function getMetaModel() { - if ($this->metaModel) { - return $this->metaModel; - } - - throw new \RuntimeException( - sprintf('Error: Filter setting %d not attached to a MetaModel', $this->arrData['id']) - ); + return $this->metaModel; } /** @@ -127,7 +123,7 @@ public function addRules(IFilter $objFilter, $arrFilterUrl, $arrIgnoredFilter = { foreach ($this->arrSettings as $objSetting) { // If the setting is on the ignore list skip it. - if (in_array($objSetting->get('id'), $arrIgnoredFilter, false)) { + if (\in_array($objSetting->get('id'), $arrIgnoredFilter, false)) { continue; } @@ -145,7 +141,7 @@ public function generateFilterUrlFrom(IItem $objItem, IRenderSettings $objRender $filterUrl[] = $objSetting->generateFilterUrlFrom($objItem, $objRenderSetting); } - return [] === $filterUrl ? [] : array_merge(...$filterUrl); + return [] === $filterUrl ? [] : \array_merge(...$filterUrl); } /** @@ -158,7 +154,7 @@ public function getParameters() $parameters[] = $objSetting->getParameters(); } - return [] === $parameters ? [] : array_merge(...$parameters); + return [] === $parameters ? [] : \array_merge(...$parameters); } /** @@ -171,7 +167,7 @@ public function getParameterDCA() $parameters[] = $objSetting->getParameterDCA(); } - return [] === $parameters ? [] : array_merge(...$parameters); + return [] === $parameters ? [] : \array_merge(...$parameters); } /** @@ -183,16 +179,16 @@ public function getParameterFilterNames() foreach ($this->arrSettings as $objSetting) { $filterNames = $objSetting->getParameterFilterNames(); $filterType = $objSetting->get('type'); - $parameters[] = \array_map(function ($name) use ($filterType) { - return $name . ' [' . $filterType . ']'; - }, $filterNames); + $parameters[] = \array_map(fn (string $name): string => $name . ' [' . $filterType . ']', $filterNames); } - return [] === $parameters ? [] : array_merge(...$parameters); + return [] === $parameters ? [] : \array_merge(...$parameters); } /** * {@inheritdoc} + * + * @SuppressWarnings(PHPMD.LongVariable) */ public function getParameterFilterWidgets( $arrFilterUrl, @@ -220,7 +216,7 @@ public function getParameterFilterWidgets( $setting->getParameterFilterWidgets($ids, $arrFilterUrl, $arrJumpTo, $objFrontendFilterOptions); } - return [] === $parameters ? [] : array_merge(...$parameters); + return [] === $parameters ? [] : \array_merge(...$parameters); } /** @@ -233,6 +229,6 @@ public function getReferencedAttributes() $attributes[] = $setting->getReferencedAttributes(); } - return [] === $attributes ? [] : array_merge(...$attributes); + return [] === $attributes ? [] : \array_merge(...$attributes); } } diff --git a/src/Filter/Setting/ConditionAndFilterSettingTypeFactory.php b/src/Filter/Setting/ConditionAndFilterSettingTypeFactory.php index 7e0ec06b2..b09585b73 100644 --- a/src/Filter/Setting/ConditionAndFilterSettingTypeFactory.php +++ b/src/Filter/Setting/ConditionAndFilterSettingTypeFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,13 +13,16 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\Filter\Setting; +use MetaModels\Filter\Setting\Condition\ConditionAnd; + /** * Attribute type factory for AND filter settings. */ @@ -35,7 +38,7 @@ public function __construct() $this ->setTypeName('conditionand') ->setTypeIcon('bundles/metamodelscore/images/icons/filter_and.png') - ->setTypeClass('MetaModels\Filter\Setting\Condition\ConditionAnd') + ->setTypeClass(ConditionAnd::class) ->allowAttributeTypes(); } } diff --git a/src/Filter/Setting/ConditionOrFilterSettingTypeFactory.php b/src/Filter/Setting/ConditionOrFilterSettingTypeFactory.php index 7f6d2637a..3f1ca0120 100644 --- a/src/Filter/Setting/ConditionOrFilterSettingTypeFactory.php +++ b/src/Filter/Setting/ConditionOrFilterSettingTypeFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,13 +13,16 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\Filter\Setting; +use MetaModels\Filter\Setting\Condition\ConditionOr; + /** * Attribute type factory for OR filter settings. */ @@ -35,7 +38,7 @@ public function __construct() $this ->setTypeName('conditionor') ->setTypeIcon('bundles/metamodelscore/images/icons/filter_or.png') - ->setTypeClass('MetaModels\Filter\Setting\Condition\ConditionOr') + ->setTypeClass(ConditionOr::class) ->allowAttributeTypes(); } } diff --git a/src/Filter/Setting/CustomSql.php b/src/Filter/Setting/CustomSql.php index ee9c9969a..d9e065130 100644 --- a/src/Filter/Setting/CustomSql.php +++ b/src/Filter/Setting/CustomSql.php @@ -44,6 +44,11 @@ /** * This filter condition generates a filter rule for a predefined SQL query. * The generated rule will only return ids that are returned from this query. + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * + * @psalm-suppress PropertyNotSetInConstructor */ class CustomSql implements ISimple, ServiceSubscriberInterface { @@ -52,21 +57,21 @@ class CustomSql implements ISimple, ServiceSubscriberInterface * * @var ICollection */ - private ?ICollection $collection = null; + private ICollection $collection; /** * The attributes of this filter setting. * - * @var array + * @var array */ - private array $data = []; + private array $data; /** - * The filter params (should be an array or null). + * The filter params. * - * @var array + * @var array */ - private array $filterParameters; + private array $filterParameters = []; /** * The query string. @@ -78,7 +83,7 @@ class CustomSql implements ISimple, ServiceSubscriberInterface /** * The query parameters. * - * @var array + * @var list */ private array $queryParameter; @@ -92,9 +97,9 @@ class CustomSql implements ISimple, ServiceSubscriberInterface /** * Constructor - initialize the object and store the parameters. * - * @param ICollection $collection The parenting filter settings object. - * @param array $data The attributes for this filter setting. - * @param ContainerInterface $container The service container. + * @param ICollection $collection The parenting filter settings object. + * @param array $data The attributes for this filter setting. + * @param ContainerInterface $container The service container. * * @throws \InvalidArgumentException When a service is missing. */ @@ -104,14 +109,14 @@ public function __construct($collection, $data, ContainerInterface $container) $this->data = $data; $missing = []; - foreach (array_keys(self::getSubscribedServices()) as $serviceId) { + foreach (\array_keys(self::getSubscribedServices()) as $serviceId) { if (!$container->has($serviceId)) { $missing[] = $serviceId; } } if (!empty($missing)) { throw new \InvalidArgumentException( - 'The service container is missing the following services: ' . implode(', ', $missing) + 'The service container is missing the following services: ' . \implode(', ', $missing) ); } $this->container = $container; @@ -120,7 +125,7 @@ public function __construct($collection, $data, ContainerInterface $container) /** * Get the needed services. * - * @return array + * @return array */ public static function getSubscribedServices() { @@ -140,7 +145,7 @@ public static function getSubscribedServices() */ public function get($strKey) { - return isset($this->data[$strKey]) ? $this->data[$strKey] : null; + return $this->data[$strKey] ?? null; } /** @@ -154,9 +159,9 @@ public function prepareRules(IFilter $objFilter, $arrFilterUrl) $objFilter->addFilterRule($this->getFilterRule()); - unset($this->filterParameters); - unset($this->queryString); - unset($this->queryParameter); + $this->filterParameters = []; + $this->queryString = ''; + $this->queryParameter = []; } /** @@ -174,7 +179,7 @@ public function getParameters() { $arrParams = []; - \preg_match_all('@\{\{param::filter\?([^}]*)\}\}@', $this->get('customsql'), $arrMatches); + \preg_match_all('@\{\{param::filter\?([^}]*)}}@', $this->get('customsql'), $arrMatches); foreach ($arrMatches[1] as $strQuery) { \parse_str($strQuery, $arrArgs); if (isset($arrArgs['name'])) { @@ -204,6 +209,8 @@ public function getParameterFilterNames() /** * {@inheritdoc} + * + * @SuppressWarnings(PHPMD.LongVariable) */ public function getParameterFilterWidgets( $arrIds, @@ -253,11 +260,11 @@ private function getFilterRule() /** * Add parameters to the list. * - * @param array $parameters The parameters to add. + * @param list $parameters The parameters to add. * * @return void */ - private function addParameters(array $parameters) + private function addParameters(array $parameters): void { if (empty($parameters)) { return; @@ -273,7 +280,7 @@ private function addParameters(array $parameters) * * @return void */ - private function addParameter(string $parameter) + private function addParameter(string $parameter): void { $this->queryParameter[] = $this->parseInsertTagsInternal($parameter); } @@ -283,7 +290,7 @@ private function addParameter(string $parameter) * * @return void */ - private function parseTable() + private function parseTable(): void { $this->queryString = $this->container->get(ReplaceTableName::class) ->replace($this->collection->getMetaModel()->getTableName(), $this->queryString); @@ -298,7 +305,7 @@ private function parseTable() * * @return mixed */ - private function getValueFromServiceContainer(string $valueName, array $arguments) + private function getValueFromServiceContainer(string $valueName, array $arguments): mixed { if (!empty($arguments['service'])) { $serviceName = $arguments['service']; @@ -319,46 +326,29 @@ private function getValueFromServiceContainer(string $valueName, array $argument * * @param string $source The source to retrieve the value from. * Valid values are: ('get', 'post', 'cookie', 'session', 'filter' or 'container'). - * * @param string $valueName The name of the value in the source to retrieve. - * * @param array $arguments The arguments of the parameter. * * @return mixed */ - private function getValueFromSource(string $source, string $valueName, array $arguments) + private function getValueFromSource(string $source, string $valueName, array $arguments): mixed { - switch (\strtolower($source)) { - case 'get': - case 'post': - case 'cookie': - case 'session': - return $this->executeInsertTagReplaceParam($source, $arguments); - - case 'filter': - if (\is_array($this->filterParameters)) { - if (\array_key_exists($valueName, $this->filterParameters)) { - return $this->filterParameters[$valueName]; - } - - return null; - } - break; - - case 'container': - // @codingStandardsIgnoreStart - @trigger_error( - 'Getting filter values from the service container is deprecated, the container will get removed.', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd - return $this->getValueFromServiceContainer($valueName, $arguments); - - default: + if (\strtolower($source) === 'container') { + // @codingStandardsIgnoreStart + @trigger_error( + 'Getting filter values from the service container is deprecated, the container will get removed.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + return $this->getValueFromServiceContainer($valueName, $arguments); } - // Unknown sources always resort to null. - return null; + return match (\strtolower($source)) { + 'get', 'post', 'cookie', 'session' => $this->executeInsertTagReplaceParam($source, $arguments), + 'filter' => $this->filterParameters[$valueName] ?? null, + // Unknown sources always resort to null. + default => null + }; } /** @@ -369,12 +359,12 @@ private function getValueFromSource(string $source, string $valueName, array $ar * * @return mixed|string */ - private function executeInsertTagReplaceParam(string $source, array $arguments) + private function executeInsertTagReplaceParam(string $source, array $arguments): mixed { $filteredArguments = \array_intersect_key($arguments, \array_flip(['name', 'default'])); $imploded = \array_reduce( \array_keys($filteredArguments), - function ($carry, $item) use ($filteredArguments) { + static function ($carry, $item) use ($filteredArguments) { return $carry . ($carry ? '&' : '') . $item . '=' . $filteredArguments[$item]; }, '' @@ -396,24 +386,20 @@ function ($carry, $item) use ($filteredArguments) { * * @return string */ - private function convertParameterAggregate(array $var, array $arguments) + private function convertParameterAggregate(array $var, array $arguments): string { if (!empty($arguments['recursive'])) { - $var = \iterator_to_array( - new \RecursiveIteratorIterator( - new \RecursiveArrayIterator( - $var - ) - ) - ); + $var = \iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveArrayIterator($var))); } - if (!$var) { + if ([] === $var) { return 'NULL'; } if ($arguments['aggregate'] === 'list') { - $var = \array_merge(...\array_map(static fn ($value) => \explode(',', $value), $var)); + $var = \array_merge( + ...\array_map(static fn (string $value): array => \explode(',', $value), \array_values($var)) + ); } if (!empty($arguments['key'])) { @@ -443,7 +429,7 @@ private function convertParameterAggregate(array $var, array $arguments) */ private function convertParameter(string $strMatch): string { - list($strSource, $strQuery) = \explode('?', $strMatch, 2); + [$strSource, $strQuery] = \explode('?', $strMatch, 2) + ['', '']; \parse_str($strQuery, $arrArgs); $arrName = (array) $arrArgs['name']; @@ -455,7 +441,7 @@ private function convertParameter(string $strMatch): string $var = $var[$arrName[$index++]]; } - if ($index != $count || $var === null) { + if ($index !== $count || $var === null) { if (\array_key_exists('default', $arrArgs) && (null !== $arrArgs['default'])) { $this->addParameter($arrArgs['default']); diff --git a/src/Filter/Setting/FilterSettingFactory.php b/src/Filter/Setting/FilterSettingFactory.php index bb9007c17..88cab44a1 100644 --- a/src/Filter/Setting/FilterSettingFactory.php +++ b/src/Filter/Setting/FilterSettingFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -30,6 +30,9 @@ /** * This is the filter settings factory interface. + * + * @psalm-suppress DeprecatedInterface + * @psalm-suppress PropertyNotSetInConstructor */ class FilterSettingFactory implements IFilterSettingFactory { @@ -37,6 +40,8 @@ class FilterSettingFactory implements IFilterSettingFactory * The event dispatcher. * * @var IMetaModelsServiceContainer + * + * @psalm-suppress DeprecatedInterface */ protected $serviceContainer; @@ -45,28 +50,28 @@ class FilterSettingFactory implements IFilterSettingFactory * * @var EventDispatcherInterface */ - private $eventDispatcher; + private EventDispatcherInterface $eventDispatcher; /** * The database connection. * * @var Connection */ - private $database; + private Connection $database; /** * The registered type factories. * * @var IFilterSettingTypeFactory[] */ - private $typeFactories; + private array $typeFactories; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Create a new instance. @@ -90,7 +95,7 @@ public function __construct( * * @deprecated The service container will get removed, use the symfony service container instead. */ - public function setServiceContainer(IMetaModelsServiceContainer $serviceContainer, $deprecationNotice = true) + public function setServiceContainer(IMetaModelsServiceContainer $serviceContainer, bool $deprecationNotice = true) { if ($deprecationNotice) { // @codingStandardsIgnoreStart @@ -262,11 +267,11 @@ public function createCollection($settingId) ->setMaxResults(1) ->setParameter('id', $settingId) ->executeQuery(); - if (!$query) { + if (0 === $query->rowCount()) { throw new \RuntimeException('Could not retrieve filter setting'); } - if (!empty($information = $query->fetchAssociative())) { + if (false !== ($information = $query->fetchAssociative())) { $metaModel = $this->factory->getMetaModel($this->factory->translateIdToMetaModelName($information['pid'])); if ($metaModel === null) { throw new \RuntimeException('Could not retrieve MetaModel ' . $information['pid']); @@ -279,7 +284,7 @@ public function createCollection($settingId) return $collection; } - return new Collection(array()); + return new Collection([]); } /** @@ -287,6 +292,6 @@ public function createCollection($settingId) */ public function getTypeNames() { - return array_keys($this->typeFactories); + return \array_keys($this->typeFactories); } } diff --git a/src/Filter/Setting/ICollection.php b/src/Filter/Setting/ICollection.php index 65fb126fc..c5adcc915 100644 --- a/src/Filter/Setting/ICollection.php +++ b/src/Filter/Setting/ICollection.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author David Maack * @author Stefan Heimes * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -55,9 +56,7 @@ public function getMetaModel(); * Generates all filter rules from the contained filter settings. * * @param IFilter $objFilter The filter object to add rules to. - * * @param array $arrFilterUrl The filter url to be applied. - * * @param array $arrIgnoredFilter An optional list with filter ids that should be ignored. * Defaults to empty array. * @@ -69,7 +68,6 @@ public function addRules(IFilter $objFilter, $arrFilterUrl, $arrIgnoredFilter = * Generate an filter url (aka jump to url) according to the contained filter rules. * * @param IItem $objItem The item from which the values shall be retrieved from. - * * @param IRenderSettings $objRenderSetting The render settings that hold the destination filter settings and * jumpTo page. * @@ -80,14 +78,14 @@ public function generateFilterUrlFrom(IItem $objItem, IRenderSettings $objRender /** * Retrieve a list of all registered parameters from the setting. * - * @return array + * @return list */ public function getParameters(); /** * Retrieve the names of all parameters for listing in frontend filter configuration. * - * @return string[] the parameters as array. parametername => label + * @return array the parameters as array. parametername => label */ public function getParameterFilterNames(); @@ -95,12 +93,12 @@ public function getParameterFilterNames(); * Retrieve a list of filter widgets for all registered parameters as form field arrays. * * @param array $arrFilterUrl The current filter url. - * * @param array $arrJumpTo The selected jump to page to use for link generating. - * * @param FrontendFilterOptions $objFrontendFilterOptions The frontend filter options to be passed to the widget. * - * @return array + * @return array + * + * @SuppressWarnings(PHPMD.LongVariable) */ public function getParameterFilterWidgets( $arrFilterUrl, @@ -118,7 +116,7 @@ public function getParameterDCA(); /** * Retrieve a list of all referenced attributes within the filter setting. * - * @return array + * @return list */ public function getReferencedAttributes(); } diff --git a/src/Filter/Setting/IFilterSettingFactory.php b/src/Filter/Setting/IFilterSettingFactory.php index 27a991a72..419ca053b 100644 --- a/src/Filter/Setting/IFilterSettingFactory.php +++ b/src/Filter/Setting/IFilterSettingFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -53,7 +53,7 @@ public function getTypeFactory($type); * * @param string $settingId The id of the ICollection. * - * @return ICollection The instance of the filter settings or null if not found. + * @return ICollection The instance of the filter settings. */ public function createCollection($settingId); diff --git a/src/Filter/Setting/IFilterSettingTypeFactory.php b/src/Filter/Setting/IFilterSettingTypeFactory.php index 30bb73a13..0f5d0281b 100644 --- a/src/Filter/Setting/IFilterSettingTypeFactory.php +++ b/src/Filter/Setting/IFilterSettingTypeFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -68,7 +69,7 @@ public function getMaxChildren(); /** * Retrieve the list of known attribute types. * - * @return string[] The list of attribute names or null if no attributes are allowed. + * @return list|null The list of attribute names or null if no attributes are allowed. */ public function getKnownAttributeTypes(); diff --git a/src/Filter/Setting/ISimple.php b/src/Filter/Setting/ISimple.php index 5f8998652..3d5e69665 100644 --- a/src/Filter/Setting/ISimple.php +++ b/src/Filter/Setting/ISimple.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author David Maack * @author Stefan Heimes * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -49,9 +50,8 @@ public function get($strKey); * A filter url hereby is a simple hash of name => value layout, it may eventually be interpreted * by attributes via IMetaModelAttribute::searchFor() method. * - * @param IFilter $objFilter The filter to append the rules to. - * - * @param string[] $arrFilterUrl The parameters to evaluate. + * @param IFilter $objFilter The filter to append the rules to. + * @param array $arrFilterUrl The parameters to evaluate. * * @return void */ @@ -64,17 +64,18 @@ public function prepareRules(IFilter $objFilter, $arrFilterUrl); * parameters have to be fetched. * * @param IItem $objItem The item to fetch the values from. - * * @param IRenderSettings $objRenderSetting The render setting to be applied. * - * @return array An array containing all the URL parameters needed by this filter setting. + * @return array An array containing all the URL parameters needed by this filter setting. + * + * @SuppressWarnings(PHPMD.LongVariable) */ public function generateFilterUrlFrom(IItem $objItem, IRenderSettings $objRenderSetting); /** * Retrieve a list of all registered parameters from the setting. * - * @return array + * @return list */ public function getParameters(); @@ -83,29 +84,28 @@ public function getParameters(); * * These parameters may be overridden by modules and content elements and the like. * - * @return array + * @return array */ public function getParameterDCA(); /** * Retrieve the names of all parameters for listing in frontend filter configuration. * - * @return string[] the parameters as array. parametername => label + * @return array the parameters as array. parametername => label */ public function getParameterFilterNames(); /** * Retrieve a list of filter widgets for all registered parameters as form field arrays. * - * @param string[]|null $arrIds The ids matching the current filter values. - * - * @param array $arrFilterUrl The current filter url. - * - * @param array $arrJumpTo The jumpTo page (array, row data from tl_page). - * + * @param list|null $arrIds The ids matching the current filter values. + * @param array $arrFilterUrl The current filter url. + * @param array $arrJumpTo The jumpTo page (array, row data from tl_page). * @param FrontendFilterOptions $objFrontendFilterOptions The frontend filter options. * - * @return array + * @return array + * + * @SuppressWarnings(PHPMD.LongVariable) */ public function getParameterFilterWidgets( $arrIds, @@ -117,7 +117,7 @@ public function getParameterFilterWidgets( /** * Retrieve a list of all referenced attributes within the filter setting. * - * @return array + * @return list */ public function getReferencedAttributes(); } diff --git a/src/Filter/Setting/Simple.php b/src/Filter/Setting/Simple.php index 6411bf252..d6adedafa 100644 --- a/src/Filter/Setting/Simple.php +++ b/src/Filter/Setting/Simple.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author David Molineus * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -37,9 +37,13 @@ use MetaModels\IMetaModelsServiceContainer; use MetaModels\Render\Setting\ICollection as IRenderSettings; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Request; /** * Base class for filter setting implementation. + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ abstract class Simple implements ISimple { @@ -48,14 +52,14 @@ abstract class Simple implements ISimple * * @var ICollection */ - private $collection = null; + private ICollection $collection; /** * The attributes of this filter setting. * * @var array */ - private $data = []; + private array $data = []; /** * The event dispatcher. @@ -69,7 +73,7 @@ abstract class Simple implements ISimple * * @var FilterUrlBuilder */ - private $filterUrlBuilder; + private FilterUrlBuilder $filterUrlBuilder; /** * Constructor - initialize the object and store the parameters. @@ -97,6 +101,7 @@ public function __construct( // @codingStandardsIgnoreEnd $eventDispatcher = System::getContainer()->get('event_dispatcher'); + assert($eventDispatcher instanceof EventDispatcherInterface); } if (null === $filterUrlBuilder) { @@ -107,6 +112,7 @@ public function __construct( ); // @codingStandardsIgnoreEnd $filterUrlBuilder = System::getContainer()->get('metamodels.filter_url'); + assert($filterUrlBuilder instanceof FilterUrlBuilder); } $this->eventDispatcher = $eventDispatcher; @@ -119,6 +125,8 @@ public function __construct( * @return IMetaModelsServiceContainer * * @deprecated Inject needed services via constructor or setter. + * + * @psalm-suppress DeprecatedInterface */ public function getServiceContainer() { @@ -128,6 +136,7 @@ public function getServiceContainer() E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + /** @psalm-suppress DeprecatedMethod */ return $this->getMetaModel()->getServiceContainer(); } @@ -155,7 +164,7 @@ public function getEventDispatcher() */ public function get($strKey) { - return isset($this->data[$strKey]) ? $this->data[$strKey] : null; + return $this->data[$strKey] ?? null; } /** @@ -182,9 +191,7 @@ public function getMetaModel() * Returns if the given value is currently active in the given filter settings. * * @param array $arrWidget The widget information. - * * @param array $arrFilterUrl The filter url parameters to use. - * * @param string $strKeyOption The option value to determine. * * @return bool true If the given value is mentioned in the given filter parameters, false otherwise. @@ -200,7 +207,7 @@ protected function isActiveFrontendFilterValue($arrWidget, $arrFilterUrl, $strKe } if ($defaultValue = $this->get('defaultid')) { - return $strKeyOption == $defaultValue; + return $strKeyOption === $defaultValue; } return false; @@ -210,15 +217,13 @@ protected function isActiveFrontendFilterValue($arrWidget, $arrFilterUrl, $strKe * Translate an option to a proper url value to be used in the filter url. * * Overriding this method allows to toggle the value in the url in addition to extract - * or inject a value into an "combined" filter url parameter (like tags i.e.) + * or inject a value into a "combined" filter url parameter (like tags i.e.) * * @param array $arrWidget The widget information. - * * @param array $arrFilterUrl The filter url parameters to use. - * * @param string $strKeyOption The option value to determine. * - * @return string The filter url value to use for link gererating. + * @return string The filter url value to use for link generating. */ protected function getFrontendFilterValue($arrWidget, $arrFilterUrl, $strKeyOption) { @@ -233,12 +238,10 @@ protected function getFrontendFilterValue($arrWidget, $arrFilterUrl, $strKeyOpti * Add a parameter to the url, if it is auto_item, it will get prepended. * * @param string $url The url built so far. - * * @param string $name The parameter name. - * * @param mixed $value The parameter value. * - * @return string. + * @return string * * @deprecated Not in use anymore, use the FilterUrlBuilder. */ @@ -246,16 +249,16 @@ protected function addUrlParameter($url, $name, $value) { // @codingStandardsIgnoreStart @trigger_error( - sprintf('"%1$s" has been deprecated in favor of the "FilterUrlBuilder"', __METHOD__), + \sprintf('"%1$s" has been deprecated in favor of the "FilterUrlBuilder"', __METHOD__), E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - if (is_array($value)) { - $value = implode(',', array_filter($value)); + if (\is_array($value)) { + $value = \implode(',', \array_filter($value)); } - $value = str_replace('%', '%%', urlencode($value)); + $value = \str_replace('%', '%%', \urlencode($value)); if (empty($value)) { return $url; @@ -274,7 +277,6 @@ protected function addUrlParameter($url, $name, $value) * Build the filter url based upon the fragments. * * @param array $fragments The parameters to be used in the Url. - * * @param string $searchKey The param key to handle for "this". * * @return string @@ -288,7 +290,7 @@ protected function buildFilterUrl($fragments, $searchKey) { // @codingStandardsIgnoreStart @trigger_error( - sprintf('"%1$s" has been deprecated in favor of the "FilterUrlBuilder"', __METHOD__), + \sprintf('"%1$s" has been deprecated in favor of the "FilterUrlBuilder"', __METHOD__), E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd @@ -300,11 +302,11 @@ protected function buildFilterUrl($fragments, $searchKey) // The URL parameter concerning us will be masked via %s to be used later on in a sprintf(). foreach ($fragments as $key => $value) { // Skip the magic "language" parameter. - if (($key == 'language') && $GLOBALS['TL_CONFIG']['addLanguageToUrl']) { + if (($key === 'language') && $GLOBALS['TL_CONFIG']['addLanguageToUrl']) { continue; } - if ($key == $searchKey) { + if ($key === $searchKey) { if ($key !== 'auto_item') { $url .= '%s'; } else { @@ -312,6 +314,7 @@ protected function buildFilterUrl($fragments, $searchKey) } $found = true; } else { + /** @psalm-suppress DeprecatedMethod */ $url = $this->addUrlParameter($url, $key, $value); } } @@ -340,12 +343,9 @@ protected function buildFilterUrl($fragments, $searchKey) * * class The CSS class to use. Contains active if the option is active or is empty otherwise. * * @param array $arrWidget The widget information to use for value generating. - * * @param array $arrFilterUrl The filter url parameters to use. - * * @param array $arrJumpTo The jumpTo page to use for URL generating - if empty, the current * frontend page will get used. - * * @param bool $blnAutoSubmit Determines if the generated options/widgets shall perform auto submitting * or not. * @@ -366,23 +366,22 @@ protected function prepareFrontendFilterOptions($arrWidget, $arrFilterUrl, $arrJ $filterUrl = new FilterUrl($arrJumpTo); foreach ($arrFilterUrl as $name => $value) { - if (is_array($value)) { - $value = implode(',', array_filter($value)); + if (\is_array($value)) { + $value = \implode(',', \array_filter($value)); } $filterUrl->setSlug($name, (string) $value); } $parameterName = $arrWidget['eval']['urlparam'] ?? ''; - if ($arrWidget['eval']['includeBlankOption'] ?? null) { + if ((bool) ($arrWidget['eval']['includeBlankOption'] ?? false)) { $blnActive = $this->isActiveFrontendFilterValue($arrWidget, $arrFilterUrl, ''); $arrOptions[] = [ 'key' => '', - 'value' => ( - !$arrWidget['eval']['blankOptionLabel'] - ? $GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'] - : $arrWidget['eval']['blankOptionLabel'] + 'value' => (string) ( + $arrWidget['eval']['blankOptionLabel'] + ?? ($GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'] ?? '') ), 'href' => $this->filterUrlBuilder->generate( $filterUrl->clone()->setSlug($parameterName, '')->setGet($parameterName, '') @@ -437,6 +436,8 @@ protected function prepareFrontendFilterOptions($arrWidget, $arrFilterUrl, $arrJ * @SuppressWarnings(PHPMD.CamelCaseVariableName) * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) + * + * @SuppressWarnings(PHPMD.LongVariable) */ protected function prepareFrontendFilterWidget( array $arrWidget, @@ -444,7 +445,8 @@ protected function prepareFrontendFilterWidget( array $arrJumpTo, FrontendFilterOptions $objFrontendFilterOptions ): array { - $strClass = $GLOBALS['TL_FFL'][$arrWidget['inputType']]; + /** @var class-string|null $strClass */ + $strClass = $GLOBALS['TL_FFL'][$arrWidget['inputType']] ?? null; // No widget? no output! that's it. if (!$strClass) { @@ -465,19 +467,26 @@ protected function prepareFrontendFilterWidget( $this->eventDispatcher->dispatch($event, ContaoEvents::WIDGET_GET_ATTRIBUTES_FROM_DCA); - if ($objFrontendFilterOptions->isAutoSubmit() && TL_MODE == 'FE') { - $min = System::getContainer()->get('kernel')->isDebug() ? '' : '.min'; - $GLOBALS['TL_JAVASCRIPT']['metamodels'] = sprintf('bundles/metamodelscore/js/metamodels%s.js', $min); + $isFrontend = (bool) System::getContainer() + ->get('contao.routing.scope_matcher') + ?->isFrontendRequest( + System::getContainer()->get('request_stack')?->getCurrentRequest() ?? Request::create('') + ); + + if ($objFrontendFilterOptions->isAutoSubmit() && $isFrontend) { + $min = ((bool) System::getContainer()->get('kernel')?->isDebug()) ? '' : '.min'; + $GLOBALS['TL_JAVASCRIPT']['metamodels'] = \sprintf('bundles/metamodelscore/js/metamodels%s.js', $min); } - /** @var \Widget $objWidget */ + /** @psalm-suppress UnsafeInstantiation */ $objWidget = new $strClass($event->getResult()); $this->validateWidget($objWidget, $arrWidget['value']); $strField = $objWidget->generate(); + /** @psalm-suppress InvalidArgument - We assume the widget array is fine. */ return [ 'cssID' => $arrWidget['eval']['cssID'] ?? '', - 'class' => sprintf( + 'class' => \sprintf( 'mm_%s %s%s%s%s', $arrWidget['inputType'], $arrWidget['eval']['urlparam'], @@ -500,7 +509,7 @@ protected function prepareFrontendFilterWidget( 'count' => isset($arrWidget['count']) ? $arrWidget['count'] : null, 'showCount' => $objFrontendFilterOptions->isShowCountValues(), 'autosubmit' => $objFrontendFilterOptions->isAutoSubmit(), - 'urlvalue' => array_key_exists('urlvalue', $arrWidget) ? $arrWidget['urlvalue'] : $arrWidget['value'], + 'urlvalue' => \array_key_exists('urlvalue', $arrWidget) ? $arrWidget['urlvalue'] : $arrWidget['value'], 'errors' => $objWidget->hasErrors() ? $objWidget->getErrors() : [], 'used' => $arrWidget['value'] !== null ? true : false, 'urlfragment' => $objFrontendFilterOptions->getUrlFragment() @@ -541,6 +550,8 @@ public function getParameterFilterNames() /** * {@inheritdoc} + * + * @SuppressWarnings(PHPMD.LongVariable) */ public function getParameterFilterWidgets( $arrIds, @@ -563,7 +574,6 @@ public function getReferencedAttributes() * Validate the widget using the value. * * @param Widget $widget The widget to validate. - * * @param string|null $value The value to validate. * * @return void @@ -585,12 +595,12 @@ protected function validateWidget($widget, $value) /** * Generate legend. * - * @param array}> $arrWidget The widget information array. + * @param array{label: list} $arrWidget The widget information array. * * @return string */ protected function generateLegend($arrWidget): string { - return '' . $arrWidget['label'][0] . ''; + return '' . ($arrWidget['label'][0] ?? '') . ''; } } diff --git a/src/Filter/Setting/SimpleLookup.php b/src/Filter/Setting/SimpleLookup.php index 93a9f7f4a..b181b621f 100644 --- a/src/Filter/Setting/SimpleLookup.php +++ b/src/Filter/Setting/SimpleLookup.php @@ -30,11 +30,14 @@ use MetaModels\Filter\IFilter; use MetaModels\Filter\Rules\StaticIdList as FilterRuleStaticIdList; use MetaModels\Filter\Rules\SearchAttribute as FilterRuleSimpleLookup; +use MetaModels\IMetaModel; +use MetaModels\ITranslatedMetaModel; use MetaModels\Render\Setting\ICollection as IRenderSettings; /** - * Filter setting implementation performing a search for a value on a - * configured attribute. + * Filter setting implementation performing a search for a value on a configured attribute. + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) - revisit after removing bc layer. */ class SimpleLookup extends Simple { @@ -93,11 +96,9 @@ public function allowEmpty() /** * Internal helper function for descendant classes to retrieve the options. * - * @param IAttribute $objAttribute The attribute to search. - * - * @param string[]|null $arrIds The Id list of items for which to retrieve the options. - * - * @param array $arrCount If non null, the amount of matches will get returned. + * @param IAttribute $objAttribute The attribute to search. + * @param list|null $arrIds The Id list of items for which to retrieve the options. + * @param array $arrCount If non-null, the amount of matches will get returned. * * @return array */ @@ -112,10 +113,10 @@ protected function getParameterFilterOptions($objAttribute, $arrIds, &$arrCount // Remove empty values. foreach ($arrOptions as $mixOptionKey => $mixOptions) { // Remove html/php tags. - $mixOptions = strip_tags($mixOptions); - $mixOptions = trim($mixOptions); + $mixOptions = \strip_tags($mixOptions); + $mixOptions = \trim($mixOptions); - if ($mixOptions === '' || $mixOptions === null) { + if ($mixOptions === '') { unset($arrOptions[$mixOptionKey]); } } @@ -154,26 +155,25 @@ public function prepareRules(IFilter $objFilter, $arrFilterUrl) $objAttribute = $this->getFilteredAttribute(); $strParam = $this->getParamName(); - if ($objAttribute && $strParam) { - if ($arrFilterValue = $this->determineFilterValue($arrFilterUrl, $strParam)) { - if ($objMetaModel->isTranslated() && $this->get('all_langs')) { - $arrLanguages = $objMetaModel->getAvailableLanguages(); - } else { - $arrLanguages = array($objMetaModel->getActiveLanguage()); - } - $objFilterRule = new FilterRuleSimpleLookup($objAttribute, $arrFilterValue, $arrLanguages); + if ($objAttribute && null !== $strParam) { + if (null !== ($arrFilterValue = $this->determineFilterValue($arrFilterUrl, $strParam))) { + $objFilterRule = new FilterRuleSimpleLookup( + $objAttribute, + $arrFilterValue, + $this->determineLanguages($objMetaModel) + ); $objFilter->addFilterRule($objFilterRule); + return; } // We found an attribute but no match in URL. So ignore this filter setting if allow_empty is set. if ($this->allowEmpty()) { - $objFilter->addFilterRule(new FilterRuleStaticIdList(null)); return; } } // Either no attribute found or no match in url, do not return anything. - $objFilter->addFilterRule(new FilterRuleStaticIdList(array())); + $objFilter->addFilterRule(new FilterRuleStaticIdList([])); } /** @@ -182,7 +182,9 @@ public function prepareRules(IFilter $objFilter, $arrFilterUrl) public function generateFilterUrlFrom(IItem $objItem, IRenderSettings $objRenderSetting) { if ($attribute = $this->getFilteredAttribute()) { - return [$this->getParamName() => $attribute->getFilterUrlValue($objItem->get($attribute->getColName()))]; + return [ + (string) $this->getParamName() => $attribute->getFilterUrlValue($objItem->get($attribute->getColName())) + ]; } return []; @@ -193,7 +195,7 @@ public function generateFilterUrlFrom(IItem $objItem, IRenderSettings $objRender */ public function getParameters() { - return ($strParamName = $this->getParamName()) ? array($strParamName) : array(); + return (null !== ($strParamName = $this->getParamName())) ? [$strParamName] : []; } /** @@ -210,16 +212,18 @@ public function getParameterDCA() } $objAttribute = $this->getFilteredAttribute(); - $arrOptions = $objAttribute->getFilterOptions(null, (bool) $this->get('onlyused')); + assert($objAttribute instanceof IAttribute); + + $arrOptions = $objAttribute->getFilterOptions(null, (bool) $this->get('onlyused')); return [ - $this->getParamName() => [ + (string) $this->getParamName() => [ 'label' => [ - sprintf( + \sprintf( $GLOBALS['TL_LANG']['MSC']['metamodel_filtersettings_parameter']['simplelookup'][0], $objAttribute->getName() ), - sprintf( + \sprintf( $GLOBALS['TL_LANG']['MSC']['metamodel_filtersettings_parameter']['simplelookup'][1], $objAttribute->getName() ) @@ -239,13 +243,13 @@ public function getParameterDCA() */ public function getParameterFilterNames() { - if (($label = $this->getLabel()) && ($paramName = $this->getParamName())) { - return array( + if (null !== ($label = $this->getLabel()) && null !== ($paramName = $this->getParamName())) { + return [ $paramName => $label - ); + ]; } - return array(); + return []; } /** @@ -253,6 +257,7 @@ public function getParameterFilterNames() * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) + * @SuppressWarnings(PHPMD.LongVariable) */ public function getParameterFilterWidgets( $arrIds, @@ -262,14 +267,17 @@ public function getParameterFilterWidgets( ) { // If defined as static, return nothing as not to be manipulated via editors. if (!$this->enableFEFilterWidget()) { - return array(); + return []; } if (!($attribute = $this->getFilteredAttribute())) { - return array(); + return []; } - $GLOBALS['MM_FILTER_PARAMS'][] = $this->getParamName(); + $paramName = $this->getParamName(); + assert(\is_string($paramName)); + + $GLOBALS['MM_FILTER_PARAMS'][] = $paramName; $cssID = StringUtil::deserialize($this->get('cssID'), true); @@ -277,7 +285,7 @@ public function getParameterFilterWidgets( $arrWidget = [ 'label' => [ $this->getLabel(), - 'GET: ' . $this->getParamName() + 'GET: ' . $paramName ], 'inputType' => 'select', 'options' => $this->getParameterFilterOptions($attribute, $arrIds, $arrCount), @@ -293,7 +301,7 @@ public function getParameterFilterWidgets( ? $this->getLabel() : $GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'], 'colname' => $attribute->getColname(), - 'urlparam' => $this->getParamName(), + 'urlparam' => $paramName, 'onlyused' => $this->get('onlyused'), 'onlypossible' => $this->get('onlypossible'), 'template' => $this->get('template'), @@ -303,15 +311,14 @@ public function getParameterFilterWidgets( ] ]; - return array - ( - $this->getParamName() => $this->prepareFrontendFilterWidget( + return [ + $paramName => $this->prepareFrontendFilterWidget( $arrWidget, $arrFilterUrl, $arrJumpTo, $objFrontendFilterOptions ) - ); + ]; } /** @@ -360,4 +367,41 @@ private function determineFilterValue($filterValues, $valueName) return $filterValues[$valueName] ?? null; } + + /** + * @return list + */ + private function determineLanguages(IMetaModel $metaModel): array + { + if ((bool) $this->get('all_langs')) { + if ($metaModel instanceof ITranslatedMetaModel) { + return \array_values(\array_filter($metaModel->getLanguages())); + } + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ + if ($metaModel->isTranslated(false)) { + /** @psalm-suppress DeprecatedMethod */ + return \array_values(\array_filter($metaModel->getAvailableLanguages() ?? [])); + } + + return []; + } + + if ($metaModel instanceof ITranslatedMetaModel) { + return \array_filter([$metaModel->getLanguage()]); + } + + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ + if ($metaModel->isTranslated(false)) { + /** @psalm-suppress DeprecatedMethod */ + return \array_filter([$metaModel->getActiveLanguage()]); + } + + return []; + } } diff --git a/src/Filter/Setting/StaticIdListFilterSettingTypeFactory.php b/src/Filter/Setting/StaticIdListFilterSettingTypeFactory.php index cdefb4632..e74541c5d 100644 --- a/src/Filter/Setting/StaticIdListFilterSettingTypeFactory.php +++ b/src/Filter/Setting/StaticIdListFilterSettingTypeFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,6 +36,6 @@ public function __construct() $this ->setTypeName('idlist') ->setTypeIcon('bundles/metamodelscore/images/icons/filter_default.png') - ->setTypeClass('MetaModels\Filter\Setting\IdList'); + ->setTypeClass(IdList::class); } } diff --git a/src/Filter/Setting/WithChildren.php b/src/Filter/Setting/WithChildren.php index 3e34c9464..afb7521a4 100644 --- a/src/Filter/Setting/WithChildren.php +++ b/src/Filter/Setting/WithChildren.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author David Maack * @author Stefan Heimes * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +27,8 @@ use MetaModels\IItem; use MetaModels\Render\Setting\ICollection as IRenderSettings; +use function array_merge; + /** * Base implementation for settings that can contain children. */ @@ -36,7 +39,7 @@ abstract class WithChildren extends Simple implements IWithChildren * * @var ISimple[] */ - protected $arrChildren = array(); + protected $arrChildren = []; /** * {@inheritdoc} @@ -84,6 +87,8 @@ public function getParameterDCA() /** * {@inheritdoc} + * + * @SuppressWarnings(PHPMD.LongVariable) */ public function getParameterFilterWidgets( $arrIds, @@ -91,7 +96,7 @@ public function getParameterFilterWidgets( $arrJumpTo, FrontendFilterOptions $objFrontendFilterOptions ) { - $arrParams = array(); + $arrParams = []; foreach ($this->arrChildren as $objSetting) { $arrParams = array_merge( $arrParams, @@ -106,7 +111,7 @@ public function getParameterFilterWidgets( */ public function getParameterFilterNames() { - $arrParams = array(); + $arrParams = []; foreach ($this->arrChildren as $objSetting) { $arrParams = array_merge($arrParams, $objSetting->getParameterFilterNames()); } @@ -116,11 +121,11 @@ public function getParameterFilterNames() /** * Retrieve a list of all referenced attributes within the filter setting. * - * @return array + * @return list */ public function getReferencedAttributes() { - $arrAttributes = array(); + $arrAttributes = []; foreach ($this->arrChildren as $objSetting) { $arrAttributes = array_merge($arrAttributes, $objSetting->getReferencedAttributes()); } diff --git a/src/FrontendIntegration/Content/Filter.php b/src/FrontendIntegration/Content/Filter.php index 820d9b601..36c061d09 100644 --- a/src/FrontendIntegration/Content/Filter.php +++ b/src/FrontendIntegration/Content/Filter.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 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,8 @@ * @author Christian Schiffler * @author Andreas Nölke * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +26,9 @@ /** * Content element for FE-filtering. + * + * @psalm-suppress DeprecatedClass + * @psalm-suppress PropertyNotSetInConstructor */ class Filter extends HybridFilterBlock { diff --git a/src/FrontendIntegration/Content/FilterClearAll.php b/src/FrontendIntegration/Content/FilterClearAll.php index 17eb72ba9..2b3540033 100644 --- a/src/FrontendIntegration/Content/FilterClearAll.php +++ b/src/FrontendIntegration/Content/FilterClearAll.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Andreas Nölke * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -27,6 +27,10 @@ /** * Content element clearing the FE-filter. + * + * @psalm-suppress DeprecatedClass + * + * @psalm-suppress PropertyNotSetInConstructor */ class FilterClearAll extends HybridFilterClearAll { diff --git a/src/FrontendIntegration/Content/ModelList.php b/src/FrontendIntegration/Content/ModelList.php index d59bf4dd2..a8cd8e795 100644 --- a/src/FrontendIntegration/Content/ModelList.php +++ b/src/FrontendIntegration/Content/ModelList.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt * @author Richard Henkenjohann - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,6 +32,9 @@ * Implementation of the MetaModel content element. * * @deprecated We switched to fragments {@see ItemListController.php} in MetaModels 2.2. To be removed in MetaModels 3. + * + * @psalm-suppress DeprecatedClass + * @psalm-suppress PropertyNotSetInConstructor */ class ModelList extends HybridList { diff --git a/src/FrontendIntegration/FrontendFilter.php b/src/FrontendIntegration/FrontendFilter.php index 475ead06d..70865b524 100644 --- a/src/FrontendIntegration/FrontendFilter.php +++ b/src/FrontendIntegration/FrontendFilter.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -20,7 +20,7 @@ * @author David Molineus * @author Marc Reimann * @author Richard Henkenjohann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -28,19 +28,28 @@ namespace MetaModels\FrontendIntegration; use Contao\CoreBundle\Exception\RedirectResponseException; +use Contao\FrontendTemplate; use Contao\Input; use Contao\System; use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; use ContaoCommunityAlliance\Contao\Bindings\Events\Controller\RedirectEvent; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use MetaModels\Filter\FilterUrl; use MetaModels\Filter\FilterUrlBuilder; use MetaModels\FrontendIntegration\Content\FilterClearAll as ContentElementFilterClearAll; use MetaModels\FrontendIntegration\Module\FilterClearAll as ModuleFilterClearAll; +use RuntimeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * FE-filtering for Contao MetaModels. + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * + * @psalm-suppress PropertyNotSetInConstructor */ class FrontendFilter { @@ -63,20 +72,20 @@ class FrontendFilter * * @var Connection */ - private $connection; + private Connection $connection; /** * The filter URL builder. * * @var FilterUrlBuilder */ - private $filterUrlBuilder; + private FilterUrlBuilder $filterUrlBuilder; /** * FrontendFilter constructor. * - * @param Connection $connection Database connection. - * @param FilterUrlBuilder $filterUrlBuilder The filter URL builder. + * @param Connection|null $connection Database connection. + * @param FilterUrlBuilder|null $filterUrlBuilder The filter URL builder. */ public function __construct(Connection $connection = null, FilterUrlBuilder $filterUrlBuilder = null) { @@ -88,7 +97,10 @@ public function __construct(Connection $connection = null, FilterUrlBuilder $fil ); // @codingStandardsIgnoreEnd $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); } + $this->connection = $connection; + if (null === $filterUrlBuilder) { // @codingStandardsIgnoreStart @trigger_error( @@ -97,9 +109,8 @@ public function __construct(Connection $connection = null, FilterUrlBuilder $fil ); // @codingStandardsIgnoreEnd $filterUrlBuilder = System::getContainer()->get('metamodels.filter_url'); + assert($filterUrlBuilder instanceof FilterUrlBuilder); } - - $this->connection = $connection; $this->filterUrlBuilder = $filterUrlBuilder; } @@ -110,7 +121,10 @@ public function __construct(Connection $connection = null, FilterUrlBuilder $fil */ protected function getDispatcher() { - return System::getContainer()->get('event_dispatcher'); + $dispatcher = System::getContainer()->get('event_dispatcher'); + assert($dispatcher instanceof EventDispatcherInterface); + + return $dispatcher; } /** @@ -124,6 +138,7 @@ public function getMetaModelFrontendFilter(HybridFilterBlock $objFilterConfig) { $this->objFilterConfig = $objFilterConfig; + /** @psalm-suppress UndefinedMagicPropertyFetch */ $this->formId .= $this->objFilterConfig->metamodel_fef_id ?: $this->objFilterConfig->id; return $this->getFilters(); } @@ -144,7 +159,7 @@ protected function getJumpToUrl($arrParams) { // @codingStandardsIgnoreStart @trigger_error( - sprintf('"%1$s" has been deprecated in favor of the new "FilterUrlBuilder"', __METHOD__), + \sprintf('"%1$s" has been deprecated in favor of the new "FilterUrlBuilder"', __METHOD__), E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd @@ -152,29 +167,29 @@ protected function getJumpToUrl($arrParams) $strFilterAction = ''; foreach ($arrParams as $strName => $varParam) { // Skip the magic "language" parameter. - if (($strName == 'language') && $GLOBALS['TL_CONFIG']['addLanguageToUrl']) { + if (($strName === 'language') && $GLOBALS['TL_CONFIG']['addLanguageToUrl']) { continue; } $strValue = $varParam; - if (is_array($varParam)) { - $strValue = implode(',', array_filter($varParam)); + if (\is_array($varParam)) { + $strValue = \implode(',', \array_filter($varParam)); } - if (strlen($strValue)) { + if (\strlen($strValue)) { // Shift auto_item to the front. if ($strName == 'auto_item') { - $strFilterAction = '/' . rawurlencode(rawurlencode($strValue)) . $strFilterAction; + $strFilterAction = '/' . \rawurlencode(\rawurlencode($strValue)) . $strFilterAction; continue; } - $strFilterAction .= sprintf( + $strFilterAction .= \sprintf( $GLOBALS['TL_CONFIG']['disableAlias'] ? '&%s=%s' : '/%s/%s', - rawurlencode($strName), + \rawurlencode($strName), // Double rawurlencode to encode all special characters. // Look at http://php.net/manual/en/function.rawurlencode.php . - rawurlencode(rawurlencode($strValue)) + \rawurlencode(\rawurlencode($strValue)) ); } } @@ -196,7 +211,7 @@ protected function redirectPost($arrParams) { // @codingStandardsIgnoreStart @trigger_error( - sprintf('"%1$s" has been deprecated in favor of the new "FilterUrlBuilder"', __METHOD__), + \sprintf('"%1$s" has been deprecated in favor of the new "FilterUrlBuilder"', __METHOD__), E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd @@ -212,11 +227,16 @@ protected function redirectPost($arrParams) /** * Retrieve the list of parameter names that shall be evaluated. * - * @return array + * @return list */ protected function getWantedNames() { - return (array) unserialize($this->objFilterConfig->metamodel_fef_params); + return \array_values( + \array_map( + static fn (mixed $value): string => (string) $value, + (array) \unserialize($this->objFilterConfig->metamodel_fef_params, ['allowed_classes' => false]) + ) + ); } /** @@ -233,39 +253,38 @@ protected function getParams() { // @codingStandardsIgnoreStart @trigger_error( - sprintf('"%1$s" has been deprecated in favor of the new "FilterUrlBuilder"', __METHOD__), + \sprintf('"%1$s" has been deprecated in favor of the new "FilterUrlBuilder"', __METHOD__), E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd $arrWantedParam = $this->getWantedNames(); - $arrMyParams = $arrOtherParams = array(); + $arrMyParams = $arrOtherParams = []; if ($_GET) { - foreach (array_keys($_GET) as $strParam) { - if (in_array($strParam, $arrWantedParam)) { - $arrMyParams[$strParam] = Input::get($strParam); - } elseif ($strParam != 'page') { + foreach (\array_keys($_GET) as $strParam) { + if (\in_array($strParam, $arrWantedParam)) { + $arrMyParams[$strParam] = Input::get((string) $strParam); + } elseif ($strParam !== 'page') { // Add only to the array if param is not page. - $arrOtherParams[$strParam] = Input::get($strParam); + $arrOtherParams[$strParam] = Input::get((string) $strParam); } } } // if POST, translate to proper GET url - if ($_POST && (Input::post('FORM_SUBMIT') == $this->formId)) { - foreach (array_keys($_POST) as $strParam) { - if (in_array($strParam, $arrWantedParam)) { - $arrMyParams[$strParam] = Input::post($strParam); + if ($_POST && (Input::post('FORM_SUBMIT') === $this->formId)) { + foreach (\array_keys($_POST) as $strParam) { + if (\in_array($strParam, $arrWantedParam)) { + $arrMyParams[$strParam] = Input::post((string) $strParam); } } } - return array - ( + return [ 'filter' => $arrMyParams, - 'other' => $arrOtherParams, - 'all' => array_merge($arrOtherParams, $arrMyParams) - ); + 'other' => $arrOtherParams, + 'all' => \array_merge($arrOtherParams, $arrMyParams) + ]; } /** @@ -280,10 +299,11 @@ protected function renderWidget($widget, $filterOptions) { $filter = $widget; $templateName = ($filter['raw']['eval']['template'] ?? 'mm_filteritem_default'); - $template = new \FrontendTemplate($templateName); + $template = new FrontendTemplate($templateName); $template->setData($filter); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ $template->submit = $filterOptions->isAutoSubmit(); $filter['value'] = $template->parse(); @@ -305,7 +325,7 @@ protected function checkRedirect($widgets, $wantedParameter, $allParameter) { // @codingStandardsIgnoreStart @trigger_error( - sprintf('"%1$s" has been deprecated in favor of the new "FilterUrlBuilder"', __METHOD__), + \sprintf('"%1$s" has been deprecated in favor of the new "FilterUrlBuilder"', __METHOD__), E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd @@ -337,17 +357,17 @@ protected function checkRedirect($widgets, $wantedParameter, $allParameter) */ protected function getFrontendFilterOptions() { - $objFrontendFilterOptions = new FrontendFilterOptions(); - $objFrontendFilterOptions->setAutoSubmit($this->objFilterConfig->metamodel_fef_autosubmit ? true : false); - $objFrontendFilterOptions->setHideClearFilter( + $filterOptions = new FrontendFilterOptions(); + $filterOptions->setAutoSubmit($this->objFilterConfig->metamodel_fef_autosubmit ? true : false); + $filterOptions->setHideClearFilter( $this->objFilterConfig->metamodel_fef_hideclearfilter ? true : false ); - $objFrontendFilterOptions->setShowCountValues( + $filterOptions->setShowCountValues( $this->objFilterConfig->metamodel_available_values ? true : false ); - $objFrontendFilterOptions->setUrlFragment((string) $this->objFilterConfig->metamodel_fef_urlfragment); + $filterOptions->setUrlFragment($this->objFilterConfig->metamodel_fef_urlfragment); - return $objFrontendFilterOptions; + return $filterOptions; } /** @@ -383,7 +403,7 @@ protected function getFilters() } $arrWidgets = $filterSetting->getParameterFilterWidgets( - array_merge($all->getSlugParameters(), $all->getGetParameters()), + \array_merge($all->getSlugParameters(), $all->getGetParameters()), $jumpToInformation, $filterOptions ); @@ -413,6 +433,7 @@ protected function getFilters() } // Return filter data. + /** @psalm-suppress UndefinedMagicPropertyFetch */ return [ 'action' => $this->filterUrlBuilder->generate($other) . ($this->objFilterConfig->metamodel_fef_urlfragment @@ -430,28 +451,30 @@ protected function getFilters() /** * Retrieve the parameter values. * - * @param FilterUrl $other Destination for "other" parameters (not originating from current filter module). - * @param FilterUrl $all Destination for "all" parameters. - * @param string[] $wantedNames The wanted parameter names. + * @param FilterUrl $other Destination for "other" parameters (not originating from current filter module). + * @param FilterUrl $all Destination for "all" parameters. + * @param list $wantedNames The wanted parameter names. * * @return void */ protected function buildParameters(FilterUrl $other, FilterUrl $all, array $wantedNames): void { - $current = $this->filterUrlBuilder->getCurrentFilterUrl([ - 'postAsSlug' => $wantedNames, - 'postAsGet' => [], - 'preserveGet' => true - ]); + $current = $this->filterUrlBuilder->getCurrentFilterUrl( + [ + 'postAsSlug' => $wantedNames, + 'postAsGet' => [], + 'preserveGet' => true + ] + ); foreach ($current->getSlugParameters() as $name => $value) { $all->setSlug($name, $value); - if (!in_array($name, $wantedNames)) { + if (!\in_array($name, $wantedNames)) { $other->setSlug($name, $value); } } foreach ($current->getGetParameters() as $name => $value) { $all->setGet($name, $value); - if (!in_array($name, $wantedNames)) { + if (!\in_array($name, $wantedNames)) { $other->setGet($name, $value); } } @@ -495,8 +518,7 @@ protected function generateModule($content, $replace, $moduleId) * * @return string * - * @throws \Doctrine\DBAL\DBALException When a database error occur. - * @throws \Doctrine\DBAL\Exception + * @throws Exception When a database error occur. */ protected function generateElement($table, $content, $replace, $elementId) { @@ -513,19 +535,21 @@ protected function generateElement($table, $content, $replace, $elementId) // Check if we have an existing module or ce element. if ($result === false) { - return str_replace($replace, '', $content); + return \str_replace($replace, '', $content); } // Get instance and call generate function. - if ($table == 'tl_module') { + if ($table === 'tl_module') { + /** @psalm-suppress ArgumentTypeCoercion */ $objElement = new ModuleFilterClearAll((object) $result); - } elseif ($table == 'tl_content') { + } elseif ($table === 'tl_content') { + /** @psalm-suppress ArgumentTypeCoercion */ $objElement = new ContentElementFilterClearAll((object) $result); } else { - return str_replace($replace, '', $content); + return \str_replace($replace, '', $content); } - return str_replace($replace, $objElement->generateReal(), $content); + return \str_replace($replace, $objElement->generateReal(), $content); } /** @@ -538,29 +562,31 @@ protected function generateElement($table, $content, $replace, $elementId) * * @return string * - * @throws \RuntimeException When an invalid selector has been used (different than "ce" or "mod"). + * @throws RuntimeException When an invalid selector has been used (different than "ce" or "mod"). */ public function generateClearAll($strContent, $strTemplate) { - if (substr($strTemplate, 0, 3) === 'fe_') { - if (preg_match_all( - '#\[\[\[metamodelfrontendfilterclearall::(ce|mod)::([^\]]*)\]\]\]#', - $strContent, - $arrMatches, - PREG_SET_ORDER - )) { + if (\str_starts_with($strTemplate, 'fe_')) { + if ( + (bool) \preg_match_all( + '#\[\[\[metamodelfrontendfilterclearall::(ce|mod)::([^\]]*)\]\]\]#', + $strContent, + $arrMatches, + PREG_SET_ORDER + ) + ) { foreach ($arrMatches as $arrMatch) { switch ($arrMatch[1]) { case 'ce': - $strContent = $this->generateContentElement($strContent, $arrMatch[0], $arrMatch[2]); + $strContent = $this->generateContentElement($strContent, $arrMatch[0], (int) $arrMatch[2]); break; case 'mod': - $strContent = $this->generateModule($strContent, $arrMatch[0], $arrMatch[2]); + $strContent = $this->generateModule($strContent, $arrMatch[0], (int) $arrMatch[2]); break; default: - throw new \RuntimeException('Unexpected element determinator encountered: ' . $arrMatch[1]); + throw new RuntimeException('Unexpected element determinator encountered: ' . $arrMatch[1]); } } } diff --git a/src/FrontendIntegration/HybridFilterBlock.php b/src/FrontendIntegration/HybridFilterBlock.php index 0a32cc75d..fd376f0dd 100644 --- a/src/FrontendIntegration/HybridFilterBlock.php +++ b/src/FrontendIntegration/HybridFilterBlock.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,13 +17,15 @@ * @author David Molineus * @author Andreas Nölke * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\FrontendIntegration; +use Contao\Database\Result; +use Contao\FrontendTemplate; use Contao\System; use MetaModels\Filter\FilterUrlBuilder; use MetaModels\Filter\Setting\ICollection; @@ -32,14 +34,18 @@ /** * FE-module for FE-filtering. * - * @property \FrontendTemplate $Template - * @property string $metamodel_jumpTo - * @property string $metamodel_fef_template - * @property bool $metamodel_fef_autosubmit - * @property bool $metamodel_fef_hideclearfilter - * @property bool $metamodel_available_values - * @property string $metamodel_fef_params - * @property int $id + * @property FrontendTemplate $Template + * @property string $metamodel_jumpTo + * @property string $metamodel_fef_template + * @property bool $metamodel_fef_autosubmit + * @property bool $metamodel_fef_hideclearfilter + * @property bool $metamodel_available_values + * @property string $metamodel_fef_params + * @property string $metamodel_fef_urlfragment + * @property int $id + * + * @psalm-suppress DeprecatedClass + * @psalm-suppress PropertyNotSetInConstructor */ class HybridFilterBlock extends MetaModelHybrid { @@ -53,23 +59,23 @@ class HybridFilterBlock extends MetaModelHybrid /** * The jumpTo page. * - * @var array + * @var array|null */ - private $arrJumpTo; + private ?array $arrJumpTo = null; /** * The database connection. * - * @var IFilterSettingFactory + * @var IFilterSettingFactory|null */ - private $filterFactory; + private ?IFilterSettingFactory $filterFactory = null; /** * The filter URL builder. * - * @var FilterUrlBuilder + * @var FilterUrlBuilder|null */ - private $filterUrlBuilder; + private ?FilterUrlBuilder $filterUrlBuilder = null; /** * Get the jump to page data. @@ -81,26 +87,28 @@ class HybridFilterBlock extends MetaModelHybrid */ public function getJumpTo() { - if (!isset($this->arrJumpTo)) { - /** @var \Database\Result $page */ - $page = $GLOBALS['objPage']; - $this->setJumpTo($page->row()); - + if (null === $this->arrJumpTo) { if ($this->metamodel_jumpTo) { // Page to jump to when filter submit. $statement = $this->getConnection() ->createQueryBuilder() - ->select('t.id, t.alias') + ->select('t.id', 't.alias') ->from('tl_page', 't') ->where('t.id=:id') ->setParameter('id', $this->metamodel_jumpTo) ->setMaxResults(1) ->executeQuery(); - if ($statement->rowCount()) { - $this->setJumpTo($statement->fetchAssociative()); + if (false !== ($row = $statement->fetchAssociative())) { + $this->arrJumpTo = $row; + + return $this->arrJumpTo; } } + + /** @var Result $page */ + $page = $GLOBALS['objPage']; + $this->arrJumpTo = $page->row(); } return $this->arrJumpTo; @@ -127,6 +135,7 @@ public function setJumpTo($arrJumpTo) */ public function getFilterCollection() { + /** @psalm-suppress UndefinedThisPropertyFetch */ return $this ->getFilterFactory() ->createCollection($this->metamodel_filtering); @@ -144,6 +153,7 @@ public function generate() $this->strTemplate = $this->metamodel_fef_template; } + /** @psalm-suppress DeprecatedClass */ return parent::generate(); } @@ -157,7 +167,8 @@ protected function compile() $objFilter = new FrontendFilter($this->getConnection(), $this->getFilterUrlBuilder()); $arrFilter = $objFilter->getMetaModelFrontendFilter($this); - $this->Template->setData(array_merge($this->Template->getData(), $arrFilter)); + $this->Template->setData(\array_merge($this->Template->getData(), $arrFilter)); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ $this->Template->submit = $arrFilter['submit']; } @@ -169,7 +180,10 @@ protected function compile() private function getFilterFactory(): IFilterSettingFactory { if (null === $this->filterFactory) { - return $this->filterFactory = System::getContainer()->get('metamodels.filter_setting_factory'); + $filterSettingFactory = System::getContainer()->get('metamodels.filter_setting_factory'); + assert($filterSettingFactory instanceof IFilterSettingFactory); + + return $this->filterFactory = $filterSettingFactory; } return $this->filterFactory; @@ -183,7 +197,10 @@ private function getFilterFactory(): IFilterSettingFactory private function getFilterUrlBuilder(): FilterUrlBuilder { if (null === $this->filterUrlBuilder) { - return $this->filterUrlBuilder = System::getContainer()->get('metamodels.filter_url'); + $filterUrl = System::getContainer()->get('metamodels.filter_url'); + assert($filterUrl instanceof FilterUrlBuilder); + + return $this->filterUrlBuilder = $filterUrl; } return $this->filterUrlBuilder; diff --git a/src/FrontendIntegration/HybridFilterClearAll.php b/src/FrontendIntegration/HybridFilterClearAll.php index 1d18b42d7..305963697 100644 --- a/src/FrontendIntegration/HybridFilterClearAll.php +++ b/src/FrontendIntegration/HybridFilterClearAll.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,19 +16,24 @@ * @author Sven Baumann * @author Andreas Nölke * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\FrontendIntegration; +use Contao\FrontendTemplate; use Contao\System; +use MetaModels\Filter\FilterUrlBuilder; +use Symfony\Component\HttpFoundation\Request; /** * Content element clearing the FE-filter. * - * @property \FrontendTemplate $Template + * @property FrontendTemplate $Template + * + * @psalm-suppress DeprecatedClass */ abstract class HybridFilterClearAll extends MetaModelHybrid { @@ -60,11 +65,17 @@ abstract class HybridFilterClearAll extends MetaModelHybrid */ public function generate() { - if (TL_MODE == 'BE') { + if ( + (bool) System::getContainer()->get('contao.routing.scope_matcher') + ?->isBackendRequest( + System::getContainer()->get('request_stack')?->getCurrentRequest() ?? Request::create('') + ) + ) { + /** @psalm-suppress DeprecatedClass */ return parent::generate(); } - return sprintf('[[[metamodelfrontendfilterclearall::%s::%s]]]', $this->type, $this->id); + return \sprintf('[[[metamodelfrontendfilterclearall::%s::%s]]]', $this->type, $this->id); } /** @@ -79,7 +90,10 @@ protected function compile() { $blnActiveParam = false; $filterUrlBuilder = System::getContainer()->get('metamodels.filter_url'); - $filterUrl = $filterUrlBuilder->getCurrentFilterUrl(); + assert($filterUrlBuilder instanceof FilterUrlBuilder); + + $filterUrl = $filterUrlBuilder->getCurrentFilterUrl(); + foreach ($GLOBALS['MM_FILTER_PARAMS'] as $param) { if ($filterUrl->hasSlug($param)) { $filterUrl->setSlug($param, ''); @@ -94,10 +108,12 @@ protected function compile() } // Check if we have filter and if we have active params. + /** @psalm-suppress InvalidPropertyAssignmentValue */ $this->Template->active = ( - !is_array($GLOBALS['MM_FILTER_PARAMS']) - || count($GLOBALS['MM_FILTER_PARAMS']) == 0 + !\is_array($GLOBALS['MM_FILTER_PARAMS']) + || \count($GLOBALS['MM_FILTER_PARAMS']) === 0 ); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ $this->Template->activeParam = $blnActiveParam; // Build FE url. @@ -116,6 +132,7 @@ public function generateReal() $this->strTemplate = $this->metamodel_fef_template; } + /** @psalm-suppress DeprecatedClass */ return parent::generate(); } } diff --git a/src/FrontendIntegration/HybridList.php b/src/FrontendIntegration/HybridList.php index d174e851b..3b194332f 100644 --- a/src/FrontendIntegration/HybridList.php +++ b/src/FrontendIntegration/HybridList.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -19,22 +19,29 @@ * @author Oliver Hoff * @author Stefan Heimes * @author Richard Henkenjohann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\FrontendIntegration; +use Contao\FrontendTemplate; use Contao\Input; use Contao\StringUtil; use Contao\System; +use MetaModels\Filter\FilterUrlBuilder; use MetaModels\ItemList; /** * Implementation of the MetaModel content element. * - * @property \FrontendTemplate $Template + * @property FrontendTemplate $Template + * + * @deprecated We switched to fragments {@see ItemListController.php} in MetaModels 2.2. To be removed in MetaModels 3. + * + * @psalm-suppress DeprecatedClass + * @psalm-suppress PropertyNotSetInConstructor */ class HybridList extends MetaModelHybrid { @@ -57,6 +64,7 @@ public function generate() $this->strTemplate = $this->metamodel_layout; } + /** @psalm-suppress DeprecatedClass */ return parent::generate(); } @@ -66,19 +74,25 @@ public function generate() * * @param ItemList $objItemRenderer The list renderer instance to be used. * - * @return string[] + * @return array> */ protected function getFilterParameters($objItemRenderer) { $filterUrlBuilder = System::getContainer()->get('metamodels.filter_url'); - $filterUrl = $filterUrlBuilder->getCurrentFilterUrl(); + assert($filterUrlBuilder instanceof FilterUrlBuilder); + + $filterUrl = $filterUrlBuilder->getCurrentFilterUrl(); $result = []; foreach ($objItemRenderer->getFilterSettings()->getParameters() as $name) { if ($filterUrl->hasSlug($name)) { - $result[$name] = $filterUrl->getSlug($name); + $value = $filterUrl->getSlug($name); + assert(\is_string($value)); + $result[$name] = $value; } elseif ($filterUrl->hasGet($name)) { - $result[$name] = $filterUrl->getGet($name); + $value = $filterUrl->getGet($name); + assert(\is_array($value) || \is_string($value)); + $result[$name] = $value; } // DAMN Contao - we have to "mark" the keys in the Input class as used as we get an 404 otherwise. Input::get($name); @@ -96,19 +110,29 @@ protected function compile() { $objItemRenderer = new ItemList(); + /** + * @psalm-suppress UndefinedThisPropertyFetch + * @psalm-suppress UndefinedMagicPropertyAssignment + */ $this->Template->searchable = !$this->metamodel_donotindex; - $sorting = $this->metamodel_sortby; + /** @psalm-suppress UndefinedThisPropertyFetch */ + $sorting = $this->metamodel_sortby; + /** @psalm-suppress UndefinedThisPropertyFetch */ $direction = $this->metamodel_sortby_direction; if ($this->metamodel_sort_override) { - if (\Input::get('orderBy')) { - $sorting = \Input::get('orderBy'); + if (Input::get('orderBy')) { + $sorting = Input::get('orderBy'); } - if (\Input::get('orderDir')) { - $direction = \Input::get('orderDir'); + if (Input::get('orderDir')) { + $direction = Input::get('orderDir'); } } + /** + * @psalm-suppress UndefinedThisPropertyFetch + * @psalm-suppress UndefinedMagicPropertyAssignment + */ $objItemRenderer ->setMetaModel($this->metamodel, $this->metamodel_rendersettings) ->setLimit($this->metamodel_use_limit, $this->metamodel_offset, $this->metamodel_limit) @@ -122,9 +146,15 @@ protected function compile() ->setMetaTags($this->metamodel_meta_title, $this->metamodel_meta_description); // Render items with encoded email strings as contao standard. + /** + * @psalm-suppress UndefinedThisPropertyFetch + * @psalm-suppress UndefinedMagicPropertyAssignment + */ $this->Template->items = - \StringUtil::encodeEmail($objItemRenderer->render($this->metamodel_noparsing, $this)); + StringUtil::encodeEmail($objItemRenderer->render($this->metamodel_noparsing, $this)); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ $this->Template->numberOfItems = $objItemRenderer->getItems()->getCount(); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ $this->Template->pagination = $objItemRenderer->getPagination(); } } diff --git a/src/FrontendIntegration/MetaModelHybrid.php b/src/FrontendIntegration/MetaModelHybrid.php index 11f0c87fb..e48d20272 100644 --- a/src/FrontendIntegration/MetaModelHybrid.php +++ b/src/FrontendIntegration/MetaModelHybrid.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Ingolf Steinhardt * @author David Molineus * @author Richard Henkenjohann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +25,7 @@ use Contao\BackendTemplate; use Contao\ContentModel; +use Contao\Database\Result; use Contao\FormModel; use Contao\Hybrid; use Contao\ModuleModel; @@ -32,17 +33,31 @@ use Contao\System; use Doctrine\DBAL\Connection; use MetaModels\IFactory; +use MetaModels\IMetaModel; use MetaModels\IMetaModelsServiceContainer; use MetaModels\MetaModelsServiceContainer; +use Symfony\Component\HttpFoundation\Request; /** * Base implementation of a MetaModel Hybrid element. * - * @property string metamodel The id of the MetaModel to use. - * @property string metamodel_filtering The id of the MetaModel filter setting to use. - * @property string metamodel_rendersettings The id of the MetaModel render setting to use. + * @property string $id The id of the element. + * @property string $name The module name to use (if type is module). + * @property string $metamodel The id of the MetaModel to use. + * @property string $metamodel_filtering The id of the MetaModel filter setting to use. + * @property string $metamodel_rendersettings The id of the MetaModel render setting to use. + * @property bool $metamodel_sort_override The flag to override sorting. + * + * @psalm-type TDatabaseResult=object{ + * cssID: string, + * typePrefix: ?string, + * type: string, + * headline: string, + * } * * @deprecated We switched to fragments in MetaModels 2.2. To be removed in MetaModels 3.0. + * + * @psalm-suppress PropertyNotSetInConstructor */ abstract class MetaModelHybrid extends Hybrid { @@ -70,9 +85,9 @@ abstract class MetaModelHybrid extends Hybrid /** * The database connection. * - * @var Connection + * @var Connection|null */ - private $connection; + private ?Connection $connection = null; /** * Retrieve the service container. @@ -80,6 +95,8 @@ abstract class MetaModelHybrid extends Hybrid * @return IMetaModelsServiceContainer * * @deprecated The service container will get removed, inject needed services instead. + * + * @psalm-suppress DeprecatedInterface */ public function getServiceContainer() { @@ -90,7 +107,11 @@ public function getServiceContainer() ); // @codingStandardsIgnoreEnd - return System::getContainer()->get(MetaModelsServiceContainer::class); + /** @psalm-suppress DeprecatedClass */ + $serviceContainer = System::getContainer()->get(MetaModelsServiceContainer::class); + assert($serviceContainer instanceof MetaModelsServiceContainer); + + return $serviceContainer; } /** @@ -100,7 +121,10 @@ public function getServiceContainer() */ protected function getFactory() { - return System::getContainer()->get('metamodels.factory'); + $factory = System::getContainer()->get('metamodels.factory'); + assert($factory instanceof IFactory); + + return $factory; } /** @@ -113,12 +137,13 @@ protected function getConnection() if (null === $this->connection) { // @codingStandardsIgnoreStart @trigger_error( - 'Connection is missing in class ' . static::class . - '. The automatic fallback will be dropped in MetaModels 3.0. Please use dependency injection', + 'Connection is missing. It has to be passed in the constructor. Fallback will be dropped.', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - return $this->connection = System::getContainer()->get('database_connection'); + $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); + $this->connection = $connection; } return $this->connection; @@ -127,23 +152,26 @@ protected function getConnection() /** * Create a new instance. * - * @param ContentModel|ModuleModel|FormModel $objElement The object from the database. - * + * @param Result|TDatabaseResult $objElement The object from the database. * @param string $strColumn The column the element is displayed within. */ public function __construct($objElement, $strColumn = 'main') { + /** @psalm-suppress ArgumentTypeCoercion - Contao has incomplete type annotation. */ parent::__construct($objElement, $strColumn); - $this->arrData = method_exists($objElement, 'row') ? $objElement->row() : (array) $objElement; + $this->arrData = \method_exists($objElement, 'row') ? $objElement->row() : (array) $objElement; // Get CSS ID and headline from the parent element (!). + /** @psalm-suppress UndefinedThisPropertyFetch */ $this->cssID = StringUtil::deserialize($objElement->cssID, true); $this->typePrefix = $objElement->typePrefix ?? ''; - $this->strKey = $objElement->type; - $arrHeadline = StringUtil::deserialize($objElement->headline); - $this->headline = is_array($arrHeadline) ? $arrHeadline['value'] : $arrHeadline; - $this->hl = is_array($arrHeadline) ? $arrHeadline['unit'] : 'h1'; + /** @psalm-suppress UndefinedThisPropertyFetch */ + $this->strKey = $objElement->type; + $arrHeadline = StringUtil::deserialize($objElement->headline); + /** @psalm-suppress UndefinedThisPropertyFetch */ + $this->headline = \is_array($arrHeadline) ? $arrHeadline['value'] : $arrHeadline; + $this->hl = \is_array($arrHeadline) ? $arrHeadline['unit'] : 'h1'; } /** @@ -157,7 +185,12 @@ public function __construct($objElement, $strColumn = 'main') */ public function generate() { - if (TL_MODE == 'BE') { + if ( + (bool) System::getContainer()->get('contao.routing.scope_matcher') + ?->isBackendRequest( + System::getContainer()->get('request_stack')?->getCurrentRequest() ?? Request::create('') + ) + ) { $strInfo = ''; if ($this->metamodel) { // Add CSS file. @@ -168,11 +201,11 @@ public function generate() '
    %s: %s
    '; $factory = $this->getFactory(); - if (null === $metaModelName = $factory->translateIdToMetaModelName($this->metamodel)) { - return 'Unknown MetaModel: ' . $this->metamodel; - } + $metaModelName = $factory->translateIdToMetaModelName($this->metamodel); $metaModel = $factory->getMetaModel($metaModelName); - $strInfo = sprintf( + assert($metaModel instanceof IMetaModel); + + $strInfo = \sprintf( $infoTemplate, $GLOBALS['TL_LANG']['MSC']['mm_be_info_name'][1], $GLOBALS['TL_LANG']['MSC']['mm_be_info_name'][0], @@ -194,7 +227,7 @@ public function generate() ->fetchFirstColumn(); if ($infoFi) { - $strInfo .= sprintf( + $strInfo .= \sprintf( $infoTemplate, $GLOBALS['TL_LANG']['MSC']['mm_be_info_filter'][1], $GLOBALS['TL_LANG']['MSC']['mm_be_info_filter'][0], @@ -216,7 +249,7 @@ public function generate() ->fetchFirstColumn(); if ($infoRs) { - $strInfo .= sprintf( + $strInfo .= \sprintf( $infoTemplate, $GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting'][1], $GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting'][0], @@ -226,12 +259,16 @@ public function generate() } } - $objTemplate = new BackendTemplate('be_wildcard'); + $objTemplate = new BackendTemplate('be_wildcard'); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ $objTemplate->wildcard = $this->wildCardName . $strInfo; - $objTemplate->title = $this->headline; - $objTemplate->id = $this->id; - $objTemplate->link = ($this->typePrefix == 'mod_' ? 'FE-Modul: ' : '') . $this->name; - $objTemplate->href = sprintf($this->wildCardLink, $this->id); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $objTemplate->title = $this->headline; + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $objTemplate->id = $this->id; + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $objTemplate->link = ($this->typePrefix === 'mod_' ? 'FE-Modul: ' : '') . $this->name; + $objTemplate->href = \sprintf($this->wildCardLink, $this->id); return $objTemplate->parse(); } diff --git a/src/FrontendIntegration/Module/Filter.php b/src/FrontendIntegration/Module/Filter.php index 887f776c9..72973ae09 100644 --- a/src/FrontendIntegration/Module/Filter.php +++ b/src/FrontendIntegration/Module/Filter.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 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-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +25,9 @@ /** * Frontend module for FE-filtering. + * + * @psalm-suppress DeprecatedClass + * @psalm-suppress PropertyNotSetInConstructor */ class Filter extends HybridFilterBlock { diff --git a/src/FrontendIntegration/Module/FilterClearAll.php b/src/FrontendIntegration/Module/FilterClearAll.php index 3a8836a8e..8a02e9e71 100644 --- a/src/FrontendIntegration/Module/FilterClearAll.php +++ b/src/FrontendIntegration/Module/FilterClearAll.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Stefan Heimes * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +26,9 @@ /** * Content element clearing the FE-filter. + * + * @psalm-suppress DeprecatedClass + * @psalm-suppress PropertyNotSetInConstructor */ class FilterClearAll extends HybridFilterClearAll { diff --git a/src/FrontendIntegration/Module/ModelList.php b/src/FrontendIntegration/Module/ModelList.php index 1584411dc..ff5c78ba0 100644 --- a/src/FrontendIntegration/Module/ModelList.php +++ b/src/FrontendIntegration/Module/ModelList.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,7 +18,7 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author Richard Henkenjohann - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -31,6 +31,9 @@ * Implementation of the MetaModel content element. * * @deprecated We switched to fragments {@see ItemListController.php} in MetaModels 2.2. To be removed in MetaModels 3. + * + * @psalm-suppress DeprecatedClass + * @psalm-suppress PropertyNotSetInConstructor */ class ModelList extends HybridList { diff --git a/src/FrontendIntegration/ViewCombinations.php b/src/FrontendIntegration/ViewCombinations.php index 4a70a6803..caa641b20 100644 --- a/src/FrontendIntegration/ViewCombinations.php +++ b/src/FrontendIntegration/ViewCombinations.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +27,8 @@ * Retrieve combinations of view and input screens for the currently logged in user (either frontend or backend). * * @deprecated This will get removed. + * + * @psalm-suppress DeprecatedClass */ class ViewCombinations extends \MetaModels\Helper\ViewCombinations { @@ -36,6 +39,7 @@ class ViewCombinations extends \MetaModels\Helper\ViewCombinations */ protected function authenticateUser() { + /** @psalm-suppress DeprecatedMethod */ return $this->getUser()->authenticate(); } @@ -44,12 +48,12 @@ protected function authenticateUser() */ protected function getUserGroups() { - /** @noinspection PhpUndefinedFieldInspection */ // Special case in combinations, anonymous frontend users have the implicit group id -1. - if (!$this->getUser()->id) { + if (0 === (int) $this->getUser()->id) { return [-1]; } + /** psalm-suppress DeprecatedClass */ return parent::getUserGroups(); } } diff --git a/src/Helper/ContaoController.php b/src/Helper/ContaoController.php index 5f0b53fdc..a769de9cb 100644 --- a/src/Helper/ContaoController.php +++ b/src/Helper/ContaoController.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2023 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,8 @@ * @author Christian Schiffler * @author David Maack * @author Sven Baumann - * @copyright 2012-2021 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -38,7 +39,7 @@ class ContaoController extends Controller /** * The instance. * - * @var ContaoController + * @var ContaoController|null */ protected static $objInstance = null; diff --git a/src/Helper/EmptyTest.php b/src/Helper/EmptyTest.php index 17ddd56f4..f46be63b0 100644 --- a/src/Helper/EmptyTest.php +++ b/src/Helper/EmptyTest.php @@ -35,9 +35,11 @@ public static function isEmptyValue($mixValue): bool { if (is_array($mixValue)) { return self::isArrayEmpty($mixValue); - } elseif ('' === $mixValue) { + } + if ('' === $mixValue) { return true; - } elseif (null === $mixValue) { + } + if (null === $mixValue) { return true; } @@ -54,7 +56,7 @@ public static function isEmptyValue($mixValue): bool public static function isArrayEmpty(array $array): bool { // First off check for simple types. - if (empty($array)) { + if ([] === $array) { return true; } // Next check for a value array. @@ -62,15 +64,12 @@ public static function isArrayEmpty(array $array): bool return self::isArrayEmpty($array['value']); } // Now check sub arrays. - if (is_array($array)) { - foreach ($array as $value) { - if (!self::isEmptyValue($value)) { - return false; - } + foreach ($array as $value) { + if (!self::isEmptyValue($value)) { + return false; } - return true; } - return false; + return true; } } diff --git a/src/Helper/LocaleUtil.php b/src/Helper/LocaleUtil.php index 2b21f49b7..e602d2b5e 100644 --- a/src/Helper/LocaleUtil.php +++ b/src/Helper/LocaleUtil.php @@ -36,8 +36,9 @@ final class LocaleUtil */ public static function formatAsLanguageTag(string $localeId): string { - $packages = System::getContainer()->getParameter('kernel.packages'); - $coreVersion = $packages['contao/core-bundle']; + $packages = System::getContainer()->getParameter('kernel.packages'); + assert(is_array($packages)); + $coreVersion = $packages['contao/core-bundle'] ?? ''; if (\version_compare($coreVersion, '4.13', '>=')) { return self::formatAsLocale($localeId); diff --git a/src/Helper/PaginationGenerator.php b/src/Helper/PaginationGenerator.php index 51bb8a279..4af8c0299 100644 --- a/src/Helper/PaginationGenerator.php +++ b/src/Helper/PaginationGenerator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,7 @@ * @package MetaModels/core * @author Ingolf Steinhardt * @author Christian Schiffler - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -119,7 +119,7 @@ public function __construct( $this->urlBuilder = $urlBuilder; $this->numRows = $numRows; $this->rowsPerPage = $rowsPerPage; - $this->totalPages = ceil($this->numRows / $this->rowsPerPage); + $this->totalPages = (int) \ceil($this->numRows / $this->rowsPerPage); $this->numberOfLinks = $numberOfLinks; $this->pageParam = $pageParam; $this->paramType = $paramType; @@ -153,19 +153,31 @@ public function generateForFilterUrl(FilterUrl $filterUrl): string $page = $this->totalPages; } - $template = $this->template; - $template->hasFirst = $this->hasFirst($page); - $template->hasPrevious = $this->hasPrevious($page); - $template->hasNext = $this->hasNext($page); - $template->hasLast = $this->hasLast($page); - $template->pages = $this->getItemsAsArray($filterUrl, $page); - $template->page = $page; - $template->totalPages = $this->totalPages; - $template->first = $template->hasFirst ? $this->linkToPage($filterUrl, 1) : ''; - $template->previous = $template->hasPrevious ? $this->linkToPage($filterUrl, ($page - 1)) : ''; - $template->next = $template->hasNext ? $this->linkToPage($filterUrl, ($page + 1)) : ''; - $template->last = $template->hasLast ? $this->linkToPage($filterUrl, $this->totalPages) : ''; - $template->class = 'pagination-' . $this->pageParam; + $template = $this->template; + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->hasFirst = $this->hasFirst($page); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->hasPrevious = $this->hasPrevious($page); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->hasNext = $this->hasNext($page); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->hasLast = $this->hasLast($page); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->pages = $this->getItemsAsArray($filterUrl, $page); + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->page = $page; + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->totalPages = $this->totalPages; + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->first = $template->hasFirst ? $this->linkToPage($filterUrl, 1) : ''; + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->previous = $template->hasPrevious ? $this->linkToPage($filterUrl, ($page - 1)) : ''; + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->next = $template->hasNext ? $this->linkToPage($filterUrl, ($page + 1)) : ''; + /** @psalm-suppress UndefinedMagicPropertyAssignment */ + $template->last = $template->hasLast ? $this->linkToPage($filterUrl, $this->totalPages) : ''; + $template->class = 'pagination-' . $this->pageParam; + /** @psalm-suppress UndefinedMagicPropertyAssignment */ $template->paginationFragment = $this->paginationFragment; // @codingStandardsIgnoreStart // Adding rel="prev" and rel="next" links is not possible @@ -188,19 +200,34 @@ private function getCurrentPage(FilterUrl $filterUrl): int { switch ($this->paramType) { case 'get': - return (int) ($filterUrl->getGet($this->pageParam) ?? 1); + return (int) ($this->getGetPageParam($filterUrl) ?? 1); case 'slug': return (int) ($filterUrl->getSlug($this->pageParam) ?? 1); case 'slugNget': - return (int) ($filterUrl->getGet($this->pageParam) - ?? $filterUrl->getSlug($this->pageParam) - ?? 1); + return (int) ($this->getGetPageParam($filterUrl) ?? $filterUrl->getSlug($this->pageParam) ?? 1); default: } throw new InvalidArgumentException('Invalid configured value: ' . $this->paramType); } + /** + * Retrieve GET parameters. + * + * @param FilterUrl $filterUrl The filter URL. + * + * @return string|null + */ + private function getGetPageParam(FilterUrl $filterUrl): ?string + { + $value = $filterUrl->getGet($this->pageParam); + if (\is_array($value)) { + return null; + } + + return $value; + } + /** * Return true if the pagination menu has a "<< first" link * @@ -261,7 +288,7 @@ private function getItemsAsArray(FilterUrl $filterUrl, int $page): array { $links = []; - $numberOfLinks = floor($this->numberOfLinks / 2); + $numberOfLinks = (int) floor($this->numberOfLinks / 2); $firstOffset = ($page - $numberOfLinks - 1); if ($firstOffset > 0) { @@ -287,7 +314,7 @@ private function getItemsAsArray(FilterUrl $filterUrl, int $page): array } for ($i = $firstLink; $i <= $lastLink; $i++) { - if ($i == $page) { + if ($i === $page) { $links[] = [ 'page' => $i, 'href' => null @@ -320,9 +347,9 @@ private function linkToPage(FilterUrl $filterUrl, int $page): string $pageFilterUrl = $filterUrl->clone(); if ($this->paramType === 'get') { - $pageFilterUrl->setGet($this->pageParam, $page); + $pageFilterUrl->setGet($this->pageParam, (string) $page); } else { - $pageFilterUrl->setSlug($this->pageParam, $page)->setGet($this->pageParam, ''); + $pageFilterUrl->setSlug($this->pageParam, (string) $page)->setGet($this->pageParam, ''); } return $this->urlBuilder->generate($pageFilterUrl); diff --git a/src/Helper/PaginationLimitCalculator.php b/src/Helper/PaginationLimitCalculator.php index 0166bc5f3..29ce680b4 100644 --- a/src/Helper/PaginationLimitCalculator.php +++ b/src/Helper/PaginationLimitCalculator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Richard Henkenjohann * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -31,6 +31,8 @@ /** * Helper class to calculate limit and offset and pagination. + * + * @SuppressWarnings(PHPMD.TooManyFields) */ class PaginationLimitCalculator { @@ -60,7 +62,7 @@ class PaginationLimitCalculator * * @var int */ - private int $currentPage; + private int $currentPage = 0; /** * Pagination page break. @@ -102,7 +104,7 @@ class PaginationLimitCalculator * * @var int */ - private int $calculatedTotal; + private int $calculatedTotal = 0; /** * Flag if the data needs to be recalculated. @@ -114,7 +116,7 @@ class PaginationLimitCalculator /** * The filter url builder. * - * @var FilterUrlBuilder|object|null + * @var FilterUrlBuilder */ private FilterUrlBuilder $filterUrlBuilder; @@ -146,6 +148,13 @@ class PaginationLimitCalculator */ private string $paginationTemplate; + /** + * The filter URL. + * + * @var FilterUrl + */ + private FilterUrl $filterUrl; + /** * Create a new instance. * @@ -170,14 +179,14 @@ public function __construct( $this->paginationTemplate = $paginationTemplate; $this->paginationFragment = $paginationFragment; if (null === $filterUrlBuilder) { - $filterUrlBuilder = System::getContainer()->get('metamodels.filter_url'); // @codingStandardsIgnoreStart - @trigger_deprecation( - 'metamodels/core', - '2.2.0', - __CLASS__ . ' parameter FilterUrlBuilder is null, but the parameter should be set' + @trigger_error( + 'FilterUrlBuilder is missing. It has to be passed in the constructor. Fallback will be dropped.', + E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + $filterUrlBuilder = System::getContainer()->get('metamodels.filter_url'); + assert($filterUrlBuilder instanceof FilterUrlBuilder); } $this->filterUrlBuilder = $filterUrlBuilder; @@ -288,19 +297,17 @@ public function setLimit(int $limit): self */ public function getCurrentPage(): int { - if (isset($this->currentPage)) { + if (0 !== $this->currentPage) { return $this->currentPage; } switch ($this->paramType) { case 'get': - return (int) ($this->filterUrl->getGet($this->pageParam) ?? 1); + return (int) ($this->getGetPageParam() ?? 1); case 'slug': return (int) ($this->filterUrl->getSlug($this->pageParam) ?? 1); case 'slugNget': - return (int) ($this->filterUrl->getGet($this->pageParam) - ?? $this->filterUrl->getSlug($this->pageParam) - ?? 1); + return (int) ($this->getGetPageParam() ?? $this->filterUrl->getSlug($this->pageParam) ?? 1); default: } @@ -321,10 +328,9 @@ public function setCurrentPage(int $currentPage): self $this->currentPage = $currentPage; // @codingStandardsIgnoreStart - @trigger_deprecation( - 'metamodels/core', - '2.2.0', - __METHOD__ . ' is deprecated - the page is determined automatically from the current request' + @trigger_error( + '"' .__METHOD__ . '" is deprecated - the page is determined automatically from the current request.', + E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd @@ -416,7 +422,7 @@ public function getPaginationString(): string { $this->calculate(); - if ($this->getPerPage() == 0) { + if ($this->getPerPage() === 0) { return ''; } @@ -440,7 +446,7 @@ public function getPaginationString(): string /** * Retrieve the calculated offset. * - * @return int + * @return int|null */ public function getCalculatedOffset(): ?int { @@ -452,7 +458,7 @@ public function getCalculatedOffset(): ?int /** * Retrieve the calculated limit. * - * @return int + * @return int|null */ public function getCalculatedLimit(): ?int { @@ -461,6 +467,21 @@ public function getCalculatedLimit(): ?int return $this->calculatedLimit; } + /** + * Retrieve GET parameters. + * + * @return string|null + */ + private function getGetPageParam(): ?string + { + $value = $this->filterUrl->getGet($this->pageParam); + if (\is_array($value)) { + return null; + } + + return $value; + } + /** * Calculate the limit and offset with pagination. * @@ -474,22 +495,28 @@ private function calculatePaginated() if (($this->calculatedLimit !== null) && ($this->calculatedTotal > $this->calculatedLimit)) { $this->calculatedTotal -= $this->calculatedLimit; } - $this->calculatedTotal -= $this->calculatedOffset; + if ($this->calculatedOffset !== null) { + $this->calculatedTotal -= $this->calculatedOffset; + } // Get the current page. $page = $this->getCurrentPage(); if ($page > ($this->calculatedTotal / $this->getPerPage())) { - $page = (int) ceil($this->calculatedTotal / $this->getPerPage()); + $page = (int) \ceil($this->calculatedTotal / $this->getPerPage()); } // Set limit and offset. - $pageOffset = ((max($page, 1) - 1) * $this->getPerPage()); - $this->calculatedOffset += $pageOffset; + if (null !== $this->calculatedOffset) { + $this->calculatedOffset += ((\max($page, 1) - 1) * $this->getPerPage()); + } if ($this->calculatedLimit === null) { $this->calculatedLimit = $this->getPerPage(); } else { - $this->calculatedLimit = min(($this->calculatedLimit - $this->calculatedOffset), $this->getPerPage()); + $this->calculatedLimit = \min( + ($this->calculatedLimit - ($this->calculatedOffset ?? 0)), + $this->getPerPage() + ); } } @@ -497,6 +524,10 @@ private function calculatePaginated() * Calculate the pagination based upon the offset, limit and total amount of items. * * @return void + * + * @psalm-assert false $this->isDirty + * @psalm-assert int $this->calculatedOffset + * @psalm-assert int $this->calculatedLimit */ protected function calculate() { @@ -511,11 +542,11 @@ protected function calculate() // If defined, we override the pagination here. if ($this->isLimited()) { - if ($this->getLimit()) { - $this->calculatedLimit = $this->getLimit(); + if ($limit = $this->getLimit()) { + $this->calculatedLimit = $limit; } - if ($this->getOffset()) { - $this->calculatedOffset = $this->getOffset(); + if ($offset = $this->getOffset()) { + $this->calculatedOffset = $offset; } } diff --git a/src/Helper/SortingLinkGenerator.php b/src/Helper/SortingLinkGenerator.php index c01a49b9a..d9c42e379 100644 --- a/src/Helper/SortingLinkGenerator.php +++ b/src/Helper/SortingLinkGenerator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,7 @@ * * @package MetaModels/core * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -125,44 +125,19 @@ public function generateSortingLink(IAttribute $attribute, string $type): array { $pageFilterUrl = $this->urlBuilder->getCurrentFilterUrl(); $sortBy = $this->tryReadFromSlugOrGet($pageFilterUrl, $this->sortOrderByParam, $this->sortParamType) - ?: $this->defaultSorting; + ?? $this->defaultSorting; $sortDirection = $this->tryReadFromSlugOrGet($pageFilterUrl, $this->sortOrderDirParam, $this->sortParamType) - ?: $this->defaultDirection; + ?? $this->defaultDirection; $attributeName = $attribute->getColName(); $active = $sortBy === $attributeName; - switch ($type) { - case 'toggle': - // In case of toggle, we override the type with the desired direction. - $type = 'asc'; - if ($active) { - $type = \strtolower($sortDirection) === 'desc' ? 'asc' : 'desc'; - } - // NO break here! - case 'asc': - case 'desc': - $dir = $type; - break; - default: - throw new RuntimeException('Unknown link type: ' . $type); - } + $dir = $this->determineDirection($type, $active, $sortDirection); if ($attributeName === $this->defaultSorting && $dir === $this->defaultDirection) { $attributeName = ''; } - if ('get' === $this->sortParamType) { - $pageFilterUrl->setGet($this->sortOrderByParam, $attributeName); - $pageFilterUrl->setGet($this->sortOrderDirParam, $attributeName ? $dir : ''); - } else { - // Use slug or slugNget. - $pageFilterUrl - ->setSlug($this->sortOrderByParam, $attributeName) - ->setGet($this->sortOrderByParam, ''); - $pageFilterUrl - ->setSlug($this->sortOrderDirParam, $attributeName ? $dir : '') - ->setGet($this->sortOrderDirParam, ''); - } + $this->updateSortingInFilterUrl($pageFilterUrl, $attributeName, $dir); return [ 'attribute' => $attribute, @@ -170,7 +145,7 @@ public function generateSortingLink(IAttribute $attribute, string $type): array 'href' => $this->urlBuilder->generate($pageFilterUrl) . ($this->sortFragment ? '#' . $this->sortFragment : ''), 'direction' => $dir, - 'active' => (bool) $active, + 'active' => $active, 'class' => 'sort' . ($active ? ' active' : '') . ' ' . $dir, 'label' => $this->translator->trans( 'MSC.orderMetaModelListBy' . ($dir === 'asc' ? 'Ascending' : 'Descending'), @@ -180,6 +155,34 @@ public function generateSortingLink(IAttribute $attribute, string $type): array ]; } + /** + * Determine the direction to use. + * + * @param string $type Type of the link to generate a direction for. + * @param bool $active Flag if the sorting is currently active. + * @param string $sortDirection The current direction (only considered when active). + * + * @return string + */ + private function determineDirection(string $type, bool $active, string $sortDirection): string + { + switch ($type) { + case 'toggle': + // In case of toggle, we override the type with the desired direction. + $type = 'asc'; + if ($active) { + $type = \strtolower($sortDirection) === 'desc' ? 'asc' : 'desc'; + } + // NO break here! + case 'asc': + case 'desc': + return $type; + break; + default: + } + throw new RuntimeException('Unknown link type: ' . $type); + } + /** * Get parameter from get or slug. * @@ -195,13 +198,13 @@ private function tryReadFromSlugOrGet(FilterUrl $filterUrl, string $sortParam, s switch ($sortType) { case 'get': - $result = $filterUrl->getGet($sortParam); + $result = $this->getGetParam($filterUrl, $sortParam); break; case 'slug': $result = $filterUrl->getSlug($sortParam); break; case 'slugNget': - $result = ($filterUrl->getGet($sortParam) ?? $filterUrl->getSlug($sortParam)); + $result = ($this->getGetParam($filterUrl, $sortParam) ?? $filterUrl->getSlug($sortParam)); break; default: } @@ -211,4 +214,47 @@ private function tryReadFromSlugOrGet(FilterUrl $filterUrl, string $sortParam, s return $result; } + + /** + * Retrieve GET parameters. + * + * @param FilterUrl $filterUrl The filter URL. + * @param string $sortParam The sort parameter. + * + * @return string|null + */ + private function getGetParam(FilterUrl $filterUrl, string $sortParam): ?string + { + $value = $filterUrl->getGet($sortParam); + if (\is_array($value)) { + return null; + } + + return $value; + } + + /** + * Write parameter to filter url. + * + * @param FilterUrl $pageFilterUrl The filter url to update. + * @param string $attributeName The name of the attribute to update. + * @param string $dir The direction. + * + * @return void + */ + private function updateSortingInFilterUrl(FilterUrl $pageFilterUrl, string $attributeName, mixed $dir): void + { + if ('get' === $this->sortParamType) { + $pageFilterUrl->setGet($this->sortOrderByParam, $attributeName); + $pageFilterUrl->setGet($this->sortOrderDirParam, $attributeName ? $dir : ''); + } else { + // Use slug or slugNget. + $pageFilterUrl + ->setSlug($this->sortOrderByParam, $attributeName) + ->setGet($this->sortOrderByParam, ''); + $pageFilterUrl + ->setSlug($this->sortOrderDirParam, $attributeName ? $dir : '') + ->setGet($this->sortOrderDirParam, ''); + } + } } diff --git a/src/Helper/TableManipulation.php b/src/Helper/TableManipulation.php index 801b787c2..fb81c8a75 100644 --- a/src/Helper/TableManipulation.php +++ b/src/Helper/TableManipulation.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Cliff Parnitzky * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,12 +26,14 @@ use Contao\System; use ContaoCommunityAlliance\DcGeneral\Contao\InputProvider; +use MetaModels\IMetaModelsServiceContainer; use MetaModels\MetaModelsServiceContainer; /** * This is the class for table manipulations like creation/renaming/deleting of tables and columns. * * @SuppressWarnings(PHPMD.TooManyPublicMethods) + * @SuppressWarnings(PHPMD.LongVariable) */ class TableManipulation { @@ -39,7 +41,7 @@ class TableManipulation * SQL statement template to create a table. * First parameter is the table name. */ - const STATEMENT_CREATE_TABLE = ' + public const STATEMENT_CREATE_TABLE = ' CREATE TABLE `%s` ( `id` int(10) unsigned NOT NULL auto_increment, `pid` int(10) unsigned NOT NULL, @@ -52,13 +54,13 @@ class TableManipulation * SQL statement template to rename a table. * First parameter is the old name, second parameter is the new name. */ - const STATEMENT_RENAME_TABLE = 'ALTER TABLE `%s` RENAME TO `%s`'; + public const STATEMENT_RENAME_TABLE = 'ALTER TABLE `%s` RENAME TO `%s`'; /** * SQL statement template to drop a table. * First parameter is the table name of the table to drop. */ - const STATEMENT_DROP_TABLE = 'DROP TABLE `%s`'; + public const STATEMENT_DROP_TABLE = 'DROP TABLE `%s`'; /** * SQL statement template to rename a column of a table. @@ -67,7 +69,7 @@ class TableManipulation * Third parameter is the new name of the column. * Fourth parameter is the new type of the column. */ - const STATEMENT_RENAME_COLUMN = 'ALTER TABLE `%s` CHANGE COLUMN %s %s %s'; + public const STATEMENT_RENAME_COLUMN = 'ALTER TABLE `%s` CHANGE COLUMN %s %s %s'; /** * SQL statement template to add a column to a table. @@ -75,13 +77,13 @@ class TableManipulation * Second parameter is the column name. * Third parameter is the type of the new column. */ - const STATEMENT_CREATE_COLUMN = 'ALTER TABLE `%s` ADD %s %s'; + public const STATEMENT_CREATE_COLUMN = 'ALTER TABLE `%s` ADD %s %s'; /** * SQL statement template to delete a column from a table. * First parameter is the name of the column. */ - const STATEMENT_DROP_COLUMN = 'ALTER TABLE `%s` DROP COLUMN %s'; + public const STATEMENT_DROP_COLUMN = 'ALTER TABLE `%s` DROP COLUMN %s'; /** * SQL statement template to add a index to a column of a table. @@ -89,14 +91,14 @@ class TableManipulation * second parameter is indextype * third parameter is name of the column. */ - const STATEMENT_ADD_INDEX_COLUMN = 'ALTER TABLE `%s` ADD %s(%s)'; + public const STATEMENT_ADD_INDEX_COLUMN = 'ALTER TABLE `%s` ADD %s(%s)'; /** * List of reserved column post fix. * * @var string[] */ - protected static $reservedColumnPostFix = array('__sort'); + protected static $reservedColumnPostFix = ['__sort']; /** * All system columns that always are defined in a MetaModel table. @@ -116,7 +118,11 @@ class TableManipulation */ protected static function getDB() { - return System::getContainer()->get(MetaModelsServiceContainer::class)->getDatabase(); + /** @psalm-suppress DeprecatedClass */ + $serviceContainer = System::getContainer()->get(MetaModelsServiceContainer::class); + assert($serviceContainer instanceof IMetaModelsServiceContainer); + /** @psalm-suppress DeprecatedMethod */ + return $serviceContainer->getDatabase(); } /** @@ -130,14 +136,15 @@ public static function isReserveColumnPostFix($strColName) { $inputProvider = new InputProvider(); - if (!$inputProvider->hasValue('colname') - || strtolower($strColName) !== strtolower($inputProvider->getValue('colname')) + if ( + !$inputProvider->hasValue('colname') + || \strtolower($strColName) !== \strtolower($inputProvider->getValue('colname')) ) { return false; } foreach (self::$reservedColumnPostFix as $postFix) { - if ($postFix !== strtolower(substr($strColName, -strlen($postFix)))) { + if ($postFix !== \strtolower(\substr($strColName, -\strlen($postFix)))) { continue; } @@ -158,7 +165,7 @@ public static function isValidMySQLIdentifier($strName) { // Match for valid table/column name, according to MySQL, a table name must start // with a letter and must be combined of letters, decimals and underscore. - return (1 == preg_match('/^[a-z_][a-z\d_]*$/i', $strName)); + return (1 === \preg_match('/^[a-z_][a-z\d_]*$/i', $strName)); } /** @@ -197,7 +204,7 @@ public static function isValidColumnName($strColName) */ public static function isSystemColumn($strColName) { - return in_array($strColName, $GLOBALS['METAMODELS_SYSTEM_COLUMNS']); + return \in_array($strColName, $GLOBALS['METAMODELS_SYSTEM_COLUMNS']); } /** @@ -215,7 +222,7 @@ public static function isSystemColumn($strColName) public static function checkTablename($strTableName) { if (!self::isValidTablename($strTableName)) { - throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['invalidTableName'], $strTableName)); + throw new \Exception(\sprintf($GLOBALS['TL_LANG']['ERR']['invalidTableName'], $strTableName)); } } @@ -225,7 +232,6 @@ public static function checkTablename($strTableName) * If there is any problem, an Exception is raised, stating the nature of the error in the Exception message. * * @param string $strColName The name of the column. - * * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. * * @return void @@ -240,11 +246,11 @@ public static function checkTablename($strTableName) public static function checkColumnName($strColName, $blnAllowSystemCol = false) { if (!self::isValidColumnName($strColName)) { - throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['invalidColumnName'], $strColName)); + throw new \Exception(\sprintf($GLOBALS['TL_LANG']['ERR']['invalidColumnName'], $strColName)); } if ((!$blnAllowSystemCol) && self::isSystemColumn($strColName)) { - throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['systemColumn'], $strColName)); + throw new \Exception(\sprintf($GLOBALS['TL_LANG']['ERR']['systemColumn'], $strColName)); } } @@ -263,8 +269,9 @@ public static function checkColumnName($strColName, $blnAllowSystemCol = false) public static function checkTableExists($strTableName) { self::checkTablename($strTableName); + /** @psalm-suppress DeprecatedMethod */ if (!self::getDB()->tableExists($strTableName, null, true)) { - throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['tableDoesNotExist'], $strTableName)); + throw new \Exception(\sprintf($GLOBALS['TL_LANG']['ERR']['tableDoesNotExist'], $strTableName)); } } @@ -283,8 +290,9 @@ public static function checkTableExists($strTableName) public static function checkTableDoesNotExist($strTableName) { self::checkTablename($strTableName); + /** @psalm-suppress DeprecatedMethod */ if (self::getDB()->tableExists($strTableName, null, true)) { - throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['tableExists'], $strTableName)); + throw new \Exception(\sprintf($GLOBALS['TL_LANG']['ERR']['tableExists'], $strTableName)); } } @@ -300,14 +308,14 @@ public static function checkTableDoesNotExist($strTableName) public static function createTable($strTableName) { self::checkTableDoesNotExist($strTableName); - self::getDB()->execute(sprintf(self::STATEMENT_CREATE_TABLE, $strTableName)); + /** @psalm-suppress DeprecatedMethod */ + self::getDB()->execute(\sprintf(self::STATEMENT_CREATE_TABLE, $strTableName)); } /** * Renames a table with the given name to the given new name. * * @param string $strTableName The name of the table to rename. - * * @param string $strNewTableName The name to which the table shall be renamed to. * * @return void @@ -318,8 +326,8 @@ public static function renameTable($strTableName, $strNewTableName) { self::checkTableExists($strTableName); self::checkTableDoesNotExist($strNewTableName); - - self::getDB()->execute(sprintf(self::STATEMENT_RENAME_TABLE, $strTableName, $strNewTableName)); + /** @psalm-suppress DeprecatedMethod */ + self::getDB()->execute(\sprintf(self::STATEMENT_RENAME_TABLE, $strTableName, $strNewTableName)); } /** @@ -334,17 +342,15 @@ public static function renameTable($strTableName, $strNewTableName) public static function deleteTable($strTableName) { self::checkTableExists($strTableName); - - self::getDB()->execute(sprintf(self::STATEMENT_DROP_TABLE, $strTableName)); + /** @psalm-suppress DeprecatedMethod */ + self::getDB()->execute(\sprintf(self::STATEMENT_DROP_TABLE, $strTableName)); } /** * Add a index to given tablename for specified columnname * * @param string $strTableName The table name. - * * @param string $strIndexType The index type. - * * @param string $strColName The column name to add a index. * * @return void @@ -355,8 +361,9 @@ public static function deleteTable($strTableName) public static function addIndex($strTableName, $strIndexType, $strColName) { self::checkColumnExists($strTableName, $strColName); + /** @psalm-suppress DeprecatedMethod */ self::getDB()->execute( - sprintf( + \sprintf( self::STATEMENT_ADD_INDEX_COLUMN, $strTableName, $strIndexType, @@ -369,9 +376,7 @@ public static function addIndex($strTableName, $strIndexType, $strColName) * Checks whether the given table exists. * * @param string $strTableName The table name to check. - * * @param string $strColName The column name to check. - * * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. * * @return void @@ -386,8 +391,11 @@ public static function checkColumnExists($strTableName, $strColName, $blnAllowSy { self::checkTableExists($strTableName); self::checkColumnName($strColName, $blnAllowSystemCol); + /** @psalm-suppress DeprecatedMethod */ if (!self::getDB()->fieldExists($strColName, $strTableName, true)) { - throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['columnDoesNotExist'], $strColName, $strTableName)); + throw new \Exception( + \sprintf($GLOBALS['TL_LANG']['ERR']['columnDoesNotExist'], $strColName, $strTableName) + ); } } @@ -395,9 +403,7 @@ public static function checkColumnExists($strTableName, $strColName, $blnAllowSy * Checks whether the given column does not exist. * * @param string $strTableName The table name to check. - * * @param string $strColName The column name to check. - * * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. * * @return void @@ -412,8 +418,9 @@ public static function checkColumnDoesNotExist($strTableName, $strColName, $blnA { self::checkTableExists($strTableName); self::checkColumnName($strColName, $blnAllowSystemCol); + /** @psalm-suppress DeprecatedMethod */ if (self::getDB()->fieldExists($strColName, $strTableName, true)) { - throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['columnExists'], $strColName, $strTableName)); + throw new \Exception(\sprintf($GLOBALS['TL_LANG']['ERR']['columnExists'], $strColName, $strTableName)); } } @@ -423,9 +430,7 @@ public static function checkColumnDoesNotExist($strTableName, $strColName, $blnA * Throws Exception if the table does not exist, the column name is invalid or the column already exists. * * @param string $strTableName The name of the table to add the column to. - * * @param string $strColumnName The name of the new column. - * * @param string $strType The SQL type notation of the new column. * * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. @@ -435,8 +440,9 @@ public static function checkColumnDoesNotExist($strTableName, $strColName, $blnA public static function createColumn($strTableName, $strColumnName, $strType, $blnAllowSystemCol = false) { self::checkColumnDoesNotExist($strTableName, $strColumnName, $blnAllowSystemCol); + /** @psalm-suppress DeprecatedMethod */ self::getDB()->execute( - sprintf( + \sprintf( self::STATEMENT_CREATE_COLUMN, $strTableName, $strColumnName, @@ -451,13 +457,9 @@ public static function createColumn($strTableName, $strColumnName, $strType, $bl * Throws Exception if the table does not exist, the column name is invalid or the column already exists. * * @param string $strTableName The name of the table the column is in. - * * @param string $strColumnName The current name of the column to be renamed. - * * @param string $strNewColumnName The new name for the column. - * * @param string $strNewType The new SQL type notation of the column. - * * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. * * @return void @@ -473,8 +475,9 @@ public static function renameColumn( self::checkColumnExists($strTableName, $strColumnName, $blnAllowSystemCol); self::checkColumnDoesNotExist($strTableName, $strNewColumnName, $blnAllowSystemCol); } + /** @psalm-suppress DeprecatedMethod */ self::getDB()->execute( - sprintf( + \sprintf( self::STATEMENT_RENAME_COLUMN, $strTableName, $strColumnName, @@ -490,9 +493,7 @@ public static function renameColumn( * Throws Exception if the table does not exist, the column name is invalid or the column does not exist. * * @param string $strTableName The name of the table the column is in. - * * @param string $strColumnName The name of the column to drop. - * * @param boolean $blnAllowSystemCol If this is set to true, no system column name checking will be applied. * * @return void @@ -500,8 +501,9 @@ public static function renameColumn( public static function dropColumn($strTableName, $strColumnName, $blnAllowSystemCol = false) { self::checkColumnExists($strTableName, $strColumnName, $blnAllowSystemCol); + /** @psalm-suppress DeprecatedMethod */ self::getDB()->execute( - sprintf( + \sprintf( self::STATEMENT_DROP_COLUMN, $strTableName, $strColumnName @@ -520,7 +522,9 @@ public static function dropColumn($strTableName, $strColumnName, $blnAllowSystem public static function setVariantSupport($strTableName, $blnVariantSupport) { if ($blnVariantSupport) { - if (self::getDB()->tableExists($strTableName, null, true) + /** @psalm-suppress DeprecatedMethod */ + if ( + self::getDB()->tableExists($strTableName, null, true) && (!self::getDB()->fieldExists('varbase', $strTableName, true)) ) { self::createColumn($strTableName, 'varbase', 'char(1) NOT NULL default \'\'', true); @@ -528,10 +532,13 @@ public static function setVariantSupport($strTableName, $blnVariantSupport) // If there is pre-existing data in the table, we need to provide a separate 'vargroup' value to all of // them, we can do this safely by setting all vargroups to the id of the base item. - self::getDB()->execute(sprintf('UPDATE `%s` t SET t.vargroup=id, t.varbase=1', $strTableName)); + /** @psalm-suppress DeprecatedMethod */ + self::getDB()->execute(\sprintf('UPDATE `%s` t SET t.vargroup=id, t.varbase=1', $strTableName)); } } else { - if (self::getDB()->tableExists($strTableName, null, true) + /** @psalm-suppress DeprecatedMethod */ + if ( + self::getDB()->tableExists($strTableName, null, true) && self::getDB()->fieldExists('varbase', $strTableName, true) ) { self::dropColumn($strTableName, 'varbase', true); diff --git a/src/Helper/TableManipulator.php b/src/Helper/TableManipulator.php index e8585e4a5..bcc799588 100644 --- a/src/Helper/TableManipulator.php +++ b/src/Helper/TableManipulator.php @@ -44,6 +44,7 @@ * This is the class for table manipulations like creation/renaming/deleting of tables and columns. * * @SuppressWarnings(PHPMD.TooManyPublicMethods) + * @SuppressWarnings(PHPMD.LongVariable) */ class TableManipulator { @@ -159,7 +160,7 @@ public function __construct(Connection $connection, array $systemColumns) */ public function isReservedWord($word): bool { - return in_array(strtoupper($word), self::$reservedWords); + return \in_array(\strtoupper($word), self::$reservedWords); } /** @@ -173,14 +174,15 @@ public function isReserveColumnPostFix($strColName): bool { $inputProvider = new InputProvider(); - if (!$inputProvider->hasValue('colname') - || strtolower($strColName) !== strtolower($inputProvider->getValue('colname')) + if ( + !$inputProvider->hasValue('colname') + || \strtolower($strColName) !== \strtolower($inputProvider->getValue('colname')) ) { return false; } foreach (self::$reservedColumnPostFix as $postFix) { - if ($postFix !== strtolower(substr($strColName, -strlen($postFix)))) { + if ($postFix !== \strtolower(\substr($strColName, -\strlen($postFix)))) { continue; } @@ -201,7 +203,7 @@ public function isValidMySQLIdentifier(string $strName): bool { // Match for valid table/column name, according to MySQL, a table name must start // with a letter and must be combined of letters, decimals and underscore. - return (1 == preg_match('/^[a-z_][a-z\d_]*$/i', $strName)); + return (1 == \preg_match('/^[a-z_][a-z\d_]*$/i', $strName)); } /** @@ -213,6 +215,7 @@ public function isValidMySQLIdentifier(string $strName): bool */ public function isValidTablename(string $strTableName): bool { + /** @psalm-suppress DeprecatedMethod */ return $this->isValidMySQLIdentifier($strTableName) && !$this->isReservedWord($strTableName); } @@ -225,6 +228,7 @@ public function isValidTablename(string $strTableName): bool */ public function isValidColumnName(string $strColName): bool { + /** @psalm-suppress DeprecatedMethod */ return $this->isValidMySQLIdentifier($strColName) && !$this->isReservedWord($strColName) && !$this->isReserveColumnPostFix($strColName); @@ -239,7 +243,7 @@ public function isValidColumnName(string $strColName): bool */ public function isSystemColumn(string $strColName): bool { - return in_array($strColName, $this->systemColumns); + return \in_array($strColName, $this->systemColumns); } /** @@ -339,7 +343,7 @@ public function checkTableDoesNotExist(string $strTableName): void public function createTable(string $strTableName): void { $this->checkTableDoesNotExist($strTableName); - $this->connection->executeQuery(sprintf(self::STATEMENT_CREATE_TABLE, $strTableName)); + $this->connection->executeQuery(\sprintf(self::STATEMENT_CREATE_TABLE, $strTableName)); } /** @@ -360,7 +364,7 @@ public function renameTable(string $strTableName, string $strNewTableName): void $this->checkTableExists($strTableName); $this->checkTableDoesNotExist($strNewTableName); - $this->connection->executeQuery(sprintf(self::STATEMENT_RENAME_TABLE, $strTableName, $strNewTableName)); + $this->connection->executeQuery(\sprintf(self::STATEMENT_RENAME_TABLE, $strTableName, $strNewTableName)); } /** @@ -400,7 +404,7 @@ public function addIndex(string $strTableName, string $strIndexType, string $str { $this->checkColumnExists($strTableName, $strColName); $this->connection->executeQuery( - sprintf( + \sprintf( self::STATEMENT_ADD_INDEX_COLUMN, $strTableName, $strIndexType, @@ -455,8 +459,7 @@ public function checkColumnDoesNotExist( string $strTableName, string $strColName, bool $blnAllowSystemCol = false - ): void - { + ): void { $this->checkTableExists($strTableName); $this->checkColumnName($strColName, $blnAllowSystemCol); @@ -484,11 +487,10 @@ public function createColumn( string $strColumnName, string $strType, bool $blnAllowSystemCol = false - ): void - { + ): void { $this->checkColumnDoesNotExist($strTableName, $strColumnName, $blnAllowSystemCol); $this->connection->executeQuery( - sprintf( + \sprintf( self::STATEMENT_CREATE_COLUMN, $strTableName, $strColumnName, @@ -518,14 +520,13 @@ public function renameColumn( string $strNewColumnName, string $strNewType, bool $blnAllowSystemCol = false - ): void - { + ): void { if ($strColumnName != $strNewColumnName) { $this->checkColumnExists($strTableName, $strColumnName, $blnAllowSystemCol); $this->checkColumnDoesNotExist($strTableName, $strNewColumnName, $blnAllowSystemCol); } $this->connection->executeQuery( - sprintf( + \sprintf( self::STATEMENT_RENAME_COLUMN, $strTableName, $strColumnName, @@ -552,7 +553,7 @@ public function dropColumn(string $strTableName, string $strColumnName, bool $bl { $this->checkColumnExists($strTableName, $strColumnName, $blnAllowSystemCol); $this->connection->executeQuery( - sprintf( + \sprintf( self::STATEMENT_DROP_COLUMN, $strTableName, $strColumnName @@ -573,19 +574,22 @@ public function dropColumn(string $strTableName, string $strColumnName, bool $bl public function setVariantSupport(string $strTableName, bool $blnVariantSupport): void { if ($blnVariantSupport) { - if ($this->connection->createSchemaManager()->tablesExist([$strTableName]) - && (!$this->fieldExists($strTableName, 'varbase'))) { + if ( + $this->connection->createSchemaManager()->tablesExist([$strTableName]) + && (!$this->fieldExists($strTableName, 'varbase')) + ) { $this->createColumn($strTableName, 'varbase', 'char(1) NOT NULL default \'\'', true); $this->createColumn($strTableName, 'vargroup', 'int(11) NOT NULL default 0', true); // If there is pre-existing data in the table, we need to provide a separate 'vargroup' value to all of // them, we can do this safely by setting all vargroups to the id of the base item. $this->connection->executeQuery( - sprintf('UPDATE `%1$s` SET %1$s.vargroup=id, %1$s.varbase=1', $strTableName) + \sprintf('UPDATE `%1$s` SET %1$s.vargroup=id, %1$s.varbase=1', $strTableName) ); } - } elseif ($this->connection->createSchemaManager()->tablesExist([$strTableName]) - && $this->fieldExists($strTableName, 'varbase') + } elseif ( + $this->connection->createSchemaManager()->tablesExist([$strTableName]) + && $this->fieldExists($strTableName, 'varbase') ) { $this->dropColumn($strTableName, 'varbase', true); $this->dropColumn($strTableName, 'vargroup', true); diff --git a/src/Helper/ToolboxFile.php b/src/Helper/ToolboxFile.php index 5065c0cb5..bb6b2c19b 100644 --- a/src/Helper/ToolboxFile.php +++ b/src/Helper/ToolboxFile.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -20,13 +20,15 @@ * @author Ingolf Steinhardt * @author Sven Baumann * @author Andreas Fischer - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\Helper; +use Contao\CoreBundle\Asset\ContaoContext; +use Contao\Model\Collection; use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; use ContaoCommunityAlliance\Contao\Bindings\Events\Image\ResizeImageEvent; use ContaoCommunityAlliance\UrlBuilder\UrlBuilder; @@ -46,6 +48,7 @@ use InvalidArgumentException; use Symfony\Component\Asset\Context\ContextInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; use Symfony\Component\HttpFoundation\Session\Session; /** @@ -53,6 +56,8 @@ * * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.ExcessiveClassLength) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) */ class ToolboxFile { @@ -63,35 +68,35 @@ class ToolboxFile * * @deprecated The event dispatcher will get removed in 3.0 as we now use the image factory. */ - private EventDispatcherInterface|null $dispatcher; + private EventDispatcherInterface|null $dispatcher = null; /** * The project root dir. * - * @var string|null + * @var string */ - private string|null $rootDir; + private string $rootDir; /** * The image factory for resizing. * * @var ImageFactoryInterface|null */ - private ImageFactoryInterface|null $imageFactory; + private ImageFactoryInterface|null $imageFactory = null; /** * The assets file context. * - * @var ContextInterface|null + * @var ContaoContext */ - private ContextInterface|null $filesContext; + private ContaoContext $filesContext; /** * The picture factory. * - * @var PictureFactoryInterface|null + * @var PictureFactoryInterface */ - private PictureFactoryInterface|null $pictureFactory; + private PictureFactoryInterface $pictureFactory; /** * Symfony session object @@ -124,9 +129,9 @@ class ToolboxFile /** * Determines if we want to generate images or not. * - * @var bool|null + * @var bool */ - protected bool|null $blnShowImages = false; + protected bool $blnShowImages = false; /** * Image resize information. @@ -220,7 +225,7 @@ public function __construct( Session $session = null ) { switch (true) { - case ($imageFactory instanceof ImageFactoryInterface) && !empty($rootDir): + case ($imageFactory instanceof ImageFactoryInterface) && (null !== $rootDir): $this->imageFactory = $imageFactory; $this->rootDir = $rootDir; break; @@ -232,6 +237,7 @@ public function __construct( E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + /** @psalm-suppress DeprecatedProperty */ $this->dispatcher = $imageFactory; break; // This is another deprecated fallback (remove in MetaModels 3.0). @@ -242,42 +248,52 @@ public function __construct( E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - $this->dispatcher = System::getContainer()->get('event_dispatcher'); + $dispatcher = System::getContainer()->get('event_dispatcher'); + assert($dispatcher instanceof EventDispatcherInterface); + /** @psalm-suppress DeprecatedProperty */ + $this->dispatcher = $dispatcher; } // Initialize some values to sane base. if (isset($GLOBALS['TL_CONFIG']) && isset($GLOBALS['TL_CONFIG']['allowedDownload'])) { $this->setAcceptedExtensions(StringUtil::trimsplit(',', $GLOBALS['TL_CONFIG']['allowedDownload'])); } - if (null === ($this->rootDir)) { + if (null === $rootDir) { // @codingStandardsIgnoreStart @trigger_error( 'Not passing an "%kernel.project_dir%" parameter is deprecated.', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - $this->rootDir = System::getContainer()->getParameter('kernel.project_dir'); + $rootDir = System::getContainer()->getParameter('kernel.project_dir'); + assert(\is_string($rootDir)); } + $this->rootDir = $rootDir; - if (null === ($this->filesContext = $filesContext)) { + if (null === $filesContext) { // @codingStandardsIgnoreStart @trigger_error( 'Not passing an "ContextInterface" is deprecated.', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - $this->filesContext = System::getContainer()->get('contao.assets.files_context'); + $filesContext = System::getContainer()->get('contao.assets.files_context'); + assert($filesContext instanceof ContextInterface); } + assert($filesContext instanceof ContaoContext); + $this->filesContext = $filesContext; - if (null === ($this->pictureFactory = $pictureFactory)) { + if (null === $pictureFactory) { // @codingStandardsIgnoreStart @trigger_error( 'Not passing an "PictureFactoryInterface" is deprecated.', E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - $this->pictureFactory = System::getContainer()->get('contao.image.picture_factory'); + $pictureFactory = System::getContainer()->get('contao.image.picture_factory'); + assert($pictureFactory instanceof PictureFactoryInterface); } + $this->pictureFactory = $pictureFactory; if (null === $session) { // @codingStandardsIgnoreStart @@ -289,7 +305,6 @@ public function __construct( $session = System::getContainer()->get('session'); assert($session instanceof Session); } - $this->session = $session; } @@ -354,7 +369,7 @@ public function getBaseLanguage() * * @param string|null $fallbackLanguage The fallback language to use. * - * @return ToolboxFile + * @return static */ public function setFallbackLanguage(?string $fallbackLanguage): static { @@ -376,11 +391,11 @@ public function getFallbackLanguage(): ?string /** * Set to show/prepare images or not. * - * @param boolean|null $blnShowImages True to show images, false otherwise. + * @param boolean $blnShowImages True to show images, false otherwise. * - * @return ToolboxFile + * @return static */ - public function setShowImages(?bool $blnShowImages): static + public function setShowImages(bool $blnShowImages): static { $this->blnShowImages = $blnShowImages; @@ -509,12 +524,12 @@ protected function collectFiles() $parameters = []; if (\count($this->pendingIds)) { $conditions[] = $table . '.uuid IN(' . - \implode(',', \array_fill(0, count($this->pendingIds), 'UNHEX(?)')) . ')'; + \implode(',', \array_fill(0, \count($this->pendingIds), 'UNHEX(?)')) . ')'; $parameters = \array_map('bin2hex', $this->pendingIds); $this->pendingIds = []; } - if (\count($this->pendingPaths)) { + if ([] !== $this->pendingPaths) { $slug = $table . '.path LIKE ?'; foreach ($this->pendingPaths as $pendingPath) { $conditions[] = $slug; @@ -527,11 +542,13 @@ protected function collectFiles() return; } - if ($files = FilesModel::findBy([\implode(' OR ', $conditions)], $parameters)) { + $files = FilesModel::findBy([\implode(' OR ', $conditions)], $parameters); + if ($files instanceof Collection) { $this->addFileModels($files); } - if (count($this->pendingPaths)) { + /** @psalm-suppress DocblockTypeContradiction - filled addFileModel */ + if ([] !== $this->pendingPaths) { // Run again. $this->collectFiles(); } @@ -556,6 +573,7 @@ protected function getDownloadLink($strFile) } $bag = $this->session->getBag('attributes'); + assert($bag instanceof AttributeBagInterface); $links = $bag->has('metaModels_downloads') ? $bag->get('metaModels_downloads') : []; if (!\is_array($links)) { @@ -604,7 +622,6 @@ protected function fetchAdditionalData() * This returns an array like: array('files' => array(), 'source' => array()) * * @param array $arrFiles The files to sort. - * * @param array $arrSource The source list. * * @return array The mapped result. @@ -639,7 +656,6 @@ protected function remapSorting($arrFiles, $arrSource) * random - Shuffle all the files around. * * @param string $sortType The sort condition to be applied. - * * @param array $sortIds The list of binary ids to sort by (sort type "manual" only). * * @return array The sorted file list. @@ -671,7 +687,8 @@ public function sortFiles($sortType, $sortIds = []) /** * Attach first, last and even/odd classes to the given array. * - * @param array $arrSource The array reference of the array to which the classes shall be added to. + * @param array> $arrSource The array reference of the array to which the classes + * shall be added to. * * @return void */ @@ -679,9 +696,9 @@ protected function addClasses(&$arrSource) { $countFiles = \count($arrSource); foreach (\array_keys($arrSource) as $k) { - $arrSource[$k]['class'] = (($k == 0) ? ' first' : '') . - (($k == ($countFiles - 1)) ? ' last' : '') . - ((($k % 2) == 0) ? ' even' : ' odd'); + $arrSource[$k]['class'] = (($k === 0) ? ' first' : '') . + (($k === ($countFiles - 1)) ? ' last' : '') . + ((($k % 2) === 0) ? ' even' : ' odd'); } } @@ -832,7 +849,9 @@ private function checkDownloads() if (($file = Input::get('file'))) { if ($this->withDownloadKeys) { $bag = $this->session->getBag('attributes'); + assert($bag instanceof AttributeBagInterface); $links = $bag->has('metaModels_downloads') ? $bag->get('metaModels_downloads') : []; + if (!\is_array($links)) { $links = []; } @@ -840,7 +859,10 @@ private function checkDownloads() // keep both null-coalescing values different to account for missing values. if (($links[$file] ?? null) !== (Input::get('fileKey') ?? false)) { $objHandler = new $GLOBALS['TL_PTY']['error_403'](); - /** @var PageError403 $objHandler */ + /** + * @var PageError403 $objHandler + * @psalm-suppress DeprecatedMethod + */ $objHandler->generate($file); } } @@ -864,7 +886,7 @@ public static function convertValueToPath($varValue) $objFiles = FilesModel::findByPk($varValue); - if ($objFiles !== null) { + if ($objFiles instanceof FilesModel) { return $objFiles->path; } return ''; @@ -920,7 +942,8 @@ public static function convertValuesToDatabase($values) */ public static function convertValuesToMetaModels($values) { - if (!is_array($values)) { + /** @psalm-suppress DocblockTypeContradiction */ + if (!\is_array($values)) { throw new InvalidArgumentException('Invalid uuid list.'); } @@ -943,7 +966,7 @@ public static function convertValuesToMetaModels($values) $models = FilesModel::findMultipleByUuids($values); - if ($models === null) { + if (!$models instanceof Collection) { return $result; } @@ -976,7 +999,7 @@ public static function convertValuesToMetaModels($values) */ public static function convertUuidsOrPathsToMetaModels($values) { - $values = \array_filter((array) $values); + $values = \array_filter($values); if (empty($values)) { return [ 'bin' => [], @@ -993,7 +1016,7 @@ public static function convertUuidsOrPathsToMetaModels($values) } $file = FilesModel::findByPath($value) ?: Dbafs::addResource($value); - if (!$file) { + if (!($file instanceof FilesModel)) { throw new InvalidArgumentException('Invalid path.'); } @@ -1010,12 +1033,14 @@ public static function convertUuidsOrPathsToMetaModels($values) * Must either be called from within collectFiles or collectFiles must be called later on as this method * will add models of type folder to the list of pending paths to allow for recursive inclusion. * - * @param FilesModel[] $files The files to add. - * @param array $skipPaths List of directories not to be added to the list of pending directories. + * @param Collection $files The files to add. + * @param list $skipPaths List of directories not to be added to the list of pending directories. * * @return void + * + * @psalm-assert list $this->pendingPaths */ - private function addFileModels($files, $skipPaths = []) + private function addFileModels(Collection $files, array $skipPaths = []): void { $baseLanguage = $this->getBaseLanguage(); $fallbackLanguage = $this->getFallbackLanguage(); @@ -1024,7 +1049,8 @@ private function addFileModels($files, $skipPaths = []) $this->pendingPaths[] = $file->path . '/'; continue; } - if (is_file(TL_ROOT . DIRECTORY_SEPARATOR . $file->path) + if ( + \is_file($this->rootDir . DIRECTORY_SEPARATOR . $file->path) && \in_array( \strtolower(pathinfo($file->path, PATHINFO_EXTENSION)), $this->acceptedExtensions @@ -1036,9 +1062,9 @@ private function addFileModels($files, $skipPaths = []) $meta = StringUtil::deserialize($file->meta, true); if (isset($meta[$baseLanguage])) { - $this->metaInformation[dirname($path)][basename($path)] = $meta[$baseLanguage]; + $this->metaInformation[\dirname($path)][\basename($path)] = $meta[$baseLanguage]; } elseif (isset($meta[$fallbackLanguage])) { - $this->metaInformation[dirname($path)][basename($path)] = $meta[$fallbackLanguage]; + $this->metaInformation[\dirname($path)][\basename($path)] = $meta[$fallbackLanguage]; } } } @@ -1052,6 +1078,7 @@ private function addFileModels($files, $skipPaths = []) * @return void * * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.Superglobals) */ private function processFile($fileName) @@ -1071,7 +1098,7 @@ private function processFile($fileName) 'file' => $fileName, 'mtime' => $file->mtime, 'alt' => $altText, - 'caption' => (!empty($meta['caption']) ? $meta['caption'] : ''), + 'caption' => $meta['caption'] ?? '', 'title' => $title, 'metafile' => $meta, 'icon' => 'assets/contao/images/' . $file->icon, @@ -1079,8 +1106,6 @@ private function processFile($fileName) 'size' => $file->filesize, 'sizetext' => \sprintf('(%s)', Controller::getReadableSize($file->filesize, 2)), 'url' => StringUtil::specialchars($this->getDownloadLink($fileName)), - 'isGdImage' => false, - 'isSvgImage' => false, 'isPicture' => false, ]; @@ -1088,8 +1113,8 @@ private function processFile($fileName) if ($information['isGdImage'] = $file->isGdImage) { $information['src'] = \urldecode($this->resizeImage($fileName)); $information['lb'] = 'lb_' . $this->getLightboxId(); - if (file_exists(TL_ROOT . '/' . $information['src'])) { - $size = getimagesize(TL_ROOT . '/' . $information['src']); + if (\file_exists($this->rootDir . '/' . $information['src'])) { + $size = \getimagesize($this->rootDir . '/' . $information['src']); $information['w'] = $size[0]; $information['h'] = $size[1]; $information['wh'] = $size[3]; @@ -1106,6 +1131,7 @@ private function processFile($fileName) // Prepare the picture for provide the image size. if ($file->isImage && ($information['isPicture'] = (int) ($this->resizeImages[2] ?? 0))) { $projectDir = $this->rootDir; + /** @psalm-suppress InternalMethod */ $staticUrl = $this->filesContext->getStaticUrl(); $picture = $this->pictureFactory->create($projectDir . '/' . $file->path, $this->getResizeImages()); @@ -1139,9 +1165,9 @@ private function processFile($fileName) * * @param string $fileName The file to resize. * - * @return null|string + * @return string */ - private function resizeImage($fileName) + private function resizeImage(string $fileName): string { [$width, $height, $mode] = $this->getResizeImages() + [null, null, null]; if ($this->getShowImages() && ($width || $height || $mode)) { @@ -1155,8 +1181,13 @@ private function resizeImage($fileName) } $event = new ResizeImageEvent($fileName, $width, $height, $mode); - $this->dispatcher->dispatch($event, ContaoEvents::IMAGE_RESIZE); - return $event->getResultImage(); + + /** @psalm-suppress DeprecatedProperty */ + $dispatcher = $this->dispatcher; + assert($dispatcher instanceof EventDispatcherInterface); + $dispatcher->dispatch($event, ContaoEvents::IMAGE_RESIZE); + + return (string) $event->getResultImage(); } return $fileName; diff --git a/src/Helper/UpgradeHandler.php b/src/Helper/UpgradeHandler.php index f5db4ae52..b2a12790c 100644 --- a/src/Helper/UpgradeHandler.php +++ b/src/Helper/UpgradeHandler.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,36 +13,39 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\Helper; +use Contao\Database; + /** * Upgrade handler class that changes structural changes in the database. - * This should rarely be necessary but sometimes we need it. + * This should rarely be necessary, but sometimes we need it. */ class UpgradeHandler { /** * Retrieve the database instance from Contao. * - * @return \Database + * @return Database * * @SuppressWarnings(PHPMD.ShortMethodName) * @SuppressWarnings(PHPMD.CamelCaseMethodName) */ protected static function DB() { - return \Database::getInstance(); + return Database::getInstance(); } /** * Handle database upgrade for the jumpTo field. * - * Introduced: pre release 1.0. + * Introduced: pre-release 1.0. * * If the field 'metamodel_jumpTo' does exist in tl_module or tl_content, * it will get created and the content from jumpTo will get copied over. @@ -52,7 +55,8 @@ protected static function DB() protected static function upgradeJumpTo() { $objDB = self::DB(); - if ($objDB->tableExists('tl_content', null, true) + if ( + $objDB->tableExists('tl_content', null, true) && !$objDB->fieldExists('metamodel_jumpTo', 'tl_content', true) ) { // Create the column in the database and copy the data over. @@ -66,7 +70,8 @@ protected static function upgradeJumpTo() } } - if ($objDB->tableExists('tl_module', null, true) + if ( + $objDB->tableExists('tl_module', null, true) && !$objDB->fieldExists('metamodel_jumpTo', 'tl_module', true) ) { // Create the column in the database and copy the data over. @@ -95,7 +100,8 @@ protected static function upgradeJumpTo() protected static function upgradeDcaSettingsPublished() { $objDB = self::DB(); - if ($objDB->tableExists('tl_metamodel_dcasetting', null, true) + if ( + $objDB->tableExists('tl_metamodel_dcasetting', null, true) && !$objDB->fieldExists('published', 'tl_metamodel_dcasetting', true) ) { // Create the column in the database and copy the data over. @@ -137,7 +143,8 @@ protected static function changeSubPalettesToConditions() ); } - if ($objDB->tableExists('tl_metamodel_dcasetting', null, true) + if ( + $objDB->tableExists('tl_metamodel_dcasetting', null, true) && $objDB->fieldExists('subpalette', 'tl_metamodel_dcasetting', true) ) { $subpalettes = $objDB->execute('SELECT * FROM tl_metamodel_dcasetting WHERE subpalette!=0'); @@ -155,6 +162,7 @@ protected static function changeSubPalettesToConditions() $attr = array(); while ($attributes->next()) { + /** @psalm-suppress UndefinedMagicPropertyFetch */ $attr[$attributes->attr_id] = $attributes->colName; } @@ -168,25 +176,27 @@ protected static function changeSubPalettesToConditions() $check = array(); while ($checkboxes->next()) { + /** @psalm-suppress UndefinedMagicPropertyFetch */ $check[$checkboxes->id] = $checkboxes->attr_id; } while ($subpalettes->next()) { // Add property value condition for parent property dependency. - $data = array( - 'pid' => 0, + /** @psalm-suppress UndefinedMagicPropertyFetch */ + $data = [ + 'pid' => 0, 'settingId' => $subpalettes->id, - 'sorting' => '128', - 'tstamp' => time(), - 'enabled' => '1', - 'type' => 'conditionpropertyvalueis', - 'attr_id' => $check[$subpalettes->subpalette], - 'comment' => sprintf( + 'sorting' => '128', + 'tstamp' => \time(), + 'enabled' => '1', + 'type' => 'conditionpropertyvalueis', + 'attr_id' => $check[$subpalettes->subpalette], + 'comment' => \sprintf( 'Only show when checkbox "%s" is checked', $attr[$check[$subpalettes->subpalette]] ), - 'value' => '1', - ); + 'value' => '1', + ]; $objDB ->prepare('INSERT INTO tl_metamodel_dcasetting_condition %s') @@ -217,8 +227,10 @@ protected static function upgradeClosed() $objDB = self::DB(); // Change isclosed to iseditable, iscreatable and isdeleteable. - if ($objDB->tableExists('tl_metamodel_dca', null, true) - && !$objDB->fieldExists('iseditable', 'tl_metamodel_dca')) { + if ( + $objDB->tableExists('tl_metamodel_dca', null, true) + && !$objDB->fieldExists('iseditable', 'tl_metamodel_dca') + ) { // Create the column in the database and copy the data over. TableManipulation::createColumn( 'tl_metamodel_dca', @@ -321,26 +333,28 @@ protected static function upgradeInputScreenFlag() while ($dca->next()) { $renderGroupLen = 0; - if (in_array($dca->flag, array(1,2,3,4))) { + /** @psalm-suppress UndefinedMagicPropertyFetch */ + if (\in_array($dca->flag, [1, 2, 3, 4])) { $renderGroupType = 'char'; - if (in_array($dca->flag, array(1,2))) { + if (\in_array($dca->flag, [1, 2])) { $renderGroupLen = 1; } else { $renderGroupLen = 2; } - } elseif (in_array($dca->flag, array(5,6))) { + } elseif (\in_array($dca->flag, [5, 6])) { $renderGroupType = 'day'; - } elseif (in_array($dca->flag, array(7,8))) { + } elseif (\in_array($dca->flag, [7, 8])) { $renderGroupType = 'month'; - } elseif (in_array($dca->flag, array(9,10))) { + } elseif (\in_array($dca->flag, [9, 10])) { $renderGroupType = 'year'; - } elseif (in_array($dca->flag, array(11,12))) { + } elseif (\in_array($dca->flag, [11, 12])) { $renderGroupType = 'digit'; } else { $renderGroupType = 'none'; } - $data = array( + /** @psalm-suppress UndefinedMagicPropertyFetch */ + $data = [ 'pid' => $dca->id, 'sorting' => 128, 'tstamp' => time(), @@ -350,9 +364,9 @@ protected static function upgradeInputScreenFlag() 'rendergrouptype' => $renderGroupType, 'rendergrouplen' => $renderGroupLen, 'rendergroupattr' => 0, - 'rendersort' => in_array($dca->flag, array(2,4,6,8,10,12)) ? 'desc' : 'asc', + 'rendersort' => \in_array($dca->flag, [2, 4, 6, 8, 10, 12]) ? 'desc' : 'asc', 'rendersortattr' => 0, - ); + ]; $objDB ->prepare('INSERT INTO tl_metamodel_dca_sortgroup %s') diff --git a/src/Helper/ViewCombinations.php b/src/Helper/ViewCombinations.php index c7c031001..d8cb4637d 100644 --- a/src/Helper/ViewCombinations.php +++ b/src/Helper/ViewCombinations.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author David Molineus - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,10 +24,13 @@ use Contao\System; use Contao\User; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use MetaModels\BackendIntegration\InputScreen\IInputScreen; use MetaModels\BackendIntegration\InputScreen\InputScreen; use MetaModels\IMetaModelsServiceContainer; +use Symfony\Component\HttpFoundation\Request; /** * Class ViewCombinations. @@ -35,13 +38,15 @@ * Retrieve combinations of view and input screens for the currently logged in user (either frontend or backend). * * @deprecated This will get removed. + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ abstract class ViewCombinations { - const COMBINATION = 'combination'; - const INPUTSCREEN = 'inputscreen'; - const RENDERSETTING = 'rendersetting'; - const MODELID = 'metamodel'; + public const COMBINATION = 'combination'; + public const INPUTSCREEN = 'inputscreen'; + public const RENDERSETTING = 'rendersetting'; + public const MODELID = 'metamodel'; /** * All MetaModel combinations for lookup. @@ -85,14 +90,14 @@ abstract class ViewCombinations * * @var User */ - private $user; + private User $user; /** * Database connection. * * @var Connection */ - private $connection; + private Connection $connection; /** * Create a new instance. @@ -119,19 +124,31 @@ public function __construct(IMetaModelsServiceContainer $container, User $user, ); // @codingStandardsIgnoreEnd $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); } - $this->connection = $connection; } /** * Try to load the combinations from cache. * - * @return string|null + * @return string */ protected function calculateCacheKey() { - $key = 'view_combination_' . strtolower(TL_MODE); + $tlMode = 'be'; + + if ( + (bool) System::getContainer() + ->get('contao.routing.scope_matcher') + ?->isFrontendRequest( + System::getContainer()->get('request_stack')?->getCurrentRequest() ?? Request::create('') + ) + ) { + $tlMode = 'fe'; + } + + $key = 'view_combination_' . $tlMode; // Authenticate the user - if this fails, we use an anonymous cache file. if ($this->authenticateUser()) { @@ -173,7 +190,7 @@ protected function loadFromCache() } // Perform loading now. - $data = json_decode($this->container->getCache()->fetch($key), true); + $data = \json_decode($this->container->getCache()->fetch($key), true); if (empty($data)) { return false; @@ -196,13 +213,13 @@ protected function saveToCache() { // Pretty print only came available with php 5.4. $flags = 0; - if (defined('JSON_PRETTY_PRINT')) { + if (\defined('JSON_PRETTY_PRINT')) { $flags = JSON_PRETTY_PRINT; } return $this->container->getCache()->save( $this->calculateCacheKey(), - json_encode( + \json_encode( array( 'information' => $this->information, 'tableMap' => $this->tableMap, @@ -217,7 +234,7 @@ protected function saveToCache() /** * Translate the MetaModel id to a valid table name. * - * @param int $metaModelId The id of the MetaModel to translate. + * @param string $metaModelId The id of the MetaModel to translate. * * @return string */ @@ -247,15 +264,12 @@ protected function resolve() ); } - $found = $this->getPaletteCombinationRows(); - - if (!$found) { - $found = array(); - } + $this->getPaletteCombinationRows(); // Clean any undefined. - foreach (array_keys($this->information) as $tableName) { - if (empty($this->information[$tableName][self::COMBINATION]) + foreach (\array_keys($this->information) as $tableName) { + if ( + empty($this->information[$tableName][self::COMBINATION]) || empty($this->information[$tableName][self::COMBINATION]['dca_id']) || empty($this->information[$tableName][self::COMBINATION]['view_id']) ) { @@ -296,7 +310,7 @@ protected function getMetaModelName($nameOrId) /** * Retrieve the Contao database singleton instance. * - * @return \Database + * @return \Contao\Database */ protected function getDatabase() { @@ -320,7 +334,7 @@ abstract protected function authenticateUser(); protected function getUserGroups() { /** @noinspection PhpUndefinedFieldInspection */ - return $this->user->groups ? array_filter($this->user->groups) : array(); + return $this->user->groups ? \array_filter($this->user->groups) : []; } @@ -336,10 +350,22 @@ protected function getCombinationsFromDatabase() return null; } + $tlMode = 'be'; + + if ( + System::getContainer() + ->get('contao.routing.scope_matcher') + ?->isFrontendRequest( + System::getContainer()->get('request_stack')?->getCurrentRequest() ?? Request::create('') + ) + ) { + $tlMode = 'fe'; + } + $statement = $this->connection->createQueryBuilder() ->select('t.*') ->from('tl_metamodel_dca_combine', 't') - ->where('t.' . strtolower(TL_MODE) . '_group IN (:groups)') + ->where('t.' . $tlMode . '_group IN (:groups)') ->orderBy('t.pid') ->addOrderBy('t.sorting', 'ASC') ->setParameter('groups', $groups) @@ -353,21 +379,21 @@ protected function getCombinationsFromDatabase() * * This returns the ids that have been resolved. * - * @return int[] + * @return list */ protected function getPaletteCombinationRows() { $combinations = $this->getCombinationsFromDatabase(); - $success = array(); + $success = []; // No combinations present, nothing to resolve. if (!$combinations) { - return array_keys($this->information); + return \array_keys($this->information); } foreach ($combinations as $combination) { /** @noinspection PhpUndefinedFieldInspection */ - $modelId = $combination['pid']; + $modelId = (string) $combination['pid']; $modelName = $this->tableNameFromId($modelId); // Already a combination present, continue with next one. @@ -379,10 +405,10 @@ protected function getPaletteCombinationRows() $this->information[$modelName][self::MODELID] = $modelId; /** @noinspection PhpUndefinedFieldInspection */ - $this->information[$modelName][self::COMBINATION] = array( + $this->information[$modelName][self::COMBINATION] = [ 'dca_id' => $combination['dca_id'], 'view_id' => $combination['view_id'] - ); + ]; $this->setTableMapping($modelId, $modelName); @@ -398,7 +424,7 @@ protected function getPaletteCombinationRows() * * @return void * - * @throws \Doctrine\DBAL\DBALException When a database error occurs. + * @throws Exception */ protected function fetchInputScreenDetails() { @@ -416,14 +442,14 @@ protected function fetchInputScreenDetails() ->select('t.*') ->from('tl_metamodel_dca', 't') ->where('t.id IN (:ids)') - ->setParameter('id', $inputScreenIds, Connection::PARAM_STR_ARRAY) + ->setParameter('id', $inputScreenIds, ArrayParameterType::STRING) ->executeQuery(); - while ($inputScreens = $statement->fetchAssociative()) { + while (false !== ($inputScreens = $statement->fetchAssociative())) { /** @noinspection PhpUndefinedFieldInspection */ $screenId = $inputScreens['id']; /** @noinspection PhpUndefinedFieldInspection */ - $metaModelId = $inputScreens['pid']; + $metaModelId = (string) $inputScreens['pid']; $metaModelName = $this->tableNameFromId($metaModelId); $propertyRows = $this->connection @@ -438,7 +464,7 @@ protected function fetchInputScreenDetails() $conditions = $this->connection ->createQueryBuilder() - ->select('cond.*, setting.attr_id AS setting_attr_id') + ->select('cond.*', 'setting.attr_id AS setting_attr_id') ->from('tl_metamodel_dcasetting_condition', 'cond') ->leftJoin('cond', 'tl_metamodel_dcasetti', 'setting', 'cond.settingId=setting.id') ->leftJoin('setting', 'tl_metamodel_dca', 'dca', 'setting.pid=dca.id') @@ -458,12 +484,12 @@ protected function fetchInputScreenDetails() ->orderBy('t.sorting', 'ASC') ->executeQuery(); - $inputScreen = array( + $inputScreen = [ 'row' => $inputScreens->row(), 'properties' => $propertyRows->fetchAllAssociative(), 'conditions' => $conditions->fetchAllAssociative(), 'groupSort' => $groupSort->fetchAllAssociative() - ); + ]; $this->information[$metaModelName][self::INPUTSCREEN] = $inputScreen; $this->information[$metaModelName][self::MODELID] = $metaModelId; @@ -488,7 +514,7 @@ protected function buildInputScreen($metaModel) $metaModelName = $this->getMetaModelName($metaModel); $inputScreen = $this->information[$metaModelName][self::INPUTSCREEN]; - if (!is_object($inputScreen)) { + if (!\is_object($inputScreen)) { $inputScreen = $this->information[$metaModelName][self::INPUTSCREEN] = new InputScreen( $this->container, $inputScreen['row'], @@ -512,8 +538,8 @@ protected function isInputScreenStandalone($metaModel) { $information = $this->information[$metaModel]; $inputScreen = isset($information[self::INPUTSCREEN]) ? $information[self::INPUTSCREEN] : null; - if (!is_object($inputScreen)) { - return ($inputScreen['row']['rendertype'] == 'standalone'); + if (!\is_object($inputScreen)) { + return ($inputScreen['row']['rendertype'] === 'standalone'); } /** @var IInputScreen $inputScreen */ @@ -531,7 +557,7 @@ public function getRenderSetting($metaModel) { $metaModelName = $this->getMetaModelName($metaModel); - return ($this->information[$metaModelName][self::COMBINATION]['view_id'] ?? null); + return ($this->information[$metaModelName][self::COMBINATION]['view_id'] ?? 0); } /** @@ -543,8 +569,7 @@ public function getRenderSetting($metaModel) */ public function getInputScreen($metaModel) { - $inputScreen = $this->getInputScreenDetails($metaModel); - return $inputScreen ? $inputScreen->getId() : null; + return $this->getInputScreenDetails($metaModel)->getId(); } /** @@ -567,7 +592,7 @@ public function getInputScreenDetails($metaModel) public function getStandaloneInputScreens() { $result = []; - foreach (array_keys($this->information) as $modelName) { + foreach (\array_keys($this->information) as $modelName) { if ($this->isInputScreenStandalone($modelName)) { $result[] = $this->getInputScreenDetails($modelName); } @@ -587,7 +612,7 @@ public function getParentOf($metaModel) { $metaModelName = $this->getMetaModelName($metaModel); - return ($this->childMap[$metaModelName] ?? null); + return ($this->childMap[$metaModelName] ?? ''); } /** @@ -599,9 +624,9 @@ public function getParentOf($metaModel) */ public function getParentedInputScreenNames($parent = null) { - $result = array(); + $result = []; - if ($parent) { + if (null !== $parent) { if (!isset($this->parentMap[$parent])) { return []; } @@ -612,7 +637,7 @@ public function getParentedInputScreenNames($parent = null) return $result; } - foreach (array_keys($this->information) as $modelName) { + foreach (\array_keys($this->information) as $modelName) { if (!$this->isInputScreenStandalone($modelName)) { $result[] = (isset($this->tableMap[$modelName])) ? $this->tableMap[$modelName] : $modelName; } @@ -630,7 +655,7 @@ public function getParentedInputScreenNames($parent = null) */ public function getParentedInputScreens($parent = null) { - $result = array(); + $result = []; foreach ($this->getParentedInputScreenNames($parent) as $modelName) { $result[] = $this->getInputScreenDetails($modelName); diff --git a/src/IFactory.php b/src/IFactory.php index 8c8c666df..5c39baf5d 100644 --- a/src/IFactory.php +++ b/src/IFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -37,6 +38,8 @@ interface IFactory extends IServiceContainerAware * @return IMetaModelsServiceContainer * * @deprecated The service container will get removed, use the symfony service container instead. + * + * @psalm-suppress DeprecatedInterface */ public function getServiceContainer(); diff --git a/src/IItem.php b/src/IItem.php index e19098003..589102a7f 100644 --- a/src/IItem.php +++ b/src/IItem.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author Stefan Heimes * @author Richard Henkenjohann * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -42,7 +43,6 @@ public function get($strAttributeName); * Set the native value of an attribute. * * @param string $strAttributeName The name of the attribute. - * * @param mixed $varValue The value of the attribute. * * @return \MetaModels\IItem @@ -50,18 +50,18 @@ public function get($strAttributeName); public function set($strAttributeName, $varValue); /** - * Fetch the meta model that represents this item. + * Fetch the MetaModel that represents this item. * * @return \MetaModels\IMetaModel The instance. */ public function getMetaModel(); /** - * Fetch the meta model attribute instance with the given name. + * Fetch the MetaModel attribute instance with the given name. * * @param string $strAttributeName The name of the attribute. * - * @return \MetaModels\Attribute\IAttribute The instance. + * @return \MetaModels\Attribute\IAttribute|null the instance or null if not found. */ public function getAttribute($strAttributeName); @@ -88,7 +88,7 @@ public function getSetAttributes(); /** * Determines if this item is a variant of another item. * - * @return bool True if it is an variant, false otherwise + * @return bool True if it is a variant, false otherwise */ public function isVariant(); @@ -99,12 +99,12 @@ public function isVariant(); * this item. It merely simply states, that this item is able * to function as variant base for other items. * - * @return bool true if it is an variant base, false otherwise. + * @return bool true if it is a variant base, false otherwise. */ public function isVariantBase(); /** - * Fetch the meta model variants for this item. + * Fetch the MetaModel variants for this item. * * @param \MetaModels\Filter\IFilter $objFilter The filter settings to be applied. * @@ -113,7 +113,7 @@ public function isVariantBase(); public function getVariants($objFilter); /** - * Fetch the meta model variant base for this item. + * Fetch the MetaModel variant base for this item. * * Note: For a non-variant item the variant base is the item itself. * @@ -138,7 +138,6 @@ public function save($timestamp = null); * For further information {@see IMetaModelAttribute::parseValue()}. * * @param string $strOutputFormat Optional, the desired output format (default: text). - * * @param ICollection $objSettings The render settings to use optional (default: null). * * @return array attribute name => format => value @@ -151,9 +150,7 @@ public function parseValue($strOutputFormat = 'text', $objSettings = null); * For further information {@see IMetaModelAttribute::parseValue()}. * * @param string $strAttributeName The desired attribute. - * * @param string $strOutputFormat Optional, the desired output format (default: text). - * * @param ICollection $objSettings The render settings to use optional (default: null). * * @return array format=>value @@ -175,7 +172,7 @@ public function copy(); * Additionally, the item will be a variant child of this item. * * NOTE: if this item is not a variant base itself, this item will return a item - * that is a child of this items variant base. i.e. exact clone. + * that is a child of these items variant base. i.e. exact clone. * * @return \MetaModels\IItem the new copy. */ diff --git a/src/IItems.php b/src/IItems.php index 06b050e7f..82198d599 100644 --- a/src/IItems.php +++ b/src/IItems.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @author Christian Schiffler * @author David Maack * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -28,13 +29,15 @@ * * @method IItems|bool next() Advance the internal cursor by one returns the current instance or false when last * item has had been reached. + * @extends \Iterator + * @extends \ArrayAccess */ interface IItems extends \Iterator, \ArrayAccess { /** * Return the current item. * - * @return IItem + * @return IItem|null */ public function getItem(); @@ -90,7 +93,6 @@ public function getClass(); * Parses the current item in the desired output format using the format settings. * * @param string $strOutputFormat Optional, defaults to text. The output format to use. - * * @param ICollection|null $objSettings Optional, defaults to null. The additional settings. * * @return array the parsed information. @@ -101,7 +103,6 @@ public function parseValue($strOutputFormat = 'text', $objSettings = null); * Parses all items in the desired output format using the format settings. * * @param string $strOutputFormat Optional, defaults to text. The output format to use. - * * @param ICollection|null $objSettings Optional, defaults to null. The additional settings. * * @return array the parsed information. diff --git a/src/IMetaModel.php b/src/IMetaModel.php index 65e44ac96..de02bf631 100644 --- a/src/IMetaModel.php +++ b/src/IMetaModel.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author David Maack * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,6 +24,7 @@ use MetaModels\Attribute\IAttribute; use MetaModels\Filter\IFilter; +use MetaModels\Render\Setting\ICollection; /** * This is the main MetaModel interface. @@ -31,9 +32,9 @@ * This interface handles all attribute definition instantiation and can be queried for a view instance to certain * entries. * - * @see MetaModelFactory::byId To instantiate a MetaModel by its ID. + * @see MetaModelFactory::byId To instantiate a MetaModel by its ID. * - * @see \MetaModels\IFactory::getMetaModel($metaModelName) To instantiate a MetaModel by its table name. + * @see IFactory::getMetaModel To instantiate a MetaModel by its table name. */ interface IMetaModel { @@ -43,6 +44,8 @@ interface IMetaModel * @return IMetaModelsServiceContainer * * @deprecated Inject services via constructor or setter. + * + * @psalm-suppress DeprecatedInterface */ public function getServiceContainer(); @@ -82,7 +85,7 @@ public function get($strKey); public function getTableName(); /** - * Retrieve the human readable name for this MetaModel. + * Retrieve the human-readable name for this MetaModel. * * @return string the name for the MetaModel. */ @@ -121,8 +124,8 @@ public function hasVariants(); /** * Fetches all language codes that have been marked as available for translation in this MetaModel. * - * @return string[]|null An array containing all codes if the MetaModel is translated, - * null if translation is not active. + * @return list|null An array containing all codes if the MetaModel is translated, + * null if translation is not active. * * @deprecated Please implement ITranslatedMetaModel instead. */ @@ -152,7 +155,7 @@ public function getActiveLanguage(); * * @param string $strAttributeName The name of the attribute to search. * - * @return IAttribute the instance or null if not found. + * @return null|IAttribute the instance or null if not found. */ public function getAttribute($strAttributeName); @@ -166,34 +169,28 @@ public function getAttribute($strAttributeName); public function getAttributeById($intId); /** - * Search the MetaModel for the item with the given Id. - * - * @param int $intId The Id to be searched. + * Search the MetaModel for the item with the given id. * - * @param string[] $arrAttrOnly Names of the attributes that shall be enclosed in the result, defaults to empty - * which means all attributes. + * @param string $intId The id to be searched. + * @param list $arrAttrOnly Names of the attributes that shall be enclosed in the result, defaults to empty + * which means all attributes. * * @return IItem|null The item if found, NULL otherwise. */ - public function findById($intId, $arrAttrOnly = array()); + public function findById($intId, $arrAttrOnly = []); /** * Filter the MetaModel by the provided filter settings. * * @param IFilter|null $objFilter The filter object to use or null if none. - * * @param string $strSortBy Optional name of the attribute the entries shall be sorted. - * * @param int $intOffset Optional offset for the first item. - * * @param int $intLimit Optional amount of items to retrieve. - * * @param string $strSortOrder Optional sorting direction, either 'ASC'(default) or 'DESC'. - * - * @param string[] $arrAttrOnly Names of the attributes that shall be enclosed in the result, defaults to + * @param list $arrAttrOnly Names of the attributes that shall be enclosed in the result, defaults to * empty which means all attributes. * - * @return IItems|IItem[] The collection of IItem instances that match the given filter. + * @return IItems The collection of IItem instances that match the given filter. */ public function findByFilter( $objFilter, @@ -201,23 +198,19 @@ public function findByFilter( $intOffset = 0, $intLimit = 0, $strSortOrder = 'ASC', - $arrAttrOnly = array() + $arrAttrOnly = [] ); /** * Filter the MetaModel by the provided filter settings and return the ids of all matching items. * * @param IFilter|null $objFilter The filter object to use or null if none. - * * @param string $strSortBy Optional name of the attribute the entries shall be sorted. - * * @param int $intOffset Optional offset for the first item. - * * @param int $intLimit Optional amount of items to retrieve. - * * @param string $strSortOrder Optional sorting direction, either 'ASC'(default) or 'DESC'. * - * @return string[] the ids of items that match the given filter. + * @return list the ids of items that match the given filter. */ public function getIdsFromFilter($objFilter, $strSortBy = '', $intOffset = 0, $intLimit = 0, $strSortOrder = 'ASC'); @@ -242,9 +235,8 @@ public function findVariantBase($objFilter); /** * Get variants for the given ids, filtered by the provided filter settings. * - * @param array $arrIds The Ids of the base elements. - * - * @param IFilter $objFilter The filter to use or null if no filtering. + * @param list $arrIds The Ids of the base elements. + * @param IFilter $objFilter The filter to use or null if no filtering. * * @return IItems The collection of IItem instances that match the given filter. */ @@ -253,10 +245,9 @@ public function findVariants($arrIds, $objFilter); /** * Find all variants of the given item. * - * This methods makes no difference between the variant base item and other variants. - * - * @param array $arrIds The Ids of the base elements. + * These methods make no difference between the variant base item and other variants. * + * @param list $arrIds The Ids of the base elements. * @param IFilter|null $objFilter The filter to use or null if no filtering. * * @return IItems the collection of IItem instances that match the given filter. @@ -267,11 +258,10 @@ public function findVariantsWithBase($arrIds, $objFilter); * Get all options of the given attribute. * * @param string $strAttribute The attribute to fetch options from. - * * @param IFilter $objFilter The filter to use or null if no filtering. * - * @return array all options matching the given filter for the given attribute to be usable in a filter select - * widget. + * @return array all options matching the given filter for the given attribute to be usable in a + * filter select widget. */ public function getAttributeOptions($strAttribute, $objFilter = null); @@ -279,7 +269,6 @@ public function getAttributeOptions($strAttribute, $objFilter = null); * Save an item into the database. * * @param IItem $objItem The item to save to the database. - * * @param int|null $timestamp Optional parameter for use own timestamp. * This is useful if save a collection of models and all shall have * the same timestamp. @@ -298,7 +287,7 @@ public function saveItem($objItem, $timestamp = null); public function delete(IItem $objItem); /** - * Prepare an empty filter object for this meta model. The returned filter contains no rules. + * Prepare an empty filter object for this MetaModel. The returned filter contains no rules. * * @return IFilter the filter object. */ @@ -307,9 +296,8 @@ public function getEmptyFilter(); /** * Generates a filter object that takes the given attributes into account. * - * @param int $intFilterSettings The id of the filter settings to use. - * - * @param array $arrFilterUrl The filter url parameters (usually the contents of $_GET etc.). + * @param string $intFilterSettings The id of the filter settings to use. + * @param array $arrFilterUrl The filter url parameters (usually the contents of $_GET etc.). * * @return IFilter the generated filter object. * @@ -322,7 +310,7 @@ public function prepareFilter($intFilterSettings, $arrFilterUrl); * * @param int $intViewId The id of the render settings to retrieve. * - * @return \MetaModels\Render\Setting\ICollection + * @return ICollection * * @deprecated To be removed in MetaModels 3.0 - use the render setting factory instead. */ diff --git a/src/IMetaModelsServiceContainer.php b/src/IMetaModelsServiceContainer.php index 36f3a2d9b..7b4ac53cc 100644 --- a/src/IMetaModelsServiceContainer.php +++ b/src/IMetaModelsServiceContainer.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -109,6 +110,8 @@ public function getCache(); * @return MetaModelsServiceContainer * * @deprecated The service container will get removed, use the symfony service container instead. + * + * @psalm-suppress DeprecatedClass */ public function setService($service, $serviceName = null); diff --git a/src/IServiceContainerAware.php b/src/IServiceContainerAware.php index eec99ea49..d6c8abd0d 100644 --- a/src/IServiceContainerAware.php +++ b/src/IServiceContainerAware.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,7 +24,9 @@ /** * Reference implementation of IMetaModelsServiceContainer. * - * @deprecated The interface has been deprecated as the whole service container is deprecated and will get removed. + * @deprecated The interface has been deprecated as the whole service container is deprecated and will get removed. + * + * @psalm-suppress DeprecatedInterface */ interface IServiceContainerAware { @@ -35,6 +38,8 @@ interface IServiceContainerAware * @return IServiceContainerAware * * @deprecated The service container will get removed, use the symfony service container instead. + * + * @psalm-suppress DeprecatedInterface */ public function setServiceContainer(IMetaModelsServiceContainer $serviceContainer); @@ -44,6 +49,8 @@ public function setServiceContainer(IMetaModelsServiceContainer $serviceContaine * @return IMetaModelsServiceContainer|null * * @deprecated The service container will get removed, use the symfony service container instead. + * + * @psalm-suppress DeprecatedInterface */ public function getServiceContainer(); } diff --git a/src/ITranslatedMetaModel.php b/src/ITranslatedMetaModel.php index 454d72278..a42ec4c25 100644 --- a/src/ITranslatedMetaModel.php +++ b/src/ITranslatedMetaModel.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2018 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,8 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2018 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -27,7 +28,7 @@ interface ITranslatedMetaModel extends IMetaModel /** * Fetches all language codes that have been marked as available for translation in this MetaModel. * - * @return string[] An array containing all codes. + * @return list An array containing all codes. */ public function getLanguages(): array; diff --git a/src/Information/AttributeInformation.php b/src/Information/AttributeInformation.php index 0f47a9ecf..cb5e04115 100644 --- a/src/Information/AttributeInformation.php +++ b/src/Information/AttributeInformation.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Information; diff --git a/src/Information/AttributeInformationInterface.php b/src/Information/AttributeInformationInterface.php index 7ece0b7e7..bd85ed5d0 100644 --- a/src/Information/AttributeInformationInterface.php +++ b/src/Information/AttributeInformationInterface.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Information; diff --git a/src/Information/ConfigurationTrait.php b/src/Information/ConfigurationTrait.php index c34bef48c..b2171f9c9 100644 --- a/src/Information/ConfigurationTrait.php +++ b/src/Information/ConfigurationTrait.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Information; diff --git a/src/Information/MetaModelCollection.php b/src/Information/MetaModelCollection.php index f1227a2c7..c9578d285 100644 --- a/src/Information/MetaModelCollection.php +++ b/src/Information/MetaModelCollection.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Information; @@ -29,7 +29,7 @@ class MetaModelCollection implements MetaModelCollectionInterface /** * The list of configured MetaModels. * - * @var MetaModelInformationInterface[] + * @var array */ private $metaModels = []; diff --git a/src/Information/MetaModelCollectionInterface.php b/src/Information/MetaModelCollectionInterface.php index 9149207ad..2a319a617 100644 --- a/src/Information/MetaModelCollectionInterface.php +++ b/src/Information/MetaModelCollectionInterface.php @@ -17,12 +17,14 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Information; /** * This is a collection of MetaModels. + * + * @extends \IteratorAggregate */ interface MetaModelCollectionInterface extends \IteratorAggregate { @@ -63,7 +65,7 @@ public function get(string $name): MetaModelInformationInterface; /** * {@inheritDoc} * - * @return \Traversable|MetaModelInformationInterface[] + * @return \Traversable */ - public function getIterator(); + public function getIterator(): \Traversable; } diff --git a/src/Information/MetaModelInformation.php b/src/Information/MetaModelInformation.php index 31bf5afaf..2e0a38cd0 100644 --- a/src/Information/MetaModelInformation.php +++ b/src/Information/MetaModelInformation.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,12 +12,13 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Information; @@ -33,14 +34,14 @@ class MetaModelInformation implements MetaModelInformationInterface * * @var string */ - private $name; + private string $name; /** * The array of attribute information. * * @var AttributeInformationInterface[] */ - private $attributes = []; + private array $attributes = []; /** * Create a new instance. @@ -67,7 +68,7 @@ public function getName(): string */ public function getAttributeNames(): array { - return array_keys($this->attributes); + return \array_keys($this->attributes); } /** @@ -91,7 +92,7 @@ public function addAttribute(AttributeInformationInterface $attribute): void /** * {@inheritDoc} * - * @return AttributeInformation + * @return AttributeInformationInterface * * @throws \InvalidArgumentException When the attribute is not registered. */ @@ -117,7 +118,7 @@ public function hasAttribute(string $name): bool */ public function getAttributes(): array { - return array_values($this->attributes); + return \array_values($this->attributes); } /** diff --git a/src/Information/MetaModelInformationInterface.php b/src/Information/MetaModelInformationInterface.php index 74de7be9e..b20e2552e 100644 --- a/src/Information/MetaModelInformationInterface.php +++ b/src/Information/MetaModelInformationInterface.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Information; @@ -90,7 +90,7 @@ public function hasAttribute(string $name): bool; /** * Retrieve attributes. * - * @return AttributeInformation[] + * @return list */ public function getAttributes(): array; @@ -99,7 +99,7 @@ public function getAttributes(): array; * * @param string $typeName Retrieve all attributes of a certain type. * - * @return \Traversable|AttributeInformation[] + * @return \Traversable */ public function getAttributesOfType(string $typeName): \Traversable; } diff --git a/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php b/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php index e51092497..d74114500 100644 --- a/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php +++ b/src/InformationProvider/ContaoDatabaseBackedInformationProvider.php @@ -18,7 +18,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\InformationProvider; @@ -85,7 +85,7 @@ public function getInformationFor(MetaModelInformation $information): void ->fetchAssociative(); // Not managed by us. - if (empty($configuration)) { + if (false === $configuration) { return; } @@ -111,7 +111,9 @@ public function getInformationFor(MetaModelInformation $information): void } $attribute = $information->getAttribute($colName); - $attribute->addConfiguration($attributeRow); + if ($attribute instanceof AttributeInformation) { + $attribute->addConfiguration($attributeRow); + } } } } diff --git a/src/InformationProvider/InformationProviderInterface.php b/src/InformationProvider/InformationProviderInterface.php index 473a96421..0ec89f1f1 100644 --- a/src/InformationProvider/InformationProviderInterface.php +++ b/src/InformationProvider/InformationProviderInterface.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,12 +12,13 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\InformationProvider; @@ -31,7 +32,7 @@ interface InformationProviderInterface /** * Gets the names of known MetaModels. * - * @return string[] + * @return list */ public function getNames(): array; diff --git a/src/InformationProvider/MetaModelInformationCollector.php b/src/InformationProvider/MetaModelInformationCollector.php index 3957ba99e..02e8c9cb8 100644 --- a/src/InformationProvider/MetaModelInformationCollector.php +++ b/src/InformationProvider/MetaModelInformationCollector.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,12 +12,13 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\InformationProvider; @@ -35,7 +36,7 @@ class MetaModelInformationCollector implements InformationProviderInterface * * @var InformationProviderInterface[] */ - private $providers; + private array $providers; /** * Create a new instance. @@ -52,9 +53,13 @@ public function __construct(array $providers) */ public function getNames(): array { - return array_values(array_unique(array_merge(...array_map(function (InformationProviderInterface $provider) { - return $provider->getNames(); - }, $this->providers)))); + $nameLists = \array_values(\array_map( + /** @return list */ + static fn (InformationProviderInterface $provider): array => $provider->getNames(), + $this->providers + )); + + return \array_values(\array_unique(\array_merge(...$nameLists))); } /** diff --git a/src/InsertTag/Node.php b/src/InsertTag/Node.php index 2db635706..0f674db76 100644 --- a/src/InsertTag/Node.php +++ b/src/InsertTag/Node.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,8 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2023 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -34,10 +35,10 @@ final class Node implements IteratorAggregate, NodeInterface /** @var list */ private array $parts; - /** @param list ...$parts */ + /** @param NodeInterface ...$parts */ public function __construct(NodeInterface ...$parts) { - $this->parts = $parts; + $this->parts = \array_values($parts); } /** @@ -55,7 +56,7 @@ public function getIterator(): Traversable */ public function asString(): string { - return '{{' . array_reduce( + return '{{' . \array_reduce( $this->parts, fn($result, $arg) => $result . $arg->asString(), '' diff --git a/src/InsertTag/NodeList.php b/src/InsertTag/NodeList.php index 8874fea64..260a7154e 100644 --- a/src/InsertTag/NodeList.php +++ b/src/InsertTag/NodeList.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,7 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -45,7 +45,7 @@ final class NodeList implements IteratorAggregate, NodeInterface */ public function __construct(NodeInterface ...$elements) { - $this->elements = $elements; + $this->elements = \array_values($elements); } /** diff --git a/src/InsertTag/Parser.php b/src/InsertTag/Parser.php index b4df94296..cf5fb30a1 100644 --- a/src/InsertTag/Parser.php +++ b/src/InsertTag/Parser.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,8 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2023 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,7 +24,6 @@ use LogicException; -use function preg_match; use function strlen; use function strpos; use function substr; @@ -77,9 +77,7 @@ private function __construct(string $content) */ public static function parse(string $content): NodeList { - $instance = new self($content); - - return $instance->parseInternal(); + return (new self($content))->parseInternal(); } /** @@ -93,13 +91,11 @@ private function parseInternal(): NodeList { $buffer = []; - while (null !== $nextOpening = $this->findNextOpenTagPosition()) { - if (null !== $nextOpening) { - if ($nextOpening > $this->position) { - $buffer[] = new LiteralNode($this->read($nextOpening - $this->position)); - } - $buffer[] = $this->readTag(); + while (null !== ($nextOpening = $this->findNextOpenTagPosition())) { + if ($nextOpening > $this->position) { + $buffer[] = new LiteralNode($this->read($nextOpening - $this->position)); } + $buffer[] = $this->readTag(); } if ($this->position < $this->length) { @@ -122,6 +118,7 @@ private function readTag(): Node if (!$this->isAtOpening()) { throw new LogicException('Expected to be at opening of insert tag.'); } + $this->read(2); // Read anything up to the next open or close tag. $parts = []; @@ -138,11 +135,12 @@ private function readTag(): Node // Tag is closed, end here. if ($this->isAtClosing()) { $this->read(2); + return new Node(...$parts); } // 2. a close tag => this tag is complete. - if ($nextClosing > $this->position) { + if ((null !== $nextClosing) && $nextClosing > $this->position) { $parts[] = new LiteralNode($this->read($nextClosing - $this->position)); } @@ -192,6 +190,7 @@ private function findNextOpenTagPosition(): ?int if (false === $next = strpos($this->content, '{{', $this->position)) { return null; } + return $next; } @@ -205,6 +204,7 @@ private function findNextCloseTagPosition(): ?int if (false === $next = strpos($this->content, '}}', $this->position)) { return null; } + return $next; } diff --git a/src/Item.php b/src/Item.php index f3ba8c997..343b73b1c 100644 --- a/src/Item.php +++ b/src/Item.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Richard Henkenjohann * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -38,13 +38,14 @@ * Interface for a MetaModel item. * * @SuppressWarnings(PHPMD.TooManyPublicMethods) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class Item implements IItem { /** * The MetaModel instance attached to the item. * - * Get's populated with the first call to getMetaModel() (lazy initialization). + * Gets populated with the first call to getMetaModel() (lazy initialization). * * @var IMetaModel */ @@ -55,14 +56,14 @@ class Item implements IItem * * @var array */ - protected $arrData = array(); + protected $arrData = []; /** * The event dispatcher. * * @var null|EventDispatcherInterface */ - private $dispatcher; + private ?EventDispatcherInterface $dispatcher; /** * Create a new instance. @@ -73,7 +74,6 @@ class Item implements IItem */ public function __construct(IMetaModel $objMetaModel, $arrData, EventDispatcherInterface $dispatcher = null) { - $this->arrData = $arrData; $this->metaModel = $objMetaModel; $this->dispatcher = $dispatcher; @@ -104,6 +104,8 @@ public function __construct(IMetaModel $objMetaModel, $arrData, EventDispatcherI * Retrieve the service container. * * @return IMetaModelsServiceContainer + * + * @psalm-suppress DeprecatedInterface */ public function getServiceContainer() { @@ -113,6 +115,7 @@ public function getServiceContainer() E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + /** @psalm-suppress DeprecatedMethod */ return $this->getMetaModel()->getServiceContainer(); } @@ -127,6 +130,7 @@ protected function getEventDispatcher() return $this->dispatcher; } + /** @psalm-suppress DeprecatedMethod */ return $this->getServiceContainer()->getEventDispatcher(); } @@ -134,9 +138,7 @@ protected function getEventDispatcher() * Helper function for {@see MetaModelItem::parseValue()} and {@see MetaModelItem::parseAttribute()}. * * @param IAttribute $objAttribute The attribute to parse. - * * @param string $strOutputFormat The desired output format. - * * @param ICollection|null $objSettings The settings object to be applied. * * @return array The parsed information for the given attribute. @@ -144,31 +146,32 @@ protected function getEventDispatcher() public function internalParseAttribute($objAttribute, $strOutputFormat, $objSettings) { if ($objAttribute instanceof IInternal) { - return array(); + return []; } - $arrResult = array(); + $arrResult = []; - if ($objAttribute) { - // Extract view settings for this attribute. - if ($objSettings) { - $objAttributeSettings = $objSettings->getSetting($objAttribute->getColName()); - } else { - $objAttributeSettings = null; - } + // Extract view settings for this attribute. + if ($objSettings) { + $objAttributeSettings = $objSettings->getSetting($objAttribute->getColName()); + } else { + $objAttributeSettings = null; + } - foreach ($objAttribute->parseValue( + foreach ( + $objAttribute->parseValue( $this->arrData, $strOutputFormat, $objAttributeSettings - ) as $strKey => $varValue) { - $arrResult[$strKey] = $varValue; - } + ) as $strKey => $varValue + ) { + $arrResult[$strKey] = $varValue; } // If "hideEmptyValues" is true and the raw is empty remove text and output format. - if (($objSettings instanceof ICollection) - && $objSettings->get('hideEmptyValues') + if ( + ($objSettings instanceof ICollection) + && (bool) $objSettings->get('hideEmptyValues') && EmptyTest::isEmptyValue($arrResult['raw']) ) { unset($arrResult[$strOutputFormat]); @@ -216,7 +219,8 @@ protected function isArrayEmpty($arrArray) E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - if (!is_array($arrArray)) { + /** @psalm-suppress DocblockTypeContradiction */ + if (!\is_array($arrArray)) { // This should never happen but was possible before. return EmptyTest::isEmptyValue($arrArray); } @@ -233,14 +237,13 @@ protected function isArrayEmpty($arrArray) */ public function get($strAttributeName) { - return array_key_exists($strAttributeName, $this->arrData) ? $this->arrData[$strAttributeName] : null; + return \array_key_exists($strAttributeName, $this->arrData) ? $this->arrData[$strAttributeName] : null; } /** * Set the native value of an Attribute. * * @param string $strAttributeName The name of the attribute. - * * @param mixed $varValue The value of the attribute. * * @return IItem @@ -267,7 +270,7 @@ public function getMetaModel() * * @param string $strAttributeName The name of the attribute. * - * @return IAttribute The instance. + * @return null|IAttribute the instance or null if not found. */ public function getAttribute($strAttributeName) { @@ -275,7 +278,7 @@ public function getAttribute($strAttributeName) } /** - * Check if the given attribute is set. This mean if in the data array + * Check if the given attribute is set. This was mean if in the data array * is the filed set or not. If the attribute is not loaded the function * will return false. * @@ -286,7 +289,7 @@ public function getAttribute($strAttributeName) */ public function isAttributeSet($strAttributeName) { - return array_key_exists($strAttributeName, $this->arrData); + return \array_key_exists($strAttributeName, $this->arrData); } /** @@ -297,13 +300,13 @@ public function isAttributeSet($strAttributeName) */ public function getSetAttributes() { - return array_keys($this->arrData); + return \array_keys($this->arrData); } /** * Determines if this item is a variant of another item. * - * @return bool True if it is an variant, false otherwise. + * @return bool True if it is a variant, false otherwise. */ public function isVariant() { @@ -317,7 +320,7 @@ public function isVariant() * this item. It merely simply states, that this item is able * to function as variant base for other items. * - * @return bool True if it is an variant base, false otherwise. + * @return bool True if it is a variant base, false otherwise. */ public function isVariantBase() { @@ -325,7 +328,7 @@ public function isVariantBase() } /** - * Fetch the meta model variants for this item. + * Fetch the MetaModel variants for this item. * * @param IFilter $objFilter The filter settings to be applied. * @@ -334,14 +337,14 @@ public function isVariantBase() public function getVariants($objFilter) { if ($this->isVariantBase()) { - return $this->getMetaModel()->findVariants(array($this->get('id')), $objFilter); + return $this->getMetaModel()->findVariants([$this->get('id')], $objFilter); } return null; } /** - * Fetch the meta model variant base for this item. + * Fetch the MetaModel variant base for this item. * * Note: For a non-variant item the variant base is the item itself. * @@ -350,7 +353,12 @@ public function getVariants($objFilter) public function getVariantBase() { if ($this->getMetaModel()->hasVariants() && !$this->isVariantBase()) { - return $this->getMetaModel()->findById($this->get('vargroup')); + $base = $this->getMetaModel()->findById($this->get('vargroup')); + if (null === $base) { + throw new \RuntimeException('Database corruption, missing base item for variant.'); + } + + return $base; } return $this; @@ -370,7 +378,8 @@ public function getSiblings($objFilter) if (!$this->getMetaModel()->hasVariants()) { return null; } - return $this->getMetaModel()->findVariantsWithBase(array($this->get('id')), $objFilter); + + return $this->getMetaModel()->findVariantsWithBase([$this->get('id')], $objFilter); } /** @@ -437,6 +446,8 @@ protected function registerAssets($objSettings) * @param ICollection $objSettings The render settings to use (optional - default: null). * * @return array attribute name => format => value + * + * @psalm-suppress InvalidArrayOffset */ public function parseValue($strOutputFormat = 'text', $objSettings = null) { @@ -464,7 +475,7 @@ public function parseValue($strOutputFormat = 'text', $objSettings = null) // Add jumpTo link. $jumpTo = $this->buildJumpToLink($objSettings); - if (isset($jumpTo['url']) && $jumpTo['url']) { + if ('' !== ($jumpTo['url'] ?? '')) { $arrResult['actions']['jumpTo'] = [ 'href' => $jumpTo['url'], 'deep' => $jumpTo['deep'], @@ -482,11 +493,13 @@ public function parseValue($strOutputFormat = 'text', $objSettings = null) $objAttribute = $this->getMetaModel()->getAttribute($strAttrName); if ($objAttribute) { $arrResult['attributes'][$objAttribute->getColName()] = $objAttribute->getName(); - foreach ($this->internalParseAttribute( - $objAttribute, - $strOutputFormat, - $objSettings - ) as $strKey => $varValue) { + foreach ( + $this->internalParseAttribute( + $objAttribute, + $strOutputFormat, + $objSettings + ) as $strKey => $varValue + ) { $arrResult[$strKey][$objAttribute->getColName()] = $varValue; } } @@ -509,7 +522,7 @@ public function parseValue($strOutputFormat = 'text', $objSettings = null) * * The returning array will hold the following keys: * * params - the url parameter (only if a valid filter setting could be determined). - * * deep - boolean true, if parameters are non empty, false otherwise. + * * deep - boolean true, if parameters are non-empty, false otherwise. * * page - id of the jumpTo page. * * url - the complete generated url * @@ -519,10 +532,6 @@ public function parseValue($strOutputFormat = 'text', $objSettings = null) */ public function buildJumpToLink($objSettings) { - if (!$objSettings) { - return null; - } - return $objSettings->buildJumpToUrlFor($this); } @@ -530,16 +539,19 @@ public function buildJumpToLink($objSettings) * Renders a single attribute in the given output format. * * @param string $strAttributeName The desired attribute. - * * @param string $strOutputFormat The desired output format (optional - default: text). - * * @param ICollection $objSettings The render settings to use (optional - default: null). * * @return array format=>value */ public function parseAttribute($strAttributeName, $strOutputFormat = 'text', $objSettings = null) { - return $this->internalParseAttribute($this->getAttribute($strAttributeName), $strOutputFormat, $objSettings); + $attribute = $this->getAttribute($strAttributeName); + if (!$attribute instanceof IAttribute) { + return []; + } + + return $this->internalParseAttribute($attribute, $strOutputFormat, $objSettings); } /** @@ -556,6 +568,7 @@ public function copy() unset($arrNewData['id']); unset($arrNewData['tstamp']); unset($arrNewData['vargroup']); + return new Item($this->getMetaModel(), $arrNewData, $this->dispatcher); } @@ -565,7 +578,7 @@ public function copy() * Additionally, the item will be a variant child of this item. * * NOTE: if this item is not a variant base itself, this item will return a item - * that is a child of this items variant base. i.e. exact clone. + * that is a child of these items variant base. i.e. exact clone. * * @return \MetaModels\IItem the new copy. */ @@ -580,6 +593,7 @@ public function varCopy() $objNewItem->set('vargroup', $this->get('vargroup')); $objNewItem->set('varbase', '0'); } + return $objNewItem; } @@ -605,7 +619,8 @@ public function varCopy() private function getCaptionText($langKey) { $tableName = $this->getMetaModel()->getTableName(); - if (isset($this->objView) + if ( + isset($this->objView) && isset($GLOBALS['TL_LANG']['MSC'][$tableName][$this->objView->get('id')][$langKey]) ) { return $GLOBALS['TL_LANG']['MSC'][$tableName][$this->objView->get('id')][$langKey]; @@ -629,7 +644,7 @@ private function variantCssClass() if ($this->isVariantBase()) { $result = 'varbase'; - if (0 !== $this->getVariants(null)->getCount()) { + if (0 !== ($this->getVariants($this->getMetaModel()->getEmptyFilter())?->getCount() ?? 0)) { $result .= ' varbase-with-variants'; } return $result; diff --git a/src/ItemList.php b/src/ItemList.php index f5bade48d..f11e9e5f0 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -25,7 +25,7 @@ * @author David Molineus * @author Ingolf Steinhardt * @author Fritz Michael Gschwantner - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -52,12 +52,26 @@ use MetaModels\Render\Template; use RuntimeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Request; + +use function array_key_exists; +use function array_keys; +use function array_merge; +use function func_num_args; +use function in_array; +use function is_object; +use function sprintf; +use function strtoupper; +use function trigger_error; /** * Implementation of a general purpose MetaModel listing. * * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.ExcessiveClassLength) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.LongVariable) */ class ItemList { @@ -78,35 +92,37 @@ class ItemList /** * The view id to use. * - * @var int + * @var string */ - protected int $intView = 0; + protected string $intView = '0'; /** * Output format type. * * @var string|null */ - protected ?string $outputFormat; + protected ?string $outputFormat = null; /** * The MetaModel id to use. * - * @var int + * @var string */ - protected int $intMetaModel = 0; + protected string $intMetaModel = '0'; /** * The filter id to use. * - * @var int + * @var string + * + * @deprecated Not in use anymore - remove in MetaModels 3.0 */ - protected int $intFilter = 0; + protected string $intFilter = '0'; /** * The parameters for the filter. * - * @var string[] + * @var array|string> */ protected array $arrParam = []; @@ -254,7 +270,7 @@ public function setFilterFactory(IFilterSettingFactory $filterFactory): self */ private function getFilterFactory(): IFilterSettingFactory { - if ($this->filterFactory) { + if (null !== $this->filterFactory) { return $this->filterFactory; } // @codingStandardsIgnoreStart @@ -264,8 +280,10 @@ private function getFilterFactory(): IFilterSettingFactory E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + $factory = System::getContainer()->get('metamodels.filter_setting_factory'); + assert($factory instanceof IFilterSettingFactory); - return $this->filterFactory = System::getContainer()->get('metamodels.filter_setting_factory'); + return $this->filterFactory = $factory; } /** @@ -307,8 +325,10 @@ private function getFactory(): IFactory E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + $factory = System::getContainer()->get('metamodels.factory'); + assert($factory instanceof IFactory); - return $this->factory = System::getContainer()->get('metamodels.factory'); + return $this->factory = $factory; } /** @@ -373,8 +393,10 @@ private function getEventDispatcher(): EventDispatcherInterface E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + $dispatcher = System::getContainer()->get('event_dispatcher'); + assert($dispatcher instanceof EventDispatcherInterface); - return $this->eventDispatcher = System::getContainer()->get('event_dispatcher'); + return $this->eventDispatcher = $dispatcher; } /** @@ -407,6 +429,8 @@ public function setServiceContainerFallback(): self * @return IMetaModelsServiceContainer|null * * @deprecated The service container will get removed, use the symfony service container instead. + * + * @psalm-suppress DeprecatedInterface */ public function getServiceContainer(): ?IMetaModelsServiceContainer { @@ -476,7 +500,7 @@ public function overrideOutputFormat(string $outputFormat = null): self if ('' !== $outputFormat) { $this->outputFormat = $outputFormat; } else { - unset($this->outputFormat); + $this->outputFormat = null; } return $this; @@ -485,12 +509,12 @@ public function overrideOutputFormat(string $outputFormat = null): self /** * Set MetaModel and render settings. * - * @param int $intMetaModel The MetaModel to use. - * @param int $intView The render settings to use (if 0, the default will be used). + * @param string $intMetaModel The MetaModel to use. + * @param string $intView The render settings to use (if 0, the default will be used). * * @return ItemList */ - public function setMetaModel(int $intMetaModel, int $intView): self + public function setMetaModel(string $intMetaModel, string $intView): self { $this->intMetaModel = $intMetaModel; $this->intView = $intView; @@ -535,44 +559,44 @@ public function setLanguage(string $language): self /** * The Metamodel to use. * - * @var IMetaModel + * @var IMetaModel|null */ - protected $objMetaModel; + protected $objMetaModel = null; /** * The render settings to use. * - * @var IRenderSettingCollection + * @var IRenderSettingCollection|null */ - protected $objView; + protected $objView = null; /** * The render template to use (metamodel_). * - * @var Template + * @var Template|null */ - protected $objTemplate; + protected $objTemplate = null; /** * The list template (ce_ or mod_). * - * @var ContaoTemplate + * @var ContaoTemplate|null */ - private $listTemplate; + private $listTemplate = null; /** * The filter settings to use. * - * @var IFilterSettingCollection + * @var IFilterSettingCollection|null */ - protected $objFilterSettings; + protected $objFilterSettings = null; /** * The filter to use. * - * @var IFilter + * @var IFilter|null */ - protected $objFilter; + protected $objFilter = null; /** * The model, can be module model or content model. @@ -581,7 +605,7 @@ public function setLanguage(string $language): self * * @deprecated Do not use. */ - private $model; + private ModuleModel|null|ContentModel $model = null; /** * Get the model. @@ -592,6 +616,7 @@ public function setLanguage(string $language): self */ public function getModel(): ?Model { + /** @psalm-suppress DeprecatedProperty */ return $this->model; } @@ -601,6 +626,8 @@ public function getModel(): ?Model * @return void * * @throws RuntimeException When the MetaModel can not be found. + * + * @psalm-assert IMetaModel $this->objMetaModel */ protected function prepareMetaModel(): void { @@ -620,46 +647,40 @@ protected function prepareMetaModel(): void */ protected function prepareView(): void { + $metaModel = $this->getMetaModel(); if ($this->renderSettingFactory) { - $this->objView = $this->renderSettingFactory->createCollection($this->objMetaModel, $this->intView); + $this->objView = $this->renderSettingFactory->createCollection($metaModel, $this->intView); } else { - $this->objView = $this->objMetaModel->getView($this->intView); + /** @psalm-suppress DeprecatedMethod */ + $this->objView = $metaModel->getView((int) $this->intView); } - if ($this->objView) { - $this->objTemplate = new Template($this->objView->get('template')); - $this->objTemplate->view = $this->objView; - } else { - // Fallback to default. - $this->objTemplate = new Template('metamodel_full'); - } + $this->objTemplate = new Template((string) $this->objView->get('template')); + $this->objTemplate->view = $this->objView; } /** * Set the filter setting to use. * - * @param int $intFilter The filter setting id to use. + * @param string $intFilter The filter setting id to use. * * @return $this * * @throws RuntimeException When the filter settings can not be found. */ - public function setFilterSettings(int $intFilter): self + public function setFilterSettings(string $intFilter): self { $this->objFilterSettings = $this->getFilterFactory()->createCollection($intFilter); - if (!$this->objFilterSettings) { - throw new RuntimeException('Error: no filter object defined.'); - } - return $this; } /** * Set parameters. * - * @param string[][] $presets The parameter preset values to use. - * @param string[] $values The dynamic parameter values that may be used. + * @param array $presets The parameter preset values to use. + * @param array|string> $values The dynamic parameter values that may be + * used. * * @return ItemList * @@ -695,7 +716,7 @@ public function setFilterParameters(array $presets, array $values): self } // Not a preset or allowed to override? - use value. - if ((!array_key_exists($filterParameterKey, $presets)) || $presets[$filterParameterKey]['use_get']) { + if ((!array_key_exists($filterParameterKey, $presets)) || (bool) $presets[$filterParameterKey]['use_get']) { $processed[$filterParameterKey] = $values[$filterParameterKey]; } } @@ -712,6 +733,10 @@ public function setFilterParameters(array $presets, array $values): self */ public function getFilter(): IFilter { + if (null === $this->objFilter) { + throw new RuntimeException('No filter is set.'); + } + return $this->objFilter; } @@ -722,6 +747,12 @@ public function getFilter(): IFilter */ public function getFilterSettings(): IFilterSettingCollection { + if (null === $this->objFilterSettings) { + throw new RuntimeException( + 'Error: no filter object defined, call setFilterSettings() before.' + ); + } + return $this->objFilterSettings; } @@ -765,9 +796,9 @@ public function setTemplateParameter(string $name, mixed $value): void /** * The items in the list view. * - * @var IItems + * @var IItems|null */ - protected IItems $objItems; + protected ?IItems $objItems = null; /** * Add additional filter rules to the list. @@ -791,7 +822,7 @@ protected function modifyFilter(): self public function addFilterRule(IFilterRule $filterRule): self { if (!$this->objFilter) { - $this->objFilter = $this->objMetaModel->getEmptyFilter(); + $this->objFilter = $this->getMetaModel()->getEmptyFilter(); } $this->objFilter->addFilterRule($filterRule); @@ -804,32 +835,52 @@ public function addFilterRule(IFilterRule $filterRule): self * * In this base implementation, this only includes the attributes mentioned in the render setting. * - * @return string[] the names of the attributes to be fetched. + * @return list the names of the attributes to be fetched. */ protected function getAttributeNames(): array { - $attributes = $this->objView->getSettingNames(); - - // Get the right jumpTo. - $desiredLanguage = $this->getMetaModel()->getActiveLanguage(); - $fallbackLanguage = $this->getMetaModel()->getFallbackLanguage(); - - $filterSettingsId = 0; + $attributes = $this->getView()->getSettingNames(); + $metaModel = $this->getMetaModel(); + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ + if ($metaModel instanceof ITranslatedMetaModel) { + $desiredLanguage = $metaModel->getLanguage(); + $fallbackLanguage = $metaModel->getMainLanguage(); + $isTranslated = true; + } elseif ($metaModel->isTranslated(false)) { + // Get the right jumpTo. + /** @psalm-suppress DeprecatedMethod */ + $desiredLanguage = $metaModel->getActiveLanguage(); + /** @psalm-suppress DeprecatedMethod */ + $fallbackLanguage = $metaModel->getFallbackLanguage(); + $isTranslated = true; + } else { + $desiredLanguage = + $fallbackLanguage = System::getContainer()->get('request_stack')?->getCurrentRequest()?->getLocale(); + $isTranslated = false; + } + $filterSettingsId = ''; foreach ((array) $this->getView()->get('jumpTo') as $jumpTo) { + $langCode = (string) ($jumpTo['langcode'] ?? ''); // If either desired language or fallback, keep the result. - if (!$this->getMetaModel()->isTranslated() - || $jumpTo['langcode'] == $desiredLanguage - || $jumpTo['langcode'] == $fallbackLanguage) { - $filterSettingsId = $jumpTo['filter'] ?? 0; + /** @psalm-suppress DeprecatedMethod */ + if ( + $langCode === $desiredLanguage + || $langCode === $fallbackLanguage + || !$isTranslated + ) { + $filterSettingsId = (string) ($jumpTo['filter'] ?? ''); // If the desired language, break. Otherwise, try to get the desired one until all have been evaluated. - if (isset($jumpTo['langcode']) && $desiredLanguage === $jumpTo['langcode']) { + if ($desiredLanguage === $langCode) { break; } } } - if ($filterSettingsId) { + if ('' !== $filterSettingsId) { $filterSettings = $this->getFilterFactory()->createCollection($filterSettingsId); $attributes = array_merge($filterSettings->getReferencedAttributes(), $attributes); } @@ -846,13 +897,14 @@ protected function getAttributeNames(): array */ public function prepare(): self { - if (isset($this->objItems)) { + if (null !== $this->objItems) { return $this; } + $metaModel = $this->getMetaModel(); // Create an empty filter object if not done before. if (!isset($this->objFilter)) { - $this->objFilter = $this->objMetaModel->getEmptyFilter(); + $this->objFilter = $metaModel->getEmptyFilter(); } if (isset($this->objFilterSettings)) { @@ -861,16 +913,18 @@ public function prepare(): self $this->modifyFilter(); - $total = $this->objMetaModel->getCount($this->objFilter); + $total = $metaModel->getCount($this->objFilter); $calculator = $this->paginationLimitCalculator; $calculator->setTotalAmount($total); - $this->objTemplate->total = $total; + if (null !== $this->objTemplate) { + $this->objTemplate->total = $total; + } - if ($this->objMetaModel instanceof TranslatedMetaModel) { + if ($metaModel instanceof TranslatedMetaModel) { if (null === $this->language) { // @codingStandardsIgnoreStart - @\trigger_error( + @trigger_error( sprintf( 'Not setting a language code in "%s" is deprecated since MetaModels 2.3 and will fail in 3.0', __CLASS__ @@ -882,20 +936,20 @@ public function prepare(): self // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. $this->language = LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'] ?? 'en'); } - $previousLanguage = $this->objMetaModel->selectLanguage($this->language); + $previousLanguage = $metaModel->selectLanguage($this->language); } - $this->objItems = $this->objMetaModel->findByFilter( + $this->objItems = $metaModel->findByFilter( $this->objFilter, $this->strSortBy, - $calculator->getCalculatedOffset(), - $calculator->getCalculatedLimit(), + (int) $calculator->getCalculatedOffset(), + (int) $calculator->getCalculatedLimit(), $this->strSortDirection, $this->getAttributeNames() ); - if (isset($previousLanguage)) { - $this->objMetaModel->selectLanguage($previousLanguage); + if (isset($previousLanguage) && ($metaModel instanceof TranslatedMetaModel)) { + $metaModel->selectLanguage($previousLanguage); } return $this; @@ -920,6 +974,10 @@ public function getPagination(): string */ public function getItems(): IItems { + if (null === $this->objItems) { + throw new RuntimeException('Call prepare first'); + } + return $this->objItems; } @@ -949,6 +1007,10 @@ public function getObjItems(): IItems */ public function getView(): IRenderSettingCollection { + if (!$this->objView) { + throw new RuntimeException('No render setting set - call prepareView() first.'); + } + return $this->objView; } @@ -959,6 +1021,10 @@ public function getView(): IRenderSettingCollection */ public function getMetaModel(): IMetaModel { + if (!$this->objMetaModel) { + throw new RuntimeException('No metamodel object set - call prepareMetaModel() first.'); + } + return $this->objMetaModel; } @@ -972,7 +1038,13 @@ public function getMetaModel(): IMetaModel */ private function getPage(): ?object { - return ('FE' === TL_MODE && is_object($GLOBALS['objPage'])) ? $GLOBALS['objPage'] : null; + $isFrontend = (bool) System::getContainer() + ->get('contao.routing.scope_matcher') + ?->isFrontendRequest( + System::getContainer()->get('request_stack')?->getCurrentRequest() ?? Request::create('') + ); + + return ($isFrontend && is_object($page = $GLOBALS['objPage'])) ? $page : null; } /** @@ -982,12 +1054,12 @@ private function getPage(): ?object */ public function getOutputFormat(): string { - if (isset($this->outputFormat)) { + if (null !== $this->outputFormat) { return $this->outputFormat; } - if (isset($this->objView) && $this->objView->get('format')) { - return $this->objView->get('format'); + if ('' !== ($format = (string) $this->objView?->get('format'))) { + return $format; } $page = $this->getPage(); @@ -1016,11 +1088,15 @@ public function getOutputFormat(): string * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) + * @psalm-suppress PossiblyNullArrayOffset */ private function getCaptionText(string $langKey): string { $tableName = $this->getMetaModel()->getTableName(); - if (isset($this->objView, $GLOBALS['TL_LANG']['MSC'][$tableName][$this->objView->get('id')][$langKey])) { + if ( + null !== $this->objView + && isset($GLOBALS['TL_LANG']['MSC'][$tableName][$this->objView->get('id')][$langKey]) + ) { return $GLOBALS['TL_LANG']['MSC'][$tableName][$this->objView->get('id')][$langKey]; } @@ -1049,11 +1125,13 @@ protected function getNoItemsCaption(): string * Set the title and description in the page object. * * @return void + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ private function setTitleAndDescription(): void { $page = $this->getPage(); - if ($page && $this->objItems->getCount()) { + if ($page && null !== $this->objItems && $this->objItems->getCount()) { // Add title if needed. if (!empty($this->strTitleAttribute)) { while ($this->objItems->next()) { @@ -1119,26 +1197,33 @@ public function setSortingLinkGenerator(SortingLinkGenerator $generator): self * else. * * @return string + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ public function render(bool $isNoNativeParsing, object $caller = null): string { if (func_num_args() > 1) { trigger_error('Passing $objCaller as second argument is deprecated', E_USER_DEPRECATED); if ($caller instanceof ContentModel || $caller instanceof ModuleModel) { + /** @psalm-suppress DeprecatedProperty */ $this->model = $caller; } } + if (null === $this->objTemplate) { + return ''; + } + $event = new RenderItemListEvent($this, $this->objTemplate, $caller); $this->getEventDispatcher()->dispatch($event, MetaModelsEvents::RENDER_ITEM_LIST); - $this->objTemplate->noItemsMsg = $this->getNoItemsCaption(); $this->objTemplate->details = $this->getCaptionText('details'); $this->prepare(); $outputFormat = $this->getOutputFormat(); - if (!$isNoNativeParsing && $this->objItems->getCount()) { + if (!$isNoNativeParsing && null !== $this->objItems && $this->objItems->getCount()) { $this->objTemplate->data = $this->objItems->parseAll($outputFormat, $this->objView); } else { $this->objTemplate->data = []; @@ -1151,16 +1236,16 @@ public function render(bool $isNoNativeParsing, object $caller = null): string return []; } - $attribute = $this->objMetaModel->getAttribute($attributeName); + $attribute = $this->getMetaModel()->getAttribute($attributeName); if (null === $attribute) { - throw new \RuntimeException('Attribute not found: ' . $attributeName); + throw new RuntimeException('Attribute not found: ' . $attributeName); } return $this->sortingLinkGenerator->generateSortingLink($attribute, $type); }; - $renderSortingLink = function (string $attributeName, string $type) use ($generateSortingLink): string { + $renderSortingLink = static function (string $attributeName, string $type) use ($generateSortingLink): string { if ([] === $sortingLink = $generateSortingLink($attributeName, $type)) { return ''; } diff --git a/src/Items.php b/src/Items.php index c2d986e99..15a4f85c0 100644 --- a/src/Items.php +++ b/src/Items.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,8 @@ * @author David Maack * @author Richard Henkenjohann * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -41,7 +42,7 @@ class Items implements IItems * * @var array */ - protected $arrItems = array(); + protected $arrItems = []; /** * Creates a new instance with the passed items. @@ -56,6 +57,7 @@ public function __construct($arrItems) /** * {@inheritDoc} */ + #[\ReturnTypeWillChange] public function rewind() { $this->first(); @@ -64,6 +66,7 @@ public function rewind() /** * {@inheritDoc} */ + #[\ReturnTypeWillChange] public function current() { return $this->getItem(); @@ -72,6 +75,7 @@ public function current() /** * {@inheritDoc} */ + #[\ReturnTypeWillChange] public function key() { return $this->intCursor; @@ -80,6 +84,7 @@ public function key() /** * {@inheritDoc} */ + #[\ReturnTypeWillChange] public function valid() { return ($this->offsetExists($this->intCursor)); @@ -88,17 +93,16 @@ public function valid() /** * {@inheritDoc} */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { - if (!is_numeric($offset)) { - return false; - } return (($this->getCount() > $offset) && ($offset > -1)); } /** * {@inheritDoc} */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { if ($this->offsetExists($offset)) { @@ -112,7 +116,6 @@ public function offsetGet($offset) * Not implemented in this class. * * @param mixed $offset The offset to assign the value to. - * * @param mixed $value The value to set. * * @return void @@ -121,6 +124,7 @@ public function offsetGet($offset) * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new \RuntimeException('MetaModelItems is a read only class, you can not manipulate the collection.', 1); @@ -137,6 +141,7 @@ public function offsetSet($offset, $value) * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { throw new \RuntimeException('MetaModelItems is a read only class, you can not manipulate the collection.', 1); @@ -165,7 +170,7 @@ public function getItem() */ public function getCount() { - return count($this->arrItems); + return \count($this->arrItems); } /** @@ -177,22 +182,29 @@ public function first() $this->intCursor = 0; return $this; } + return false; } /** * {@inheritdoc} + * + * @psalm-suppress InvalidReturnType + * @psalm-suppress InvalidReturnStatement + * @psalm-suppress InvalidFalsableReturnType */ + #[\ReturnTypeWillChange] public function next() { - if ($this->getCount() == $this->intCursor) { + if ($this->getCount() === $this->intCursor) { return false; } + // We must advance over the last element. - $this->intCursor += 1; + ++$this->intCursor; // Check the index again, see #461. - return ($this->getCount() == $this->intCursor) ? false : $this; + return ($this->getCount() === $this->intCursor) ? false : $this; } /** @@ -205,6 +217,7 @@ public function prev() } $this->intCursor--; + return $this; } @@ -232,7 +245,7 @@ public function reset() */ public function getClass() { - $arrClass = array(); + $arrClass = []; if ($this->intCursor == 0) { $arrClass[] = 'first'; } @@ -246,7 +259,8 @@ public function getClass() } else { $arrClass[] = 'odd'; } - return implode(' ', $arrClass); + + return \implode(' ', $arrClass); } /** @@ -254,7 +268,10 @@ public function getClass() */ public function parseValue($strOutputFormat = 'text', $objSettings = null) { - return $this->getItem()->parseValue($strOutputFormat, $objSettings); + $item = $this->getItem(); + assert($item instanceof IItem); + + return $item->parseValue($strOutputFormat, $objSettings); } /** @@ -264,7 +281,7 @@ public function parseValue($strOutputFormat = 'text', $objSettings = null) */ public function parseAll($strOutputFormat = 'text', $objSettings = null) { - $arrResult = array(); + $arrResult = []; // Buffer cursor. $intCursor = $this->intCursor; diff --git a/src/MetaModel.php b/src/MetaModel.php index f59bf909e..23464b7f9 100644 --- a/src/MetaModel.php +++ b/src/MetaModel.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,13 +21,16 @@ * @author David Molineus * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels; +use Contao\Database; +use Contao\System; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\QueryBuilder; use MetaModels\Attribute\IAttribute; @@ -49,6 +52,7 @@ * @SuppressWarnings(PHPMD.ExcessiveClassLength) * @SuppressWarnings(PHPMD.TooManyPublicMethods) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class MetaModel implements IMetaModel { @@ -59,7 +63,7 @@ class MetaModel implements IMetaModel * * @var array */ - protected $arrData = array(); + protected $arrData = []; /** * This holds all attribute instances. @@ -68,47 +72,49 @@ class MetaModel implements IMetaModel * * @var array */ - protected $arrAttributes = array(); + protected $arrAttributes = []; /** * The service container. * - * @var IMetaModelsServiceContainer + * @var \Closure|IMetaModelsServiceContainer|null + * + * @psalm-suppress DeprecatedInterface */ - protected $serviceContainer; + protected $serviceContainer = null; /** * The database connection. * * @var Connection */ - private $connection; + private Connection $connection; /** * The event dispatcher. * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * The system columns to preserve. * * @var string[] */ - private $systemColumns; + private mixed $systemColumns; /** * The cache existing ids. * * @var array */ - private $existingIds = []; + private array $existingIds = []; /** * Instantiate a MetaModel. * - * @param array $arrData The information array, for information on the available + * @param array $arrData The information array, for information on the available * columns, refer to documentation of table tl_metamodel. * @param EventDispatcherInterface|null $dispatcher The event dispatcher. * @param Connection|null $connection The database connection. @@ -121,11 +127,9 @@ public function __construct( foreach ($arrData as $strKey => $varValue) { $this->arrData[$strKey] = $this->tryUnserialize($varValue); } - $this->systemColumns = array_key_exists('system_columns', $arrData) ? $arrData['system_columns'] : []; + $this->systemColumns = \array_key_exists('system_columns', $arrData) ? $arrData['system_columns'] : []; - $this->connection = $connection; - $this->dispatcher = $dispatcher; - if (null === $this->dispatcher) { + if (null === $dispatcher) { // @codingStandardsIgnoreStart @trigger_error( 'Not passing the event dispatcher as 2nd argument to "' . __METHOD__ . '" is deprecated ' . @@ -133,8 +137,13 @@ public function __construct( E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + + $dispatcher = System::getContainer()->get('event_dispatcher'); + assert($dispatcher instanceof EventDispatcherInterface); } - if (null === $this->connection) { + $this->dispatcher = $dispatcher; + + if (null === $connection) { // @codingStandardsIgnoreStart @trigger_error( 'Not passing the database connection as 3rd argument to "' . __METHOD__ . '" is deprecated ' . @@ -142,7 +151,11 @@ public function __construct( E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + + $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); } + $this->connection = $connection; } /** @@ -158,7 +171,14 @@ public function getServiceContainer() E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - return is_callable($this->serviceContainer) ? call_user_func($this->serviceContainer) : $this->serviceContainer; + + if (null === $this->serviceContainer) { + throw new \RuntimeException('Deprecated service container has not been set.'); + } + + return \is_callable($this->serviceContainer) + ? \call_user_func($this->serviceContainer) + : $this->serviceContainer; } /** @@ -167,11 +187,14 @@ public function getServiceContainer() * NOTE: this is deprecated - to prevent triggering deprecation notices, you may pass a closure here which * will then return the service container. * - * @param \Closure|IMetaModelsServiceContainer $serviceContainer The service container. + * @param \Closure|IMetaModelsServiceContainer $serviceContainer The service container. + * @param bool $deprecationNotice Send deprecation notice. * * @return MetaModel * * @deprecated Inject services via constructor or setter. + * + * @psalm-suppress DeprecatedInterface */ public function setServiceContainer($serviceContainer, $deprecationNotice = true) { @@ -191,7 +214,7 @@ public function setServiceContainer($serviceContainer, $deprecationNotice = true /** * Retrieve the database instance to use. * - * @return \Contao\Database + * @return Database * * @deprecated Use the doctrine connection instead. */ @@ -203,6 +226,7 @@ protected function getDatabase() E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + /** @psalm-suppress DeprecatedMethod */ return $this->getServiceContainer()->getDatabase(); } @@ -215,10 +239,11 @@ protected function getDatabase() */ protected function tryUnserialize(mixed $value): mixed { - if (\is_string($value) - && 0 === \strpos($value, 'a:') - && \is_array($unSerialized = \unserialize($value, ['allowed_classes' => false]))) { - + if ( + \is_string($value) + && \str_starts_with($value, 'a:') + && \is_array($unSerialized = \unserialize($value, ['allowed_classes' => false])) + ) { return $unSerialized; } @@ -255,7 +280,7 @@ public function addAttribute(IAttribute $objAttribute) */ public function hasAttribute($strAttributeName) { - return array_key_exists($strAttributeName, $this->arrAttributes); + return \array_key_exists($strAttributeName, $this->arrAttributes); } /** @@ -303,7 +328,7 @@ protected function isTranslatedAttribute($objAttribute) */ protected function getAttributeImplementing($interface) { - $result = array(); + $result = []; foreach ($this->getAttributes() as $colName => $attribute) { if ($attribute instanceof $interface) { $result[$colName] = $attribute; @@ -348,7 +373,7 @@ protected function getTranslatedAttributes() * * @param IFilter|null $objFilter The filter to search the matching ids for. * - * @return array all matching Ids. + * @return list all matching Ids. */ protected function getMatchingIds($objFilter) { @@ -379,7 +404,7 @@ protected function getMatchingIds($objFilter) */ protected function buildDatabaseParameterList($parameters) { - return implode(',', array_fill(0, count($parameters), '?')); + return \implode(',', \array_fill(0, \count($parameters), '?')); } /** @@ -387,7 +412,6 @@ protected function buildDatabaseParameterList($parameters) * * @param string[] $arrIds The ids of the items to retrieve the order of ids is used for sorting of the return * values. - * * @param string[] $arrAttrOnly Names of the attributes that shall be contained in the result, defaults to array() * which means all attributes. * @@ -404,20 +428,20 @@ protected function fetchRows($arrIds, $arrAttrOnly = array()) ->select('t.*') ->from($this->getTableName(), 't') ->where($builder->expr()->in('t.id', ':values')) - ->setParameter('values', $arrIds, Connection::PARAM_STR_ARRAY) + ->setParameter('values', $arrIds, ArrayParameterType::STRING) ->orderBy('FIELD(id, :values)') ->executeQuery(); // If we have an attribute restriction, make sure we keep the system columns. See #196. if ($arrAttrOnly) { - $arrAttrOnly = array_merge($this->systemColumns, $arrAttrOnly); + $arrAttrOnly = \array_merge($this->systemColumns, $arrAttrOnly); } $result = []; while ($row = $query->fetchAssociative()) { $data = []; foreach ($row as $attribute => $value) { - if ((!$arrAttrOnly) || (in_array($attribute, $arrAttrOnly, true))) { + if ((!$arrAttrOnly) || (\in_array($attribute, $arrAttrOnly, true))) { $data[$attribute] = $value; } } @@ -431,10 +455,9 @@ protected function fetchRows($arrIds, $arrAttrOnly = array()) /** * This method is called to retrieve the data for certain items from the database. * - * @param ITranslated $attribute The attribute to fetch the values for. - * - * @param string[] $ids The ids of the items to retrieve the order of ids is used for sorting of the return - * values. + * @param ITranslated $attribute The attribute to fetch the values for. + * @param list $ids The ids of the items to retrieve the order of ids is used for sorting of the + * return values. * * @return array an array of all matched items, sorted by the id list. * @@ -442,11 +465,13 @@ protected function fetchRows($arrIds, $arrAttrOnly = array()) */ protected function fetchTranslatedAttributeValues(ITranslated $attribute, $ids) { + /** @psalm-suppress DeprecatedMethod */ $attributeData = $attribute->getTranslatedDataFor($ids, $this->getActiveLanguage()); - $missing = array_diff($ids, array_keys($attributeData)); + $missing = \array_values(\array_diff($ids, array_keys($attributeData))); if ($missing) { - $attributeData += $attribute->getTranslatedDataFor($missing, $this->getFallbackLanguage()); + /** @psalm-suppress DeprecatedMethod */ + $attributeData += $attribute->getTranslatedDataFor($missing, $this->getFallbackLanguage() ?? ''); } return $attributeData; @@ -455,22 +480,20 @@ protected function fetchTranslatedAttributeValues(ITranslated $attribute, $ids) /** * This method is called to retrieve the data for certain items from the database. * - * @param string[] $ids The ids of the items to retrieve the order of ids is used for sorting of the - * return values. - * - * @param array $result The current values. - * - * @param string[] $attrOnly Names of the attributes that shall be contained in the result, defaults to array() - * which means all attributes. + * @param list $ids The ids of the items to retrieve the order of ids is used for sorting of the + * return values. + * @param array $result The current values. + * @param string[] $attrOnly Names of the attributes that shall be contained in the result, defaults to array() + * which means all attributes. * * @return array an array of all matched items, sorted by the id list. */ - protected function fetchAdditionalAttributes($ids, $result, $attrOnly = array()) + protected function fetchAdditionalAttributes($ids, $result, $attrOnly = []) { $attributes = $this->getAttributeByNames($attrOnly); - $attributeNames = array_intersect( - array_keys($attributes), - array_keys(array_merge($this->getComplexAttributes(), $this->getTranslatedAttributes())) + $attributeNames = \array_intersect( + \array_keys($attributes), + \array_keys(\array_merge($this->getComplexAttributes(), $this->getTranslatedAttributes())) ); foreach ($attributeNames as $attributeName) { @@ -481,14 +504,17 @@ protected function fetchAdditionalAttributes($ids, $result, $attrOnly = array()) // If it is translated, fetch the translated data now. if ($this->isTranslatedAttribute($attribute)) { - /** @var ITranslated $attribute */ + /** + * @var ITranslated $attribute + * @psalm-suppress DeprecatedMethod + */ $attributeData = $this->fetchTranslatedAttributeValues($attribute, $ids); } else { /** @var IComplex $attribute */ $attributeData = $attribute->getDataFor($ids); } - foreach (array_keys($result) as $id) { + foreach (\array_keys($result) as $id) { $result[$id][$attributeName] = ($attributeData[$id] ?? null); } } @@ -499,24 +525,23 @@ protected function fetchAdditionalAttributes($ids, $result, $attrOnly = array()) /** * This method is called to retrieve the data for certain items from the database. * - * @param int[] $arrIds The ids of the items to retrieve the order of ids is used for sorting of the - * return values. - * - * @param string[] $arrAttrOnly Names of the attributes that shall be contained in the result, defaults to array() - * which means all attributes. + * @param list $arrIds The ids of the items to retrieve the order of ids is used for sorting of the + * return values. + * @param string[] $arrAttrOnly Names of the attributes that shall be contained in the result, defaults to + * array() which means all attributes. * - * @return \MetaModels\IItems a collection of all matched items, sorted by the id list. + * @return IItems a collection of all matched items, sorted by the id list. */ - protected function getItemsWithId($arrIds, $arrAttrOnly = array()) + protected function getItemsWithId($arrIds, $arrAttrOnly = []) { - $arrIds = array_unique(array_filter($arrIds)); + $arrIds = \array_values(\array_unique(\array_filter($arrIds))); if (!$arrIds) { - return new Items(array()); + return new Items([]); } if (!$arrAttrOnly) { - $arrAttrOnly = array_keys($this->getAttributes()); + $arrAttrOnly = \array_keys($this->getAttributes()); } $arrResult = $this->fetchRows($arrIds, $arrAttrOnly); @@ -527,9 +552,9 @@ protected function getItemsWithId($arrIds, $arrAttrOnly = array()) $strColName = $objAttribute->getColName(); // Run each row. - foreach (array_keys($arrResult) as $intId) { + foreach (\array_keys($arrResult) as $intId) { // Do only skip if the key does not exist. Do not use isset() here as "null" is a valid value. - if (!array_key_exists($strColName, $arrResult[$intId])) { + if (!\array_key_exists($strColName, $arrResult[$intId])) { continue; } $value = $arrResult[$intId][$strColName]; @@ -538,8 +563,8 @@ protected function getItemsWithId($arrIds, $arrAttrOnly = array()) if ($value === $value2) { $value2 = $this->tryUnserialize($value); if ($value !== $value2) { - trigger_error( - sprintf( + \trigger_error( + \sprintf( 'Attribute type %s should implement method unserializeData() and serializeData().', $objAttribute->get('type') ), @@ -554,7 +579,7 @@ protected function getItemsWithId($arrIds, $arrAttrOnly = array()) // Determine "independent attributes" (complex and translated) and inject their content into the row. $arrResult = $this->fetchAdditionalAttributes($arrIds, $arrResult, $arrAttrOnly); - $arrItems = array(); + $arrItems = []; foreach ($arrResult as $arrEntry) { $arrItems[] = new Item($this, $arrEntry, $this->dispatcher); } @@ -576,6 +601,7 @@ protected function copyFilter($objFilter) } else { $objNewFilter = $this->getEmptyFilter(); } + return $objNewFilter; } @@ -586,12 +612,12 @@ public function get($strKey) { // Try to retrieve via getter method. $strGetter = 'get' . $strKey; - if (method_exists($this, $strGetter)) { + if (\method_exists($this, $strGetter)) { return $this->$strGetter(); } // Return via raw array if available. - if (array_key_exists($strKey, $this->arrData)) { + if (\array_key_exists($strKey, $this->arrData)) { return $this->arrData[$strKey]; } @@ -603,7 +629,7 @@ public function get($strKey) */ public function getTableName() { - return ($this->arrData['tableName'] ?? null); + return ($this->arrData['tableName'] ?? ''); } /** @@ -631,12 +657,14 @@ public function getInVariantAttributes() if (!$this->hasVariants()) { return $arrAttributes; } + // Remove all attributes that are selected for overriding. foreach ($arrAttributes as $strAttributeId => $objAttribute) { if ($objAttribute->get('isvariant')) { unset($arrAttributes[$strAttributeId]); } } + return $arrAttributes; } @@ -650,20 +678,22 @@ public function isTranslated(bool $deprecation = true) if (!$deprecation) { return $this->arrData['translated']; } + if ($this instanceof ITranslatedMetaModel) { // @codingStandardsIgnoreStart @\trigger_error( - sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . + \sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'Please use "instanceof \MetaModels\ITranslatedMetaModel" instead.', __METHOD__), E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd return true; } + if ($this->arrData['translated']) { // @codingStandardsIgnoreStart @\trigger_error( - sprintf( + \sprintf( 'The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'MetaModel "%s" should implement "\MetaModels\ITranslatedMetaModel" instead.', __METHOD__, @@ -672,12 +702,13 @@ public function isTranslated(bool $deprecation = true) E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + return true; } // @codingStandardsIgnoreStart @\trigger_error( - sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . + \sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'Please use "instanceof \MetaModels\ITranslatedMetaModel" instead.', __METHOD__), E_USER_DEPRECATED ); @@ -704,7 +735,7 @@ public function getAvailableLanguages() if ($this instanceof ITranslatedMetaModel) { // @codingStandardsIgnoreStart @\trigger_error( - sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . + \sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'Please use "\MetaModels\ITranslatedMetaModel::getLanguages" instead.', __METHOD__), E_USER_DEPRECATED ); @@ -712,21 +743,22 @@ public function getAvailableLanguages() return $this->getLanguages(); } + /** @psalm-suppress DeprecatedMethod */ if ($this->isTranslated(false)) { // @codingStandardsIgnoreStart @\trigger_error( - sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . + \sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'Please test for "instanceof "\MetaModels\ITranslatedMetaModel" and use '. '"\MetaModels\ITranslatedMetaModel::getLanguages" instead.', __METHOD__), E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - return array_keys((array) $this->arrData['languages']); + return \array_keys((array) $this->arrData['languages']); } // @codingStandardsIgnoreStart @\trigger_error( - sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . + \sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'Please test for "instanceof \MetaModels\ITranslatedMetaModel".', __METHOD__), E_USER_DEPRECATED ); @@ -745,7 +777,7 @@ public function getFallbackLanguage() if ($this instanceof ITranslatedMetaModel) { // @codingStandardsIgnoreStart @\trigger_error( - sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . + \sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'Please use "\MetaModels\ITranslatedMetaModel::getMainLanguage" instead.', __METHOD__), E_USER_DEPRECATED ); @@ -753,10 +785,11 @@ public function getFallbackLanguage() return $this->getMainLanguage(); } + /** @psalm-suppress DeprecatedMethod */ if ($this->isTranslated(false)) { // @codingStandardsIgnoreStart @\trigger_error( - sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . + \sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'Please implement interface "\MetaModels\ITranslatedMetaModel" and use ' . '"\MetaModels\ITranslatedMetaModel::getMainLanguage" instead.', __METHOD__), E_USER_DEPRECATED @@ -770,7 +803,7 @@ public function getFallbackLanguage() } // @codingStandardsIgnoreStart @\trigger_error( - sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . + \sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'Please test for translations via "instanceof \MetaModels\ITranslatedMetaModel" and call ' . '"\MetaModels\ITranslatedMetaModel::getMainLanguage" instead.', __METHOD__), E_USER_DEPRECATED @@ -795,7 +828,7 @@ public function getActiveLanguage() if ($this instanceof ITranslatedMetaModel) { // @codingStandardsIgnoreStart @\trigger_error( - sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . + \sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'Please use "\MetaModels\ITranslatedMetaModel::getLanguage" and ' . '"\MetaModels\ITranslatedMetaModel::selectLanguage" instead.', __METHOD__), E_USER_DEPRECATED @@ -804,7 +837,7 @@ public function getActiveLanguage() } else { // @codingStandardsIgnoreStart @\trigger_error( - sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . + \sprintf('The method "%s" is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'Please use "\MetaModels\ITranslatedMetaModel::getLanguage" instead.', __METHOD__), E_USER_DEPRECATED ); @@ -821,6 +854,7 @@ public function getActiveLanguage() public function getAttribute($strAttributeName) { $arrAttributes = $this->getAttributes(); + return ($arrAttributes[$strAttributeName] ?? null); } @@ -830,10 +864,11 @@ public function getAttribute($strAttributeName) public function getAttributeById($intId) { foreach ($this->getAttributes() as $objAttribute) { - if ((int) $objAttribute->get('id') === (int) $intId) { + if ((int) $objAttribute->get('id') === $intId) { return $objAttribute; } } + return null; } @@ -864,15 +899,17 @@ protected function getAttributeByNames($attrNames = []) /** * {@inheritdoc} */ - public function findById($intId, $arrAttrOnly = array()) + public function findById($intId, $arrAttrOnly = []) { if (!$intId) { return null; } - $objItems = $this->getItemsWithId(array($intId), $arrAttrOnly); - if ($objItems && $objItems->first()) { + + $objItems = $this->getItemsWithId([$intId], $arrAttrOnly); + if ($objItems->first()) { return $objItems->getItem(); } + return null; } @@ -885,7 +922,7 @@ public function findByFilter( $intOffset = 0, $intLimit = 0, $strSortOrder = 'ASC', - $arrAttrOnly = array() + $arrAttrOnly = [] ) { return $this->getItemsWithId( $this->getIdsFromFilter( @@ -906,7 +943,7 @@ public function findByFilter( */ public function getIdsFromFilter($objFilter, $strSortBy = '', $intOffset = 0, $intLimit = 0, $strSortOrder = 'ASC') { - if ([] === $arrFilteredIds = array_filter($this->getMatchingIds($objFilter))) { + if ([] === $arrFilteredIds = \array_values(\array_filter($this->getMatchingIds($objFilter)))) { return []; } @@ -916,28 +953,28 @@ public function getIdsFromFilter($objFilter, $strSortBy = '', $intOffset = 0, $i $arrFilteredIds = $objSortAttribute->sortIds($arrFilteredIds, $strSortOrder); } elseif ('id' === $strSortBy) { if ($strSortOrder === 'ASC') { - asort($arrFilteredIds); + \asort($arrFilteredIds); } else { - rsort($arrFilteredIds); + \rsort($arrFilteredIds); } - } elseif (in_array($strSortBy, array('pid', 'tstamp', 'sorting'))) { + } elseif (\in_array($strSortBy, array('pid', 'tstamp', 'sorting'))) { // Build the right key for the cache. $sortKey = \sprintf('%s-%s', $strSortBy, \strtolower($strSortOrder)); // Used the cached ID list, and make a list of wanted ID's with the sorting of the cache. if (!isset($this->existingIds[$sortKey])) { $this->existingIds[$sortKey] = []; } - $cacheResult = array_intersect($this->existingIds[$sortKey], $arrFilteredIds); + $cacheResult = \array_intersect($this->existingIds[$sortKey], $arrFilteredIds); // Check if we have all ID's or if we have one missing, now we are using the order of the MM Filter. - if (array_intersect($arrFilteredIds, $cacheResult) === $arrFilteredIds) { + if (\array_intersect($arrFilteredIds, $cacheResult) === $arrFilteredIds) { if ($intOffset > 0 || $intLimit > 0) { - return array_values(array_slice($cacheResult, $intOffset, $intLimit ?: null)); + return \array_values(\array_slice($cacheResult, $intOffset, $intLimit ?: null)); } - return array_values($cacheResult); + return \array_values($cacheResult); } // Merge the already known and the new one. - $fullIdList = array_merge((array) $this->existingIds[$sortKey], $arrFilteredIds); + $fullIdList = \array_merge((array) $this->existingIds[$sortKey], $arrFilteredIds); $fullIdList = \array_keys(\array_flip($fullIdList)); // Sort by database values. @@ -947,24 +984,24 @@ public function getIdsFromFilter($objFilter, $strSortBy = '', $intOffset = 0, $i ->select('t.id') ->from($this->getTableName(), 't') ->where($builder->expr()->in('t.id', ':values')) - ->setParameter('values', $arrFilteredIds, Connection::PARAM_STR_ARRAY) + ->setParameter('values', $arrFilteredIds, ArrayParameterType::STRING) ->orderBy($strSortBy, $strSortOrder) ->executeQuery() ->fetchFirstColumn(); // Add the new sorted Id's to the cache and use only the wanted. $this->existingIds[$sortKey] = $arrSortedFilteredIds; - $arrFilteredIds = array_intersect($arrSortedFilteredIds, $arrFilteredIds); - } elseif ($strSortBy == 'random') { - shuffle($arrFilteredIds); + $arrFilteredIds = \array_intersect($arrSortedFilteredIds, $arrFilteredIds); + } elseif ($strSortBy === 'random') { + \shuffle($arrFilteredIds); } } // Apply limiting then. if ($intOffset > 0 || $intLimit > 0) { - $arrFilteredIds = array_slice($arrFilteredIds, $intOffset, $intLimit ?: null); + $arrFilteredIds = \array_slice($arrFilteredIds, $intOffset, $intLimit ?: null); } - return array_values($arrFilteredIds); + return \array_values($arrFilteredIds); } /** @@ -973,7 +1010,7 @@ public function getIdsFromFilter($objFilter, $strSortBy = '', $intOffset = 0, $i public function getCount($objFilter) { $arrFilteredIds = $this->getMatchingIds($objFilter); - if (0 === count($arrFilteredIds)) { + if (0 === \count($arrFilteredIds)) { return 0; } @@ -983,7 +1020,7 @@ public function getCount($objFilter) ->select('COUNT(t.id)') ->from($this->getTableName(), 't') ->where($builder->expr()->in('t.id', ':values')) - ->setParameter('values', $arrFilteredIds, Connection::PARAM_STR_ARRAY) + ->setParameter('values', $arrFilteredIds, ArrayParameterType::STRING) ->executeQuery() ->fetchOne(); } @@ -1005,6 +1042,7 @@ public function findVariantBase($objFilter) ->fetchFirstColumn(); $objNewFilter->addFilterRule(new StaticIdList($idList)); + return $this->findByFilter($objNewFilter); } @@ -1015,7 +1053,7 @@ public function findVariants($arrIds, $objFilter) { if (!$arrIds) { // Return an empty result. - return $this->getItemsWithId(array()); + return $this->getItemsWithId([]); } $objNewFilter = $this->copyFilter($objFilter); @@ -1026,11 +1064,12 @@ public function findVariants($arrIds, $objFilter) ->from($this->getTableName(), 't') ->where('t.varbase=0') ->andWhere($builder->expr()->in('t.vargroup', ':ids')) - ->setParameter('ids', $arrIds, Connection::PARAM_STR_ARRAY) + ->setParameter('ids', $arrIds, ArrayParameterType::STRING) ->executeQuery() ->fetchFirstColumn(); $objNewFilter->addFilterRule(new StaticIdList($idList)); + return $this->findByFilter($objNewFilter); } @@ -1052,11 +1091,12 @@ public function findVariantsWithBase($arrIds, $objFilter) ->from($this->getTableName(), 't') ->leftJoin('t', $this->getTableName(), 't2', 't.vargroup=t2.vargroup') ->where($builder->expr()->in('t2.id', ':ids')) - ->setParameter('ids', $arrIds, Connection::PARAM_STR_ARRAY) + ->setParameter('ids', $arrIds, ArrayParameterType::STRING) ->executeQuery() ->fetchFirstColumn(); $objNewFilter->addFilterRule(new StaticIdList($idList)); + return $this->findByFilter($objNewFilter); } @@ -1070,10 +1110,11 @@ public function getAttributeOptions($strAttribute, $objFilter = null) if ($objFilter) { $arrFilteredIds = $this->getMatchingIds($objFilter); $arrFilteredIds = $objAttribute->sortIds($arrFilteredIds, 'ASC'); + return $objAttribute->getFilterOptions($arrFilteredIds, true); - } else { - return $objAttribute->getFilterOptions(null, true); } + + return $objAttribute->getFilterOptions(null, true); } return []; @@ -1083,38 +1124,33 @@ public function getAttributeOptions($strAttribute, $objFilter = null) * Update the value of a native column for the given ids with the given data. * * @param string $strColumn The column name to update (i.e. tstamp). - * * @param array $arrIds The ids of the rows that shall be updated. - * * @param mixed $varData The data to save. If this is an array, it is automatically serialized. * * @return void */ protected function saveSimpleColumn($strColumn, $arrIds, $varData) { - if (is_array($varData)) { - $varData = serialize($varData); + if (\is_array($varData)) { + $varData = \serialize($varData); } $builder = $this->getConnection()->createQueryBuilder(); $builder ->update($this->getTableName(), 't2') - ->set('t2.' . $strColumn, is_array($varData) ? serialize($varData) : $varData) + ->set('t2.' . $strColumn, \is_array($varData) ? \serialize($varData) : $varData) ->where($builder->expr()->in('t2.id', ':ids')) - ->setParameter('ids', $arrIds, Connection::PARAM_STR_ARRAY) - ->execute(); + ->setParameter('ids', $arrIds, ArrayParameterType::STRING) + ->executeQuery(); } /** * Update an attribute for the given ids with the given data. * * @param IAttribute $objAttribute The attribute to save. - * * @param array $arrIds The ids of the rows that shall be updated. - * * @param mixed $varData The data to save in raw data. - * * @param string $strLangCode The language code to save. * * @return void @@ -1129,7 +1165,7 @@ protected function saveAttribute($objAttribute, $arrIds, $varData, $strLangCode) $varData = $objAttribute->serializeData($varData); } - $arrData = array(); + $arrData = []; foreach ($arrIds as $intId) { $arrData[$intId] = $varData; } @@ -1146,7 +1182,7 @@ protected function saveAttribute($objAttribute, $arrIds, $varData, $strLangCode) } else { throw new \RuntimeException( 'Unknown attribute type, can not save. Interfaces implemented: ' . - implode(', ', class_implements($objAttribute)) + \implode(', ', \class_implements($objAttribute)) ); } } @@ -1155,11 +1191,8 @@ protected function saveAttribute($objAttribute, $arrIds, $varData, $strLangCode) * Update the variants with the value if needed. * * @param IItem $item The item to save. - * * @param string $activeLanguage The language the values are in. - * * @param int[] $allIds The ids of all variants. - * * @param bool $baseAttributes If also the base attributes get updated as well. * * @return void @@ -1220,7 +1253,7 @@ protected function createNewItem($item) ->insert($this->getTableName()) ->values($parameters) ->setParameters($data) - ->execute(); + ->executeQuery(); $item->set('id', $connection->lastInsertId()); @@ -1242,28 +1275,32 @@ public function saveItem($objItem, $timestamp = null) E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + + $timestamp = \time(); } $baseAttributes = $this->saveBaseColumns($objItem, $timestamp ?: \time()); + /** @psalm-suppress DeprecatedMethod */ if ($this instanceof ITranslatedMetaModel) { $strActiveLanguage = $this->getLanguage(); } elseif ($this->isTranslated(false)) { // @codingStandardsIgnoreStart @\trigger_error( - sprintf('Support for translated MetaModels not implementing "\MetaModels\ITranslatedMetaModel" '. - 'is deprecated since MetaModels 2.2 and to be removed in 3.0. ' . + \sprintf('Support for translated MetaModels not implementing "\MetaModels\ITranslatedMetaModel" '. + 'is %s deprecated since MetaModels 2.2 and to be removed in 3.0. ' . 'Please implement interface "\MetaModels\ITranslatedMetaModel".', __METHOD__), E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + /** @psalm-suppress DeprecatedMethod */ $strActiveLanguage = $this->getActiveLanguage(); } else { - $strActiveLanguage = null; + $strActiveLanguage = ''; } $arrAllIds = array(); if ($objItem->isVariantBase()) { - $objVariants = $this->findVariantsWithBase(array($objItem->get('id')), null); + $objVariants = $this->findVariantsWithBase([$objItem->get('id')], null); foreach ($objVariants as $objVariant) { /** @var IItem $objVariant */ $arrAllIds[] = $objVariant->get('id'); @@ -1285,10 +1322,11 @@ public function saveItem($objItem, $timestamp = null) */ public function delete(IItem $objItem) { - $arrIds = array($objItem->get('id')); + $arrIds = [$objItem->get('id')]; // Determine if the model is a variant base and if so, fetch the variants additionally. if ($objItem->isVariantBase()) { $objVariants = $objItem->getVariants(new Filter($this)); + assert($objVariants instanceof IItems); foreach ($objVariants as $objVariant) { /** @var IItem $objVariant */ $arrIds[] = $objVariant->get('id'); @@ -1308,8 +1346,8 @@ public function delete(IItem $objItem) $builder ->delete($this->getTableName()) ->where($builder->expr()->in($this->getTableName() . '.id', ':ids')) - ->setParameter('ids', $arrIds, Connection::PARAM_STR_ARRAY) - ->execute(); + ->setParameter('ids', $arrIds, ArrayParameterType::STRING) + ->executeQuery(); } /** @@ -1335,6 +1373,7 @@ public function prepareFilter($intFilterSettings, $arrFilterUrl) $objFilter = $this->getEmptyFilter(); if ($intFilterSettings) { + /** @psalm-suppress DeprecatedMethod */ $objFilterSettings = $this->getServiceContainer()->getFilterFactory()->createCollection($intFilterSettings); $objFilterSettings->addRules($objFilter, $arrFilterUrl); } @@ -1354,26 +1393,18 @@ public function getView($intViewId = 0) ); // @codingStandardsIgnoreEnd - return $this->getServiceContainer()->getRenderSettingFactory()->createCollection($this, $intViewId); + /** @psalm-suppress DeprecatedMethod */ + return $this->getServiceContainer()->getRenderSettingFactory()->createCollection($this, (string) $intViewId); } /** * Obtain the doctrine connection. * * @return Connection - * - * @throws \ReflectionException Throws could not connect to database. */ private function getConnection() { - if ($this->connection) { - return $this->connection; - } - - $reflection = new \ReflectionProperty(\Contao\Database::class, 'resConnection'); - $reflection->setAccessible(true); - - return $this->connection = $reflection->getValue($this->getDatabase()); + return $this->connection; } /** @@ -1384,7 +1415,7 @@ private function getConnection() * * @return bool */ - private function saveBaseColumns(IItem $item, $timestamp) + private function saveBaseColumns(IItem $item, int $timestamp): bool { $isNew = false; $item->set('tstamp', $timestamp); diff --git a/src/MetaModelsEvents.php b/src/MetaModelsEvents.php index cff4065b1..c3d19bdbd 100644 --- a/src/MetaModelsEvents.php +++ b/src/MetaModelsEvents.php @@ -35,7 +35,7 @@ class MetaModelsEvents * * @see MetaModelsEvents::SUBSYSTEM_BOOT_BACKEND */ - const SUBSYSTEM_BOOT = 'metamodels.boot'; + public const SUBSYSTEM_BOOT = 'metamodels.boot'; /** * Event for booting a MetaModels subsystem in the frontend. @@ -44,7 +44,7 @@ class MetaModelsEvents * * @see \MetaModels\Events\MetaModelsBootEvent */ - const SUBSYSTEM_BOOT_FRONTEND = 'metamodels.boot.frontend'; + public const SUBSYSTEM_BOOT_FRONTEND = 'metamodels.boot.frontend'; /** * Event for booting a MetaModels subsystem in the backend. @@ -53,40 +53,40 @@ class MetaModelsEvents * * @see \MetaModels\Events\MetaModelsBootEvent */ - const SUBSYSTEM_BOOT_BACKEND = 'metamodels.boot.backend'; + public const SUBSYSTEM_BOOT_BACKEND = 'metamodels.boot.backend'; /** * Event when a attribute factory is created. * * @see \MetaModels\Attribute\Events\CreateAttributeFactoryEvent */ - const ATTRIBUTE_FACTORY_CREATE = 'metamodels.attribute.factory.create'; + public const ATTRIBUTE_FACTORY_CREATE = 'metamodels.attribute.factory.create'; /** * Event when a filter setting factory is created. * * @see \MetaModels\Filter\Setting\Events\CreateFilterSettingFactoryEvent */ - const FILTER_SETTING_FACTORY_CREATE = 'metamodels.filter-setting.factory.create'; + public const FILTER_SETTING_FACTORY_CREATE = 'metamodels.filter-setting.factory.create'; /** * Event when a render setting factory is created. * * @see \MetaModels\Render\Setting\Events\CreateRenderSettingFactoryEvent */ - const RENDER_SETTING_FACTORY_CREATE = 'metamodels.render-setting.factory.create'; + public const RENDER_SETTING_FACTORY_CREATE = 'metamodels.render-setting.factory.create'; /** * Event when an item is parsed. * * @see \MetaModels\Events\ParseItemEvent. */ - const PARSE_ITEM = 'metamodels.parse-item'; + public const PARSE_ITEM = 'metamodels.parse-item'; /** * Event when an item list is rendered. * * @see \MetaModels\Events\RenderItemListEvent. */ - const RENDER_ITEM_LIST = 'metamodels.render-item-list'; + public const RENDER_ITEM_LIST = 'metamodels.render-item-list'; } diff --git a/src/MetaModelsServiceContainer.php b/src/MetaModelsServiceContainer.php index 916e5e108..1ead59852 100644 --- a/src/MetaModelsServiceContainer.php +++ b/src/MetaModelsServiceContainer.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,17 +15,25 @@ * @author Sven Baumann * @author David Molineus * @author Richard Henkenjohann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels; +use Closure; use Contao\BackendUser; +use Contao\Database; use Contao\FrontendUser; +use Contao\System; +use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use Doctrine\Common\Cache\Cache; +use Doctrine\DBAL\Connection; +use InvalidArgumentException; use MetaModels\Attribute\IAttributeFactory; +use MetaModels\BackendIntegration\ViewCombinations; use MetaModels\Filter\Setting\IFilterSettingFactory; use MetaModels\Render\Setting\IRenderSettingFactory; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -34,62 +42,67 @@ * Reference implementation of IMetaModelsServiceContainer. * * @deprecated The service container will get removed, use the symfony service container instead. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * + * @psalm-suppress DeprecatedInterface + * @psalm-suppress MissingConstructor */ class MetaModelsServiceContainer implements IMetaModelsServiceContainer { /** * The factory to use. * - * @var IFactory + * @var IFactory|callable */ protected $factory; /** * The factory to use. * - * @var IAttributeFactory + * @var IAttributeFactory|callable */ protected $attributeFactory; /** * The filter setting factory. * - * @var IFilterSettingFactory + * @var IFilterSettingFactory|callable */ protected $filterFactory; /** * The render setting factory. * - * @var IRenderSettingFactory + * @var IRenderSettingFactory|callable */ protected $renderFactory; /** * The event dispatcher. * - * @var EventDispatcherInterface + * @var EventDispatcherInterface|callable */ protected $dispatcher; /** * The Contao database instance to use. * - * @var \Contao\Database + * @var Database|callable */ protected $database; /** * The cache in use. * - * @var Cache + * @var Cache|callable */ protected $cache; /** * Registered services. * - * @var object[] + * @var array */ protected $services; @@ -123,6 +136,7 @@ public function getFactory() if (\is_callable($this->factory)) { $this->factory = \call_user_func($this->factory); + /** @psalm-suppress DeprecatedMethod */ $this->factory->setServiceContainer($this, false); } @@ -159,6 +173,7 @@ public function getAttributeFactory() if (\is_callable($this->attributeFactory)) { $this->attributeFactory = \call_user_func($this->attributeFactory); + /** @psalm-suppress DeprecatedMethod */ $this->attributeFactory->setServiceContainer($this, false); } @@ -195,6 +210,7 @@ public function getFilterFactory() if (\is_callable($this->filterFactory)) { $this->filterFactory = \call_user_func($this->filterFactory); + /** @psalm-suppress DeprecatedMethod */ $this->filterFactory->setServiceContainer($this, false); } @@ -231,6 +247,7 @@ public function getRenderSettingFactory() if (\is_callable($this->renderFactory)) { $this->renderFactory = \call_user_func($this->renderFactory); + /** @psalm-suppress DeprecatedMethod */ $this->renderFactory->setServiceContainer($this, false); } @@ -275,7 +292,7 @@ public function getEventDispatcher() /** * Set the Contao database instance. * - * @param \Contao\Database|callable $database The contao database instance. + * @param Database|callable $database The contao database instance. * * @return MetaModelsServiceContainer */ @@ -347,7 +364,7 @@ public function setCache($cache) /** * {@inheritdoc} * - * @throws \InvalidArgumentException When the passed service is not an object and no service name has been passed. + * @throws InvalidArgumentException When the passed service is not an object and no service name has been passed. * * @deprecated The service container will get removed, use the symfony service container instead. */ @@ -360,8 +377,8 @@ public function setService($service, $serviceName = null) ); // @codingStandardsIgnoreEnd if ($serviceName === null) { - if (!\is_object($service) || $service instanceof \Closure) { - throw new \InvalidArgumentException( + if (!\is_object($service) || $service instanceof Closure) { + throw new InvalidArgumentException( 'Service name must be given to ' . __CLASS__ . '::setService when not passing a class instance.' ); } @@ -392,29 +409,34 @@ public function getService($serviceName) // @codingStandardsIgnoreEnd // Hacked in here as initialization is dead now. - if (!isset($this->services[(string) $serviceName]) && 'metamodels-view-combinations' === $serviceName) { - $determinator = \System::getContainer()->get('cca.dc-general.scope-matcher'); + if (!isset($this->services[$serviceName]) && 'metamodels-view-combinations' === $serviceName) { + $determinator = System::getContainer()->get('cca.dc-general.scope-matcher'); + assert($determinator instanceof RequestScopeDeterminator); + $connection = System::getContainer()->get('database_connection'); + assert($connection instanceof Connection); switch (true) { case $determinator->currentScopeIsFrontend(): + /** @psalm-suppress DeprecatedClass */ $this->services['metamodels-view-combinations'] = - new \MetaModels\FrontendIntegration\ViewCombinations( + new FrontendIntegration\ViewCombinations( $this, FrontendUser::getInstance(), - \System::getContainer()->get('database_connection') + $connection ); break; case $determinator->currentScopeIsBackend(): + /** @psalm-suppress DeprecatedClass */ $this->services['metamodels-view-combinations'] = - new \MetaModels\BackendIntegration\ViewCombinations( + new ViewCombinations( $this, BackendUser::getInstance(), - \System::getContainer()->get('database_connection') + $connection ); break; default: } } - return ($this->services[(string) $serviceName] ?? null); + return ($this->services[$serviceName] ?? null); } } diff --git a/src/Render/Setting/Collection.php b/src/Render/Setting/Collection.php index eddf15154..f55ee9fe0 100644 --- a/src/Render/Setting/Collection.php +++ b/src/Render/Setting/Collection.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Ingolf Steinhardt * @author Sven Baumann * @author Richard Henkenjohann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -53,42 +53,42 @@ class Collection implements ICollection * * @var EventDispatcherInterface */ - private $dispatcher; + private EventDispatcherInterface $dispatcher; /** * The filter setting factory. * * @var IFilterSettingFactory */ - private $filterFactory; + private IFilterSettingFactory $filterFactory; /** * The filter URL builder. * * @var FilterUrlBuilder */ - private $filterUrlBuilder; + private FilterUrlBuilder $filterUrlBuilder; /** * The base information for this render settings object. * * @var array */ - protected $arrBase = array(); + protected $arrBase = []; /** * The sub settings for all attributes. * * @var array */ - protected $arrSettings = array(); + protected $arrSettings = []; /** * The jump to information buffered in this setting. * * @var array */ - protected $jumpToCache; + protected $jumpToCache = []; /** * Create a new instance. @@ -97,11 +97,11 @@ class Collection implements ICollection * @param array $arrInformation The array that holds all base information for the new instance. * @param EventDispatcherInterface $dispatcher The event dispatcher. * @param IFilterSettingFactory $filterFactory The filter setting factory. - * @param FilterUrlBuilder $filterUrlBuilder The filter URL builder. + * @param FilterUrlBuilder|null $filterUrlBuilder The filter URL builder. */ public function __construct( IMetaModel $metaModel, - $arrInformation, + array $arrInformation, EventDispatcherInterface $dispatcher, IFilterSettingFactory $filterFactory, FilterUrlBuilder $filterUrlBuilder = null @@ -109,26 +109,7 @@ public function __construct( $this->metaModel = $metaModel; $this->dispatcher = $dispatcher; $this->filterFactory = $filterFactory; - if (null === $this->dispatcher) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Not passing the event dispatcher as 3rd argument to "' . __METHOD__ . '" is deprecated ' . - 'and will cause an error in MetaModels 3.0', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd - $this->dispatcher = System::getContainer()->get('event_dispatcher'); - } - if (null === $this->filterFactory) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Not passing the filter setting factory as 4th argument to "' . __METHOD__ . '" is deprecated ' . - 'and will cause an error in MetaModels 3.0', - E_USER_DEPRECATED - ); - // @codingStandardsIgnoreEnd - $this->filterFactory = System::getContainer()->get('metamodels.filter_setting_factory'); - } + if (null === $filterUrlBuilder) { // @codingStandardsIgnoreStart @trigger_error( @@ -138,6 +119,7 @@ public function __construct( ); // @codingStandardsIgnoreEnd $filterUrlBuilder = System::getContainer()->get('metamodels.filter_url'); + assert($filterUrlBuilder instanceof FilterUrlBuilder); } $this->filterUrlBuilder = $filterUrlBuilder; @@ -191,7 +173,7 @@ public function setSetting($strAttributeName, $objSetting) */ public function getSettingNames() { - return array_keys($this->arrSettings); + return \array_keys($this->arrSettings); } /** @@ -201,14 +183,15 @@ public function getSettingNames() * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) + * @psalm-suppress PossiblyNullArrayOffset */ private function getJumpToLabel() { $tableName = $this->metaModel->getTableName(); return ($GLOBALS['TL_LANG']['MSC'][$tableName][$this->get('id')]['details'] ?? - ($GLOBALS['TL_LANG']['MSC'][$tableName]['details'] ?? - $GLOBALS['TL_LANG']['MSC']['details'])); + ($GLOBALS['TL_LANG']['MSC'][$tableName]['details'] ?? + $GLOBALS['TL_LANG']['MSC']['details'])); } /** @@ -218,16 +201,16 @@ private function getJumpToLabel() * * @return array */ - private function getPageDetails($pageId): array + private function getPageDetails(string $pageId): array { if (empty($pageId)) { return []; } - $event = new GetPageDetailsEvent($pageId); + $event = new GetPageDetailsEvent((int) $pageId); $this->dispatcher->dispatch($event, ContaoEvents::CONTROLLER_GET_PAGE_DETAILS); - return ($event->getPageDetails() ?? []); + return $event->getPageDetails(); } /** @@ -241,11 +224,14 @@ private function determineJumpToInformation(): array $translated = false; $desiredLanguage = null; $fallbackLanguage = null; + + /** @psalm-suppress DeprecatedMethod */ if ($this->metaModel instanceof ITranslatedMetaModel) { $translated = true; $desiredLanguage = $this->metaModel->getLanguage(); $fallbackLanguage = $this->metaModel->getMainLanguage(); - } elseif ($this->metaModel->isTranslated(false)) { + /** @psalm-suppress DeprecatedMethod */ + } elseif ($this->metaModel->isTranslated()) { // @coverageIgnoreStart // @codingStandardsIgnoreStart @\trigger_error( @@ -255,12 +241,14 @@ private function determineJumpToInformation(): array ); // @codingStandardsIgnoreEnd $translated = true; - $desiredLanguage = $this->metaModel->getActiveLanguage(); + /** @psalm-suppress DeprecatedMethod */ + $desiredLanguage = $this->metaModel->getActiveLanguage(); + /** @psalm-suppress DeprecatedMethod */ $fallbackLanguage = $this->metaModel->getFallbackLanguage(); // @coverageIgnoreEnd } - $cacheKey = $desiredLanguage . '.' . $fallbackLanguage; + $cacheKey = ($desiredLanguage ?? '') . '.' . ($fallbackLanguage ?? ''); if (!isset($this->jumpToCache[$cacheKey])) { $this->jumpToCache[$cacheKey] = $this->lookupJumpTo($translated, $desiredLanguage, $fallbackLanguage); } @@ -286,7 +274,7 @@ private function lookupJumpTo(bool $translated, string $desired = null, string $ // If either desired language or fallback, keep the result. if (!$translated || ($langCode === $desired) || ($langCode === $fallback)) { $jumpToPageId = $jumpTo['value'] ?? ''; - $filterSettingId = $jumpTo['filter'] ?? ''; + $filterSettingId = (string) ($jumpTo['filter'] ?? ''); // If the desired language, break. // Otherwise, try to get the desired one until all have been evaluated. if (!$translated || ($desired === $jumpTo['langcode'])) { @@ -318,7 +306,7 @@ public function buildJumpToUrlFor(IItem $item) { $information = $this->determineJumpToInformation(); if (empty($information['pageDetails'])) { - return array(); + return []; } $result = $information; @@ -337,7 +325,7 @@ public function buildJumpToUrlFor(IItem $item) foreach ($parameterList as $strKey => $strValue) { // Sadly the filter values are currently encoded due to legacy reasons. // For MetaModels 3, they should be passed around decoded everywhere. - $filterUrl->setSlug($strKey, rawurldecode($strValue))->setGet($strKey, ''); + $filterUrl->setSlug($strKey, \rawurldecode($strValue))->setGet($strKey, ''); } } diff --git a/src/Render/Setting/ICollection.php b/src/Render/Setting/ICollection.php index 81be3d9e5..94dfe37cb 100644 --- a/src/Render/Setting/ICollection.php +++ b/src/Render/Setting/ICollection.php @@ -71,7 +71,7 @@ public function setSetting($strAttributeName, $objSetting); /** * Retrieve the names of all columns getting rendered via this setting. * - * @return string[] + * @return list */ public function getSettingNames(); diff --git a/src/Render/Setting/IRenderSettingFactory.php b/src/Render/Setting/IRenderSettingFactory.php index f2f274cd5..b5a221698 100644 --- a/src/Render/Setting/IRenderSettingFactory.php +++ b/src/Render/Setting/IRenderSettingFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2019 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -35,7 +35,6 @@ interface IRenderSettingFactory extends IServiceContainerAware * Create a ICollection instance from the id. * * @param IMetaModel $metaModel The MetaModel for which to retrieve the render setting. - * * @param string $settingId The id of the ICollection. * * @return ICollection The instance or null if not found. diff --git a/src/Render/Setting/ISimple.php b/src/Render/Setting/ISimple.php index 0c1b4b218..9ceb568e2 100644 --- a/src/Render/Setting/ISimple.php +++ b/src/Render/Setting/ISimple.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -54,7 +55,6 @@ public function get($strName); * Set a base property in the settings object. * * @param string $strName The name of the setting to set. - * * @param mixed $varSetting The value to use. * * @return ISimple The setting itself. diff --git a/src/Render/Setting/RenderSettingFactory.php b/src/Render/Setting/RenderSettingFactory.php index dfbab6ed5..9a9a6ab2a 100644 --- a/src/Render/Setting/RenderSettingFactory.php +++ b/src/Render/Setting/RenderSettingFactory.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author David Molineus * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,6 +24,7 @@ use Contao\StringUtil; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use MetaModels\Filter\FilterUrlBuilder; use MetaModels\Filter\Setting\IFilterSettingFactory; use MetaModels\IMetaModel; @@ -34,52 +35,57 @@ /** * This is the filter settings factory interface. + * + * @psalm-suppress DeprecatedInterface + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class RenderSettingFactory implements IRenderSettingFactory { /** - * The event dispatcher. + * The service container. * - * @var IMetaModelsServiceContainer + * @var IMetaModelsServiceContainer|null * * @deprecated The service container will get removed. + * + * @psalm-suppress DeprecatedInterface */ - private $serviceContainer; + private ?IMetaModelsServiceContainer $serviceContainer = null; /** * The database connection. * * @var Connection */ - private $database; + private Connection $database; /** * The event dispatcher. * * @var EventDispatcherInterface */ - private $eventDispatcher; + private EventDispatcherInterface $eventDispatcher; /** * The filter setting factory. * * @var IFilterSettingFactory */ - private $filterFactory; + private IFilterSettingFactory $filterFactory; /** * The already created render settings. * - * @var ICollection[] + * @var array> */ - private $renderSettings; + private array $renderSettings = []; /** * The filter URL builder. * * @var FilterUrlBuilder */ - private $filterUrlBuilder; + private FilterUrlBuilder $filterUrlBuilder; /** * Create a new instance. @@ -110,6 +116,8 @@ public function __construct( * @return RenderSettingFactory * * @deprecated The service container will get removed, use the symfony service container instead. + * + * @psalm-suppress DeprecatedInterface */ public function setServiceContainer(IMetaModelsServiceContainer $serviceContainer, $deprecationNotice = true) { @@ -121,6 +129,7 @@ public function setServiceContainer(IMetaModelsServiceContainer $serviceContaine ); // @codingStandardsIgnoreEnd } + /** @psalm-suppress DeprecatedProperty */ $this->serviceContainer = $serviceContainer; if ($this->eventDispatcher->hasListeners(MetaModelsEvents::RENDER_SETTING_FACTORY_CREATE)) { @@ -133,6 +142,10 @@ public function setServiceContainer(IMetaModelsServiceContainer $serviceContaine ); // @codingStandardsIgnoreEnd + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress DeprecatedProperty + */ $this->serviceContainer->getEventDispatcher()->dispatch( new CreateRenderSettingFactoryEvent($this), MetaModelsEvents::RENDER_SETTING_FACTORY_CREATE @@ -148,6 +161,8 @@ public function setServiceContainer(IMetaModelsServiceContainer $serviceContaine * @return IMetaModelsServiceContainer * * @deprecated The service container will get removed, use the symfony service container instead. + * + * @psalm-suppress DeprecatedInterface */ public function getServiceContainer() { @@ -157,6 +172,13 @@ public function getServiceContainer() E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd + + /** @psalm-suppress DeprecatedProperty */ + if (null === $this->serviceContainer) { + throw new \RuntimeException('Deprecated service container has not been set.'); + } + + /** @psalm-suppress DeprecatedProperty */ return $this->serviceContainer; } @@ -167,7 +189,7 @@ public function getServiceContainer() * @param ICollection $renderSetting The render setting. * * @return void - * @throws \Doctrine\DBAL\Exception + * @throws Exception */ public function collectAttributeSettings(IMetaModel $metaModel, $renderSetting) { @@ -206,12 +228,12 @@ public function collectAttributeSettings(IMetaModel $metaModel, $renderSetting) * Create a ICollection instance from the id. * * @param IMetaModel $metaModel The MetaModel for which to retrieve the render setting. - * @param string $settingId The id of the ICollection. + * @param string|int $settingId The id of the ICollection. * - * @return ICollection The instance or null if not found. - * @throws \Doctrine\DBAL\Exception + * @return ICollection The instance. + * @throws Exception */ - protected function internalCreateRenderSetting(IMetaModel $metaModel, $settingId) + protected function internalCreateRenderSetting(IMetaModel $metaModel, string|int $settingId) { $row = $this ->database @@ -221,12 +243,12 @@ protected function internalCreateRenderSetting(IMetaModel $metaModel, $settingId ->where('t.pid=:pid') ->andWhere('t.id=:id') ->setParameter('pid', $metaModel->get('id')) - ->setParameter('id', $settingId ?: 0) + ->setParameter('id', (int) $settingId ?: 0) ->setMaxResults(1) ->executeQuery() ->fetchAssociative(); - if (!$row) { + if (false === $row) { $row = []; } @@ -238,7 +260,7 @@ protected function internalCreateRenderSetting(IMetaModel $metaModel, $settingId $this->filterUrlBuilder ); - if ($renderSetting->get('id')) { + if (null !== $renderSetting->get('id')) { $this->collectAttributeSettings($metaModel, $renderSetting); } @@ -252,7 +274,7 @@ public function createCollection(IMetaModel $metaModel, $settingId = '') { $tableName = $metaModel->getTableName(); if (!isset($this->renderSettings[$tableName])) { - $this->renderSettings[$tableName] = array(); + $this->renderSettings[$tableName] = []; } if (!isset($this->renderSettings[$tableName][$settingId])) { diff --git a/src/Render/Setting/Simple.php b/src/Render/Setting/Simple.php index 774f909fc..a6c8379f5 100644 --- a/src/Render/Setting/Simple.php +++ b/src/Render/Setting/Simple.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,8 @@ * @package MetaModels/core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,21 +33,21 @@ class Simple implements ISimple * * @var array */ - protected $arrBase = array(); + protected $arrBase = []; /** * The parenting instance. * - * @var ICollection + * @var ICollection|null */ - protected $parent; + protected $parent = null; /** * Create a new instance. * * @param array $arrInformation The array that holds all base information for the new instance. */ - public function __construct($arrInformation = array()) + public function __construct($arrInformation = []) { foreach ($arrInformation as $strKey => $varValue) { $this->set($strKey, StringUtil::deserialize($varValue)); @@ -74,6 +75,10 @@ public function setParent($parent) */ public function getParent() { + if (null === $this->parent) { + throw new \RuntimeException('Parent has not been set'); + } + return $this->parent; } @@ -93,7 +98,6 @@ public function get($strName) * Set a base property in the settings object. * * @param string $strName The name of the setting to set. - * * @param mixed $varSetting The value to use. * * @return ISimple The setting itself. @@ -111,6 +115,6 @@ public function set($strName, $varSetting) */ public function getKeys() { - return array_keys($this->arrBase); + return \array_keys($this->arrBase); } } diff --git a/src/Render/Template.php b/src/Render/Template.php index 95e1adf67..a9a0fdaf3 100644 --- a/src/Render/Template.php +++ b/src/Render/Template.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,29 +18,36 @@ * @author Sven Baumann * @author David Molineus * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\Render; +use Contao\Config; +use Contao\BackendTemplate; use Contao\CoreBundle\Framework\Adapter; +use Contao\FrontendTemplate; use Contao\System; use Contao\TemplateLoader; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use Exception; use MetaModels\Helper\ContaoController; +use RuntimeException; + use function array_key_exists; /** * Template class for MetaModels. - * In most aspects this behaves identically to the FrontendTemplate class from Contao but it differs in respect to + * In most aspects this behaves identically to the FrontendTemplate class from Contao, but it differs in respect to * format selection. * The format is being determined upon parsing and not upon instantiation. There is also an optional "fail on not * found" flag, which defaults to false and therefore one can parse the template and have zero output instead of * cluttering the frontend with exceptions. * * @SuppressWarnings(PHPMD.TooManyPublicMethods) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class Template { @@ -54,14 +61,14 @@ class Template /** * Parent template. * - * @var string + * @var string|null */ protected $strParent; /** * Default template. * - * @var string + * @var string|null */ protected $strDefault; @@ -70,33 +77,33 @@ class Template * * @var array */ - protected $arrData = array(); + protected $arrData = []; /** * Current output format. Only valid when within {@link MetaModelTemplate::parse()}. * * @var string */ - protected $strFormat = null; + protected $strFormat = ''; /** * Blocks. * * @var array */ - protected $arrBlocks = array(); + protected $arrBlocks = []; /** * Block names. * * @var array */ - protected $arrBlockNames = array(); + protected $arrBlockNames = []; /** * The template loader. * - * @var Adapter|Adapter|null Template loader adapter. + * @var Adapter|Adapter Template loader adapter. */ protected $templateLoader; @@ -117,21 +124,21 @@ class Template protected static $templatePathCache = []; /** - * Makes all protected methods from class Controller callable publically. + * Makes all protected methods from class Controller callable publicly. * * @param string $strMethod The method name. - * * @param array $arrArgs The parameters for the method. * * @return mixed */ public function __call($strMethod, $arrArgs) { - if (isset($this->$strMethod) && is_callable($this->$strMethod)) { - return call_user_func_array($this->$strMethod, $arrArgs); + if (isset($this->$strMethod) && \is_callable($this->$strMethod)) { + return \call_user_func_array($this->$strMethod, $arrArgs); } - return call_user_func_array(array(ContaoController::getInstance(), $strMethod), $arrArgs); + /** @psalm-suppress DeprecatedClass */ + return \call_user_func_array(array(ContaoController::getInstance(), $strMethod), $arrArgs); } /** @@ -139,7 +146,7 @@ public function __call($strMethod, $arrArgs) * * @param string $strTemplate The name of the template file. * @param Adapter|Adapter|null $templateLoader Template loader adapter. - * @param RequestScopeDeterminator $scopeDeterminator Request scope determinator. + * @param RequestScopeDeterminator|null $scopeDeterminator Request scope determinator. */ public function __construct( $strTemplate = '', @@ -156,7 +163,8 @@ public function __construct( E_USER_DEPRECATED ); // @codingStandardsIgnoreEnd - $templateLoader = System::getContainer()->get('contao.framework')->getAdapter(TemplateLoader::class); + $templateLoader = System::getContainer()->get('contao.framework')?->getAdapter(TemplateLoader::class); + assert($templateLoader instanceof Adapter); } $this->templateLoader = $templateLoader; @@ -169,6 +177,7 @@ public function __construct( ); // @codingStandardsIgnoreEnd $scopeDeterminator = System::getContainer()->get('cca.dc-general.scope-matcher'); + assert($scopeDeterminator instanceof RequestScopeDeterminator); } $this->scopeDeterminator = $scopeDeterminator; } @@ -177,7 +186,6 @@ public function __construct( * Set an object property. * * @param string $strKey The name of the property. - * * @param mixed $varValue The value to set. * * @return void @@ -199,12 +207,12 @@ public function __set($strKey, $varValue) */ public function __get($strKey) { - if (array_key_exists($strKey, $this->arrData)) { + if (\array_key_exists($strKey, $this->arrData)) { return $this->arrData[$strKey]; } if (!empty($GLOBALS['TL_CONFIG']['debugMode'])) { - trigger_error($this->getName() . ': Undefined template variable: ' . $strKey, E_USER_WARNING); + \trigger_error($this->getName() . ': Undefined template variable: ' . $strKey, E_USER_WARNING); } return null; } @@ -269,12 +277,14 @@ public function getName() * Print all template variables to the screen using print_r. * * @return void + * + * @SuppressWarnings(PHPMD.DevelopmentCodeFragment) */ public function showTemplateVars() { echo "
    \n";
             // @codingStandardsIgnoreStart - We really want to keep this debug function here.
    -        print_r($this->arrData);
    +        \print_r($this->arrData);
             // @codingStandardsIgnoreEnd
             echo "
    \n"; } @@ -283,12 +293,16 @@ public function showTemplateVars() * Print all template variables to the screen using var_dump. * * @return void + * + * @SuppressWarnings(PHPMD.DevelopmentCodeFragment) + * + * @psalm-suppress ForbiddenCode */ public function dumpTemplateVars() { echo "
    \n";
             // @codingStandardsIgnoreStart - We really want to keep this debug function here.
    -        var_dump($this->arrData);
    +        \var_dump($this->arrData);
             // @codingStandardsIgnoreEnd
             echo "
    \n"; } @@ -297,34 +311,33 @@ public function dumpTemplateVars() * Find a particular template file and return its path. * * @param string $strTemplate Name of the template file. - * * @param string $strFormat The format to search for. - * * @param bool $blnFailIfNotFound Boolean flag telling if an Exception shall be thrown when the file can not * be found. * - * @throws \RuntimeException When the flag has been set and the file has not been found. + * @throws RuntimeException When the flag has been set and the file has not been found. * - * @return string + * @return string|null * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ protected function getTemplate($strTemplate, $strFormat = 'html5', $blnFailIfNotFound = false) { - $strTemplate = basename($strTemplate); + $strTemplate = \basename($strTemplate); $strCustom = 'templates'; // Check for a theme folder if scope frontend and a normal page. if (isset($GLOBALS['objPage']) && $this->scopeDeterminator->currentScopeIsFrontend()) { - $tmpDir = str_replace('../', '', $GLOBALS['objPage']->templateGroup); - if (!empty($tmpDir)) { + $tmpDir = \str_replace('../', '', (string) $GLOBALS['objPage']->templateGroup); + if ('' !== $tmpDir) { $strCustom = $tmpDir; } } - if (isset(self::$templatePathCache[$strTemplate][$strFormat]) - && array_key_exists($strCustom, self::$templatePathCache[$strTemplate][$strFormat]) + if ( + isset(self::$templatePathCache[$strTemplate][$strFormat]) + && \array_key_exists($strCustom, self::$templatePathCache[$strTemplate][$strFormat]) ) { return self::$templatePathCache[$strTemplate][$strFormat][$strCustom] !== false ? self::$templatePathCache[$strTemplate][$strFormat][$strCustom] @@ -332,6 +345,7 @@ protected function getTemplate($strTemplate, $strFormat = 'html5', $blnFailIfNot } try { + /** @psalm-suppress InternalMethod - the ContaoFramework class is internal, not the method usage. */ self::$templatePathCache[$strTemplate][$strFormat][$strCustom] = $this->templateLoader->getPath( $strTemplate, $strFormat, @@ -339,11 +353,11 @@ protected function getTemplate($strTemplate, $strFormat = 'html5', $blnFailIfNot ); return self::$templatePathCache[$strTemplate][$strFormat][$strCustom]; - } catch (\Exception $exception) { + } catch (Exception $exception) { self::$templatePathCache[$strTemplate][$strFormat][$strCustom] = false; if ($blnFailIfNotFound) { - throw new \RuntimeException( - sprintf('Could not find template %s.%s', $strTemplate, $strFormat), + throw new RuntimeException( + \sprintf('Could not find template %s.%s', $strTemplate, $strFormat), 1, $exception ); @@ -363,14 +377,15 @@ protected function getTemplate($strTemplate, $strFormat = 'html5', $blnFailIfNot */ protected function callParseTemplateHook() { - if (isset($GLOBALS['METAMODEL_HOOKS']['parseTemplate']) - && is_array($GLOBALS['METAMODEL_HOOKS']['parseTemplate']) + if ( + isset($GLOBALS['METAMODEL_HOOKS']['parseTemplate']) + && \is_array($GLOBALS['METAMODEL_HOOKS']['parseTemplate']) ) { foreach ($GLOBALS['METAMODEL_HOOKS']['parseTemplate'] as $callback) { [$strClass, $strMethod] = $callback; - $objCallback = (in_array('getInstance', get_class_methods($strClass))) - ? call_user_func(array($strClass, 'getInstance')) + $objCallback = (\in_array('getInstance', \get_class_methods($strClass))) + ? \call_user_func(array($strClass, 'getInstance')) : new $strClass(); $objCallback->$strMethod($this); @@ -382,7 +397,6 @@ protected function callParseTemplateHook() * Parse the template file and return it as string. * * @param string $strOutputFormat The desired output format. - * * @param boolean $blnFailIfNotFound If set to true, the template object will throw an exception if the template * can not be found. Defaults to false. * @@ -390,7 +404,7 @@ protected function callParseTemplateHook() */ public function parse($strOutputFormat, $blnFailIfNotFound = false) { - if ($this->strTemplate == '') { + if ($this->strTemplate === '') { return ''; } @@ -409,11 +423,11 @@ public function parse($strOutputFormat, $blnFailIfNotFound = false) while ($this->strParent !== null) { $strCurrent = $this->strParent; $strParent = $this->strDefault - ?: $this->getTemplate($this->strParent, $this->strFormat, $blnFailIfNotFound); + ?? $this->getTemplate($this->strParent, $this->strFormat, $blnFailIfNotFound); // Check if we have the template. - if (empty($strParent)) { - return sprintf( + if (null === $strParent) { + return \sprintf( 'Template %s.%s not found (it is maybe within a unreachable theme folder?).', $this->strParent, $this->strFormat @@ -424,25 +438,30 @@ public function parse($strOutputFormat, $blnFailIfNotFound = false) $this->strParent = null; $this->strDefault = null; - ob_start(); + \ob_start(); + assert(\is_file($strParent)); + /** @var string|null $this->strParent */ include($strParent); - // Capture the output of the root template + // Capture the output of the root template. if ($this->strParent === null) { - $strBuffer = ob_get_contents(); - } elseif ($this->strParent == $strCurrent) { + $strBuffer = \ob_get_contents(); + } elseif ($this->strParent === $strCurrent) { $this->strDefault = $this->getTemplate($this->strParent, $this->strFormat, $blnFailIfNotFound); } - ob_end_clean(); + \ob_end_clean(); } // Reset the internal arrays. $this->arrBlocks = []; // Add start and end markers in debug mode. - if (\Config::get('debugMode') && ('html5' === $this->strFormat)) { - $strRelPath = str_replace(TL_ROOT . '/', '', $this->getTemplate($this->strTemplate, $this->strFormat)); + if (Config::get('debugMode') && ('html5' === $this->strFormat)) { + $rootDir = System::getContainer()->getParameter('kernel.project_dir'); + assert(\is_string($rootDir)); + $strRelPath = + \str_replace($rootDir . '/', '', (string) $this->getTemplate($this->strTemplate, $this->strFormat)); $strBuffer = << $strBuffer @@ -451,7 +470,7 @@ public function parse($strOutputFormat, $blnFailIfNotFound = false) EOF; } - return $strBuffer; + return (string) $strBuffer; } /** @@ -470,9 +489,7 @@ protected function getFormat() * Static convenience method to perform the whole rendering within one line of code. * * @param string $strTemplate Name of the template file. - * * @param string $strOutputFormat The desired output format. - * * @param array $arrTplData The data to use in the template. * * @param bool $blnFailIfNotFound If set to true, the template object will throw an exception if the template @@ -517,50 +534,50 @@ public function parent() * * @return void * - * @throws \Exception If a child templates contains nested blocks. + * @throws Exception If a child templates contains nested blocks. */ public function block($strName) { $this->arrBlockNames[] = $strName; - // Root template + // Root template. if ($this->strParent === null) { - // Register the block name + // Register the block name. if (!isset($this->arrBlocks[$strName])) { $this->arrBlocks[$strName] = '[[TL_PARENT]]'; - } elseif (is_array($this->arrBlocks[$strName])) { + } elseif (\is_array($this->arrBlocks[$strName])) { // Combine the contents of the child blocks - $callback = function ($current, $parent) { - return str_replace('[[TL_PARENT]]', $parent, $current); + $callback = static function (string $current, string $parent): string { + return \str_replace('[[TL_PARENT]]', $parent, $current); }; - $this->arrBlocks[$strName] = array_reduce($this->arrBlocks[$strName], $callback, '[[TL_PARENT]]'); + $this->arrBlocks[$strName] = \array_reduce($this->arrBlocks[$strName], $callback, '[[TL_PARENT]]'); } - // Handle nested blocks - if ($this->arrBlocks[$strName] != '[[TL_PARENT]]') { - // Output everything before the first TL_PARENT tag - if (strpos($this->arrBlocks[$strName], '[[TL_PARENT]]') !== false) { - [$content] = explode('[[TL_PARENT]]', $this->arrBlocks[$strName], 2); + // Handle nested blocks. + if ($this->arrBlocks[$strName] !== '[[TL_PARENT]]') { + // Output everything before the first TL_PARENT tag. + if (\strpos($this->arrBlocks[$strName], '[[TL_PARENT]]') !== false) { + [$content] = \explode('[[TL_PARENT]]', $this->arrBlocks[$strName], 2); echo $content; } else { // Output the current block and start a new output buffer to remove the following blocks echo $this->arrBlocks[$strName]; - ob_start(); + \ob_start(); } } } else { // Child template - // Clean the output buffer - ob_end_clean(); + // Clean the output buffer. + \ob_end_clean(); - // Check for nested blocks - if (count($this->arrBlockNames) > 1) { - throw new \Exception('Nested blocks are not allowed in child templates'); + // Check for nested blocks. + if (\count($this->arrBlockNames) > 1) { + throw new Exception('Nested blocks are not allowed in child templates'); } - // Start a new output buffer - ob_start(); + // Start a new output buffer. + \ob_start(); } } @@ -569,62 +586,61 @@ public function block($strName) * * @return void * - * @throws \Exception If there is no open block. + * @throws Exception If there is no open block. */ public function endblock() { - // Check for open blocks + // Check for open blocks. if (empty($this->arrBlockNames)) { - throw new \Exception('You must start a block before you can end it'); + throw new Exception('You must start a block before you can end it'); } // Get the block name - $name = array_pop($this->arrBlockNames); + $name = \array_pop($this->arrBlockNames); - // Root template + // Root template. if ($this->strParent === null) { // Handle nested blocks - if ($this->arrBlocks[$name] != '[[TL_PARENT]]') { + if ($this->arrBlocks[$name] !== '[[TL_PARENT]]') { // Output everything after the first TL_PARENT tag - if (strpos($this->arrBlocks[$name], '[[TL_PARENT]]') !== false) { - [, $content] = explode('[[TL_PARENT]]', $this->arrBlocks[$name], 2); + if (\str_contains($this->arrBlocks[$name], '[[TL_PARENT]]')) { + [, $content] = \array_merge(\explode('[[TL_PARENT]]', $this->arrBlocks[$name], 2), ['']); echo $content; } else { // Remove the overwritten content - ob_end_clean(); + \ob_end_clean(); } } } else { // Child template - // Capture the block content - $this->arrBlocks[$name][] = ob_get_contents(); - ob_end_clean(); + // Capture the block content. + $this->arrBlocks[$name][] = \ob_get_clean(); // Start a new output buffer - ob_start(); + \ob_start(); } } /** * Insert a template * - * @param string $strName The template name. - * @param array $arrData An optional data array. + * @param string $strName The template name. + * @param array|null $arrData An optional data array. * * @return void */ public function insert($strName, array $arrData = null) { if ($this->scopeDeterminator->currentScopeIsBackend()) { - $objTemplate = new \BackendTemplate($strName); + $objTemplate = new BackendTemplate($strName); } else { - $objTemplate = new \FrontendTemplate($strName); + $objTemplate = new FrontendTemplate($strName); } if ($arrData !== null) { $objTemplate->setData($arrData); } - echo $objTemplate->parse($this->getFormat()); + echo $objTemplate->parse(); } } diff --git a/src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php b/src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php index 87428cbd1..b3035a5aa 100644 --- a/src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php +++ b/src/Schema/Doctrine/AbstractAttributeTypeSchemaGenerator.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema\Doctrine; @@ -39,12 +39,11 @@ public function generate(DoctrineSchemaInformation $schema, MetaModelCollectionI { $typeName = $this->getTypeName(); foreach ($collection as $metaModelInformation) { - if ([] !== $attributes = $metaModelInformation->getAttributesOfType($typeName)) { - $tableSchema = $this->getSchemaForMetaModel($schema, $metaModelInformation); - - foreach ($attributes as $attribute) { - $this->generateAttribute($tableSchema, $attribute); - } + $attributes = $metaModelInformation->getAttributesOfType($typeName); + $tableSchema = $this->getSchemaForMetaModel($schema, $metaModelInformation); + foreach ($attributes as $attribute) { + assert($attribute instanceof AttributeInformation, 'Sorry, we mistyped the generateAttribute method.'); + $this->generateAttribute($tableSchema, $attribute); } } } diff --git a/src/Schema/Doctrine/DoctrineSchemaGenerator.php b/src/Schema/Doctrine/DoctrineSchemaGenerator.php index df22020ae..7fb80c98b 100644 --- a/src/Schema/Doctrine/DoctrineSchemaGenerator.php +++ b/src/Schema/Doctrine/DoctrineSchemaGenerator.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema\Doctrine; diff --git a/src/Schema/Doctrine/DoctrineSchemaGeneratorHelperTrait.php b/src/Schema/Doctrine/DoctrineSchemaGeneratorHelperTrait.php index 6993c7284..924e495af 100644 --- a/src/Schema/Doctrine/DoctrineSchemaGeneratorHelperTrait.php +++ b/src/Schema/Doctrine/DoctrineSchemaGeneratorHelperTrait.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema\Doctrine; diff --git a/src/Schema/Doctrine/DoctrineSchemaGeneratorInterface.php b/src/Schema/Doctrine/DoctrineSchemaGeneratorInterface.php index 6615d6724..bf959afe7 100644 --- a/src/Schema/Doctrine/DoctrineSchemaGeneratorInterface.php +++ b/src/Schema/Doctrine/DoctrineSchemaGeneratorInterface.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema\Doctrine; diff --git a/src/Schema/Doctrine/DoctrineSchemaInformation.php b/src/Schema/Doctrine/DoctrineSchemaInformation.php index 3a1526b15..c788fab42 100644 --- a/src/Schema/Doctrine/DoctrineSchemaInformation.php +++ b/src/Schema/Doctrine/DoctrineSchemaInformation.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema\Doctrine; diff --git a/src/Schema/Doctrine/DoctrineSchemaManager.php b/src/Schema/Doctrine/DoctrineSchemaManager.php index 4c1528617..3573079d1 100644 --- a/src/Schema/Doctrine/DoctrineSchemaManager.php +++ b/src/Schema/Doctrine/DoctrineSchemaManager.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema\Doctrine; diff --git a/src/Schema/Doctrine/DoctrineSchemaManipulator.php b/src/Schema/Doctrine/DoctrineSchemaManipulator.php index 6d0b2224a..21c1bf2f5 100644 --- a/src/Schema/Doctrine/DoctrineSchemaManipulator.php +++ b/src/Schema/Doctrine/DoctrineSchemaManipulator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,17 +12,26 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema\Doctrine; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Schema\Comparator; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Schema\AbstractSchemaManager; +use Doctrine\DBAL\Schema\Column; +use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Schema\SchemaDiff; +use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; + +use function in_array; /** * This updates the database to be in sync with the passed schema. @@ -34,7 +43,7 @@ class DoctrineSchemaManipulator * * @var Connection */ - private $connection; + private Connection $connection; /** * Create a new instance. @@ -77,14 +86,17 @@ public function getScript(DoctrineSchemaInformation $schemaInformation): array * * @param DoctrineSchemaInformation $schemaInformation The schema information. * - * @return string[] - * @throws \Doctrine\DBAL\Exception + * @return list + * @throws Exception + * + * @psalm-suppress InternalProperty */ private function buildChangeSet(DoctrineSchemaInformation $schemaInformation): array { - $manager = $this->connection->createSchemaManager(); - $current = $manager->createSchema(); - $diff = Comparator::compareSchemas($current, $schemaInformation->getSchema()); + $platform = $this->connection->getDatabasePlatform(); + $manager = $this->connection->createSchemaManager(); + $current = $manager->introspectSchema(); + $diff = $this->diff($current, $schemaInformation->getSchema(), $manager); foreach ($diff->changedTables as $changedTable) { foreach ($changedTable->removedColumns as $removedColumn) { @@ -97,7 +109,59 @@ private function buildChangeSet(DoctrineSchemaInformation $schemaInformation): a } $changedTable->removedColumns = []; } + foreach ($diff->removedTables as $removedTable) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Ignoring drop of table "' . $removedTable->getName(), + E_USER_WARNING + ); + // @codingStandardsIgnoreEnd + } + $diff->removedTables = []; - return $diff->toSaveSql($this->connection->getDatabasePlatform()); + return $platform->getAlterSchemaSQL($diff); + } + + private function diff(Schema $current, Schema $desired, AbstractSchemaManager $manager): SchemaDiff + { + // We have to "inherit" collation and charset for certain types as doctrine will report them in the current + // columns and always mark them as changed when no charset/collation has been explicitly specified in the + // desired column - despite being already in the correct condition "on disk". + $checkTypes = [ + Types::ASCII_STRING, + Types::STRING, + Types::TEXT, + ]; + + $registry = Type::getTypeRegistry(); + foreach ($desired->getTables() as $table) { + if (!$current->hasTable($table->getName())) { + continue; + } + $existingTable = $current->getTable($table->getName()); + foreach ($table->getColumns() as $column) { + if (!$existingTable->hasColumn($column->getName())) { + continue; + } + $existingColumn = $existingTable->getColumn($column->getName()); + if (!in_array($registry->lookupName($column->getType()), $checkTypes, true)) { + continue; + } + $this->inheritPlatformOptionIfNotSet('collation', $column, $existingColumn); + $this->inheritPlatformOptionIfNotSet('charset', $column, $existingColumn); + } + } + + return $manager->createComparator()->compareSchemas($current, $desired); + } + + private function inheritPlatformOptionIfNotSet(string $optionName, Column $column, Column $existingColumn): void + { + if (!$column->hasPlatformOption($optionName)) { + if (!$existingColumn->hasPlatformOption($optionName)) { + return; + } + $column->setPlatformOption($optionName, $existingColumn->getPlatformOption($optionName)); + } } } diff --git a/src/Schema/Doctrine/SchemaProcessorInterface.php b/src/Schema/Doctrine/SchemaProcessorInterface.php index c695a95fd..a938539cf 100644 --- a/src/Schema/Doctrine/SchemaProcessorInterface.php +++ b/src/Schema/Doctrine/SchemaProcessorInterface.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema\Doctrine; diff --git a/src/Schema/Doctrine/SystemColumnSchemaGenerator.php b/src/Schema/Doctrine/SystemColumnSchemaGenerator.php index 9a1def6e9..02eae5fb7 100644 --- a/src/Schema/Doctrine/SystemColumnSchemaGenerator.php +++ b/src/Schema/Doctrine/SystemColumnSchemaGenerator.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema\Doctrine; @@ -75,8 +75,10 @@ private function generateMetaModelSchema( $tableSchema->setPrimaryKey(['id']); - if ($metaModelInformation->hasConfigurationValue('varsupport') - && '1' === $metaModelInformation->getConfigurationValue('varsupport')) { + if ( + $metaModelInformation->hasConfigurationValue('varsupport') + && '1' === $metaModelInformation->getConfigurationValue('varsupport') + ) { $this->setColumnData($tableSchema, 'varbase', Types::STRING, [ 'length' => 1, 'fixed' => true, diff --git a/src/Schema/LegacySchemaGenerator.php b/src/Schema/LegacySchemaGenerator.php index 70e573903..a7c60e6a2 100644 --- a/src/Schema/LegacySchemaGenerator.php +++ b/src/Schema/LegacySchemaGenerator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,17 +12,19 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema; use MetaModels\Attribute\IInternal; use MetaModels\IFactory; +use MetaModels\IMetaModel; use MetaModels\Information\MetaModelCollectionInterface; use function in_array; @@ -61,20 +63,26 @@ public function __construct(IFactory $factory, array $ignoredTypeNames) */ public function generate(SchemaInformation $information, MetaModelCollectionInterface $collection): void { + /** @psalm-suppress DeprecatedClass */ if (!$information->has(LegacySchemaInformation::class)) { + /** @psalm-suppress DeprecatedClass */ $information->add(new LegacySchemaInformation()); } - /** @var LegacySchemaInformation $legacy */ + /** + * @var LegacySchemaInformation $legacy + * @psalm-suppress DeprecatedClass + */ $legacy = $information->get(LegacySchemaInformation::class); foreach ($collection as $metaModelInformation) { $metaModel = $this->factory->getMetaModel($metaModelInformation->getName()); + assert($metaModel instanceof IMetaModel); foreach ($metaModel->getAttributes() as $attribute) { // Skip managed and internal attributes. if ( $attribute instanceof IInternal - || in_array($attribute->get('type'), $this->ignoredTypeNames, true) + || \in_array($attribute->get('type'), $this->ignoredTypeNames, true) ) { continue; } diff --git a/src/Schema/LegacySchemaInformation.php b/src/Schema/LegacySchemaInformation.php index 1198eb587..c1b8e40a0 100644 --- a/src/Schema/LegacySchemaInformation.php +++ b/src/Schema/LegacySchemaInformation.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema; diff --git a/src/Schema/LegacySchemaManager.php b/src/Schema/LegacySchemaManager.php index 508f9cb7b..d7e1fcbbf 100644 --- a/src/Schema/LegacySchemaManager.php +++ b/src/Schema/LegacySchemaManager.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,12 +12,13 @@ * * @package MetaModels/core * @author Christian Schiffler - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema; @@ -43,37 +44,46 @@ public function preprocess(SchemaInformation $information): void */ public function process(SchemaInformation $information): void { + /** @psalm-suppress DeprecatedClass */ if (!$information->has(LegacySchemaInformation::class)) { return; } - /** @var LegacySchemaInformation $legacySchema */ + /** + * @var LegacySchemaInformation $legacySchema + * @psalm-suppress DeprecatedClass + */ $legacySchema = $information->get(LegacySchemaInformation::class); foreach ($legacySchema->getAttributes() as $attribute) { try { + /** @psalm-suppress DeprecatedMethod */ $attribute->initializeAUX(); } catch (\Throwable $exception) { // Transcribe known exceptions. switch (true) { case $exception instanceof NonUniqueFieldNameException: - if (preg_match( - '/SQLSTATE\[42S21\]: Column already exists: 1060 Duplicate column name \'(?P.+)\'/', - $exception->getMessage(), - $matches - )) { + if ( + \preg_match( + '/SQLSTATE\[42S21\]: ' . + 'Column already exists: 1060 Duplicate column name \'(?P.+)\'/', + $exception->getMessage(), + $matches + ) + ) { // @codingStandardsIgnoreStart @trigger_error('Column already exists: "' . $matches['name'] . '"'); // @codingStandardsIgnoreEnd continue 2; } + break; default: } // @codingStandardsIgnoreStart @trigger_error( - sprintf( + \sprintf( 'Ignored exception "%1$s" for attribute "%2$s": %3$s', - get_class($exception), + \get_class($exception), $attribute->getColName(), $exception->getMessage() ), @@ -97,15 +107,20 @@ public function postprocess(SchemaInformation $information): void */ public function validate(SchemaInformation $information): array { + /** @psalm-suppress DeprecatedClass */ if (!$information->has(LegacySchemaInformation::class)) { return []; } - /** @var LegacySchemaInformation $legacySchema */ + + /** + * @var LegacySchemaInformation $legacySchema + * @psalm-suppress DeprecatedClass + */ $legacySchema = $information->get(LegacySchemaInformation::class); $tasks = []; foreach ($legacySchema->getAttributes() as $attribute) { - $tasks[] = sprintf( + $tasks[] = \sprintf( '(Re-)Initialize attribute "%1$s" (type: "%2$s") via legacy method.', $attribute->getColName(), $attribute->get('type') diff --git a/src/Schema/SchemaGenerator.php b/src/Schema/SchemaGenerator.php index e11174abf..1dcb56f02 100644 --- a/src/Schema/SchemaGenerator.php +++ b/src/Schema/SchemaGenerator.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema; diff --git a/src/Schema/SchemaGeneratorInterface.php b/src/Schema/SchemaGeneratorInterface.php index 444148371..232a608bb 100644 --- a/src/Schema/SchemaGeneratorInterface.php +++ b/src/Schema/SchemaGeneratorInterface.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema; diff --git a/src/Schema/SchemaInformation.php b/src/Schema/SchemaInformation.php index e0e73b7f6..4e1e60d44 100644 --- a/src/Schema/SchemaInformation.php +++ b/src/Schema/SchemaInformation.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema; @@ -31,7 +31,7 @@ class SchemaInformation /** * The list of registered schema information. * - * @var list + * @var array */ private array $information = []; diff --git a/src/Schema/SchemaInformationInterface.php b/src/Schema/SchemaInformationInterface.php index 3b44cf2f9..c4cd595d3 100644 --- a/src/Schema/SchemaInformationInterface.php +++ b/src/Schema/SchemaInformationInterface.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema; diff --git a/src/Schema/SchemaManager.php b/src/Schema/SchemaManager.php index 55bd85079..0ecd506e2 100644 --- a/src/Schema/SchemaManager.php +++ b/src/Schema/SchemaManager.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema; @@ -29,7 +29,7 @@ class SchemaManager implements SchemaManagerInterface /** * The list of registered schema managers. * - * @var list + * @var SchemaManagerInterface[] */ private array $managers; diff --git a/src/Schema/SchemaManagerInterface.php b/src/Schema/SchemaManagerInterface.php index f83d7dcb8..636f65f88 100644 --- a/src/Schema/SchemaManagerInterface.php +++ b/src/Schema/SchemaManagerInterface.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Schema; diff --git a/src/TranslatedMetaModel.php b/src/TranslatedMetaModel.php index bc9dc14c1..aa0f3d131 100644 --- a/src/TranslatedMetaModel.php +++ b/src/TranslatedMetaModel.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,7 @@ * @package MetaModels/core * @author Christian Schiffler * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -27,6 +27,8 @@ /** * This defines a translated MetaModel. + * + * @psalm-suppress PropertyNotSetInConstructor */ class TranslatedMetaModel extends MetaModel implements ITranslatedMetaModel { @@ -35,14 +37,14 @@ class TranslatedMetaModel extends MetaModel implements ITranslatedMetaModel * * @var string */ - private $activeLanguage; + private string $activeLanguage = ''; /** * The fallback language. * * @var string */ - private $mainLanguage; + private string $mainLanguage = ''; /** * The locale territory support. @@ -85,7 +87,7 @@ public function __construct($arrData, EventDispatcherInterface $dispatcher, Conn */ public function getLanguages(): array { - return array_keys((array) $this->arrData['languages']); + return \array_keys((array) $this->arrData['languages']); } /** @@ -140,7 +142,7 @@ protected function fetchTranslatedAttributeValues(ITranslated $attribute, $ids) try { $attributeData = $attribute->getTranslatedDataFor($ids, $this->getLanguage()); // Second round, fetch missing data from main language. - if ([] !== $missing = array_diff($ids, array_keys($attributeData))) { + if ([] !== $missing = \array_values(\array_diff($ids, \array_keys($attributeData)))) { $attributeData += $attribute->getTranslatedDataFor($missing, $this->getMainLanguage()); } diff --git a/src/ViewCombination/InputScreenInformationBuilder.php b/src/ViewCombination/InputScreenInformationBuilder.php index 33e694394..66be513d9 100644 --- a/src/ViewCombination/InputScreenInformationBuilder.php +++ b/src/ViewCombination/InputScreenInformationBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author David Molineus * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,7 +23,9 @@ namespace MetaModels\ViewCombination; use Contao\StringUtil; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; use MetaModels\IFactory; use MetaModels\IMetaModel; use MetaModels\ITranslatedMetaModel; @@ -38,14 +40,14 @@ class InputScreenInformationBuilder * * @var Connection */ - private $connection; + private Connection $connection; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Create a new instance. @@ -65,23 +67,24 @@ public function __construct(Connection $connection, IFactory $factory) * @param array $idList The ids of the input screens to obtain (table name => id). * * @return array + * @throws Exception */ public function fetchInputScreens($idList): array { - $idList = array_filter($idList); + $idList = \array_filter($idList); $builder = $this->connection->createQueryBuilder(); $screens = $builder ->select('d.*') ->from('tl_metamodel_dca', 'd') ->leftJoin('d', 'tl_metamodel', 'm', 'm.id=d.pid') ->where($builder->expr()->in('d.id', ':idList')) - ->setParameter('idList', $idList, Connection::PARAM_STR_ARRAY) + ->setParameter('idList', $idList, ArrayParameterType::STRING) ->orderBy('m.sorting') ->executeQuery() ->fetchAllAssociative(); $result = []; - $keys = array_flip($idList); + $keys = \array_flip($idList); foreach ($screens as $screen) { $metaModelName = $keys[$screen['id']]; $result[$metaModelName] = $this->prepareInputScreen($metaModelName, $screen); @@ -96,11 +99,19 @@ public function fetchInputScreens($idList): array * @param string $modelName The MetaModel name. * @param array $screen The screen meta data. * - * @return array + * @return array{ + * meta: array, + * properties: array, + * conditions: list}>, + * groupSort: array, + * label: array, + * description: array, + * legends: array, + * } * * @throws \InvalidArgumentException When the MetaModel can not be retrieved. */ - private function prepareInputScreen($modelName, $screen): array + private function prepareInputScreen(string $modelName, array $screen): array { if (null === $metaModel = $this->factory->getMetaModel($modelName)) { throw new \InvalidArgumentException('Could not retrieve MetaModel ' . $modelName); @@ -108,9 +119,14 @@ private function prepareInputScreen($modelName, $screen): array $caption = ['' => $metaModel->getName()]; $description = ['' => $metaModel->getName()]; $fallback = null; + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ if ($metaModel instanceof ITranslatedMetaModel) { $fallback = $metaModel->getMainLanguage(); } elseif ($metaModel->isTranslated(false)) { + /** @psalm-suppress DeprecatedMethod */ $fallback = $metaModel->getFallbackLanguage(); } foreach (StringUtil::deserialize($screen['backendcaption'], true) as $languageEntry) { @@ -152,28 +168,33 @@ private function buildConditionTree(array $conditions): array $bySetting = []; foreach ($conditions as $condition) { unset($converted); + $conditionId = $condition['id']; + $conditionPid = $condition['pid']; + $conditionSettingId = $condition['settingId']; // Check if already mapped, if so, we need to set the values. - if (array_key_exists($condition['id'], $conditionMap)) { - $converted = &$conditionMap[$condition['id']]; + if (\array_key_exists($conditionId, $conditionMap)) { + $converted = &$conditionMap[$conditionId]; foreach ($condition as $key => $value) { $converted[$key] = $value; } } else { - $converted = \array_slice($condition, 0); - $conditionMap[$condition['id']] = &$converted; + $converted = \array_slice($condition, 0); + $conditionMap[$conditionId] = &$converted; } // Is on root level - add to setting now. - if (empty($condition['pid'])) { - $bySetting[$condition['settingId']][] = &$converted; + if (empty($conditionPid)) { + /** @psalm-suppress UnsupportedReferenceUsage */ + $bySetting[$conditionSettingId][] = &$converted; continue; } // Is a child, check if parent already added. - if (!isset($conditionMap[$condition['pid']])) { - $temp = ['children' => []]; - $conditionMap[$condition['pid']] = &$temp; + if (!isset($conditionMap[$conditionPid])) { + $temp = ['children' => []]; + $conditionMap[$conditionPid] = &$temp; } // Add child to parent now. - $conditionMap[$condition['pid']]['children'][] = &$converted; + /** @psalm-suppress UnsupportedReferenceUsage */ + $conditionMap[$conditionPid]['children'][] = &$converted; } return $bySetting; @@ -186,32 +207,36 @@ private function buildConditionTree(array $conditions): array * @param IMetaModel $metaModel The MetaModel to fetch properties for. * * @return array + * @throws Exception */ - private function fetchPropertiesFor($inputScreenId, IMetaModel $metaModel): array + private function fetchPropertiesFor(string $inputScreenId, IMetaModel $metaModel): array { $builder = $this->connection->createQueryBuilder(); - return array_map(function ($column) use ($inputScreenId, $metaModel) { - if ('attribute' !== $column['dcatype']) { - return $column; - } - if (!($attribute = $metaModel->getAttributeById((int) $column['attr_id']))) { - // @codingStandardsIgnoreStart - @trigger_error( - 'Unknown attribute "' . $column['attr_id'] . '" in input screen "' . $inputScreenId . '"', - E_USER_WARNING - ); - // @codingStandardsIgnoreEnd - return $column; - } - $column = array_merge( - $column, - $attribute->getFieldDefinition($column), - ['col_name' => $attribute->getColName()] - ); + return \array_map( + static function ($column) use ($inputScreenId, $metaModel) { + if ('attribute' !== $column['dcatype']) { + return $column; + } + if (!($attribute = $metaModel->getAttributeById((int)$column['attr_id']))) { + // @codingStandardsIgnoreStart + @trigger_error( + 'Unknown attribute "' . $column['attr_id'] . '" in input screen "' . $inputScreenId . '"', + E_USER_WARNING + ); + + // @codingStandardsIgnoreEnd + return $column; + } + + $column = \array_merge( + $column, + $attribute->getFieldDefinition($column), + ['col_name' => $attribute->getColName()] + ); - return $column; - }, + return $column; + }, $builder ->select('t.*') ->from('tl_metamodel_dcasetting', 't') @@ -221,7 +246,8 @@ private function fetchPropertiesFor($inputScreenId, IMetaModel $metaModel): arra ->setParameter('published', 1) ->orderBy('t.sorting') ->executeQuery() - ->fetchAllAssociative()); + ->fetchAllAssociative() + ); } /** @@ -229,9 +255,9 @@ private function fetchPropertiesFor($inputScreenId, IMetaModel $metaModel): arra * * @param string $inputScreenId The input screen to obtain conditions for. * - * @return array + * @return list}> */ - private function fetchConditions($inputScreenId): array + private function fetchConditions(string $inputScreenId): array { $builder = $this->connection->createQueryBuilder(); @@ -257,39 +283,43 @@ private function fetchConditions($inputScreenId): array * @param IMetaModel $metaModel The MetaModel to fetch properties for. * * @return array + * + * @throws Exception */ - private function fetchGroupSort($inputScreenId, IMetaModel $metaModel): array + private function fetchGroupSort(string $inputScreenId, IMetaModel $metaModel): array { $builder = $this->connection->createQueryBuilder(); - return array_map(function ($information) use ($inputScreenId, $metaModel) { - $information['isdefault'] = (bool) $information['isdefault']; - $information['ismanualsort'] = (bool) $information['ismanualsort']; - $information['rendergrouplen'] = (int) $information['rendergrouplen']; - if ($information['ismanualsort']) { - $information['rendergrouptype'] = 'none'; - } + return \array_map( + static function ($information) use ($inputScreenId, $metaModel) { + $information['isdefault'] = (bool)$information['isdefault']; + $information['ismanualsort'] = (bool)$information['ismanualsort']; + $information['rendergrouplen'] = (int)$information['rendergrouplen']; + if ($information['ismanualsort']) { + $information['rendergrouptype'] = 'none'; + } - if (!empty($information['rendersortattr'])) { - if (!($attribute = $metaModel->getAttributeById((int) $information['rendersortattr']))) { - // @codingStandardsIgnoreStart - @trigger_error( - sprintf( - 'Unknown attribute "%1$s" in group sorting "%2$s.%3$s"', - $information['rendersortattr'], - $inputScreenId, - $information['id'] - ), - E_USER_WARNING - ); - // @codingStandardsIgnoreEnd - return $information; + if (!empty($information['rendersortattr'])) { + if (!($attribute = $metaModel->getAttributeById((int)$information['rendersortattr']))) { + // @codingStandardsIgnoreStart + @trigger_error( + \sprintf( + 'Unknown attribute "%1$s" in group sorting "%2$s.%3$s"', + $information['rendersortattr'], + $inputScreenId, + $information['id'] + ), + E_USER_WARNING + ); + + // @codingStandardsIgnoreEnd + return $information; + } + $information['col_name'] = $attribute->getColName(); } - $information['col_name'] = $attribute->getColName(); - } - return $information; - }, + return $information; + }, $builder ->select('t.*') ->from('tl_metamodel_dca_sortgroup', 't') @@ -297,7 +327,8 @@ private function fetchGroupSort($inputScreenId, IMetaModel $metaModel): array ->setParameter('screenId', $inputScreenId) ->orderBy('t.sorting') ->executeQuery() - ->fetchAllAssociative()); + ->fetchAllAssociative() + ); } /** @@ -305,7 +336,6 @@ private function fetchGroupSort($inputScreenId, IMetaModel $metaModel): array * * @param array $properties The property and legend information. * @param IMetaModel $metaModel The MetaModel to fetch properties for. - * * @param array $conditions The conditions for the entries. * * @return array @@ -313,6 +343,10 @@ private function fetchGroupSort($inputScreenId, IMetaModel $metaModel): array private function convertLegends(array $properties, IMetaModel $metaModel, array $conditions): array { $result = []; + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ $trans = (($metaModel instanceof ITranslatedMetaModel) || $metaModel->isTranslated(false)); $label = $this->buildLabel($trans, $metaModel); $legend = [ @@ -321,8 +355,8 @@ private function convertLegends(array $properties, IMetaModel $metaModel, array 'properties' => [] ]; - $condition = function ($property) use ($conditions) { - if (!isset($conditions[$property['id']])) { + $condition = function (array $property) use ($conditions): ?array { + if (!isset($conditions[($property['id'])])) { return null; } @@ -333,9 +367,14 @@ private function convertLegends(array $properties, IMetaModel $metaModel, array }; $fallbackLanguage = null; + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ if ($metaModel instanceof ITranslatedMetaModel) { $fallbackLanguage = $metaModel->getMainLanguage(); } elseif ($metaModel->isTranslated(false)) { + /** @psalm-suppress DeprecatedMethod */ $fallbackLanguage = $metaModel->getFallbackLanguage(); } foreach ($properties as $property) { @@ -372,9 +411,11 @@ private function buildLabel(bool $isTranslated, IMetaModel $metaModel): array { if ($isTranslated) { $label = []; - foreach (($metaModel instanceof ITranslatedMetaModel) + /** @psalm-suppress DeprecatedMethod */ + foreach ( + ($metaModel instanceof ITranslatedMetaModel) ? $metaModel->getLanguages() - : $metaModel->getAvailableLanguages() as $availableLanguage + : ($metaModel->getAvailableLanguages() ?? []) as $availableLanguage ) { $label[$availableLanguage] = $metaModel->getName(); } diff --git a/src/ViewCombination/ViewCombination.php b/src/ViewCombination/ViewCombination.php index 3153ec5c9..9d43cd3af 100644 --- a/src/ViewCombination/ViewCombination.php +++ b/src/ViewCombination/ViewCombination.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @author Christian Schiffler * @author Sven Baumann * @author Richard Henkenjohann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -36,28 +37,28 @@ class ViewCombination * * @var Cache */ - private $cache; + private Cache $cache; /** * The token storage. * * @var TokenStorageInterface */ - private $tokenStorage; + private TokenStorageInterface $tokenStorage; /** * The combination builder. * * @var ViewCombinationBuilder */ - private $builder; + private ViewCombinationBuilder $builder; /** * The input screen information builder. * * @var InputScreenInformationBuilder */ - private $inputScreens; + private InputScreenInformationBuilder $inputScreens; /** * Create a new instance. @@ -93,11 +94,11 @@ public function getCombinations() $mode = 'be'; // Try to get the group(s) // there might be a NULL in there as BE admins have no groups and - // user might have one but it is not mandatory. + // user might have one, but it is not mandatory. // I would prefer a default group for both, fe and be groups. $groups = $user->groups; // Special case in combinations, admins have the implicit group id -1. - if ($user->admin) { + if ((bool) $user->admin) { $groups[] = -1; } @@ -117,9 +118,9 @@ public function getCombinations() $groups = [-1]; } - $groups = array_filter($groups); + $groups = \array_filter($groups); - if ($this->cache->contains($cacheKey = 'combinations_' . $mode . '_' . implode(',', $groups))) { + if ($this->cache->contains($cacheKey = 'combinations_' . $mode . '_' . \implode(',', $groups))) { return $this->cache->fetch($cacheKey); } @@ -140,21 +141,18 @@ public function getCombinations() public function getCombination($tableName) { $combinations = $this->getCombinations(); - if (isset($combinations['byName'][$tableName])) { - return $combinations['byName'][$tableName]; - } - return null; + return $combinations['byName'][$tableName] ?? null; } /** - * Obtain stand alone input screens. + * Obtain stand-alone input screens. * * @return array */ public function getStandalone() { - $inputScreens = array_filter($this->getInputScreens(), function ($inputScreen) { + $inputScreens = \array_filter($this->getInputScreens(), static function ($inputScreen) { return $inputScreen['meta']['rendertype'] === 'standalone'; }); @@ -168,7 +166,7 @@ public function getStandalone() */ public function getParented() { - $inputScreens = array_filter($this->getInputScreens(), function ($inputScreen) { + $inputScreens = \array_filter($this->getInputScreens(), static function ($inputScreen) { return $inputScreen['meta']['rendertype'] === 'ctable'; }); @@ -184,7 +182,7 @@ public function getParented() */ public function getChildrenOf($parentTable) { - $inputScreens = array_filter($this->getInputScreens(), function ($inputScreen) use ($parentTable) { + $inputScreens = \array_filter($this->getInputScreens(), static function ($inputScreen) use ($parentTable) { return ($inputScreen['meta']['rendertype'] === 'ctable') && ($inputScreen['meta']['ptable'] === $parentTable); }); @@ -202,11 +200,8 @@ public function getChildrenOf($parentTable) public function getScreen($tableName) { $inputScreens = $this->getInputScreens(); - if (isset($inputScreens[$tableName])) { - return $inputScreens[$tableName]; - } - return null; + return $inputScreens[$tableName] ?? null; } /** @@ -221,11 +216,11 @@ private function getInputScreens() return []; } - $screenIds = array_map(function ($combination) { + $screenIds = \array_map(static function (array $combination): mixed { return $combination['dca_id']; }, $combinations['byName']); - if ($this->cache->contains($cacheKey = 'screens_' . implode(',', $screenIds))) { + if ($this->cache->contains($cacheKey = 'screens_' . \implode(',', $screenIds))) { return $this->cache->fetch($cacheKey); } diff --git a/src/ViewCombination/ViewCombinationBuilder.php b/src/ViewCombination/ViewCombinationBuilder.php index bdab6c657..e55c60852 100644 --- a/src/ViewCombination/ViewCombinationBuilder.php +++ b/src/ViewCombination/ViewCombinationBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -14,13 +14,14 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\ViewCombination; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; use MetaModels\IFactory; @@ -34,14 +35,14 @@ class ViewCombinationBuilder * * @var Connection */ - private $connection; + private Connection $connection; /** * The MetaModels factory. * * @var IFactory */ - private $factory; + private IFactory $factory; /** * Create a new instance. @@ -67,7 +68,7 @@ public function __construct(Connection $connection, IFactory $factory) */ public function getCombinationsForUser($userGroups, $userType) { - $userType = strtolower($userType); + $userType = \strtolower($userType); if ('fe' !== $userType && 'be' !== $userType) { throw new \InvalidArgumentException('Unknown user type: ' . $userType); } @@ -78,12 +79,12 @@ public function getCombinationsForUser($userGroups, $userType) /** * Retrieve the palette combinations from the database. * - * @param string $userGroups The user groups of the user to fetch information for. - * @param string $userType The user type. + * @param string[] $userGroups The user groups of the user to fetch information for. + * @param string $userType The user type. * * @return null|array */ - private function getCombinationsFromDatabase($userGroups, $userType) + private function getCombinationsFromDatabase(array $userGroups, string $userType): ?array { if (empty($userGroups)) { return null; @@ -94,10 +95,10 @@ private function getCombinationsFromDatabase($userGroups, $userType) ->createQueryBuilder(); $combinations = $builder - ->select('*') + ->select('t.*') ->from('tl_metamodel_dca_combine', 't') ->where($builder->expr()->in('t.' . $userType . '_group', ':groupList')) - ->setParameter('groupList', $userGroups, Connection::PARAM_STR_ARRAY) + ->setParameter('groupList', $userGroups, ArrayParameterType::STRING) ->orWhere('t.' . $userType . '_group=0') ->orderBy('t.pid') ->addOrderBy('t.sorting') diff --git a/src/Widgets/FileSelectorWidget.php b/src/Widgets/FileSelectorWidget.php index d16f75466..2db608e63 100644 --- a/src/Widgets/FileSelectorWidget.php +++ b/src/Widgets/FileSelectorWidget.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2023 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,8 @@ * @author David Maack * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +27,9 @@ /** * Provide methods to handle input field "file tree". + * + * @psalm-suppress PropertyNotSetInConstructor + * @psalm-suppress DeprecatedClass */ class FileSelectorWidget extends FileSelector { @@ -41,38 +45,42 @@ class FileSelectorWidget extends FileSelector */ public function __construct($arrAttributes = null) { + /** @psalm-suppress DeprecatedClass */ parent::__construct($arrAttributes); if (!$this->strField) { - $this->strField = $arrAttributes['name']; + $this->strField = $arrAttributes['name'] ?? ''; } // Strip the leading "ctrl_" from the field name if present. - if (substr($this->strField, 0, 5) === 'ctrl_') { - $chunks = explode('_', $this->strField); - array_shift($chunks); - $this->strField = implode('_', $chunks); + if (\str_starts_with($this->strField ?? '', 'ctrl_')) { + $chunks = \explode('_', $this->strField ?? ''); + \array_shift($chunks); + $this->strField = \implode('_', $chunks); } } /** * Generate a particular sub part of the file tree and return it as HTML string. * - * @param string $folder The folder name. - * - * @param string $strField The property name. - * - * @param int $level The level where the given folder shall be rendered within. - * - * @param bool $mount Flag determining if the passed folder shall be handled as root level - * (optional, default: no). + * @param string $strFolder The folder name. + * @param string $strField The property name. + * @param int $level The level where the given folder shall be rendered within. + * @param bool $mount Flag determining if the passed folder shall be handled as root level + * (optional, default: no). * * @return string * * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * + * @psalm-suppress ImplementedParamTypeMismatch */ - public function generateAjax($folder, $strField, $level, $mount = false) + public function generateAjax($strFolder, $strField, $level, $mount = false) { - return parent::generateAjax($folder, $this->strField, $level, $mount); + /** + * @psalm-suppress InvalidArgument + * @psalm-suppress DeprecatedClass + */ + return parent::generateAjax($strFolder, $this->strField, $level, $mount); } } diff --git a/src/Widgets/MultiTextWidget.php b/src/Widgets/MultiTextWidget.php index b61f2de9b..e54bfc3d8 100644 --- a/src/Widgets/MultiTextWidget.php +++ b/src/Widgets/MultiTextWidget.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2023 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2023 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +26,8 @@ /** * Form field with more than 1 input, based on form field by Leo Feyer. + * + * @psalm-suppress PropertyNotSetInConstructor */ class MultiTextWidget extends Widget { @@ -47,7 +49,6 @@ class MultiTextWidget extends Widget * Add specific attributes. * * @param string $strKey Name of the key to set. - * * @param mixed $varValue The value to use. * * @return void @@ -89,8 +90,8 @@ public function __set($strKey, $varValue) */ protected function validator($varInput) { - if (is_array($varInput)) { - $value = array(); + if (\is_array($varInput)) { + $value = []; foreach ($varInput as $key => $input) { $value[$key] = parent::validator($input); } @@ -110,15 +111,16 @@ protected function validator($varInput) public function generate() { $return = ''; + /** @psalm-suppress UndefinedThisPropertyFetch */ for ($i = 0; $i < $this->size; $i++) { - $return .= sprintf( + $return .= \sprintf( 'strName, $this->strId, $i, '', - (strlen($this->strClass) ? ' ' . $this->strClass : ''), + (\strlen($this->strClass) ? ' ' . $this->strClass : ''), StringUtil::specialchars($this->varValue[$i] ?? ''), $this->getAttributes(), $this->strTagEnding diff --git a/src/Widgets/SubDcaWidget.php b/src/Widgets/SubDcaWidget.php index 189116a15..8e1303991 100644 --- a/src/Widgets/SubDcaWidget.php +++ b/src/Widgets/SubDcaWidget.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,13 +17,14 @@ * @author Sven Baumann * @author Cliff Parnitzky * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\Widgets; +use Contao\DataContainer; use Contao\Date; use Contao\StringUtil; use Contao\System; @@ -33,9 +34,14 @@ use ContaoCommunityAlliance\Contao\Bindings\Events\Widget\GetAttributesFromDcaEvent; use Exception; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Request; /** * Provide methods to handle multiple widgets in one. + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * + * @psalm-suppress PropertyNotSetInConstructor */ class SubDcaWidget extends Widget { @@ -58,28 +64,28 @@ class SubDcaWidget extends Widget * * @var array */ - protected $arrOptions = array(); + protected $arrOptions = []; /** * SubFields. * * @var array */ - protected $arrSubFields = array(); + protected $arrSubFields = []; /** * Flag fields to be applied to each subfield. * * @var array */ - protected $arrFlagFields = array(); + protected $arrFlagFields = []; /** * The prepared widgets. * * @var array */ - protected $arrWidgets = array(); + protected $arrWidgets = []; /** * Initialize the object. @@ -89,14 +95,17 @@ class SubDcaWidget extends Widget public function __construct($attributes = false) { parent::__construct(); - $this->addAttributes($attributes); - // Input field callback. - if (isset($attributes['getsubfields_callback']) && is_array($attributes['getsubfields_callback'])) { - $arrCallback = $this->$attributes['getsubfields_callback']; - if (!is_object($arrCallback[0])) { - $this->import($arrCallback[0]); + if (\is_array($attributes)) { + $this->addAttributes($attributes); + + // Input field callback. + if (isset($attributes['getsubfields_callback']) && is_array($attributes['getsubfields_callback'])) { + $arrCallback = $this->$attributes['getsubfields_callback']; + if (!is_object($arrCallback[0])) { + $this->import($arrCallback[0]); + } + $this->arrSubFields = $this->{$arrCallback[0]}->{$arrCallback[1]}($this, $attributes); } - $this->arrSubFields = $this->{$arrCallback[0]}->{$arrCallback[1]}($this, $attributes); } } @@ -107,7 +116,6 @@ public function __construct($attributes = false) * widget does understand: 'options', 'subfields' and 'flagfields'. * * @param string $strKey The key of the attribute to set. - * * @param mixed $varValue The value to use. * * @return void @@ -145,14 +153,16 @@ public function __set($strKey, $varValue) */ public function getEventDispatcher() { - return System::getContainer()->get('event_dispatcher'); + $dispatcher = System::getContainer()->get('event_dispatcher'); + assert($dispatcher instanceof EventDispatcherInterface); + + return $dispatcher; } /** - * Generate an help wizard if needed. + * Generate a help wizard if needed. * * @param string $key The widget name. - * * @param array $field The field DCA - might get changed within this routine. * * @return string @@ -174,14 +184,15 @@ protected function getHelpWizard($key, $field) ); $this->getEventDispatcher()->dispatch($event, ContaoEvents::IMAGE_GET_HTML); - return sprintf( - ' %s', + /** @psalm-suppress UndefinedConstant */ + return \sprintf( + ' %s', TL_PATH . 'contao/', $this->strTable, $this->strName, $key, StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['helpWizard']), - $event->getHtml() + $event->getHtml() ?? '' ); } @@ -189,9 +200,7 @@ protected function getHelpWizard($key, $field) * Make fields mandatory if necessary. * * @param array $field The field DCA. - * * @param string $row The setting name. - * * @param string $key The widget name. * * @return array @@ -204,14 +213,12 @@ protected function makeMandatory($field, $row, $key) return $field; } - if (is_array($this->varValue[$row][$key])) { + if (\is_array($this->varValue[$row][$key])) { if (empty($this->varValue[$row][$key])) { $field['eval']['required'] = true; } - } else { - if (!strlen($this->varValue[$row][$key])) { - $field['eval']['required'] = true; - } + } elseif ($this->varValue[$row][$key] === '') { + $field['eval']['required'] = true; } return $field; @@ -229,20 +236,25 @@ protected function makeMandatory($field, $row, $key) */ protected function getWidgetClass($field) { - $className = $GLOBALS[(TL_MODE == 'BE' ? 'BE_FFL' : 'TL_FFL')][$field['inputType']]; + $isBackend = (bool) System::getContainer() + ->get('contao.routing.scope_matcher') + ?->isBackendRequest( + System::getContainer()->get('request_stack')?->getCurrentRequest() ?? Request::create('') + ); + /** @var class-string|null $strClass */ + $className = $GLOBALS[($isBackend ? 'BE_FFL' : 'TL_FFL')][$field['inputType']]; - if (($className !== '') && class_exists($className)) { + if (($className !== '') && \class_exists($className)) { return $className; } - return null; + return ''; } /** * Handle the onload_callback. * * @param array $field The field information. - * * @param mixed $value The value. * * @return mixed @@ -250,7 +262,7 @@ protected function getWidgetClass($field) protected function handleLoadCallback($field, $value) { // Load callback. - if (isset($field['load_callback']) && is_array($field['load_callback'])) { + if (isset($field['load_callback']) && \is_array($field['load_callback'])) { foreach ($field['load_callback'] as $callback) { $this->import($callback[0]); $value = $this->{$callback[0]}->{$callback[1]}($value, $this); @@ -266,11 +278,8 @@ protected function handleLoadCallback($field, $value) * Based on DataContainer::row() from Contao 2.10.1. * * @param array $arrField The field DCA - might get changed within this routine. - * * @param string $strRow The setting name. - * * @param string $strKey The widget name. - * * @param mixed $varValue The widget value. * * @return Widget|null The widget on success, null otherwise. @@ -280,14 +289,15 @@ protected function initializeWidget(&$arrField, $strRow, $strKey, $varValue) $xlabel = $this->getHelpWizard($strKey, $arrField); // Input field callback. - if (isset($arrField['input_field_callback']) && is_array($arrField['input_field_callback'])) { - if (!is_object($this->$arrField['input_field_callback'][0])) { + if (isset($arrField['input_field_callback']) && \is_array($arrField['input_field_callback'])) { + if (!\is_object($this->$arrField['input_field_callback'][0])) { $this->import($arrField['input_field_callback'][0]); } return $this->{$arrField['input_field_callback'][0]}->$arrField['input_field_callback'][1]($this, $xlabel); } + /** @var class-string|null $strClass */ $strClass = $this->getWidgetClass($arrField); if (empty($strClass)) { @@ -308,15 +318,19 @@ protected function initializeWidget(&$arrField, $strRow, $strKey, $varValue) $arrField['value'], '', $this->strTable, - $this->objDca + ((\is_a($this->objDca, DataContainer::class)) ? $this->objDca : null) ); $this->getEventDispatcher()->dispatch($event, ContaoEvents::WIDGET_GET_ATTRIBUTES_FROM_DCA); + /** @psalm-suppress UnsafeInstantiation */ $objWidget = new $strClass($event->getResult()); + if (!($objWidget instanceof Widget)) { + return null; + } - $objWidget->strId = $arrField['id']; - $objWidget->storeValues = true; + $objWidget->strId = (int) $arrField['id']; + $objWidget->storeValues = 1; // The type is int in the widget. $objWidget->xlabel = $xlabel; return $objWidget; @@ -333,15 +347,15 @@ protected function prepareWidgets() return; } - $arrWidgets = array(); + $arrWidgets = []; foreach ($this->arrSubFields as $strFieldName => &$arrSubField) { - $varValue = $this->value[$strFieldName]; - $arrRow = array(); + $varValue = $this->value[$strFieldName] ?? []; + $arrRow = []; $objWidget = $this->initializeWidget( $arrSubField, $strFieldName, 'value', - $varValue['value'] + $varValue['value'] ?? null ); if (!$objWidget) { @@ -353,7 +367,7 @@ protected function prepareWidgets() $arrFlagField, $strFieldName, $strFlag, - $varValue[$strFlag] + $varValue[$strFlag] ?? null ); if ($objWidget) { @@ -369,9 +383,7 @@ protected function prepareWidgets() * Handle the onsave_callback for a widget. * * @param array $field The field DCA. - * * @param Widget $widget The widget to validate. - * * @param mixed $value The value. * * @return mixed @@ -380,7 +392,7 @@ protected function handleSaveCallback($field, $widget, $value) { $newValue = $value; - if (isset($field['save_callback']) && is_array($field['save_callback'])) { + if (isset($field['save_callback']) && \is_array($field['save_callback'])) { foreach ($field['save_callback'] as $callback) { $this->import($callback[0]); @@ -404,11 +416,8 @@ protected function handleSaveCallback($field, $widget, $value) * Based on DataContainer::row() from Contao 2.10.1 * * @param array $arrField The field DCA. - * * @param string $strRow The setting name. - * * @param string $strKey The widget name. - * * @param mixed $varInput The overall input value. * * @return bool @@ -420,7 +429,7 @@ protected function validateWidget(&$arrField, $strRow, $strKey, &$varInput) { $varValue = $varInput[$strRow][$strKey] ?? ''; $objWidget = $this->initializeWidget($arrField, $strRow, $strKey, $varValue); - if (!is_object($objWidget)) { + if (!\is_object($objWidget)) { return false; } @@ -497,10 +506,11 @@ protected function validator($varInput) */ protected function getHelpForWidget($widget) { - if ($GLOBALS['TL_CONFIG']['showHelp'] && $widget->description) { - return sprintf( + if (!empty($GLOBALS['TL_CONFIG']['showHelp']) && !empty($widget->description)) { + /** @psalm-suppress UndefinedMagicPropertyFetch */ + return \sprintf( '

    %s

    ', - $widget->tl_class, + (string) $widget->tl_class, $widget->description ); } @@ -511,21 +521,23 @@ protected function getHelpForWidget($widget) /** * Build the options for a widget. * - * @return array. + * @return array */ protected function buildOptions() { - $options = array(); + $options = []; foreach ($this->arrWidgets as $widgetRow) { - $columns = array(); - foreach ($widgetRow as $widget) { + $columns = []; + foreach ((array) $widgetRow as $widget) { /** @var Widget $widget */ - $valign = ($widget->valign != '' ? ' valign="' . $widget->valign . '"' : ''); - $class = ($widget->tl_class != '' ? ' class="' . $widget->tl_class . '"' : ''); + /** @psalm-suppress UndefinedMagicPropertyFetch */ + $valign = ($widget->valign != '' ? ' valign="' . ($widget->valign ?? '') . '"' : ''); + /** @psalm-suppress UndefinedMagicPropertyFetch */ + $class = ($widget->tl_class != '' ? ' class="' . ($widget->tl_class ?? '') . '"' : ''); $style = ($widget->style != '' ? ' style="' . $widget->style . '"' : ''); $help = $this->getHelpForWidget($widget); - $columns[] = sprintf( + $columns[] = \sprintf( '%4$s%5$s', $valign, $class, @@ -534,7 +546,7 @@ protected function buildOptions() $help ); } - $options[] = implode('', $columns); + $options[] = \implode('', $columns); } return $options; @@ -557,25 +569,27 @@ public function generate() $arrOptions = $this->buildOptions(); // Add a "no entries found" message if there are no sub widgets. - if (!count($arrOptions)) { - $arrOptions[] = '

    '.$GLOBALS['TL_LANG']['MSC']['noResult'].'

    '; + if (!\count($arrOptions)) { + $arrOptions[] = '

    ' + . (string) ($GLOBALS['TL_LANG']['MSC']['noResult'] ?? '') + . '

    '; } $strHead = ''; - $strBody = sprintf('%s', implode("\n", $arrOptions)); + $strBody = \sprintf('%s', \implode("\n", $arrOptions)); - $strOutput = sprintf( - '%s%s
    ', + $strOutput = \sprintf( + '%s%s', (($this->style) ? ('style="' . $this->style . '"') : ('')), $this->strId, $strHead, $strBody ); - return sprintf( + return \sprintf( '
    %s
    ', $this->strName, - (strlen($this->strClass) ? ' ' . $this->strClass : ''), + (\strlen($this->strClass) ? ' ' . $this->strClass : ''), $strOutput ); } diff --git a/src/Widgets/TagsWidget.php b/src/Widgets/TagsWidget.php index e7f47e147..86f75ee52 100644 --- a/src/Widgets/TagsWidget.php +++ b/src/Widgets/TagsWidget.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2021 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Stefan Heimes * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2021 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -26,6 +26,12 @@ /** * Form field "tags", based on form field by Leo Feyer. + * + * @psalm-type TTagOption=array{value: string, label: string} + * + * @property list|null $options + * + * @psalm-suppress PropertyNotSetInConstructor */ class TagsWidget extends Widget { @@ -36,7 +42,6 @@ class TagsWidget extends Widget */ protected $strTemplate = 'form_tags'; - /** * {@inheritDoc} */ @@ -74,11 +79,11 @@ public function __set($strKey, $varValue) */ protected function validator($varInput) { - if (is_array($varInput)) { + if (\is_array($varInput)) { return parent::validator($varInput); } - return parent::validator(trim($varInput)); + return parent::validator(\trim((string) ($varInput ?? ''))); } /** @@ -88,7 +93,7 @@ protected function validator($varInput) * * @return string */ - protected function getClassForOption($index) + protected function getClassForOption(int $index): string { // If true we need another offset. $intSub = ($this->arrConfiguration['includeBlankOption'] ? 1 : 0); @@ -96,43 +101,42 @@ protected function getClassForOption($index) && null !== $this->arrConfiguration['showSelectAll']) ? 0 : 1); $strClass = $this->strName; - if ($index == 0) { + if ($index === 0) { $strClass .= ' first'; - } elseif ($index === (count($this->options) - 1 + $intSub)) { + } elseif ($index === (\count($this->options ?? []) - 1 + $intSub)) { $strClass .= ' last'; } - if (($index % 2) == 1) { + if (($index % 2) === 1) { $strClass .= ' even'; } else { $strClass .= ' odd'; } - return ((strlen($this->strClass)) ? $this->strClass . ' ' : '') . $strClass; + return ((\strlen($this->strClass)) ? $this->strClass . ' ' : '') . $strClass; } /** * Generate a single checkbox. * - * @param array $val The value array (needs keys "value" and "label"). - * - * @param int $index The sequence number of this option (used for even/odd determination). + * @param TTagOption $val The value array (needs keys "value" and "label"). + * @param int $index The sequence number of this option (used for even/odd determination). * * @return string */ - protected function generateOption($val, $index) + protected function generateOption(array $val, int $index): string { $checked = ''; - if (is_array($this->varValue) && in_array($val['value'], $this->varValue)) { + if (\is_array($this->varValue) && \in_array($val['value'], $this->varValue)) { $checked = ' checked="checked"'; } - return sprintf( + return \sprintf( '' . '%7$s', // @codingStandardsIgnoreStart - Keep the comments. - $this->getClassForOption($index), // 1 + $this->getClassForOption($index), // 1 $index, // 2 $this->strName . '_' . $index, // 3 $val['value'], // 4 @@ -140,7 +144,7 @@ protected function generateOption($val, $index) $this->getAttributes() . $this->strTagEnding, // 6 $val['label'], // 7 $this->strName // 8 - // @codingStandardsIgnoreEnd + // @codingStandardsIgnoreEnd ); } @@ -150,9 +154,9 @@ protected function generateOption($val, $index) * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - public function generate() + public function generate(): string { - $return = sprintf( + $return = \sprintf( '
    ', $this->strName @@ -160,22 +164,27 @@ public function generate() $count = 0; - if ($this->options && is_array($this->options)) { + /** @psalm-suppress MixedAssignment */ + $langBase = $GLOBALS['TL_LANG']['metamodels_frontendfilter'] ?? []; + assert(\is_array($langBase)); + if (\is_array($this->options) && [] !== $this->options) { // Show not filter option. - if ($this->arrConfiguration['includeBlankOption']) { + if ((bool) $this->arrConfiguration['includeBlankOption']) { $return .= $this->generateOption( - ['value' => '--none--', 'label' => $this->arrConfiguration['blankOptionLabel']], + [ + 'value' => '--none--', + 'label' => (string) ($this->arrConfiguration['blankOptionLabel'] ?? '') + ], $count++ ); } // Show select all checkbox - check null as BC-Layer. - if (isset($this->arrConfiguration['showSelectAll']) - && ($this->arrConfiguration['showSelectAll'] || null === $this->arrConfiguration['showSelectAll'])) { + if ((bool) $this->arrConfiguration['showSelectAll']) { $return .= $this->generateOption( [ 'value' => '--all--', - 'label' => $GLOBALS['TL_LANG']['metamodels_frontendfilter']['select_all'] + 'label' => (string) ($langBase['select_all'] ?? '') ], $count++ ); @@ -185,7 +194,7 @@ public function generate() $return .= $this->generateOption($val, $count++); } } else { - $return .= '' . $GLOBALS['TL_LANG']['metamodels_frontendfilter']['no_combinations'] . ''; + $return .= '' . (string) ($langBase['no_combinations'] ?? '') . ''; } $return .= '
    '; diff --git a/tests/Attribute/AttributeFactoryTest.php b/tests/Attribute/AttributeFactoryTest.php index c5ce38b2c..c8823ddb7 100644 --- a/tests/Attribute/AttributeFactoryTest.php +++ b/tests/Attribute/AttributeFactoryTest.php @@ -165,6 +165,8 @@ public function testAttributeTypeMatchesFlags() * Test that the method attributeTypeMatchesFlags() works correctly. * * @return void + * + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testGetTypeNames() { @@ -277,7 +279,7 @@ public function testGetTypeNames() public function testGetTypeIcon() { $factory = new AttributeFactory($this->getMockForAbstractClass(EventDispatcherInterface::class)); - $typeFactory = $this->mockAttributeFactory('test', true, false, false, new \stdClass, 'icon.png'); + $typeFactory = $this->mockAttributeFactory('test', true, false, false, new \stdClass(), 'icon.png'); $factory->addTypeFactory($typeFactory); self::assertEquals($typeFactory->getTypeIcon(), $factory->getIconForType('test')); diff --git a/tests/Attribute/BaseTest.php b/tests/Attribute/BaseTest.php index 0d1ce491b..382036b2b 100644 --- a/tests/Attribute/BaseTest.php +++ b/tests/Attribute/BaseTest.php @@ -169,6 +169,8 @@ public function testDoesNotAcceptArbitraryConfiguration() * Test that the attribute does not accept config keys not specified via getAttributeSettingNames(). * * @return void + * + * @SuppressWarnings(PHPMD.Superglobals) */ public function testGetFieldDefinition() { diff --git a/tests/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPassTest.php b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPassTest.php index 43861c3ba..19abb02c9 100644 --- a/tests/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPassTest.php +++ b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectDoctrineSchemaGeneratorsPassTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\CoreBundle\DependencyInjection\CompilerPass; diff --git a/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php index 63b602ea0..a4ca2fbf2 100644 --- a/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php +++ b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaGeneratorsPassTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\CoreBundle\DependencyInjection\CompilerPass; diff --git a/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPassTest.php b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPassTest.php index 324b35be5..e24a99ca9 100644 --- a/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPassTest.php +++ b/tests/CoreBundle/DependencyInjection/CompilerPass/CollectSchemaManagersPassTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\CoreBundle\DependencyInjection\CompilerPass; diff --git a/tests/Data/FilterBuilderSqlTest.php b/tests/Data/FilterBuilderSqlTest.php index 196ce354a..f987c0092 100644 --- a/tests/Data/FilterBuilderSqlTest.php +++ b/tests/Data/FilterBuilderSqlTest.php @@ -21,7 +21,7 @@ namespace MetaModels\Test\Data; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Driver\ResultStatement; +use Doctrine\DBAL\Result; use MetaModels\DcGeneral\Data\FilterBuilderSql; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -35,10 +35,8 @@ class FilterBuilderSqlTest extends TestCase { /** * Test that a new builder is empty. - * - * @return void */ - public function testBuilderIsInitiallyEmpty() + public function testBuilderIsInitiallyEmpty(): void { $connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock(); $builder = new FilterBuilderSql('mm_test', 'AND', $connection); @@ -49,10 +47,8 @@ public function testBuilderIsInitiallyEmpty() /** * Data provider for testBuild() - * - * @return array */ - public function buildTestProvider() + public function buildTestProvider(): array { return [ 'equality compare' => [ @@ -90,11 +86,9 @@ public function buildTestProvider() * @param array $expectedParams The expected parameters. * @param array $filter The filter input array. * - * @return void - * * @dataProvider buildTestProvider */ - public function testBuild($expectedSql, $expectedParams, array $filter) + public function testBuild(string $expectedSql, array $expectedParams, array $filter): void { $connection = $this->mockConnection($expectedSql, $expectedParams, [['id' => 'succ'], ['id' => 'ess']]); $builder = new FilterBuilderSql('mm_test', 'AND', $connection); @@ -105,10 +99,8 @@ public function testBuild($expectedSql, $expectedParams, array $filter) /** * Test the build process. - * - * @return void */ - public function testBuildMultiple() + public function testBuildMultiple(): void { $connection = $this->mockConnection( 'SELECT t.id FROM mm_test AS t WHERE ((t.foo = ?) AND (t.bar = ?))', @@ -125,10 +117,8 @@ public function testBuildMultiple() /** * Test the build process. - * - * @return void */ - public function testAddSubProcedure() + public function testAddSubProcedure(): void { $child = new FilterBuilderSql( 'mm_test', @@ -157,27 +147,24 @@ public function testAddSubProcedure() * @param string $queryString The expected SQL query. * @param array $params The expected parameters. * @param array $result The query result. - * - * @return MockObject|Connection */ - private function mockConnection($queryString, $params, $result) + private function mockConnection(string $queryString, array $params, array $result): Connection&MockObject { $connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock(); - $statement = $this - ->getMockBuilder(ResultStatement::class) + $resultSet = $this + ->getMockBuilder(Result::class) ->disableOriginalConstructor() ->getMock(); - $statement + $resultSet ->expects(self::once()) - ->method('fetchAll') - ->with(\PDO::FETCH_ASSOC) + ->method('fetchAllAssociative') ->willReturn($result); $connection ->expects(self::once()) ->method('executeQuery') ->with($queryString, $params) - ->willReturn($statement); + ->willReturn($resultSet); return $connection; } diff --git a/tests/Data/FilterBuilderTest.php b/tests/Data/FilterBuilderTest.php index 6aad2f03a..053abe73f 100644 --- a/tests/Data/FilterBuilderTest.php +++ b/tests/Data/FilterBuilderTest.php @@ -22,11 +22,10 @@ use ContaoCommunityAlliance\DcGeneral\Data\DefaultConfig; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Driver\ResultStatement; +use Doctrine\DBAL\Result; use MetaModels\DcGeneral\Data\FilterBuilder; use MetaModels\IMetaModel; use MetaModels\MetaModel; -use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use MetaModels\Attribute\Base; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -71,37 +70,6 @@ private function mockMetaModel(Connection $connection = null) return $metaModel; } - /** - * Mock a database connection with the passed query. - * - * @param string $queryString The expected SQL query. - * @param array $params The expected parameters. - * @param array $result The query result. - * - * @return MockObject|Connection - */ - private function mockConnection($queryString, $params, $result) - { - $connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock(); - - $statement = $this - ->getMockBuilder(ResultStatement::class) - ->disableOriginalConstructor() - ->getMock(); - $statement - ->expects(self::once()) - ->method('fetchAll') - ->with(\PDO::FETCH_ASSOC) - ->willReturn($result); - $connection - ->expects(self::once()) - ->method('executeQuery') - ->with($queryString, $params) - ->willReturn($statement); - - return $connection; - } - /** * Test the build process. * @@ -138,7 +106,7 @@ public function testBuildSqlOnly() $attribute = $this ->getMockBuilder(Base::class) ->setConstructorArgs([$metaModel, ['colname' => 'test1']]) - ->setMethods(['searchFor']) + ->onlyMethods(['searchFor']) ->getMockForAbstractClass(); $attribute @@ -167,14 +135,13 @@ public function testBuildSqlOnly() $connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock(); - $statement = $this - ->getMockBuilder(ResultStatement::class) + $result = $this + ->getMockBuilder(Result::class) ->disableOriginalConstructor() ->getMock(); - $statement + $result ->expects(self::once()) - ->method('fetchAll') - ->with(\PDO::FETCH_ASSOC) + ->method('fetchAllAssociative') ->willReturn([ ['id' => 0], ['id' => 1], @@ -187,7 +154,7 @@ public function testBuildSqlOnly() ->expects(self::once()) ->method('executeQuery') ->with('SELECT t.id FROM mm_test AS t WHERE ((t.foo = ?))', [0]) - ->willReturn($statement); + ->willReturn($result); $builder = new FilterBuilder($metaModel, $config, $connection); diff --git a/tests/Filter/FilterUrlBuilderTest.php b/tests/Filter/FilterUrlBuilderTest.php index 416e8ec87..548075823 100644 --- a/tests/Filter/FilterUrlBuilderTest.php +++ b/tests/Filter/FilterUrlBuilderTest.php @@ -50,7 +50,6 @@ public function generateProvider(): array 'expectedUrl' => 'page-alias/auto/slug/sluggy', 'expectedParameters' => [ 'get2' => 'value', - '_locale' => 'en', ], 'page' => [ 'alias' => 'page-alias', @@ -71,7 +70,7 @@ public function generateProvider(): array 'expectedUrl' => 'alias/auto/slug/sluggy', 'expectedParameters' => [ 'get2' => 'value', - '_locale' => 'en', + 'get-param' => 'get-value', ], 'page' => [ ], @@ -134,7 +133,7 @@ public function testGenerate( $adapter = $this->getMockBuilder(Adapter::class)->disableOriginalConstructor()->getMock(); $requestStack = $this->mockRequestStack($requestGet, $requestUrl); - $builder = new FilterUrlBuilder($generator, $requestStack, true, '.html', $adapter); + $builder = new FilterUrlBuilder($generator, $requestStack, true, '.html', $adapter, true); self::assertSame('success', $builder->generate($filterUrl)); } @@ -155,20 +154,20 @@ public function testGeneratesNonStandardPorts(): void $generator ->expects(self::once()) ->method('generate') - ->with('folder/page/auto/slug/sluggy', ['get2' => 'value', '_locale' => 'en']) + ->with('folder/page/auto/slug/sluggy', ['get2' => 'value', 'get-param' => 'get-value']) ->willReturn('success'); $adapter = $this ->getMockBuilder(Adapter::class) - ->setMethods(['findByAliases']) + ->addMethods(['findByAliases']) ->disableOriginalConstructor() ->getMock(); $requestStack = $this->getMockBuilder(RequestStack::class)->getMock(); - $requestStack->method('getMasterRequest')->willReturn( + $requestStack->method('getCurrentRequest')->willReturn( new Request( ['get-param' => 'get-value'], [], - ['_locale' => 'en'], + [], [], [], [ @@ -196,7 +195,7 @@ public function testGeneratesNonStandardPorts(): void ->with(['folder/page', 'folder']) ->willReturn($pages); - $builder = new FilterUrlBuilder($generator, $requestStack, true, '.html', $adapter); + $builder = new FilterUrlBuilder($generator, $requestStack, false, '.html', $adapter, true); $prevFolderUrl = Config::get('folderUrl'); Config::set('folderUrl', true); @@ -212,13 +211,11 @@ public function testGeneratesNonStandardPorts(): void * * @param array $requestGet The current GET parameters. * @param string $requestUrl The request URL. - * - * @return RequestStack */ private function mockRequestStack(array $requestGet, string $requestUrl): RequestStack { $requestStack = $this->getMockBuilder(RequestStack::class)->getMock(); - $requestStack->method('getMasterRequest')->willReturn( + $requestStack->method('getCurrentRequest')->willReturn( new Request($requestGet, [], [], [], [], ['REQUEST_URI' => $requestUrl]) ); diff --git a/tests/Filter/Rules/SimpleQueryTest.php b/tests/Filter/Rules/SimpleQueryTest.php index 6578b4e00..aafb6b8b9 100644 --- a/tests/Filter/Rules/SimpleQueryTest.php +++ b/tests/Filter/Rules/SimpleQueryTest.php @@ -22,6 +22,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver\Statement; +use Doctrine\DBAL\Result; use MetaModels\Filter\Rules\SimpleQuery; use PHPUnit\Framework\TestCase; @@ -48,17 +49,20 @@ public function testExecution() ->disableOriginalConstructor() ->onlyMethods(['executeQuery']) ->getMock(); - $statement = $this->getMockForAbstractClass(Statement::class); + $result = $this + ->getMockBuilder(Result::class) + ->disableOriginalConstructor() + ->onlyMethods(['fetchAllAssociative']) + ->getMock(); $connection ->expects(self::once()) ->method('executeQuery') ->with($query, $params, $types) - ->willReturn($statement); - $statement + ->willReturn($result); + $result ->expects(self::once()) - ->method('fetchAll') - ->with(\PDO::FETCH_ASSOC) + ->method('fetchAllAssociative') ->willReturn([['idcolumn' => 'a'], ['idcolumn' => 'b'], ['idcolumn' => 'c']]); $rule = new SimpleQuery($query, $params, 'idcolumn', $connection, $types); diff --git a/tests/Filter/Setting/CustomSqlTest.php b/tests/Filter/Setting/CustomSqlTest.php index 48e8e4c74..2b186944e 100644 --- a/tests/Filter/Setting/CustomSqlTest.php +++ b/tests/Filter/Setting/CustomSqlTest.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,6 +22,7 @@ namespace MetaModels\Test\Filter\Setting; use Contao\CoreBundle\Framework\Adapter; +use Contao\CoreBundle\Framework\ContaoFramework; use Contao\Input; use Contao\PageModel; use Contao\Session as ContaoSession; @@ -52,6 +53,7 @@ * @covers \MetaModels\CoreBundle\Contao\InsertTag\ReplaceTableName * * @SuppressWarnings(PHPMD.TooManyPublicMethods) + * @SuppressWarnings(PHPMD.TooManyMethods) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CustomSqlTest extends AutoLoadingTestCase @@ -64,6 +66,9 @@ class CustomSqlTest extends AutoLoadingTestCase * @param array $services The services to inject. * * @return CustomSql + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ private function mockCustomSql( array $properties = [], @@ -104,11 +109,9 @@ private function mockCustomSql( ->addMethods(['cookie', 'get', 'post']) ->getMock(); } - if (!isset($services[Session::class])) { $services[Session::class] = $this->mockSession([]); } - if (!isset($services[PageModel::class])) { $services[PageModel::class] = $this ->getMockBuilder(PageModel::class) @@ -121,6 +124,7 @@ private function mockCustomSql( $services[Request::class] = new Request(); $services[Request::class]->attributes->set('pageModel', $services[PageModel::class]); $services[Request::class]->attributes->set('_locale', $services[PageModel::class]->language); + $services[Request::class]->setSession($services[Session::class]); } if (!isset($services[RequestStack::class])) { $services[RequestStack::class] = new RequestStack(); @@ -136,13 +140,27 @@ private function mockCustomSql( ->disableOriginalConstructor() ->getMockForAbstractClass(); } - + if (!isset($services[ContaoFramework::class])) { + $services[ContaoFramework::class] = $this + ->getMockBuilder(ContaoFramework::class) + ->disableOriginalConstructor() + ->onlyMethods(['getAdapter']) + ->getMock(); + $services[ContaoFramework::class]->method('getAdapter')->willReturnCallback( + fn (string $class) => match ($class) { + Input::class => $services[Input::class], + default => throw new \RuntimeException('Override ContaoFramework instance'), + } + ); + } $services[ReplaceTableName::class] = new ReplaceTableName(); - $services[ReplaceParam::class] = new ReplaceParam($services[Input::class], $services[ContaoSession::class]); + $services[ReplaceParam::class] = new ReplaceParam( + $services[ContaoFramework::class], + $services[RequestStack::class] + ); $services[ResolveLanguageTag::class] = new ResolveLanguageTag($services[RequestStack::class]); $container = new Container(); - foreach (CustomSql::getSubscribedServices() as $serviceId) { $container->set($serviceId, $services[$serviceId]); } @@ -437,10 +455,7 @@ public function testValueFromSession(): void $setting = $this->mockCustomSql( ['customsql' => 'SELECT id FROM tableName WHERE catname={{param::session?name=category}}'], 'tableName', - [ - Session::class => $this->mockSession(['category' => 'category name']), - ContaoSession::class => $this->mockLegacySession(['category' => 'category name']), - ] + [Session::class => $this->mockSession(['category' => 'category name'])] ); $this->assertGeneratedSqlIs($setting, 'SELECT id FROM tableName WHERE catname=?', ['category name'], []); @@ -454,19 +469,13 @@ public function testValueFromSessionAggregated(): void $setting = $this->mockCustomSql( ['customsql' => 'SELECT id FROM tableName WHERE catname IN ({{param::session?name=category&aggregate}})'], 'tableName', - [ - Session::class => $this->mockSession(['category' => ['first', 'second']]), - ContaoSession::class => $this->mockLegacySession(['category' => ['first', 'second']]), - ] + [Session::class => $this->mockSession(['category' => ['first', 'second']])] ); $this->assertGeneratedSqlIs( $setting, - 'SELECT id FROM tableName WHERE catname IN (?,?)', - [ - 'first', - 'second' - ], + 'SELECT id FROM tableName WHERE catname IN (?)', + ['first,second'], [] ); } @@ -480,10 +489,7 @@ public function testValueFromSessionEmpty(): void ['customsql' => 'SELECT id FROM tableName WHERE catname={{param::session?name=category&default=defaultcat}}'], 'tableName', - [ - Session::class => $this->mockSession(['category' => null]), - ContaoSession::class => $this->mockLegacySession(['category' => null]), - ] + [Session::class => $this->mockSession(['category' => null])] ); $this->assertGeneratedSqlIs( @@ -536,11 +542,8 @@ public function testRequestParameterAggregated(): void $this->assertGeneratedSqlIs( $setting, - 'SELECT id FROM tableName WHERE catname IN (?,?)', - [ - 'first', - 'second' - ], + 'SELECT id FROM tableName WHERE catname IN (?)', + ['first,second'], [] ); } @@ -567,7 +570,7 @@ public function testRequestParameterAggregatedSet(): void [Input::class => $input] ); - $this->assertGeneratedSqlIs($setting, 'SELECT id FROM tableName WHERE catids IN (?)', ['1,2'], []); + $this->assertGeneratedSqlIs($setting, 'SELECT id FROM tableName WHERE catids IN (?,?)', ['1','2'], []); } /** @@ -707,7 +710,8 @@ public function issue1495IfLangProvider(): \Iterator ]; yield [ 'sql' => 'SELECT id FROM {{table}} -WHERE alias = {{iflng::de}}moe-yer-ss-hans-herbert-oeaeue{{iflng::en}}3{{iflng::nl}}2{{iflng::es}}4{{iflng::el}}5{{iflng}}', +WHERE alias = {{iflng::de}}moe-yer-ss-hans-herbert-oeaeue' . + '{{iflng::en}}3{{iflng::nl}}2{{iflng::es}}4{{iflng::el}}5{{iflng}}', 'language' => 'de', 'exp_sql' => 'SELECT id FROM tableName WHERE alias = moe-yer-ss-hans-herbert-oeaeue', diff --git a/tests/Helper/TableManipulatorTest.php b/tests/Helper/TableManipulatorTest.php index 6689a48d0..bccfa00f7 100644 --- a/tests/Helper/TableManipulatorTest.php +++ b/tests/Helper/TableManipulatorTest.php @@ -36,9 +36,9 @@ class TableManipulatorTest extends TestCase /** * System columns. * - * @var array + * @var list */ - private $systemColumns = [ + private array $systemColumns = [ 'id', 'pid', 'sorting', @@ -51,10 +51,8 @@ class TableManipulatorTest extends TestCase * Create the table manipulator. * * @param Connection|null $connection Optional pass a connection mock. - * - * @return TableManipulator */ - private function createTableManipulator(Connection $connection = null) + private function createTableManipulator(?Connection $connection = null): TableManipulator { $connection = $connection ?: $this->mockConnection(); @@ -63,10 +61,8 @@ private function createTableManipulator(Connection $connection = null) /** * Mock the database connection. - * - * @return MockObject|Connection */ - private function mockConnection() + private function mockConnection(): Connection&MockObject { $connection = $this->getMockBuilder(Connection::class) ->disableOriginalConstructor() @@ -77,10 +73,8 @@ private function mockConnection() /** * Test the instantiation. - * - * @return void */ - public function testInstantiation() + public function testInstantiation(): void { $manipulator = $this->createTableManipulator(); @@ -89,10 +83,8 @@ public function testInstantiation() /** * Tests the reserved words. - * - * @return void */ - public function testReservedWords() + public function testReservedWords(): void { $property = new \ReflectionProperty(TableManipulator::class, 'reservedWords'); $property->setAccessible(true); diff --git a/tests/Helper/ToolBoxFileTest.php b/tests/Helper/ToolBoxFileTest.php index fdc84845d..6a1927d4e 100644 --- a/tests/Helper/ToolBoxFileTest.php +++ b/tests/Helper/ToolBoxFileTest.php @@ -47,7 +47,7 @@ public function testConvertUuidsOrPathsToMetaModelsEmpty() 'meta' => [] ]; - self::assertEquals($emptyExpected, ToolboxFile::convertUuidsOrPathsToMetaModels(null)); + self::assertEquals($emptyExpected, ToolboxFile::convertUuidsOrPathsToMetaModels([])); self::assertEquals($emptyExpected, ToolboxFile::convertUuidsOrPathsToMetaModels([])); self::assertEquals($emptyExpected, ToolboxFile::convertUuidsOrPathsToMetaModels([null])); } diff --git a/tests/Information/AttributeInformationTest.php b/tests/Information/AttributeInformationTest.php index e97d2c8f3..3d3a2c26d 100644 --- a/tests/Information/AttributeInformationTest.php +++ b/tests/Information/AttributeInformationTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Information; diff --git a/tests/Information/ConfigurationTraitTest.php b/tests/Information/ConfigurationTraitTest.php index 63c72fbac..b9085b7c7 100644 --- a/tests/Information/ConfigurationTraitTest.php +++ b/tests/Information/ConfigurationTraitTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Information; diff --git a/tests/Information/MetaModelCollectionTest.php b/tests/Information/MetaModelCollectionTest.php index 6ca04e511..f49934afb 100644 --- a/tests/Information/MetaModelCollectionTest.php +++ b/tests/Information/MetaModelCollectionTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Information; diff --git a/tests/Information/MetaModelInformationTest.php b/tests/Information/MetaModelInformationTest.php index da1026619..1e5f72d77 100644 --- a/tests/Information/MetaModelInformationTest.php +++ b/tests/Information/MetaModelInformationTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Information; diff --git a/tests/InformationProvider/MetaModelInformationCollectorTest.php b/tests/InformationProvider/MetaModelInformationCollectorTest.php index f667bf6e8..19e9a1bd1 100644 --- a/tests/InformationProvider/MetaModelInformationCollectorTest.php +++ b/tests/InformationProvider/MetaModelInformationCollectorTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\InformationProvider; diff --git a/tests/ItemListTest.php b/tests/ItemListTest.php index 4e6bd0ca1..329cc1676 100644 --- a/tests/ItemListTest.php +++ b/tests/ItemListTest.php @@ -23,12 +23,15 @@ namespace MetaModels\Test; +use Contao\CoreBundle\Routing\ScopeMatcher; +use Contao\System; use MetaModels\Filter\Setting\IFilterSettingFactory; use MetaModels\IFactory; use MetaModels\ItemList; use MetaModels\Filter\FilterUrlBuilder; use MetaModels\Render\Setting\IRenderSettingFactory; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** @@ -38,6 +41,7 @@ */ final class ItemListTest extends TestCase { + /** @SuppressWarnings(PHPMD.Superglobals) */ public function testGetOutputFormat(): void { $factory = $this->getMockForAbstractClass(IFactory::class); @@ -45,7 +49,13 @@ public function testGetOutputFormat(): void $renderSettingFactory = $this->getMockForAbstractClass(IRenderSettingFactory::class); $eventDispatcher = $this->getMockForAbstractClass(EventDispatcherInterface::class); $filterUrlBuilder = $this->getMockBuilder(FilterUrlBuilder::class)->disableOriginalConstructor()->getMock(); - $itemlist = new ItemList($factory, $filterFactory, $renderSettingFactory, $eventDispatcher, $filterUrlBuilder); + $itemlist = new ItemList( + $factory, + $filterFactory, + $renderSettingFactory, + $eventDispatcher, + $filterUrlBuilder + ); if (!defined('TL_MODE')) { define('TL_MODE', 'FE'); @@ -55,6 +65,22 @@ public function testGetOutputFormat(): void self::markTestSkipped('Test assumes that TL_MODE is set to "FE"'); } + $scopeMatcher = $this + ->getMockBuilder(ScopeMatcher::class) + ->onlyMethods(['isFrontendRequest']) + ->disableOriginalConstructor() + ->getMock(); + $scopeMatcher->method('isFrontendRequest')->willReturn(true); + + $mockContainer = $this->getMockForAbstractClass(ContainerInterface::class); + $mockContainer + ->method('get') + ->willReturnCallback(fn(string $service) => match ($service) { + 'contao.routing.scope_matcher' => $scopeMatcher, + 'request_stack' => null, + }); + System::setContainer($mockContainer); + $GLOBALS['objPage'] = null; self::assertSame('text', $itemlist->getOutputFormat()); diff --git a/tests/MetaModelsTest.php b/tests/MetaModelsTest.php index 07fc89d0d..689003076 100644 --- a/tests/MetaModelsTest.php +++ b/tests/MetaModelsTest.php @@ -23,6 +23,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\Expression\ExpressionBuilder; use Doctrine\DBAL\Query\QueryBuilder; +use Doctrine\DBAL\Result; use Doctrine\DBAL\Statement; use MetaModels\MetaModel; use PHPUnit\Framework\MockObject\MockObject; @@ -38,12 +39,10 @@ class MetaModelsTest extends TestCase { /** * Test instantiation of a MetaModel. - * - * @return void */ - public function testCreation() + public function testCreation(): void { - $values = array( + $values = [ 'id' => '1', 'sorting' => '1', 'tstamp' => '0', @@ -51,12 +50,12 @@ public function testCreation() 'tableName' => 'mm_test', 'mode' => '', 'translated' => '1', - 'languages' => array( - 'en' => array('isfallback' => '1'), - 'de' => array('isfallback' => '') - ), + 'languages' => [ + 'en' => ['isfallback' => '1'], + 'de' => ['isfallback' => ''] + ], 'varsupport' => '1', - ); + ]; $serialized = array(); foreach ($values as $key => $value) { @@ -67,14 +66,22 @@ public function testCreation() } } - $metaModel = new MetaModel($serialized); + $metaModel = new MetaModel( + $serialized, + $this->getMockForAbstractClass(EventDispatcherInterface::class), + $this->mockConnection() + ); self::assertEmpty($metaModel->getAttributes()); foreach ($values as $key => $value) { self::assertEquals($value, $metaModel->get($key), $key); } - $metaModel = new MetaModel($values); + $metaModel = new MetaModel( + $values, + $this->getMockForAbstractClass(EventDispatcherInterface::class), + $this->mockConnection() + ); foreach ($values as $key => $value) { self::assertEquals($value, $metaModel->get($key), $key); @@ -83,26 +90,26 @@ public function testCreation() /** * Ensure the buildDatabaseParameterList works correctly. - * - * @return void */ - public function testBuildDatabaseParameterList() + public function testBuildDatabaseParameterList(): void { - $metaModel = new MetaModel(array()); + $metaModel = new MetaModel( + [], + $this->getMockForAbstractClass(EventDispatcherInterface::class), + $this->mockConnection() + ); $reflection = new \ReflectionMethod($metaModel, 'buildDatabaseParameterList'); $reflection->setAccessible(true); - self::assertEquals('?', $reflection->invoke($metaModel, array(1))); - self::assertEquals('?,?', $reflection->invoke($metaModel, array(1, 2))); - self::assertEquals('?,?,?,?,?,?', $reflection->invoke($metaModel, array(1, 2, 'fooo', 'bar', null, 'test'))); + self::assertEquals('?', $reflection->invoke($metaModel, [1])); + self::assertEquals('?,?', $reflection->invoke($metaModel, [1, 2])); + self::assertEquals('?,?,?,?,?,?', $reflection->invoke($metaModel, [1, 2, 'fooo', 'bar', null, 'test'])); } /** * Ensure the system columns are present. See issue #196. - * - * @return void */ - public function testRetrieveSystemColumns() + public function testRetrieveSystemColumns(): void { $metaModel = new MetaModel( [ @@ -116,8 +123,8 @@ public function testRetrieveSystemColumns() 'varsupport' => '', ], $this->getMockForAbstractClass(EventDispatcherInterface::class), - $this->mockConnection([ - \Closure::fromCallable(function () { + $this->mockConnection( + (function () { $builder = $this ->getMockBuilder(QueryBuilder::class) ->disableOriginalConstructor() @@ -136,7 +143,7 @@ public function testRetrieveSystemColumns() $expr = $this ->getMockBuilder(ExpressionBuilder::class) ->disableOriginalConstructor() - ->setMethods() + ->onlyMethods([]) ->getMock(); $builder @@ -162,31 +169,30 @@ public function testRetrieveSystemColumns() ->with('FIELD(id, :values)') ->willReturn($builder); - $statement = $this - ->getMockBuilder(Statement::class) + $result = $this + ->getMockBuilder(Result::class) ->disableOriginalConstructor() ->getMock(); - $statement + $result ->expects($this->exactly(2)) - ->method('fetch') - ->with(\PDO::FETCH_ASSOC) + ->method('fetchAssociative') ->willReturnOnConsecutiveCalls([ 'id' => 1, 'pid' => 0, 'sorting' => 1, 'tstamp' => 343094400, - ], null); + ], false); $builder ->expects($this->once()) - ->method('execute') - ->willReturn($statement); + ->method('executeQuery') + ->willReturn($result); return $builder; })->__invoke() - ]) + ) ); - self::assertEquals($metaModel->getName(), 'Test RetrieveSystemColumns'); + self::assertEquals('Test RetrieveSystemColumns', $metaModel->getName()); $item = $metaModel->findById(1); @@ -200,18 +206,16 @@ public function testRetrieveSystemColumns() /** * Ensure the getIdsFromFilter works correctly. - * - * @return void */ - public function testGetIdsFromFilterSortedById() + public function testGetIdsFromFilterSortedById(): void { $metaModel = $this ->getMockBuilder(MetaModel::class) - ->setMethods(['getMatchingIds']) + ->onlyMethods(['getMatchingIds']) ->setConstructorArgs([ ['tableName' => 'mm_test_retrieve'], $this->getMockForAbstractClass(EventDispatcherInterface::class), - $this->mockConnection([]) + $this->mockConnection() ]) ->getMock(); $metaModel @@ -219,7 +223,6 @@ public function testGetIdsFromFilterSortedById() ->method('getMatchingIds') ->willReturn([4, 3, 2, 1]); - /** @var MetaModel $metaModel */ self::assertSame([1, 2, 3, 4], $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'id')); self::assertSame([1, 2], $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'id', 0, 2)); self::assertSame([3, 4], $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'id', 2, 2)); @@ -230,19 +233,17 @@ public function testGetIdsFromFilterSortedById() /** * Ensure the getIdsFromFilter works correctly when sorting by pid and slicing the results. - * - * @return void */ - public function testGetIdsFromFilterSortedByPid() + public function testGetIdsFromFilterSortedByPid(): void { $metaModel = $this ->getMockBuilder(MetaModel::class) - ->setMethods(['getMatchingIds']) + ->onlyMethods(['getMatchingIds']) ->setConstructorArgs([ ['tableName' => 'mm_test_retrieve'], $this->getMockForAbstractClass(EventDispatcherInterface::class), - $this->mockConnection([ - \Closure::fromCallable(function () { + $this->mockConnection( + (function () { $builder = $this ->getMockBuilder(QueryBuilder::class) ->disableOriginalConstructor() @@ -261,7 +262,7 @@ public function testGetIdsFromFilterSortedByPid() $expr = $this ->getMockBuilder(ExpressionBuilder::class) ->disableOriginalConstructor() - ->setMethods() + ->onlyMethods([]) ->getMock(); $builder @@ -287,23 +288,22 @@ public function testGetIdsFromFilterSortedByPid() ->with('pid', 'ASC') ->willReturn($builder); - $statement = $this - ->getMockBuilder(Statement::class) + $result = $this + ->getMockBuilder(Result::class) ->disableOriginalConstructor() ->getMock(); - $statement + $result ->expects($this->once()) - ->method('fetchAll') - ->with(\PDO::FETCH_COLUMN) + ->method('fetchFirstColumn') ->willReturn([1, 2, 3, 4]); $builder ->expects($this->once()) - ->method('execute') - ->willReturn($statement); + ->method('executeQuery') + ->willReturn($result); return $builder; })->__invoke() - ]) + ) ]) ->getMock(); $metaModel @@ -311,30 +311,27 @@ public function testGetIdsFromFilterSortedByPid() ->method('getMatchingIds') ->willReturn([4, 3, 2, 1]); - /** @var MetaModel $metaModel */ - self::assertSame(array(1, 2, 3, 4), $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid')); - self::assertSame(array(1, 2), $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid', 0, 2)); - self::assertSame(array(3, 4), $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid', 2, 2)); - self::assertSame(array(3), $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid', 2, 1)); - self::assertSame(array(), $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid', 20, 0)); - self::assertSame(array(2, 3, 4), $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid', 1, 10)); + self::assertSame([1, 2, 3, 4], $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid')); + self::assertSame([1, 2], $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid', 0, 2)); + self::assertSame([3, 4], $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid', 2, 2)); + self::assertSame([3], $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid', 2, 1)); + self::assertSame([], $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid', 20, 0)); + self::assertSame([2, 3, 4], $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid', 1, 10)); } /** * Ensure the getIdsFromFilter works correctly when the results have been cached. - * - * @return void */ - public function testGetIdsFromFilterSortedByPidWithCache() + public function testGetIdsFromFilterSortedByPidWithCache(): void { $metaModel = $this ->getMockBuilder(MetaModel::class) - ->setMethods(['getMatchingIds']) + ->onlyMethods(['getMatchingIds']) ->setConstructorArgs([ ['tableName' => 'mm_test_retrieve'], $this->getMockForAbstractClass(EventDispatcherInterface::class), - $this->mockConnection([ - \Closure::fromCallable(function () { + $this->mockConnection( + (function () { $builder = $this ->getMockBuilder(QueryBuilder::class) ->disableOriginalConstructor() @@ -353,7 +350,7 @@ public function testGetIdsFromFilterSortedByPidWithCache() $expr = $this ->getMockBuilder(ExpressionBuilder::class) ->disableOriginalConstructor() - ->setMethods() + ->onlyMethods([]) ->getMock(); $builder @@ -379,23 +376,22 @@ public function testGetIdsFromFilterSortedByPidWithCache() ->with('pid', 'ASC') ->willReturn($builder); - $statement = $this - ->getMockBuilder(Statement::class) + $result = $this + ->getMockBuilder(Result::class) ->disableOriginalConstructor() ->getMock(); - $statement + $result ->expects($this->once()) - ->method('fetchAll') - ->with(\PDO::FETCH_COLUMN) + ->method('fetchFirstColumn') ->willReturn([1, 2, 3, 4]); $builder ->expects($this->once()) - ->method('execute') - ->willReturn($statement); + ->method('executeQuery') + ->willReturn($result); return $builder; })->__invoke() - ]) + ) ]) ->getMock(); $metaModel @@ -403,26 +399,23 @@ public function testGetIdsFromFilterSortedByPidWithCache() ->method('getMatchingIds') ->willReturnOnConsecutiveCalls([4, 3, 2, 1], [3, 2]); - /** @var MetaModel $metaModel */ self::assertSame([1, 2, 3, 4], $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid')); self::assertSame([2, 3], $metaModel->getIdsFromFilter($metaModel->getEmptyFilter(), 'pid')); } /** * Ensure the getCount works correctly. - * - * @return void */ - public function testGetCountForEmptyList() + public function testGetCountForEmptyList(): void { $metaModel = $this ->getMockBuilder(MetaModel::class) - ->setMethods(['getMatchingIds']) + ->onlyMethods(['getMatchingIds']) ->setConstructorArgs( [ ['tableName' => 'mm_test_retrieve'], $this->getMockForAbstractClass(EventDispatcherInterface::class), - $this->mockConnection([]) + $this->mockConnection() ] ) ->getMock(); @@ -437,18 +430,16 @@ public function testGetCountForEmptyList() /** * Ensure the getCount works correctly. - * - * @return void */ - public function testGetCountForNonEmptyList() + public function testGetCountForNonEmptyList(): void { $metaModel = $this->getMockBuilder(MetaModel::class) - ->setMethods(['getMatchingIds']) + ->onlyMethods(['getMatchingIds']) ->setConstructorArgs([ ['tableName' => 'mm_test_retrieve'], $this->getMockForAbstractClass(EventDispatcherInterface::class), - $this->mockConnection([ - \Closure::fromCallable(function () { + $this->mockConnection( + (function () { $builder = $this ->getMockBuilder(QueryBuilder::class) ->disableOriginalConstructor() @@ -467,7 +458,7 @@ public function testGetCountForNonEmptyList() $expr = $this ->getMockBuilder(ExpressionBuilder::class) ->disableOriginalConstructor() - ->setMethods() + ->onlyMethods([]) ->getMock(); $builder @@ -487,23 +478,22 @@ public function testGetCountForNonEmptyList() ->with('values', [4, 3, 2, 1], Connection::PARAM_STR_ARRAY) ->willReturn($builder); - $statement = $this - ->getMockBuilder(Statement::class) + $result = $this + ->getMockBuilder(Result::class) ->disableOriginalConstructor() ->getMock(); - $statement + $result ->expects($this->once()) - ->method('fetch') - ->with(\PDO::FETCH_COLUMN) + ->method('fetchOne') ->willReturn(4); $builder ->expects($this->once()) - ->method('execute') - ->willReturn($statement); + ->method('executeQuery') + ->willReturn($result); return $builder; })->__invoke() - ]) + ) ]) ->getMock(); $metaModel @@ -511,18 +501,15 @@ public function testGetCountForNonEmptyList() ->method('getMatchingIds') ->willReturn([4, 3, 2, 1]); - /** @var MetaModel $metaModel */ self::assertEquals(4, $metaModel->getCount($metaModel->getEmptyFilter())); } /** * Mock a database connection with hte passed query builders. * - * @param array $queryBuilders The query builder list. - * - * @return MockObject|Connection + * @param QueryBuilder ...$queryBuilders The query builder list. */ - private function mockConnection(array $queryBuilders) + private function mockConnection(QueryBuilder ...$queryBuilders): Connection&MockObject { $connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock(); diff --git a/tests/Render/TemplateTest.php b/tests/Render/TemplateTest.php index 54f92abd8..ae153c757 100644 --- a/tests/Render/TemplateTest.php +++ b/tests/Render/TemplateTest.php @@ -130,6 +130,8 @@ public function testCacheOverMultipleInstances(): void * Test different caches for custom paths. * * @return void + * + * @SuppressWarnings(PHPMD.Superglobals) */ public function testCacheForEachCustomPathInstances(): void { diff --git a/tests/Schema/Doctrine/DoctrineSchemaGeneratorTest.php b/tests/Schema/Doctrine/DoctrineSchemaGeneratorTest.php index ecd1ea0a7..fabe5fba2 100644 --- a/tests/Schema/Doctrine/DoctrineSchemaGeneratorTest.php +++ b/tests/Schema/Doctrine/DoctrineSchemaGeneratorTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Schema\Doctrine; diff --git a/tests/Schema/Doctrine/DoctrineSchemaInformationTest.php b/tests/Schema/Doctrine/DoctrineSchemaInformationTest.php index 7535283cb..bb9765576 100644 --- a/tests/Schema/Doctrine/DoctrineSchemaInformationTest.php +++ b/tests/Schema/Doctrine/DoctrineSchemaInformationTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Schema\Doctrine; diff --git a/tests/Schema/Doctrine/DoctrineSchemaManagerTest.php b/tests/Schema/Doctrine/DoctrineSchemaManagerTest.php index 90a19c690..33d84a442 100644 --- a/tests/Schema/Doctrine/DoctrineSchemaManagerTest.php +++ b/tests/Schema/Doctrine/DoctrineSchemaManagerTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Schema\Doctrine; diff --git a/tests/Schema/LegacySchemaGeneratorTest.php b/tests/Schema/LegacySchemaGeneratorTest.php index 047e3cbb3..a306f297d 100644 --- a/tests/Schema/LegacySchemaGeneratorTest.php +++ b/tests/Schema/LegacySchemaGeneratorTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Schema\Doctrine; @@ -39,6 +39,8 @@ * This tests the doctrine schema. * * @covers \MetaModels\Schema\LegacySchemaGenerator + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class LegacySchemaGeneratorTest extends TestCase { diff --git a/tests/Schema/LegacySchemaInformationTest.php b/tests/Schema/LegacySchemaInformationTest.php index 942052be6..aca52effc 100644 --- a/tests/Schema/LegacySchemaInformationTest.php +++ b/tests/Schema/LegacySchemaInformationTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Schema\Doctrine; diff --git a/tests/Schema/LegacySchemaManagerTest.php b/tests/Schema/LegacySchemaManagerTest.php index 4496a4dfc..802f8a3d3 100644 --- a/tests/Schema/LegacySchemaManagerTest.php +++ b/tests/Schema/LegacySchemaManagerTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Schema\Doctrine; diff --git a/tests/Schema/SchemaGeneratorTest.php b/tests/Schema/SchemaGeneratorTest.php index 922118904..2fbbb0813 100644 --- a/tests/Schema/SchemaGeneratorTest.php +++ b/tests/Schema/SchemaGeneratorTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Schema; diff --git a/tests/Schema/SchemaInformationTest.php b/tests/Schema/SchemaInformationTest.php index e964efc2d..4184d4064 100644 --- a/tests/Schema/SchemaInformationTest.php +++ b/tests/Schema/SchemaInformationTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Schema; diff --git a/tests/Schema/SchemaManagerTest.php b/tests/Schema/SchemaManagerTest.php index d4083049d..0527c774d 100644 --- a/tests/Schema/SchemaManagerTest.php +++ b/tests/Schema/SchemaManagerTest.php @@ -17,7 +17,7 @@ * @filesource */ -declare(strict_types = 1); +declare(strict_types=1); namespace MetaModels\Test\Schema; From 1592a88ff2dddc37ea7650344559f2bfaeeb8794 Mon Sep 17 00:00:00 2001 From: Ingolf Steinardt Date: Sat, 6 Apr 2024 21:52:07 +0200 Subject: [PATCH 211/224] Fix PHPCQ errors --- .../DcGeneral/Table/DcaSetting/DisableMandatoryListener.php | 5 +++-- .../DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php index 3cca5a750..d71ef9133 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php @@ -25,6 +25,7 @@ use Contao\Message; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\BuildWidgetEvent; +use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use Doctrine\DBAL\Connection; use MetaModels\IFactory; @@ -41,7 +42,7 @@ class DisableMandatoryListener extends AbstractListener * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * Create a new instance. @@ -81,7 +82,7 @@ public function handle(BuildWidgetEvent $event) } $model = $event->getModel(); - assert($model instanceof IMetaModel); + assert($model instanceof ModelInterface); $metaModel = $this->getMetaModelFromModel($model); assert($metaModel instanceof IMetaModel); $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php index 8742e3c22..0bb5568dd 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php @@ -24,9 +24,9 @@ use Contao\Message; use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\BuildWidgetEvent; +use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use Doctrine\DBAL\Connection; -use MetaModels\Attribute\IAttribute; use MetaModels\IFactory; use MetaModels\IMetaModel; use Symfony\Contracts\Translation\TranslatorInterface; @@ -82,8 +82,8 @@ public function handle(BuildWidgetEvent $event) return; } - $model = $event->getModel(); - assert($model instanceof IMetaModel); + $model = $event->getModel(); + assert($model instanceof ModelInterface); $metaModel = $this->getMetaModelFromModel($model); assert($metaModel instanceof IMetaModel); $attribute = $metaModel->getAttributeById((int) $model->getProperty('attr_id')); From 552e325a4c0b250a3f0bd95387cd0a5e6448c62d Mon Sep 17 00:00:00 2001 From: Ingolf Steinardt Date: Mon, 8 Apr 2024 21:43:29 +0200 Subject: [PATCH 212/224] Fix filter settings if not selected --- src/Filter/Setting/FilterSettingFactory.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Filter/Setting/FilterSettingFactory.php b/src/Filter/Setting/FilterSettingFactory.php index 88cab44a1..2e0d46075 100644 --- a/src/Filter/Setting/FilterSettingFactory.php +++ b/src/Filter/Setting/FilterSettingFactory.php @@ -267,9 +267,6 @@ public function createCollection($settingId) ->setMaxResults(1) ->setParameter('id', $settingId) ->executeQuery(); - if (0 === $query->rowCount()) { - throw new \RuntimeException('Could not retrieve filter setting'); - } if (false !== ($information = $query->fetchAssociative())) { $metaModel = $this->factory->getMetaModel($this->factory->translateIdToMetaModelName($information['pid'])); From 6a7d59debdc9b4fad413a4a092024b67b4119e3f Mon Sep 17 00:00:00 2001 From: Ingolf Steinardt Date: Tue, 9 Apr 2024 14:37:57 +0200 Subject: [PATCH 213/224] Fix check isUnique --- src/Attribute/BaseSimple.php | 4 +++- src/DcGeneral/Data/Driver.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Attribute/BaseSimple.php b/src/Attribute/BaseSimple.php index f95de6c6c..d2a4f3218 100644 --- a/src/Attribute/BaseSimple.php +++ b/src/Attribute/BaseSimple.php @@ -249,13 +249,15 @@ public function searchFor($strPattern) // Base implementation, do a simple search on given column. $strPattern = \str_replace(['*', '?'], ['%', '_'], $strPattern); - return $this->connection->createQueryBuilder() + $result = $this->connection->createQueryBuilder() ->select('t.id') ->from($this->getMetaModel()->getTableName(), 't') ->where('t.' . $this->getColName() . ' LIKE :pattern') ->setParameter('pattern', $strPattern) ->executeQuery() ->fetchFirstColumn(); + + return \array_map(static fn (mixed $value) => (string) $value, $result); } /** diff --git a/src/DcGeneral/Data/Driver.php b/src/DcGeneral/Data/Driver.php index aad9d9cb0..c04b07436 100644 --- a/src/DcGeneral/Data/Driver.php +++ b/src/DcGeneral/Data/Driver.php @@ -566,7 +566,7 @@ public function getVersions($mixID, $onlyActive = false) */ public function isUniqueValue($field, $new, $primaryId = null) { - $attribute = $this->getMetaModel()->getAttribute($field); + $attribute = $this->getMetaModel()?->getAttribute($field); if ($attribute) { $matchingIds = $this ->prepareFilter( From b82bc1d989880c64152cf1891dc2b7353207b95c Mon Sep 17 00:00:00 2001 From: Ingolf Steinardt Date: Tue, 9 Apr 2024 19:34:42 +0200 Subject: [PATCH 214/224] Fix check isUnique --- src/Attribute/TranslatedReference.php | 13 ++++++++----- src/MetaModel.php | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Attribute/TranslatedReference.php b/src/Attribute/TranslatedReference.php index 4c0dea630..d28bf675a 100644 --- a/src/Attribute/TranslatedReference.php +++ b/src/Attribute/TranslatedReference.php @@ -299,7 +299,9 @@ public function searchForInLanguages($strPattern, $arrLanguages = []) $this->buildWhere($queryBuilder, null, $arrLanguages, 't'); - return $queryBuilder->executeQuery()->fetchFirstColumn(); + $statement = $queryBuilder->executeQuery(); + + return \array_map(static fn (mixed $value) => (string) $value, $statement->fetchFirstColumn()); } /** @@ -366,24 +368,24 @@ public function setTranslatedDataFor($arrValues, $strLangCode) $arrIds = \array_keys($arrValues); $arrExisting = $this->fetchExistingIdsFor($arrIds, $strLangCode); $arrNewIds = \array_diff($arrIds, $arrExisting); + $tableAlias = $this->getValueTable(); // Update existing values - delete if empty. foreach ($arrExisting as $intId) { $queryBuilder = $this->connection->createQueryBuilder(); - $this->buildWhere($queryBuilder, $intId, [$strLangCode], 't'); + $this->buildWhere($queryBuilder, $intId, [$strLangCode], $tableAlias); $itemValues = $arrValues[$intId] ?? []; if ($this->isValidItemValue($itemValues)) { - $queryBuilder->update($this->getValueTable(), 't'); + $queryBuilder->update($this->getValueTable()); foreach ($this->getSetValues($itemValues, $intId, $strLangCode) as $name => $value) { $queryBuilder - ->set('t.' . $name, ':' . $name) + ->set($tableAlias . '.' . $name, ':' . $name) ->setParameter($name, $value); } } else { $queryBuilder->delete($this->getValueTable()); } - $queryBuilder->executeQuery(); } @@ -440,6 +442,7 @@ public function getTranslatedDataFor($arrIds, $strLangCode) while ($value = $statement->fetchAssociative()) { $arrReturn[$value['item_id']] = $value; } + return $arrReturn; } diff --git a/src/MetaModel.php b/src/MetaModel.php index 23464b7f9..04bdc457a 100644 --- a/src/MetaModel.php +++ b/src/MetaModel.php @@ -1216,6 +1216,7 @@ protected function updateVariants($item, $activeLanguage, $allIds, $baseAttribut } else { $arrIds = array($item->get('id')); } + $this->saveAttribute($objAttribute, $arrIds, $item->get($strAttributeId), $activeLanguage); } } From 12c0cd8d6eac8752387bf22228c73ad1c646bbf6 Mon Sep 17 00:00:00 2001 From: Ingolf Steinardt Date: Thu, 11 Apr 2024 14:23:58 +0200 Subject: [PATCH 215/224] Fix delete trans data --- src/Attribute/TranslatedReference.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Attribute/TranslatedReference.php b/src/Attribute/TranslatedReference.php index d28bf675a..3892e00db 100644 --- a/src/Attribute/TranslatedReference.php +++ b/src/Attribute/TranslatedReference.php @@ -454,8 +454,8 @@ public function unsetValueFor($arrIds, $strLangCode) if ('' === $strLangCode) { throw new \InvalidArgumentException('Empty language code provided.'); } - $queryBuilder = $this->connection->createQueryBuilder()->delete($this->getValueTable(), 't'); - $this->buildWhere($queryBuilder, $arrIds, [$strLangCode], 't'); + $queryBuilder = $this->connection->createQueryBuilder()->delete($this->getValueTable()); + $this->buildWhere($queryBuilder, $arrIds, [$strLangCode], $this->getValueTable()); $queryBuilder->executeQuery(); } From d612d08bbe97b6dd9950b224d959843537d65346 Mon Sep 17 00:00:00 2001 From: Ingolf Steinardt Date: Fri, 12 Apr 2024 12:38:55 +0200 Subject: [PATCH 216/224] Fix pagination page param --- src/CoreBundle/Controller/ListControllerTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoreBundle/Controller/ListControllerTrait.php b/src/CoreBundle/Controller/ListControllerTrait.php index a6713bfe6..9832684a9 100644 --- a/src/CoreBundle/Controller/ListControllerTrait.php +++ b/src/CoreBundle/Controller/ListControllerTrait.php @@ -190,7 +190,7 @@ public function __construct( private function getResponseInternal(Template $template, Model $model, Request $request): Response { /** @psalm-suppress UndefinedMagicPropertyFetch */ - if (null === ($pageParam = $model->metamodel_page_param)) { + if ('' === ($pageParam = $model->metamodel_page_param)) { /** @psalm-suppress UndefinedMagicPropertyFetch */ switch ($model->type) { case 'metamodel_content': From a758884af646f754bd1fa3e1b1ba9663ce911622 Mon Sep 17 00:00:00 2001 From: Ingolf Steinardt Date: Mon, 15 Apr 2024 20:43:19 +0200 Subject: [PATCH 217/224] Fix sub-filter validation --- src/DcGeneral/Data/FilterBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DcGeneral/Data/FilterBuilder.php b/src/DcGeneral/Data/FilterBuilder.php index 9ce788f5f..bf5aca5d5 100644 --- a/src/DcGeneral/Data/FilterBuilder.php +++ b/src/DcGeneral/Data/FilterBuilder.php @@ -455,7 +455,7 @@ private function assertValidAndOr(array $filter): void private function assertValidCompareOperation(array $filter): void { assert(\is_string($filter['property'] ?? null)); - assert(\is_string($filter['value'] ?? null)); + assert(\is_string($filter['value'] ?? null) || \is_int($filter['value'] ?? null)); assert(\in_array($filter['operation'], ['<', '=', '>'], true)); } From 5b42550880e1ad321c539598df44f23711886b11 Mon Sep 17 00:00:00 2001 From: Ingolf Steinardt Date: Tue, 16 Apr 2024 09:35:23 +0200 Subject: [PATCH 218/224] Fix sub-filter validation --- src/DcGeneral/Data/FilterBuilder.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/DcGeneral/Data/FilterBuilder.php b/src/DcGeneral/Data/FilterBuilder.php index bf5aca5d5..911690cd9 100644 --- a/src/DcGeneral/Data/FilterBuilder.php +++ b/src/DcGeneral/Data/FilterBuilder.php @@ -42,8 +42,8 @@ * Class to generate a MetaModels filter from a data configuration. * * @psalm-type TFilterANDOR=array{operation: 'AND'|'OR', children: list>} - * @psalm-type TFilterCMP=array{operation: "="|">"|"<", property: string, value: string} - * @psalm-type TFilterIN=array{operation: 'IN', property: string, values: list} + * @psalm-type TFilterCMP=array{operation: "="|">"|"<", property: string, value: string|int|float} + * @psalm-type TFilterIN=array{operation: 'IN', property: string, values: list} * @psalm-type TFilterLIKE=array{operation: 'LIKE', property: string, value: string} * @psalm-type TFilterForProperty=TFilterCMP|TFilterIN|TFilterLIKE * @psalm-type TFilter=TFilterANDOR|TFilterForProperty @@ -455,7 +455,11 @@ private function assertValidAndOr(array $filter): void private function assertValidCompareOperation(array $filter): void { assert(\is_string($filter['property'] ?? null)); - assert(\is_string($filter['value'] ?? null) || \is_int($filter['value'] ?? null)); + assert( + \is_string($filter['value'] ?? null) + || \is_int($filter['value'] ?? null) + || \is_float($filter['value'] ?? null) + ); assert(\in_array($filter['operation'], ['<', '=', '>'], true)); } @@ -463,7 +467,11 @@ private function assertValidCompareOperation(array $filter): void private function assertValidInList(array $filter): void { assert(\is_string($filter['property'] ?? null)); - assert(\is_string($filter['value'] ?? null)); + assert( + \is_string($filter['value'] ?? null) + || \is_int($filter['value'] ?? null) + || \is_float($filter['value'] ?? null) + ); assert($filter['operation'] === 'IN'); } From c010eab33f5625183383203dfb690de8bb21d74f Mon Sep 17 00:00:00 2001 From: Ingolf Steinardt Date: Tue, 16 Apr 2024 12:12:10 +0200 Subject: [PATCH 219/224] Fix sub-filter validation --- src/DcGeneral/Data/FilterBuilder.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/DcGeneral/Data/FilterBuilder.php b/src/DcGeneral/Data/FilterBuilder.php index 911690cd9..1c33e57cc 100644 --- a/src/DcGeneral/Data/FilterBuilder.php +++ b/src/DcGeneral/Data/FilterBuilder.php @@ -455,11 +455,7 @@ private function assertValidAndOr(array $filter): void private function assertValidCompareOperation(array $filter): void { assert(\is_string($filter['property'] ?? null)); - assert( - \is_string($filter['value'] ?? null) - || \is_int($filter['value'] ?? null) - || \is_float($filter['value'] ?? null) - ); + assert(\is_string($value = ($filter['value'] ?? null)) || \is_int($value) || \is_float($value)); assert(\in_array($filter['operation'], ['<', '=', '>'], true)); } @@ -467,11 +463,7 @@ private function assertValidCompareOperation(array $filter): void private function assertValidInList(array $filter): void { assert(\is_string($filter['property'] ?? null)); - assert( - \is_string($filter['value'] ?? null) - || \is_int($filter['value'] ?? null) - || \is_float($filter['value'] ?? null) - ); + assert(\is_string($value = ($filter['value'] ?? null)) || \is_int($value) || \is_float($value)); assert($filter['operation'] === 'IN'); } From 06099e8f98599c74bf8b2f03796a36f765b4a151 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 16 Apr 2024 18:48:08 +0000 Subject: [PATCH 220/224] Fix pagination page param --- src/Helper/PaginationLimitCalculator.php | 102 +++++++++++------------ 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/src/Helper/PaginationLimitCalculator.php b/src/Helper/PaginationLimitCalculator.php index 29ce680b4..14d033bc9 100644 --- a/src/Helper/PaginationLimitCalculator.php +++ b/src/Helper/PaginationLimitCalculator.php @@ -467,59 +467,6 @@ public function getCalculatedLimit(): ?int return $this->calculatedLimit; } - /** - * Retrieve GET parameters. - * - * @return string|null - */ - private function getGetPageParam(): ?string - { - $value = $this->filterUrl->getGet($this->pageParam); - if (\is_array($value)) { - return null; - } - - return $value; - } - - /** - * Calculate the limit and offset with pagination. - * - * @return void - */ - private function calculatePaginated() - { - $this->calculatedTotal = $this->getTotalAmount(); - - // If a total limit has been defined, we need to honor that. - if (($this->calculatedLimit !== null) && ($this->calculatedTotal > $this->calculatedLimit)) { - $this->calculatedTotal -= $this->calculatedLimit; - } - if ($this->calculatedOffset !== null) { - $this->calculatedTotal -= $this->calculatedOffset; - } - - // Get the current page. - $page = $this->getCurrentPage(); - - if ($page > ($this->calculatedTotal / $this->getPerPage())) { - $page = (int) \ceil($this->calculatedTotal / $this->getPerPage()); - } - - // Set limit and offset. - if (null !== $this->calculatedOffset) { - $this->calculatedOffset += ((\max($page, 1) - 1) * $this->getPerPage()); - } - if ($this->calculatedLimit === null) { - $this->calculatedLimit = $this->getPerPage(); - } else { - $this->calculatedLimit = \min( - ($this->calculatedLimit - ($this->calculatedOffset ?? 0)), - $this->getPerPage() - ); - } - } - /** * Calculate the pagination based upon the offset, limit and total amount of items. * @@ -563,4 +510,53 @@ protected function calculate() $this->calculatedOffset = 0; } } + + /** + * Calculate the limit and offset with pagination. + * + * @return void + */ + private function calculatePaginated(): void + { + $this->calculatedTotal = $this->getTotalAmount(); + + // If a total limit has been defined, we need to honor that. + if ($this->calculatedOffset !== null) { + $this->calculatedTotal -= $this->calculatedOffset; + } + if (($this->calculatedLimit !== null) && ($this->calculatedTotal > $this->calculatedLimit)) { + $this->calculatedTotal = $this->calculatedLimit; + } + + // Get the current page. + $page = $this->getCurrentPage(); + $perPage = $this->getPerPage(); + + if ($page > ($this->calculatedTotal / $perPage)) { + $page = (int) \ceil($this->calculatedTotal / $perPage); + } + + // Set offset and limit. + $this->calculatedOffset = ($this->calculatedOffset ?? 0) + ((\max($page, 1) - 1) * $perPage); + if (null === $this->calculatedLimit) { + $this->calculatedLimit = $perPage; + } else { + $this->calculatedLimit = \min($this->calculatedTotal, $perPage); + } + } + + /** + * Retrieve GET parameters. + * + * @return string|null + */ + private function getGetPageParam(): ?string + { + $value = $this->filterUrl->getGet($this->pageParam); + if (\is_array($value)) { + return null; + } + + return $value; + } } From 8c49716b0e5e450acd9bf288051ca188c0261354 Mon Sep 17 00:00:00 2001 From: Cliff Parnitzky Date: Tue, 16 Apr 2024 20:07:43 +0000 Subject: [PATCH 221/224] Hotfix/ml checkbox icon --- src/CoreBundle/Resources/public/css/style.css | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/CoreBundle/Resources/public/css/style.css b/src/CoreBundle/Resources/public/css/style.css index 9b615cb3b..6543da192 100644 --- a/src/CoreBundle/Resources/public/css/style.css +++ b/src/CoreBundle/Resources/public/css/style.css @@ -1,7 +1,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @author Ingolf Steinhardt * @author Sven Baumann * @author Carolina Koehn - * @copyright 2012-2022 The MetaModels team. + * @author Cliff Parnitzky + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -153,7 +154,8 @@ form[id^=mm_] .sort_hint { } .widget.translat-attr > h3 > label, -.widget.translat-attr > fieldset > legend { +.widget.translat-attr > fieldset > legend, +.widget.translat-attr > .tl_checkbox_single_container label { padding-left: 20px; display: inline-block; background: url("../images/icons/locale.png") no-repeat left center; From 2c39dce0d35991cf7ea9993a3da3a6e90d759f71 Mon Sep 17 00:00:00 2001 From: Ingolf Steinhardt Date: Tue, 2 Aug 2022 07:26:05 +0200 Subject: [PATCH 222/224] Feature translation loader --- src/CoreBundle/Resources/config/services.yml | 8 ++ .../mm_testselecttags.en.metamodels | 0 .../Translator/MetaModelTranslationLoader.php | 40 ++++++++++ src/CoreBundle/Translator/Translator.php | 79 +++++++++++++++++++ 4 files changed, 127 insertions(+) create mode 100644 src/CoreBundle/Resources/translations/mm_testselecttags.en.metamodels create mode 100644 src/CoreBundle/Translator/MetaModelTranslationLoader.php create mode 100644 src/CoreBundle/Translator/Translator.php diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index b9eae2ef3..6062f0181 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -284,3 +284,11 @@ services: - "@contao.assets.files_context" - "@contao.image.picture_factory" - "@session" + + MetaModels\CoreBundle\Translator\Translator: + decorates: 'contao.translation.translator' + arguments: + - '@MetaModels\CoreBundle\Translator\Translator.inner' + + MetaModels\CoreBundle\Translator\MetaModelTranslationLoader: + tags: [ { name: translation.loader, alias: 'metamodels' } ] diff --git a/src/CoreBundle/Resources/translations/mm_testselecttags.en.metamodels b/src/CoreBundle/Resources/translations/mm_testselecttags.en.metamodels new file mode 100644 index 000000000..e69de29bb diff --git a/src/CoreBundle/Translator/MetaModelTranslationLoader.php b/src/CoreBundle/Translator/MetaModelTranslationLoader.php new file mode 100644 index 000000000..45e2f356a --- /dev/null +++ b/src/CoreBundle/Translator/MetaModelTranslationLoader.php @@ -0,0 +1,40 @@ + + * @author Sven Baumann + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\Translator; + +use Symfony\Component\Translation\Loader\LoaderInterface; +use Symfony\Component\Translation\MessageCatalogue; + +final class MetaModelTranslationLoader implements LoaderInterface +{ + public function load($resource, $locale, $domain = 'messages') + { + dump($resource, $locale, $domain); + $catalog = new MessageCatalogue($locale); + if ($domain === 'mm_testselecttags') { + $catalog->set('mm_testselecttags.select_normal.0', 'Label !!!!', $domain); + $catalog->set('mm_testselecttags.select_normal.1', 'Description', $domain); + } + dump($catalog); + + return $catalog; + } +} diff --git a/src/CoreBundle/Translator/Translator.php b/src/CoreBundle/Translator/Translator.php new file mode 100644 index 000000000..b54fc51e9 --- /dev/null +++ b/src/CoreBundle/Translator/Translator.php @@ -0,0 +1,79 @@ + + * @author Sven Baumann + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\Translator; + +use Symfony\Component\Translation\TranslatorBagInterface; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +final class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface, LegacyTranslatorInterface +{ + /** + * @var TranslatorInterface|TranslatorBagInterface|LegacyTranslatorInterface + */ + private $translator; + + /** + * @internal Do not inherit from this class; decorate the "contao.translation.translator" service instead + */ + public function __construct(TranslatorInterface $translator) + { + $this->translator = $translator; + } + + /** + * {@inheritdoc} + * + * Gets the translation from Contao’s $GLOBALS['TL_LANG'] array if the message + * domain starts with "contao_". The locale parameter is ignored in this case. + */ + public function trans($id, array $parameters = [], $domain = null, $locale = null): string + { + // Cut off the contao_ prefix for mm_ domains as they are already loaded via symfony. + if (0 === strncmp($domain, 'contao_mm_', 10)) { + $domain = substr($domain, 7); + dump('REDIRECTED TO: ' . $domain); + } + // Forward to Contao translator + return $this->translator->trans($id, $parameters, $domain, $locale); + } + + public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null): string + { + return $this->translator->transChoice($id, $number, $parameters, $domain, $locale); + } + + public function setLocale($locale): void + { + $this->translator->setLocale($locale); + } + + public function getLocale(): string + { + return $this->translator->getLocale(); + } + + public function getCatalogue($locale = null) + { + return $this->translator->getCatalogue($locale); + } +} From 96771d624b4567783f536b434cc324f7a1340342 Mon Sep 17 00:00:00 2001 From: Christian Schiffler Date: Mon, 10 Jul 2023 20:03:59 +0200 Subject: [PATCH 223/224] Changes to show translations from xlf and fixes for PHPCQ --- .composer-require-checker.json | 4 + .phpcq.lock | 2 +- composer.json | 10 +- psalm.xml | 3 + src/Attribute/Base.php | 5 +- src/Attribute/BaseSimple.php | 31 +- src/Attribute/TranslatedReference.php | 17 +- src/BackendIntegration/Module.php | 8 +- src/BackendIntegration/TemplateList.php | 62 +++- ...bstractContentElementAndModuleCallback.php | 53 ++- .../Contao/Hooks/FixupUserGroupModules.php | 156 -------- .../Contao/InsertTag/ResolveLanguageTag.php | 4 +- .../Backend/AbstractAddAllController.php | 26 +- .../Backend/ConfigurationController.php | 96 +++++ .../Backend/DcGeneralControllerTrait.php | 94 +++++ .../Backend/InputScreenAddAllController.php | 2 +- .../Backend/MetaModelController.php | 114 ++++++ .../Backend/SupportMetaModelsController.php | 16 +- .../ContentElement/ItemListController.php | 6 +- .../FrontendModule/ItemListController.php | 2 +- .../Controller/ListControllerTrait.php | 23 +- .../CompilerPass/PrepareTranslatorPass.php | 47 +++ .../MetaModelsCoreExtension.php | 6 +- .../BackendNavigationListener.php | 300 ++++++++++++--- .../BreadcrumbMetaModelListener.php | 2 +- .../DcGeneral/Breadcrumb/BreadcrumbStore.php | 27 +- .../DefinitionBuilder/CommandBuilder.php | 65 +--- .../Contao2BackendViewDefinitionBuilder.php | 6 +- .../DefinitionBuilder/PaletteBuilder.php | 12 +- .../PropertyDefinitionBuilder.php | 35 +- .../TranslatorPopulator.php | 43 +-- .../Attribute/AttributeRendererListener.php | 4 +- .../AttributeSchemaManagerHintListener.php | 12 +- .../Attribute/ColNameValidationListener.php | 32 +- .../Attribute/NameAndDescriptionListener.php | 19 +- .../Dca/BackendSectionOptionListener.php | 41 +- .../Table/Dca/RenderModeHintListener.php | 6 +- .../DcaSetting/DisableMandatoryListener.php | 6 +- .../DcaSetting/DisableReadOnlyListener.php | 6 +- .../EditMaskSubHeadlineListener.php | 2 +- .../Table/DcaSetting/ModelToLabelListener.php | 6 +- .../SetVisibilityConditionIconListener.php | 5 +- .../ModelToLabelListener.php | 57 ++- .../TypeOptionsListener.php | 13 +- .../DcaSortGroup/ModelToLabelListener.php | 6 +- .../Table/DeleteOperationButtonListener.php | 122 ++++++ .../AbstractFilterSettingTypeRenderer.php | 29 +- .../ModelSchemaManagerHintListener.php | 12 +- .../Table/MetaModel/ModelToLabelListener.php | 20 +- .../MetaModel/TableNamePrefixingListener.php | 14 +- .../RenderSetting/ModelToLabelListener.php | 21 +- .../Table/RenderSettings/JumpToListener.php | 13 +- .../LanguageCodeWizardListener.php | 4 +- src/CoreBundle/EventListener/UserListener.php | 1 + src/CoreBundle/MetaModelsCoreBundle.php | 2 + .../dc-general/environment-populator.yml | 1 + .../Resources/config/dc-general/listener.yml | 9 + .../config/dc-general/table/tl_dca.yml | 4 + src/CoreBundle/Resources/config/hooks.yml | 2 + src/CoreBundle/Resources/config/listeners.yml | 1 + src/CoreBundle/Resources/config/routing.yml | 16 + src/CoreBundle/Resources/config/services.yml | 23 ++ .../Resources/contao/config/config.php | 44 +-- .../Resources/contao/dca/tl_content.php | 0 .../Resources/contao/dca/tl_metamodel.php | 220 ++++++----- .../contao/dca/tl_metamodel_attribute.php | 126 ++++--- .../Resources/contao/dca/tl_metamodel_dca.php | 246 ++++++------ .../contao/dca/tl_metamodel_dca_combine.php | 94 ++--- .../contao/dca/tl_metamodel_dca_sortgroup.php | 176 +++++---- .../contao/dca/tl_metamodel_dcasetting.php | 321 +++++++++------- .../dca/tl_metamodel_dcasetting_condition.php | 119 +++--- .../contao/dca/tl_metamodel_filter.php | 82 ++-- .../contao/dca/tl_metamodel_filtersetting.php | 349 ++++++++++-------- .../contao/dca/tl_metamodel_item.php | 9 +- .../contao/dca/tl_metamodel_rendersetting.php | 97 ++--- .../dca/tl_metamodel_rendersettings.php | 240 ++++++------ .../dca/tl_metamodel_searchable_pages.php | 108 +++--- .../Resources/contao/dca/tl_module.php | 0 .../Resources/contao/dca/tl_user_group.php | 17 +- .../Resources/contao/languages/da/default.php | 80 ---- .../Resources/contao/languages/da/explain.php | 34 -- .../Resources/contao/languages/da/modules.php | 26 -- .../contao/languages/da/tl_metamodel.php | 16 - .../languages/da/tl_metamodel_dcasetting.php | 16 - .../da/tl_metamodel_dcasetting_condition.php | 16 - .../da/tl_metamodel_filtersetting.php | 26 -- .../contao/languages/da/tl_metamodel_item.php | 16 - .../da/tl_metamodel_rendersetting.php | 16 - .../da/tl_metamodel_rendersettings.php | 15 - .../da/tl_metamodel_searchable_pages.php | 16 - .../languages/da/tl_syncCto_database.php | 23 -- .../Resources/contao/languages/de/default.php | 116 ------ .../Resources/contao/languages/de/explain.php | 102 ----- .../Resources/contao/languages/de/modules.php | 25 -- .../contao/languages/de/tl_content.php | 113 ------ .../contao/languages/de/tl_form_field.php | 28 -- .../contao/languages/de/tl_maintenance.php | 18 - .../contao/languages/de/tl_metamodel.php | 82 ---- .../languages/de/tl_metamodel_attribute.php | 60 --- .../contao/languages/de/tl_metamodel_dca.php | 85 ----- .../languages/de/tl_metamodel_dca_combine.php | 36 -- .../de/tl_metamodel_dca_sortgroup.php | 74 ---- .../languages/de/tl_metamodel_dcasetting.php | 112 ------ .../de/tl_metamodel_dcasetting_condition.php | 70 ---- .../languages/de/tl_metamodel_filter.php | 35 -- .../de/tl_metamodel_filtersetting.php | 112 ------ .../contao/languages/de/tl_metamodel_item.php | 52 --- .../de/tl_metamodel_rendersetting.php | 55 --- .../de/tl_metamodel_rendersettings.php | 75 ---- .../de/tl_metamodel_searchable_pages.php | 50 --- .../contao/languages/de/tl_module.php | 112 ------ .../languages/de/tl_syncCto_database.php | 23 -- .../Resources/contao/languages/el/default.php | 32 -- .../Resources/contao/languages/el/explain.php | 22 -- .../Resources/contao/languages/el/modules.php | 26 -- .../contao/languages/el/tl_content.php | 71 ---- .../contao/languages/el/tl_metamodel.php | 69 ---- .../languages/el/tl_metamodel_attribute.php | 45 --- .../contao/languages/el/tl_metamodel_dca.php | 32 -- .../languages/el/tl_metamodel_dca_combine.php | 33 -- .../el/tl_metamodel_dca_sortgroup.php | 23 -- .../languages/el/tl_metamodel_dcasetting.php | 78 ---- .../el/tl_metamodel_dcasetting_condition.php | 31 -- .../languages/el/tl_metamodel_filter.php | 33 -- .../el/tl_metamodel_filtersetting.php | 71 ---- .../contao/languages/el/tl_metamodel_item.php | 45 --- .../el/tl_metamodel_rendersetting.php | 37 -- .../el/tl_metamodel_rendersettings.php | 64 ---- .../el/tl_metamodel_searchable_pages.php | 21 -- .../contao/languages/el/tl_module.php | 70 ---- .../languages/el/tl_syncCto_database.php | 23 -- .../Resources/contao/languages/en/default.php | 168 +-------- .../Resources/contao/languages/en/explain.php | 0 .../Resources/contao/languages/en/modules.php | 10 +- .../contao/languages/en/tl_content.php | 20 +- .../contao/languages/en/tl_form_field.php | 0 .../contao/languages/en/tl_maintenance.php | 0 .../contao/languages/en/tl_metamodel.php | 93 ----- .../languages/en/tl_metamodel_attribute.php | 73 ---- .../contao/languages/en/tl_metamodel_dca.php | 106 ------ .../languages/en/tl_metamodel_dca_combine.php | 40 -- .../en/tl_metamodel_dca_sortgroup.php | 90 ----- .../languages/en/tl_metamodel_dcasetting.php | 145 -------- .../en/tl_metamodel_dcasetting_condition.php | 110 ------ .../languages/en/tl_metamodel_filter.php | 45 --- .../en/tl_metamodel_filtersetting.php | 157 -------- .../contao/languages/en/tl_metamodel_item.php | 57 --- .../en/tl_metamodel_rendersetting.php | 63 ---- .../en/tl_metamodel_rendersettings.php | 85 ----- .../en/tl_metamodel_searchable_pages.php | 58 --- .../contao/languages/en/tl_module.php | 16 +- .../languages/en/tl_syncCto_database.php | 0 .../Resources/contao/languages/et/default.php | 62 ---- .../Resources/contao/languages/et/explain.php | 39 -- .../Resources/contao/languages/et/modules.php | 19 - .../contao/languages/et/tl_content.php | 47 --- .../contao/languages/et/tl_maintenance.php | 16 - .../contao/languages/et/tl_metamodel.php | 37 -- .../languages/et/tl_metamodel_attribute.php | 32 -- .../contao/languages/et/tl_metamodel_dca.php | 45 --- .../languages/et/tl_metamodel_dca_combine.php | 17 - .../et/tl_metamodel_dca_sortgroup.php | 40 -- .../languages/et/tl_metamodel_dcasetting.php | 61 --- .../et/tl_metamodel_dcasetting_condition.php | 38 -- .../languages/et/tl_metamodel_filter.php | 28 -- .../et/tl_metamodel_filtersetting.php | 55 --- .../contao/languages/et/tl_metamodel_item.php | 30 -- .../et/tl_metamodel_rendersetting.php | 23 -- .../et/tl_metamodel_rendersettings.php | 52 --- .../et/tl_metamodel_searchable_pages.php | 20 - .../contao/languages/et/tl_module.php | 48 --- .../languages/et/tl_syncCto_database.php | 17 - .../Resources/contao/languages/fa/default.php | 27 -- .../contao/languages/fa/tl_content.php | 16 - .../contao/languages/fa/tl_metamodel.php | 16 - .../fa/tl_metamodel_filtersetting.php | 25 -- .../contao/languages/fa/tl_metamodel_item.php | 16 - .../contao/languages/fa/tl_module.php | 16 - .../Resources/contao/languages/fr/default.php | 101 ----- .../Resources/contao/languages/fr/explain.php | 45 --- .../Resources/contao/languages/fr/modules.php | 25 -- .../contao/languages/fr/tl_content.php | 78 ---- .../contao/languages/fr/tl_maintenance.php | 17 - .../contao/languages/fr/tl_metamodel.php | 76 ---- .../languages/fr/tl_metamodel_attribute.php | 45 --- .../contao/languages/fr/tl_metamodel_dca.php | 78 ---- .../languages/fr/tl_metamodel_dca_combine.php | 33 -- .../fr/tl_metamodel_dca_sortgroup.php | 29 -- .../languages/fr/tl_metamodel_dcasetting.php | 83 ----- .../fr/tl_metamodel_dcasetting_condition.php | 32 -- .../languages/fr/tl_metamodel_filter.php | 33 -- .../fr/tl_metamodel_filtersetting.php | 75 ---- .../contao/languages/fr/tl_metamodel_item.php | 46 --- .../fr/tl_metamodel_rendersetting.php | 37 -- .../fr/tl_metamodel_rendersettings.php | 65 ---- .../fr/tl_metamodel_searchable_pages.php | 22 -- .../contao/languages/fr/tl_module.php | 77 ---- .../languages/fr/tl_syncCto_database.php | 22 -- .../Resources/contao/languages/it/default.php | 95 ----- .../Resources/contao/languages/it/explain.php | 45 --- .../Resources/contao/languages/it/modules.php | 25 -- .../contao/languages/it/tl_content.php | 78 ---- .../contao/languages/it/tl_metamodel.php | 70 ---- .../languages/it/tl_metamodel_attribute.php | 45 --- .../contao/languages/it/tl_metamodel_dca.php | 65 ---- .../languages/it/tl_metamodel_dca_combine.php | 33 -- .../it/tl_metamodel_dca_sortgroup.php | 28 -- .../languages/it/tl_metamodel_dcasetting.php | 83 ----- .../it/tl_metamodel_dcasetting_condition.php | 32 -- .../languages/it/tl_metamodel_filter.php | 33 -- .../it/tl_metamodel_filtersetting.php | 77 ---- .../contao/languages/it/tl_metamodel_item.php | 46 --- .../it/tl_metamodel_rendersetting.php | 37 -- .../it/tl_metamodel_rendersettings.php | 65 ---- .../it/tl_metamodel_searchable_pages.php | 22 -- .../contao/languages/it/tl_module.php | 77 ---- .../languages/it/tl_syncCto_database.php | 22 -- .../Resources/contao/languages/rm/default.php | 97 ----- .../Resources/contao/languages/rm/explain.php | 45 --- .../Resources/contao/languages/rm/modules.php | 26 -- .../contao/languages/rm/tl_content.php | 73 ---- .../contao/languages/rm/tl_metamodel.php | 69 ---- .../languages/rm/tl_metamodel_attribute.php | 45 --- .../contao/languages/rm/tl_metamodel_dca.php | 65 ---- .../languages/rm/tl_metamodel_dca_combine.php | 33 -- .../rm/tl_metamodel_dca_sortgroup.php | 28 -- .../languages/rm/tl_metamodel_dcasetting.php | 83 ----- .../rm/tl_metamodel_dcasetting_condition.php | 32 -- .../languages/rm/tl_metamodel_filter.php | 33 -- .../rm/tl_metamodel_filtersetting.php | 75 ---- .../contao/languages/rm/tl_metamodel_item.php | 46 --- .../rm/tl_metamodel_rendersetting.php | 37 -- .../rm/tl_metamodel_rendersettings.php | 65 ---- .../rm/tl_metamodel_searchable_pages.php | 22 -- .../contao/languages/rm/tl_module.php | 72 ---- .../languages/rm/tl_syncCto_database.php | 23 -- .../Resources/contao/languages/ru/default.php | 141 ------- .../Resources/contao/languages/ru/explain.php | 85 ----- .../Resources/contao/languages/ru/modules.php | 26 -- .../contao/languages/ru/tl_content.php | 81 ---- .../contao/languages/ru/tl_maintenance.php | 18 - .../contao/languages/ru/tl_metamodel.php | 80 ---- .../languages/ru/tl_metamodel_attribute.php | 50 --- .../contao/languages/ru/tl_metamodel_dca.php | 83 ----- .../languages/ru/tl_metamodel_dca_combine.php | 34 -- .../ru/tl_metamodel_dca_sortgroup.php | 64 ---- .../languages/ru/tl_metamodel_dcasetting.php | 106 ------ .../ru/tl_metamodel_dcasetting_condition.php | 59 --- .../languages/ru/tl_metamodel_filter.php | 35 -- .../ru/tl_metamodel_filtersetting.php | 93 ----- .../contao/languages/ru/tl_metamodel_item.php | 52 --- .../ru/tl_metamodel_rendersetting.php | 52 --- .../ru/tl_metamodel_rendersettings.php | 73 ---- .../ru/tl_metamodel_searchable_pages.php | 40 -- .../contao/languages/ru/tl_module.php | 80 ---- .../languages/ru/tl_syncCto_database.php | 23 -- .../Resources/contao/languages/sk/default.php | 65 ---- .../Resources/contao/languages/sk/explain.php | 34 -- .../Resources/contao/languages/sk/modules.php | 18 - .../contao/languages/sk/tl_metamodel.php | 16 - .../sk/tl_metamodel_filtersetting.php | 25 -- .../contao/languages/sk/tl_metamodel_item.php | 16 - .../languages/sk/tl_syncCto_database.php | 15 - .../Resources/contao/languages/tr/default.php | 16 - .../contao/languages/tr/tl_content.php | 16 - .../languages/tr/tl_metamodel_dcasetting.php | 16 - .../tr/tl_metamodel_dcasetting_condition.php | 16 - .../tr/tl_metamodel_filtersetting.php | 25 -- .../tr/tl_metamodel_rendersetting.php | 16 - .../tr/tl_metamodel_searchable_pages.php | 16 - .../contao/languages/tr/tl_module.php | 16 - .../Resources/contao/languages/uk/default.php | 32 -- .../contao/languages/uk/tl_metamodel.php | 16 - .../uk/tl_metamodel_filtersetting.php | 25 -- .../contao/languages/uk/tl_metamodel_item.php | 16 - .../templates/be_addallattributes.html5 | 2 +- .../templates/be_detectedproblems.html5 | 2 +- .../templates/metamodel_prerendered.html5 | 17 +- .../templates/metamodel_prerendered.text | 5 +- .../templates/metamodel_unrendered.html5 | 16 +- .../templates/metamodel_unrendered.text | 3 +- .../contao/templates/mm_actionbutton.html5 | 2 +- .../templates/mm_clearall_default.html5 | 4 +- .../contao/templates/mm_pagination.html5 | 2 +- src/CoreBundle/Resources/public/css/style.css | 2 +- .../Resources/public/scss/style.scss | 2 +- .../translations/metamodels_default.en.xlf | 16 + .../translations/metamodels_filter.en.xlf | 13 + .../translations/metamodels_list.en.xlf | 25 ++ .../translations/metamodels_navigation.en.xlf | 53 +++ .../translations/metamodels_support.en.xlf | 62 ++++ .../translations/metamodels_wildcard.en.xlf | 41 ++ .../mm_testselecttags.en.metamodels | 0 .../Resources/translations/modules.en.xlf | 7 + .../Resources/translations/tl_content.en.xlf | 25 ++ .../translations/tl_metamodel.en.xlf | 243 ++++++++++++ .../tl_metamodel_attribute.en.xlf | 192 ++++++++++ .../translations/tl_metamodel_dca.en.xlf | 284 ++++++++++++++ .../tl_metamodel_dca_combine.en.xlf | 73 ++++ .../tl_metamodel_dca_sortgroup.en.xlf | 231 ++++++++++++ .../tl_metamodel_dcasetting.en.xlf | 335 +++++++++++++++++ .../tl_metamodel_dcasetting_condition.en.xlf | 192 ++++++++++ .../translations/tl_metamodel_filter.en.xlf | 128 +++++++ .../tl_metamodel_filtersetting.en.xlf | 339 +++++++++++++++++ .../translations/tl_metamodel_item.en.xlf | 150 ++++++++ .../tl_metamodel_rendersetting.en.xlf | 178 +++++++++ .../tl_metamodel_rendersettings.en.xlf | 225 +++++++++++ .../tl_metamodel_searchable_pages.en.xlf | 140 +++++++ .../Resources/translations/tl_modules.en.xlf | 25 ++ .../Resources/views/Backend/add-all.html.twig | 2 +- .../views/Backend/be_config.html.twig | 15 + .../Translator/MetaModelTranslationLoader.php | 238 +++++++++++- .../MetaModelTranslatorConfigurator.php | 109 ++++++ src/CoreBundle/Translator/Translator.php | 28 +- src/DcGeneral/Data/Driver.php | 6 +- src/DcGeneral/Data/FilterBuilder.php | 3 +- .../Events/MetaModel/DuplicateModel.php | 3 +- src/Dca/Helper.php | 32 +- src/Filter/Rules/SimpleQuery.php | 6 +- src/Filter/Rules/StaticIdList.php | 4 +- src/Filter/Setting/SimpleLookup.php | 26 +- src/FrontendIntegration/FrontendFilter.php | 2 +- src/FrontendIntegration/MetaModelHybrid.php | 23 +- src/Item.php | 36 +- src/ItemList.php | 9 +- src/Render/Setting/Collection.php | 15 +- .../InputScreenInformationBuilder.php | 31 +- tests/Data/FilterBuilderTest.php | 6 +- tests/MetaModelsTest.php | 1 - 329 files changed, 5900 insertions(+), 11158 deletions(-) delete mode 100644 src/CoreBundle/Contao/Hooks/FixupUserGroupModules.php create mode 100644 src/CoreBundle/Controller/Backend/ConfigurationController.php create mode 100644 src/CoreBundle/Controller/Backend/DcGeneralControllerTrait.php create mode 100644 src/CoreBundle/Controller/Backend/MetaModelController.php create mode 100644 src/CoreBundle/DependencyInjection/CompilerPass/PrepareTranslatorPass.php create mode 100755 src/CoreBundle/EventListener/DcGeneral/Table/DeleteOperationButtonListener.php mode change 100644 => 100755 src/CoreBundle/Resources/contao/dca/tl_content.php mode change 100644 => 100755 src/CoreBundle/Resources/contao/dca/tl_module.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/explain.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/modules.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/tl_metamodel_dcasetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/tl_metamodel_dcasetting_condition.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/tl_metamodel_item.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/tl_metamodel_rendersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/tl_metamodel_rendersettings.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/tl_metamodel_searchable_pages.php delete mode 100644 src/CoreBundle/Resources/contao/languages/da/tl_syncCto_database.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/explain.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/modules.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_content.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_form_field.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_maintenance.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_attribute.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_dca.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_dca_combine.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_dca_sortgroup.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_dcasetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_dcasetting_condition.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_filter.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_item.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_rendersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_rendersettings.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_metamodel_searchable_pages.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_module.php delete mode 100644 src/CoreBundle/Resources/contao/languages/de/tl_syncCto_database.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/explain.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/modules.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_content.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_attribute.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_dca.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_dca_combine.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_dca_sortgroup.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_dcasetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_dcasetting_condition.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_filter.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_item.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_rendersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_rendersettings.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_metamodel_searchable_pages.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_module.php delete mode 100644 src/CoreBundle/Resources/contao/languages/el/tl_syncCto_database.php mode change 100644 => 100755 src/CoreBundle/Resources/contao/languages/en/default.php mode change 100644 => 100755 src/CoreBundle/Resources/contao/languages/en/explain.php mode change 100644 => 100755 src/CoreBundle/Resources/contao/languages/en/modules.php mode change 100644 => 100755 src/CoreBundle/Resources/contao/languages/en/tl_content.php mode change 100644 => 100755 src/CoreBundle/Resources/contao/languages/en/tl_form_field.php mode change 100644 => 100755 src/CoreBundle/Resources/contao/languages/en/tl_maintenance.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_combine.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting_condition.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filter.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_item.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersettings.php delete mode 100644 src/CoreBundle/Resources/contao/languages/en/tl_metamodel_searchable_pages.php mode change 100644 => 100755 src/CoreBundle/Resources/contao/languages/en/tl_module.php mode change 100644 => 100755 src/CoreBundle/Resources/contao/languages/en/tl_syncCto_database.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/explain.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/modules.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_content.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_maintenance.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_attribute.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_dca.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_dca_combine.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_dca_sortgroup.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_dcasetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_dcasetting_condition.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_filter.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_item.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_rendersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_rendersettings.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_metamodel_searchable_pages.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_module.php delete mode 100644 src/CoreBundle/Resources/contao/languages/et/tl_syncCto_database.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fa/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fa/tl_content.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fa/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fa/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fa/tl_metamodel_item.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fa/tl_module.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/explain.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/modules.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_content.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_maintenance.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_attribute.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_dca.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_dca_combine.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_dca_sortgroup.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_dcasetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_dcasetting_condition.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_filter.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_item.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_rendersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_rendersettings.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_searchable_pages.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_module.php delete mode 100644 src/CoreBundle/Resources/contao/languages/fr/tl_syncCto_database.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/explain.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/modules.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_content.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_attribute.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_dca.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_dca_combine.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_dca_sortgroup.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_dcasetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_dcasetting_condition.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_filter.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_item.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_rendersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_rendersettings.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_metamodel_searchable_pages.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_module.php delete mode 100644 src/CoreBundle/Resources/contao/languages/it/tl_syncCto_database.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/explain.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/modules.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_content.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_attribute.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_dca.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_dca_combine.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_dca_sortgroup.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_dcasetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_dcasetting_condition.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_filter.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_item.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_rendersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_rendersettings.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_searchable_pages.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_module.php delete mode 100644 src/CoreBundle/Resources/contao/languages/rm/tl_syncCto_database.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/explain.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/modules.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_content.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_maintenance.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_attribute.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_dca.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_dca_combine.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_dca_sortgroup.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_dcasetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_dcasetting_condition.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_filter.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_item.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_rendersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_rendersettings.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_searchable_pages.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_module.php delete mode 100644 src/CoreBundle/Resources/contao/languages/ru/tl_syncCto_database.php delete mode 100644 src/CoreBundle/Resources/contao/languages/sk/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/sk/explain.php delete mode 100644 src/CoreBundle/Resources/contao/languages/sk/modules.php delete mode 100644 src/CoreBundle/Resources/contao/languages/sk/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/sk/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/sk/tl_metamodel_item.php delete mode 100644 src/CoreBundle/Resources/contao/languages/sk/tl_syncCto_database.php delete mode 100644 src/CoreBundle/Resources/contao/languages/tr/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/tr/tl_content.php delete mode 100644 src/CoreBundle/Resources/contao/languages/tr/tl_metamodel_dcasetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/tr/tl_metamodel_dcasetting_condition.php delete mode 100644 src/CoreBundle/Resources/contao/languages/tr/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/tr/tl_metamodel_rendersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/tr/tl_metamodel_searchable_pages.php delete mode 100644 src/CoreBundle/Resources/contao/languages/tr/tl_module.php delete mode 100644 src/CoreBundle/Resources/contao/languages/uk/default.php delete mode 100644 src/CoreBundle/Resources/contao/languages/uk/tl_metamodel.php delete mode 100644 src/CoreBundle/Resources/contao/languages/uk/tl_metamodel_filtersetting.php delete mode 100644 src/CoreBundle/Resources/contao/languages/uk/tl_metamodel_item.php create mode 100644 src/CoreBundle/Resources/translations/metamodels_default.en.xlf create mode 100644 src/CoreBundle/Resources/translations/metamodels_filter.en.xlf create mode 100644 src/CoreBundle/Resources/translations/metamodels_list.en.xlf create mode 100644 src/CoreBundle/Resources/translations/metamodels_navigation.en.xlf create mode 100644 src/CoreBundle/Resources/translations/metamodels_support.en.xlf create mode 100644 src/CoreBundle/Resources/translations/metamodels_wildcard.en.xlf delete mode 100644 src/CoreBundle/Resources/translations/mm_testselecttags.en.metamodels create mode 100644 src/CoreBundle/Resources/translations/modules.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_content.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_attribute.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_dca.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_dca_combine.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_dca_sortgroup.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_dcasetting_condition.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_filter.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_filtersetting.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_item.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_rendersetting.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_rendersettings.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_metamodel_searchable_pages.en.xlf create mode 100644 src/CoreBundle/Resources/translations/tl_modules.en.xlf create mode 100644 src/CoreBundle/Resources/views/Backend/be_config.html.twig create mode 100644 src/CoreBundle/Translator/MetaModelTranslatorConfigurator.php diff --git a/.composer-require-checker.json b/.composer-require-checker.json index 8a45915bd..53cf5c017 100644 --- a/.composer-require-checker.json +++ b/.composer-require-checker.json @@ -7,6 +7,10 @@ "Contao\\ManagerPlugin\\Bundle\\Parser\\ParserInterface", "Contao\\ManagerPlugin\\Routing\\RoutingPluginInterface", "Doctrine\\Bundle\\DoctrineBundle\\DoctrineBundle", + "Knp\\Menu\\FactoryInterface", + "Knp\\Menu\\ItemInterface", + "Symfony\\Bundle\\FrameworkBundle\\Translation\\Translator", + "Symfony\\Contracts\\Cache\\CacheInterface", "tl_user_group" ] } diff --git a/.phpcq.lock b/.phpcq.lock index 4ec1fc353..d79776ed4 100644 --- a/.phpcq.lock +++ b/.phpcq.lock @@ -1 +1 @@ -{"plugins":{"phpunit":{"api-version":"1.0.0","version":"1.0.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpunit/phpunit-1.0.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0"},"tool":{"phpunit":"^6.0 || ^7.0 || ^8.0 || ^9.0"}},"checksum":{"type":"sha-512","value":"c73f15658e3ba62665f09492ec91c3a6a715760bfaa88473a987538439fff442540148e086e46a6aa18ce55a3ea2fbf76caaa581384cb84a38859fcc609ae7e4"},"tools":{"phpunit":{"version":"9.6.18","url":"https://phar.phpunit.de/phpunit-9.6.18.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*","ext-json":"*","ext-libxml":"*","ext-mbstring":"*","ext-xml":"*","ext-xmlwriter":"*"}},"checksum":{"type":"sha-256","value":"fc3729afdbab93cbf9f662de730bcc2f936bd9255bb08c6c53d41b9b0a30ec62"},"signature":"https://phar.phpunit.de/phpunit-9.6.18.phar.asc"}},"composerLock":null},"psalm":{"api-version":"1.0.0","version":"1.2.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/psalm/psalm-1.2.0.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0","ext-dom":"*"},"tool":{"psalm":"^3.0 || ^4.0 || ^5.0"}},"checksum":{"type":"sha-512","value":"4a550c9226d7bca582d7c10bd87cce01190c96398936b1613421640c83df62ed1c6e0d44c1b39635414ea8cf4a892a6458d27590793238add24e7cb5547e6ffd"},"tools":{"psalm":{"version":"5.23.1","url":"https://github.com/vimeo/psalm/releases/download/5.23.1/psalm.phar","requirements":{"php":{"php":"^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0","ext-SimpleXML":"*","ext-ctype":"*","ext-dom":"*","ext-json":"*","ext-libxml":"*","ext-mbstring":"*","ext-tokenizer":"*"}},"checksum":null,"signature":"https://github.com/vimeo/psalm/releases/download/5.23.1/psalm.phar.asc"}},"composerLock":null},"composer-require-checker":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/composer-require-checker/composer-require-checker-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0"},"tool":{"composer-require-checker":"^3.8 || ^4.0"}},"checksum":{"type":"sha-512","value":"d5415bddfe024c5749d894034583882aee4e5c3e1087815d9fdd81cb5e71630f631a0e35de0ff84b97fbbf738c16ece5f83bd8c00695913eb846aa6f04577dc2"},"tools":{"composer-require-checker":{"version":"4.7.1","url":"https://github.com/maglnet/ComposerRequireChecker/releases/download/4.7.1/composer-require-checker.phar","requirements":{"php":{"php":"~8.1.0 || ~8.2.0 || ~8.3.0","ext-phar":"*"}},"checksum":null,"signature":"https://github.com/maglnet/ComposerRequireChecker/releases/download/4.7.1/composer-require-checker.phar.asc"}},"composerLock":null},"phpmd":{"api-version":"1.0.0","version":"1.0.2.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpmd/phpmd-1.0.2.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpmd":"^2.6.1"}},"checksum":{"type":"sha-512","value":"f22280a6dec8dbdd2ec1d83b294f23237fe32c34f4a298e52038e0a7a0074d541635b2b488b1a6098a42d8418a6cd8eb804406ea82b91e362be2b5d11a0915b0"},"tools":{"phpmd":{"version":"2.15.0","url":"https://github.com/phpmd/phpmd/releases/download/2.15.0/phpmd.phar","requirements":{"php":{"php":">=5.3.9","ext-xml":"*"}},"checksum":null,"signature":"https://github.com/phpmd/phpmd/releases/download/2.15.0/phpmd.phar.asc"}},"composerLock":null},"phpcpd":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpcpd/phpcpd-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpcpd":"^6.0"}},"checksum":{"type":"sha-512","value":"1189ce0bf3fade4cb4241f1d96f915ef8fc7651f4450dc79fdf464ee3d6be3009316f0d423ce2d4af9d76ad50807b7fdf4d77bfa6d9ee2c91d6eda32ea214433"},"tools":{"phpcpd":{"version":"6.0.3","url":"https://phar.phpunit.de/phpcpd-6.0.3.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*"}},"checksum":{"type":"sha-256","value":"2cbaea7cfda1bb4299d863eb075e977c3f49055dd16d88529fae5150d48a84cb"},"signature":"https://phar.phpunit.de/phpcpd-6.0.3.phar.asc"}},"composerLock":null},"phploc":{"api-version":"1.0.0","version":"1.0.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phploc/phploc-1.0.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*","ext-json":"*"},"tool":{"phploc":"^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0"}},"checksum":{"type":"sha-512","value":"f67b02d494796adf553cb3dd13ec06c1cb8e53c799954061749424251379541637538199afb3afa3c7a01cabd1cb6f1c53eb621f015dff9644c6c7cbf10c56d1"},"tools":{"phploc":{"version":"7.0.2","url":"https://phar.phpunit.de/phploc-7.0.2.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*","ext-json":"*"}},"checksum":{"type":"sha-256","value":"3d59778ec86faf25fd00e3a329b2f9ad4a3c751ca91601ea7dab70f887b0bf46"},"signature":"https://phar.phpunit.de/phploc-7.0.2.phar.asc"}},"composerLock":null},"phpcs":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpcs/phpcs-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpcs":"^3.0 || ^2.0","phpcbf":"^3.0 || ^2.0"}},"checksum":{"type":"sha-512","value":"2737022369da1318cc4e0ea194e8a81019f7b079080d869aab878b7486052fdbe68fee3f28131f35573226def1aabd4bd005e038ee7b767c137b1107c1492a83"},"tools":{"phpcs":{"version":"3.9.1","url":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.1/phpcs.phar","requirements":{"php":{"php":">=5.4.0","ext-simplexml":"*","ext-tokenizer":"*","ext-xmlwriter":"*"}},"checksum":null,"signature":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.1/phpcs.phar.asc"},"phpcbf":{"version":"3.9.1","url":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.1/phpcbf.phar","requirements":{"php":{"php":">=5.4.0","ext-simplexml":"*","ext-tokenizer":"*","ext-xmlwriter":"*"}},"checksum":null,"signature":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.1/phpcbf.phar.asc"}},"composerLock":null},"composer-normalize":{"api-version":"1.0.0","version":"1.1.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/composer-normalize/composer-normalize-1.1.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-json":"*"},"tool":{"composer-normalize":"^2.1"}},"checksum":{"type":"sha-512","value":"d59d3557cb20630734878a9115df5dd32d5aff815e5b15be36f6fb5d6e9d83dd36efd84215ab6529edcc924f600946f739a0d9e67723deff95c88346ab502498"},"tools":{"composer-normalize":{"version":"2.42.0","url":"https://github.com/ergebnis/composer-normalize/releases/download/2.42.0/composer-normalize.phar","requirements":{"php":{"php":"~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0","ext-json":"*"}},"checksum":null,"signature":"https://github.com/ergebnis/composer-normalize/releases/download/2.42.0/composer-normalize.phar.asc"}},"composerLock":null}},"tools":[]} \ No newline at end of file +{"plugins":{"phpunit":{"api-version":"1.0.0","version":"1.0.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpunit/phpunit-1.0.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0"},"tool":{"phpunit":"^6.0 || ^7.0 || ^8.0 || ^9.0"}},"checksum":{"type":"sha-512","value":"c73f15658e3ba62665f09492ec91c3a6a715760bfaa88473a987538439fff442540148e086e46a6aa18ce55a3ea2fbf76caaa581384cb84a38859fcc609ae7e4"},"tools":{"phpunit":{"version":"9.6.19","url":"https://phar.phpunit.de/phpunit-9.6.19.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*","ext-json":"*","ext-libxml":"*","ext-mbstring":"*","ext-xml":"*","ext-xmlwriter":"*"}},"checksum":{"type":"sha-256","value":"f30c21743f4fbea14ad8ab8f47673f9067117262dafa147fcb182e75fbc1c249"},"signature":"https://phar.phpunit.de/phpunit-9.6.19.phar.asc"}},"composerLock":null},"psalm":{"api-version":"1.0.0","version":"1.2.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/psalm/psalm-1.2.0.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0","ext-dom":"*"},"tool":{"psalm":"^3.0 || ^4.0 || ^5.0"}},"checksum":{"type":"sha-512","value":"4a550c9226d7bca582d7c10bd87cce01190c96398936b1613421640c83df62ed1c6e0d44c1b39635414ea8cf4a892a6458d27590793238add24e7cb5547e6ffd"},"tools":{"psalm":{"version":"5.24.0","url":"https://github.com/vimeo/psalm/releases/download/5.24.0/psalm.phar","requirements":{"php":{"php":"^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0","ext-SimpleXML":"*","ext-ctype":"*","ext-dom":"*","ext-json":"*","ext-libxml":"*","ext-mbstring":"*","ext-tokenizer":"*"}},"checksum":null,"signature":"https://github.com/vimeo/psalm/releases/download/5.24.0/psalm.phar.asc"}},"composerLock":null},"composer-require-checker":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/composer-require-checker/composer-require-checker-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0"},"tool":{"composer-require-checker":"^3.8 || ^4.0"}},"checksum":{"type":"sha-512","value":"d5415bddfe024c5749d894034583882aee4e5c3e1087815d9fdd81cb5e71630f631a0e35de0ff84b97fbbf738c16ece5f83bd8c00695913eb846aa6f04577dc2"},"tools":{"composer-require-checker":{"version":"4.7.1","url":"https://github.com/maglnet/ComposerRequireChecker/releases/download/4.7.1/composer-require-checker.phar","requirements":{"php":{"php":"~8.1.0 || ~8.2.0 || ~8.3.0","ext-phar":"*"}},"checksum":null,"signature":"https://github.com/maglnet/ComposerRequireChecker/releases/download/4.7.1/composer-require-checker.phar.asc"}},"composerLock":null},"phpmd":{"api-version":"1.0.0","version":"1.0.2.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpmd/phpmd-1.0.2.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpmd":"^2.6.1"}},"checksum":{"type":"sha-512","value":"f22280a6dec8dbdd2ec1d83b294f23237fe32c34f4a298e52038e0a7a0074d541635b2b488b1a6098a42d8418a6cd8eb804406ea82b91e362be2b5d11a0915b0"},"tools":{"phpmd":{"version":"2.15.0","url":"https://github.com/phpmd/phpmd/releases/download/2.15.0/phpmd.phar","requirements":{"php":{"php":">=5.3.9","ext-xml":"*"}},"checksum":null,"signature":"https://github.com/phpmd/phpmd/releases/download/2.15.0/phpmd.phar.asc"}},"composerLock":null},"phpcpd":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpcpd/phpcpd-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpcpd":"^6.0"}},"checksum":{"type":"sha-512","value":"1189ce0bf3fade4cb4241f1d96f915ef8fc7651f4450dc79fdf464ee3d6be3009316f0d423ce2d4af9d76ad50807b7fdf4d77bfa6d9ee2c91d6eda32ea214433"},"tools":{"phpcpd":{"version":"6.0.3","url":"https://phar.phpunit.de/phpcpd-6.0.3.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*"}},"checksum":{"type":"sha-256","value":"2cbaea7cfda1bb4299d863eb075e977c3f49055dd16d88529fae5150d48a84cb"},"signature":"https://phar.phpunit.de/phpcpd-6.0.3.phar.asc"}},"composerLock":null},"phploc":{"api-version":"1.0.0","version":"1.0.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phploc/phploc-1.0.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*","ext-json":"*"},"tool":{"phploc":"^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0"}},"checksum":{"type":"sha-512","value":"f67b02d494796adf553cb3dd13ec06c1cb8e53c799954061749424251379541637538199afb3afa3c7a01cabd1cb6f1c53eb621f015dff9644c6c7cbf10c56d1"},"tools":{"phploc":{"version":"7.0.2","url":"https://phar.phpunit.de/phploc-7.0.2.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*","ext-json":"*"}},"checksum":{"type":"sha-256","value":"3d59778ec86faf25fd00e3a329b2f9ad4a3c751ca91601ea7dab70f887b0bf46"},"signature":"https://phar.phpunit.de/phploc-7.0.2.phar.asc"}},"composerLock":null},"phpcs":{"api-version":"1.0.0","version":"1.2.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpcs/phpcs-1.2.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpcs":"^3.0 || ^2.0","phpcbf":"^3.0 || ^2.0"}},"checksum":{"type":"sha-512","value":"b6ed00306e76068a6af5e3b1dec837724f9e1900ef1049ce88e7ce195b0583524ca33a73613fba13244307a7ca853b6ddaa14ded69f651c3f184ac130bd1aaad"},"tools":{"phpcs":{"version":"3.9.2","url":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.2/phpcs.phar","requirements":{"php":{"php":">=5.4.0","ext-simplexml":"*","ext-tokenizer":"*","ext-xmlwriter":"*"}},"checksum":null,"signature":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.2/phpcs.phar.asc"},"phpcbf":{"version":"3.9.2","url":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.2/phpcbf.phar","requirements":{"php":{"php":">=5.4.0","ext-simplexml":"*","ext-tokenizer":"*","ext-xmlwriter":"*"}},"checksum":null,"signature":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.9.2/phpcbf.phar.asc"}},"composerLock":null},"composer-normalize":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/composer-normalize/composer-normalize-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-json":"*"},"tool":{"composer-normalize":"^2.1"}},"checksum":{"type":"sha-512","value":"d9abda440b85d501c58abf9c81bf76f417594b397129215ffa8b777e9bb5e5eda37d7661d661db3c8d11c24f20345bc6fbe56f013b3b9435d459d2b94f086e0f"},"tools":{"composer-normalize":{"version":"2.42.0","url":"https://github.com/ergebnis/composer-normalize/releases/download/2.42.0/composer-normalize.phar","requirements":{"php":{"php":"~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0","ext-json":"*"}},"checksum":null,"signature":"https://github.com/ergebnis/composer-normalize/releases/download/2.42.0/composer-normalize.phar.asc"}},"composerLock":null}},"tools":[]} \ No newline at end of file diff --git a/composer.json b/composer.json index 34642032b..5bfbeab09 100644 --- a/composer.json +++ b/composer.json @@ -33,16 +33,16 @@ "php": "^8.1", "ext-dom": "*", "contao-community-alliance/dc-general": "^2.3", - "contao-community-alliance/events-contao-bindings": "^4.13", + "contao-community-alliance/events-contao-bindings": "^4.13.1", "contao-community-alliance/meta-palettes": "^2.0.10", - "contao-community-alliance/translator": "^2.3", + "contao-community-alliance/translator": "^2.4.2", "contao-community-alliance/url-builder": "^1.3.3", "contao/core-bundle": "^4.13.5 <5.0", "discordier/justtextwidgets": "^1.3", "doctrine/cache": "^2.1", "doctrine/dbal": "^3.6.0", "doctrine/orm": "^2.16.0", - "menatwork/contao-multicolumnwizard-bundle": "^3.5.7", + "menatwork/contao-multicolumnwizard-bundle": "^3.6.7", "psr/container": "^1.1.2", "psr/log": "^2.0.0", "symfony/asset": "^5.4", @@ -60,6 +60,7 @@ "symfony/routing": "^5.4", "symfony/security-core": "^5.4", "symfony/service-contracts": "^2.5.2", + "symfony/translation": "^5.4", "symfony/translation-contracts": "^2.5.2", "terminal42/service-annotation-bundle": "^1.0", "twig/twig": "^3.7.0" @@ -90,7 +91,8 @@ }, "extra": { "branch-alias": { - "dev-feature/2.3.0": "2.3.x-dev" + "dev-feature/2.3.0": "2.3.x-dev", + "dev-feature/translation_loader": "2.3.x-trans-dev" }, "contao": { "runonce": [ diff --git a/psalm.xml b/psalm.xml index 39a76c1f4..6878801dc 100644 --- a/psalm.xml +++ b/psalm.xml @@ -12,6 +12,9 @@ + + + diff --git a/src/Attribute/Base.php b/src/Attribute/Base.php index 6c6c28c43..681b40da5 100644 --- a/src/Attribute/Base.php +++ b/src/Attribute/Base.php @@ -40,6 +40,8 @@ * * @SuppressWarnings(PHPMD.TooManyPublicMethods) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ abstract class Base implements IAttribute { @@ -192,7 +194,8 @@ protected function getLangValue($arrValues, $strLangCode = null): ?string ); } - if (\array_key_exists($strLangCode, $arrValues)) { + // If empty, use main-language. + if (\array_key_exists($strLangCode, $arrValues) && '' !== $arrValues[$strLangCode]) { return $arrValues[$strLangCode]; } diff --git a/src/Attribute/BaseSimple.php b/src/Attribute/BaseSimple.php index d2a4f3218..9d3666c92 100644 --- a/src/Attribute/BaseSimple.php +++ b/src/Attribute/BaseSimple.php @@ -32,6 +32,11 @@ use MetaModels\Helper\TableManipulator; use MetaModels\IMetaModel; +use function array_map; +use function is_array; +use function serialize; +use function str_replace; + /** * Reference implementation for Simple attributes. * Simple fields are fields that only consist of one column in the metamodel table and therefore do not need @@ -117,7 +122,7 @@ public function __construct( * @param string $strMetaName Name of the meta information that shall be updated. * @param mixed $varNewValue The new value for this meta information. * - * @return \MetaModels\Attribute\IAttribute The instance of this attribute, to support chaining. + * @return IAttribute The instance of this attribute, to support chaining. * * @throws Exception * @@ -163,7 +168,7 @@ public function setDataFor($arrValues) ->update($strTable, 't') ->where('t.id=:id') ->set('t.' . $strColName, ':' . $strColName) - ->setParameter($strColName, \is_array($varData) ? \serialize($varData) : $varData) + ->setParameter($strColName, is_array($varData) ? serialize($varData) : $varData) ->setParameter('id', $intId) ->executeQuery(); } @@ -202,7 +207,7 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) $arrResult = []; while ($objRow = $statement->fetchAssociative()) { - if (\is_array($arrCount)) { + if (is_array($arrCount)) { $arrCount[$objRow[$strCol]] = $objRow['mm_count']; } @@ -222,14 +227,17 @@ public function getFilterOptions($idList, $usedOnly, &$arrCount = null) public function sortIds($idList, $strDirection) { // Base implementation, do a simple sorting on given column. - return $this->connection->createQueryBuilder() + $statement = $this->connection + ->createQueryBuilder() ->select('t.id') ->from($this->getMetaModel()->getTableName(), 't') ->where('t.id IN (:ids)') ->setParameter('ids', $idList, ArrayParameterType::STRING) ->orderBy('t.' . $this->getColName(), $strDirection) - ->executeQuery() - ->fetchFirstColumn(); + ->executeQuery(); + + // Return value list as list, parent function wants a list so we make a cast. + return array_map(static fn (mixed $value) => (string) $value, $statement->fetchFirstColumn()); } /** @@ -247,17 +255,18 @@ public function sortIds($idList, $strDirection) public function searchFor($strPattern) { // Base implementation, do a simple search on given column. - $strPattern = \str_replace(['*', '?'], ['%', '_'], $strPattern); + $strPattern = str_replace(['*', '?'], ['%', '_'], $strPattern); - $result = $this->connection->createQueryBuilder() + $statement = $this->connection + ->createQueryBuilder() ->select('t.id') ->from($this->getMetaModel()->getTableName(), 't') ->where('t.' . $this->getColName() . ' LIKE :pattern') ->setParameter('pattern', $strPattern) - ->executeQuery() - ->fetchFirstColumn(); + ->executeQuery(); - return \array_map(static fn (mixed $value) => (string) $value, $result); + // Return value list as list, parent function wants a list so we make a cast. + return array_map(static fn (mixed $value) => (string) $value, $statement->fetchFirstColumn()); } /** diff --git a/src/Attribute/TranslatedReference.php b/src/Attribute/TranslatedReference.php index 3892e00db..900b999e1 100644 --- a/src/Attribute/TranslatedReference.php +++ b/src/Attribute/TranslatedReference.php @@ -207,10 +207,10 @@ public function getDataFor($arrIds) $arrReturn = $this->getTranslatedDataFor($arrIds, $strActiveLanguage); // Second round, fetch fallback languages if not all items could be resolved. - if ((\count($arrReturn) < \count($arrIds)) && ($strActiveLanguage !== $strFallbackLanguage)) { + if (($strActiveLanguage !== $strFallbackLanguage) && (\count($arrReturn) < \count($arrIds))) { $arrFallbackIds = []; foreach ($arrIds as $intId) { - if (empty($arrReturn[$intId])) { + if (!\array_key_exists($intId, $arrReturn)) { $arrFallbackIds[] = $intId; } } @@ -223,6 +223,7 @@ public function getDataFor($arrIds) } } } + return $arrReturn; } @@ -301,6 +302,7 @@ public function searchForInLanguages($strPattern, $arrLanguages = []) $statement = $queryBuilder->executeQuery(); + // Return value list as list, parent function wants a list so we make a cast. return \array_map(static fn (mixed $value) => (string) $value, $statement->fetchFirstColumn()); } @@ -309,9 +311,9 @@ public function searchForInLanguages($strPattern, $arrLanguages = []) */ public function sortIds($idList, $strDirection) { - $builder = $this->connection->createQueryBuilder(); - $expr = $builder->expr(); - $builder + $queryBuilder = $this->connection->createQueryBuilder(); + $expr = $queryBuilder->expr(); + $queryBuilder ->select('IF(t2.item_id IS NOT NULL, t2.item_id, t1.item_id)') ->from($this->getValueTable(), 't1') ->leftJoin( @@ -332,7 +334,10 @@ public function sortIds($idList, $strDirection) ->setParameter('att_id', $this->get('id')) ->setParameter('id_list', \array_unique($idList), ArrayParameterType::STRING); - return $builder->executeQuery()->fetchFirstColumn(); + $statement = $queryBuilder->executeQuery(); + + // Return value list as list, parent function wants a list so we make a cast. + return \array_map(static fn(mixed $value) => (string) $value, $statement->fetchFirstColumn()); } /** diff --git a/src/BackendIntegration/Module.php b/src/BackendIntegration/Module.php index 662466eed..8104802a3 100644 --- a/src/BackendIntegration/Module.php +++ b/src/BackendIntegration/Module.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Stefan Heimes * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -31,7 +31,9 @@ /** * Implementation of the MetaModel Backend Module that allowing access to MetaModel configuration etc. Everything below - * http://..../contao?do=metamodels&.... ends up here. + * https://..../contao/metamodels?.... ends up here. + * + * @deprecated Not in use anymore since 2.3. */ class Module { diff --git a/src/BackendIntegration/TemplateList.php b/src/BackendIntegration/TemplateList.php index a5de5d86b..4484f6e38 100644 --- a/src/BackendIntegration/TemplateList.php +++ b/src/BackendIntegration/TemplateList.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2020 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2020 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -23,6 +23,14 @@ use Doctrine\DBAL\Connection; use Symfony\Component\Finder\Finder; +use Symfony\Component\Finder\SplFileInfo; +use Symfony\Contracts\Translation\TranslatorInterface; + +use function array_replace_recursive; +use function array_unique; +use function implode; +use function is_dir; +use function ksort; /** * Handy helper class to retrieve a list of templates. @@ -34,14 +42,14 @@ class TemplateList * * @var Connection */ - private $database; + private Connection $database; /** * The resource directories. * * @var string[] */ - private $resourceDirs; + private array $resourceDirs; /** * The project root directory. @@ -50,18 +58,27 @@ class TemplateList */ private $rootDir; + /** + * The translator. + * + * @var TranslatorInterface + */ + private TranslatorInterface $translator; + /** * Create a new instance. * - * @param Connection $database The database connection. - * @param string[] $resourceDirs The resource directories. - * @param string $rootDir The root directory. + * @param Connection $database The database connection. + * @param string[] $resourceDirs The resource directories. + * @param string $rootDir The root directory. + * @param TranslatorInterface $translator The translator. */ - public function __construct(Connection $database, $resourceDirs, $rootDir) + public function __construct(Connection $database, $resourceDirs, $rootDir, TranslatorInterface $translator) { $this->database = $database; $this->resourceDirs = $resourceDirs; $this->rootDir = $rootDir; + $this->translator = $translator; } /** @@ -82,12 +99,15 @@ public function getTemplatesForBase($templateBaseName) $this->fetchTemplatesFromResourceDirectories($templateBaseName) ); - $templateList = array(); + $templateList = []; foreach ($allTemplates as $template => $themeList) { - $templateList[$template] = sprintf( - $GLOBALS['TL_LANG']['MSC']['template_in_theme'], - $template, - implode(', ', $themeList) + $templateList[$template] = $this->translator->trans( + 'template_in_theme', + [ + '%template%' => $template, + '%themes%' => implode(', ', $themeList) + ], + 'metamodels_default' ); } @@ -106,7 +126,7 @@ public function getTemplatesForBase($templateBaseName) */ private function getNoThemeMessage() { - return $GLOBALS['TL_LANG']['MSC']['no_theme']; + return $this->translator->trans('no_theme', [], 'metamodels_default'); } /** @@ -121,7 +141,8 @@ private function fetchRootTemplates($templateBaseName) return $this->getTemplatesForBaseFrom( $templateBaseName, $this->rootDir . '/templates', - $this->getNoThemeMessage() + $this->getNoThemeMessage(), + true ); } @@ -147,7 +168,7 @@ private function fetchTemplatesFromThemes($templateBaseName) foreach ($themes as $theme) { $templateDir = $theme['templates']; $themeName = $theme['name']; - if ($templateDir != '') { + if ($templateDir !== '') { $allTemplates = array_replace_recursive( $allTemplates, $this->getTemplatesForBaseFrom( @@ -188,15 +209,13 @@ private function fetchTemplatesFromResourceDirectories($templateBaseName) * Fetch a list of matching templates of the current base within the given folder and the passed theme name. * * @param string $base The base for the templates to be retrieved. - * * @param string $folder The folder to search in. - * * @param string $themeName The name of the theme for the given folder (will get used in the returned description * text). * * @return array */ - private function getTemplatesForBaseFrom($base, $folder, $themeName) + private function getTemplatesForBaseFrom($base, $folder, $themeName, bool $onlyOneLevel = false) { if (!is_dir($folder)) { return []; @@ -204,10 +223,13 @@ private function getTemplatesForBaseFrom($base, $folder, $themeName) $themeName = trim($themeName); $foundTemplates = Finder::create()->in($folder)->name($base . '*'); + if ($onlyOneLevel) { + $foundTemplates->depth('<1'); + } $templates = []; foreach ($foundTemplates as $template) { - /** @var \Symfony\Component\Finder\SplFileInfo $template */ + /** @var SplFileInfo $template */ $templates[$template->getBasename('.' . $template->getExtension())] = [$themeName => $themeName]; } diff --git a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php index dfb2bb455..0ec480529 100644 --- a/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php +++ b/src/CoreBundle/Contao/Hooks/AbstractContentElementAndModuleCallback.php @@ -35,6 +35,7 @@ use MetaModels\IFactory; use RuntimeException; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Contracts\Translation\TranslatorInterface; use function asort; use function base64_decode; @@ -107,6 +108,8 @@ abstract class AbstractContentElementAndModuleCallback */ private RequestStack $requestStack; + private TranslatorInterface $translator; + /** * Create a new instance. * @@ -117,6 +120,7 @@ abstract class AbstractContentElementAndModuleCallback * @param Connection $connection The database connection. * @param TemplateList $templateList The template list loader. * @param RequestStack $requestStack The request stack. + * @param TranslatorInterface $translator The translator. */ public function __construct( IconBuilder $iconBuilder, @@ -125,7 +129,8 @@ public function __construct( FilterSettingFactory $filterFactory, Connection $connection, TemplateList $templateList, - RequestStack $requestStack + RequestStack $requestStack, + TranslatorInterface $translator, ) { $this->iconBuilder = $iconBuilder; $this->urlBuilderFactory = $urlBuilderFactory; @@ -134,6 +139,7 @@ public function __construct( $this->templateList = $templateList; $this->factory = $factory; $this->requestStack = $requestStack; + $this->translator = $translator; } /** @@ -152,14 +158,17 @@ public function editMetaModelButton(DC_Table $dataContainer) return ''; } - $url = $this->urlBuilderFactory->create('contao/main.php?do=metamodels&act=edit') + $url = $this->urlBuilderFactory->create('contao/metamodels?act=edit') ->setQueryParameter('id', ModelId::fromValues('tl_metamodel', $dataContainer->value)->getSerialized()); return $this->renderEditButton( - $GLOBALS['TL_LANG'][static::$tableName]['editmetamodel'][0], - sprintf( - StringUtil::specialchars($GLOBALS['TL_LANG'][static::$tableName]['editmetamodel'][1]), - $dataContainer->value + $this->translator->trans('editmetamodel.label', [], static::$tableName), + StringUtil::specialchars( + $this->translator->trans( + 'editmetamodel.description', + ['%id%' => $dataContainer->value], + static::$tableName + ) ), $url ); @@ -181,17 +190,20 @@ public function editFilterSettingButton(DC_Table $dataContainer) return ''; } - $url = $this->urlBuilderFactory->create('contao/main.php?do=metamodels&table=tl_metamodel_filtersetting') + $url = $this->urlBuilderFactory->create('contao/metamodels?table=tl_metamodel_filtersetting') ->setQueryParameter( 'pid', ModelId::fromValues('tl_metamodel_filter', $dataContainer->value)->getSerialized() ); return $this->renderEditButton( - $GLOBALS['TL_LANG'][static::$tableName]['editfiltersetting'][0], - sprintf( - StringUtil::specialchars($GLOBALS['TL_LANG'][static::$tableName]['editfiltersetting'][1]), - $dataContainer->value + $this->translator->trans('editfiltersetting.label', [], static::$tableName), + StringUtil::specialchars( + $this->translator->trans( + 'editfiltersetting.description', + ['%id%' => $dataContainer->value], + static::$tableName + ) ), $url ); @@ -213,17 +225,20 @@ public function editRenderSettingButton(DC_Table $dataContainer) return ''; } - $url = $this->urlBuilderFactory->create('contao/main.php?do=metamodels&table=tl_metamodel_rendersetting') + $url = $this->urlBuilderFactory->create('contao/metamodels?table=tl_metamodel_rendersetting') ->setQueryParameter( 'pid', ModelId::fromValues('tl_metamodel_rendersettings', $dataContainer->value)->getSerialized() ); return $this->renderEditButton( - $GLOBALS['TL_LANG'][static::$tableName]['editrendersetting'][0], - sprintf( - StringUtil::specialchars($GLOBALS['TL_LANG'][static::$tableName]['editrendersetting'][1]), - $dataContainer->value + $this->translator->trans('editrendersetting.label', [], static::$tableName), + StringUtil::specialchars( + $this->translator->trans( + 'editrendersetting.description', + ['%id%' => $dataContainer->value], + static::$tableName + ), ), $url ); @@ -242,9 +257,9 @@ public function editRenderSettingButton(DC_Table $dataContainer) public function getAttributeNames(DC_Table $objDc) { $attributeNames = [ - 'sorting' => $GLOBALS['TL_LANG']['MSC']['metamodels_sorting'], - 'random' => $GLOBALS['TL_LANG']['MSC']['random'], - 'id' => $GLOBALS['TL_LANG']['MSC']['id'][0] + 'sorting' => $this->translator->trans('metamodels_sorting', [], 'metamodels_list'), + 'random' => $this->translator->trans('random', [], 'metamodels_list'), + 'id' => $this->translator->trans('id', [], 'metamodels_list') ]; assert(null !== $objDc->activeRecord); diff --git a/src/CoreBundle/Contao/Hooks/FixupUserGroupModules.php b/src/CoreBundle/Contao/Hooks/FixupUserGroupModules.php deleted file mode 100644 index b093c5dd2..000000000 --- a/src/CoreBundle/Contao/Hooks/FixupUserGroupModules.php +++ /dev/null @@ -1,156 +0,0 @@ - - * @author Ben - * @author Ingolf Steinhardt - * @copyright 2012-2024 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\DataContainer; -use MetaModels\ViewCombination\InputScreenInformationBuilder; -use MetaModels\ViewCombination\ViewCombinationBuilder; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; - -/** - * This is called as a HOOK from tl_user_group. - */ -class FixupUserGroupModules -{ - /** - * The view combination builder. - * - * @var ViewCombinationBuilder - */ - private ViewCombinationBuilder $combinationBuilder; - - /** - * The input screen information builder. - * - * @var InputScreenInformationBuilder - */ - private InputScreenInformationBuilder $inputScreens; - - /** - * The request stack. - * - * @var RequestStack - */ - protected $requestStack; - - /** - * Create a new instance. - * - * @param ViewCombinationBuilder $combinationBuilder The view combination builder. - * @param InputScreenInformationBuilder $inputScreens The input screen information builder. - * @param RequestStack $requestStack The request stack. - */ - public function __construct( - ViewCombinationBuilder $combinationBuilder, - InputScreenInformationBuilder $inputScreens, - RequestStack $requestStack - ) { - $this->combinationBuilder = $combinationBuilder; - $this->inputScreens = $inputScreens; - $this->requestStack = $requestStack; - } - - /** - * Fix up the modules in the backend. - * - * @param DataContainer $dataContainer The current data container. - * - * @return array - * - * @throws \RuntimeException When the "parenting" class can not be found. - */ - public function fixupModules(DataContainer $dataContainer) - { - if (!\class_exists('tl_user_group', false)) { - throw new \RuntimeException('data container is not loaded!'); - } - - $original = new \tl_user_group(); - /** @var array> $modules */ - $modules = $original->getModules($dataContainer); - - // 1. remove all MetaModels - foreach (\array_keys($modules) as $group) { - foreach ($modules[$group] as $key => $module) { - if (\str_starts_with($module, 'metamodel_')) { - unset($modules[$group][$key]); - } - } - // Otherwise we end up with an associative array. - $modules[$group] = \array_values($modules[$group]); - } - if (!\is_array($modules['metamodels'] ?? null)) { - $modules['metamodels'] = []; - } - - // 2. Add our "custom" modules and remove the main module. - $modules['metamodels'][] = 'support_metamodels'; - if (false !== ($index = \array_search('metamodels', $modules['metamodels'], true))) { - unset($modules['metamodels'][$index]); - $modules['metamodels'] = \array_values($modules['metamodels']); - } - - // 3. Add back all MetaModels for the current group. - assert(null !== $dataContainer->activeRecord); - $combinations = $this->combinationBuilder->getCombinationsForUser([$dataContainer->activeRecord->id], 'be'); - - $screenIds = \array_map(static function (array $combination): mixed { - return $combination['dca_id']; - }, $combinations['byName'] ?? []); - - $screens = $this->inputScreens->fetchInputScreens($screenIds); - $currentRequest = $this->requestStack->getCurrentRequest(); - assert($currentRequest instanceof Request); - $locale = $currentRequest->getLocale(); - foreach ($screens as $metaModel => $screen) { - if ('standalone' === $screen['meta']['rendertype']) { - $modules[$screen['meta']['backendsection']][] = 'metamodel_' . $metaModel; - $this->buildLanguageString('metamodel_' . $metaModel, $screen, $locale); - } - } - - return $modules; - } - - /** - * Build the language string for the passed backend module. - * - * @param string $name The module name. - * @param array $screen The input screen information. - * @param string $locale The locale. - * - * @return void - * - * @SuppressWarnings(PHPMD.Superglobals) - * @SuppressWarnings(PHPMD.CamelCaseVariableName) - */ - private function buildLanguageString(string $name, array $screen, string $locale): void - { - if (isset($screen['label'][$locale])) { - $GLOBALS['TL_LANG']['MOD'][$name] = $screen['label'][$locale]; - return; - } - - $GLOBALS['TL_LANG']['MOD'][$name] = $screen['label']['']; - } -} diff --git a/src/CoreBundle/Contao/InsertTag/ResolveLanguageTag.php b/src/CoreBundle/Contao/InsertTag/ResolveLanguageTag.php index 77f9de229..d1f6e7377 100644 --- a/src/CoreBundle/Contao/InsertTag/ResolveLanguageTag.php +++ b/src/CoreBundle/Contao/InsertTag/ResolveLanguageTag.php @@ -83,12 +83,12 @@ public function resolve(string $queryString): string $flags = \explode('|', $strTag); $tag = \array_shift($flags); - $elements = \explode('::', $tag); + $elements = \array_merge(\explode('::', $tag), ['']); $arrCache[$strTag] = ''; if ( - !empty($elements[1]) && + '' !== $elements[1] && $this->languageMatches($elements[1]) === (\strtolower($elements[0]) === 'ifnlng') ) { for (; $_rit<$_cnt; $_rit+=2) { diff --git a/src/CoreBundle/Controller/Backend/AbstractAddAllController.php b/src/CoreBundle/Controller/Backend/AbstractAddAllController.php index 6db831cb1..1d5981599 100644 --- a/src/CoreBundle/Controller/Backend/AbstractAddAllController.php +++ b/src/CoreBundle/Controller/Backend/AbstractAddAllController.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -201,13 +201,13 @@ protected function render($table, $metaModel, Request $request) 'action' => '', 'requestToken' => System::getContainer()->get('contao.csrf.token_manager')?->getDefaultTokenValue(), 'href' => $this->getReferer($request, $table, true), - 'backBt' => $this->translator->trans('MSC.backBT', [], 'contao_default'), - 'add' => $this->translator->trans('MSC.continue', [], 'contao_default'), - 'saveNclose' => $this->translator->trans('MSC.saveNclose', [], 'contao_default'), - 'activate' => $this->translator->trans($table . '.addAll_activate', [], 'contao_' . $table), + 'backBt' => $this->translator->trans('backBT', [], $table), + 'add' => $this->translator->trans('continue', [], $table), + 'saveNclose' => $this->translator->trans('saveNclose', [], $table), + 'activate' => $this->translator->trans('addAll_activate', [], $table), 'tlclass' => '', - 'headline' => $this->translator->trans($table . '.addall.1', [], 'contao_' . $table), - 'selectAll' => $this->translator->trans('MSC.selectAll', [], 'contao_default') . '.', + 'headline' => $this->translator->trans('addall.description', [], $table), + 'selectAll' => $this->translator->trans('selectAll', [], $table) . '.', 'cacheMessage' => '', 'updateMessage' => '', 'hasCheckbox' => \count($fields) > 0, @@ -320,9 +320,13 @@ private function generateForm(string $table, IMetaModel $metaModel, Request $req private function checkboxCaption(string $key, string $table, IAttribute $attribute): string { return $this->translator->trans( - $table . '.' . $key, - [$attribute->getName(), $attribute->get('type'), $attribute->getColName()], - 'contao_' . $table + $key, + [ + '%name%' => $attribute->getName(), + '%type%' => $attribute->get('type'), + '%colName%' => $attribute->getColName() + ], + $table ); } diff --git a/src/CoreBundle/Controller/Backend/ConfigurationController.php b/src/CoreBundle/Controller/Backend/ConfigurationController.php new file mode 100644 index 000000000..6795b63cb --- /dev/null +++ b/src/CoreBundle/Controller/Backend/ConfigurationController.php @@ -0,0 +1,96 @@ + + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\Controller\Backend; + +use Contao\CoreBundle\Framework\ContaoFramework; +use ContaoCommunityAlliance\DcGeneral\Factory\DcGeneralFactoryService; +use ContaoCommunityAlliance\Translator\TranslatorInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Twig\Environment as TwigEnvironment; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Error\SyntaxError; + +final class ConfigurationController +{ + use DcGeneralControllerTrait; + + /** + * @param Request $request The request. + * @param TwigEnvironment $twig The twig environment. + * @param DcGeneralFactoryService $factoryFactory The DCG factory + * @param EventDispatcherInterface $dispatcher The event dispatcher. + * @param TranslatorInterface $translator The translator. + * @param ContaoFramework $framework The Contao framework + * + * @return Response + * @throws LoaderError + * @throws RuntimeError + * @throws SyntaxError + */ + public function __invoke( + Request $request, + TwigEnvironment $twig, + DcGeneralFactoryService $factoryFactory, + EventDispatcherInterface $dispatcher, + TranslatorInterface $translator, + ContaoFramework $framework, + ): Response { + $containerName = (string) $request->query->get('table', 'tl_metamodel'); + $controllerResult = $this->bootDcGeneralAndProcess( + $request, + $containerName, + $factoryFactory, + $dispatcher, + $translator, + $framework + ); + $headline = $this->determineHeadline($containerName, $translator); + + return new Response( + $twig->render( + '@MetaModelsCore/Backend/be_config.html.twig', + [ + 'headline' => $headline, + 'body' => $controllerResult, + 'stylesheets' => ['bundles/metamodelscore/css/style.css'] + ] + ) + ); + } + + /** + * Generate headline. + * + * @param string $containerName The container. + * @param TranslatorInterface $translator The translator. + * + * @return string + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + private function determineHeadline(string $containerName, TranslatorInterface $translator): string + { + return $translator->translate('backend-module.headline', $containerName); + } +} diff --git a/src/CoreBundle/Controller/Backend/DcGeneralControllerTrait.php b/src/CoreBundle/Controller/Backend/DcGeneralControllerTrait.php new file mode 100644 index 000000000..5651e4b2c --- /dev/null +++ b/src/CoreBundle/Controller/Backend/DcGeneralControllerTrait.php @@ -0,0 +1,94 @@ + + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\Controller\Backend; + +use Contao\Ajax; +use Contao\Controller; +use Contao\CoreBundle\Framework\ContaoFramework; +use ContaoCommunityAlliance\DcGeneral\Action; +use ContaoCommunityAlliance\DcGeneral\Clipboard\ClipboardInterface; +use ContaoCommunityAlliance\DcGeneral\Controller\ControllerInterface; +use ContaoCommunityAlliance\DcGeneral\Factory\DcGeneralFactoryService; +use ContaoCommunityAlliance\Translator\TranslatorInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Request; + +trait DcGeneralControllerTrait +{ + /** + * @param Request $request The request. + * @param string $tableName The table name + * @param DcGeneralFactoryService $factoryFactory The DCG factory + * @param EventDispatcherInterface $dispatcher The event dispatcher. + * @param TranslatorInterface $translator The translator. + * @param ContaoFramework $framework The Contao framework + * + * @return string + * @throws \Exception + */ + public function bootDcGeneralAndProcess( + Request $request, + string $tableName, + DcGeneralFactoryService $factoryFactory, + EventDispatcherInterface $dispatcher, + TranslatorInterface $translator, + ContaoFramework $framework, + ): string { + $act = (string) $request->query->get('act', 'showAll'); + + // Work around legacy Contao code. + /** @psalm-suppress InternalMethod - Class ContaoFramework is internal, not the getAdapter() method. */ + $contaoController = $framework->getAdapter(Controller::class); + // Need to load the language file due to Widget class using hardcoded lang array offsets. + $contaoController->loadLanguageFile('default'); + + // Handle Ajax calls. + $action = null; + if ($request->isXmlHttpRequest() && '' !== ($action = (string) $request->request->get('action', ''))) { + $ajaxClass = new Ajax($action); + $ajaxClass->executePreActions(); + } + + // Build data container. + $factory = $factoryFactory->createFactory(); + $general = $factory + ->setContainerName($tableName) + ->setTranslator($translator) + ->setEventDispatcher($dispatcher) + ->createDcGeneral(); + + $environment = $general->getEnvironment(); + $clipboard = $environment->getClipboard(); + assert($clipboard instanceof ClipboardInterface); + + // Load the clipboard. + $clipboard->loadFrom($environment); + + $controller = $environment->getController(); + assert($controller instanceof ControllerInterface); + + if (null !== $action) { + $environment->getView()?->handleAjaxCall(); + } + + return $controller->handle(new Action($act)); + } +} diff --git a/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php b/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php index 0741fc633..4106bd209 100644 --- a/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php +++ b/src/CoreBundle/Controller/Backend/InputScreenAddAllController.php @@ -102,7 +102,7 @@ protected function render($table, $metaModel, Request $request) { return \array_merge( parent::render($table, $metaModel, $request), - ['tlclass' => $this->translator->trans($table . '.addAll_tlclass', [], 'contao_' . $table)] + ['tlclass' => $this->translator->trans('addAll_tlclass', [], $table)] ); } diff --git a/src/CoreBundle/Controller/Backend/MetaModelController.php b/src/CoreBundle/Controller/Backend/MetaModelController.php new file mode 100644 index 000000000..7dfe28bc6 --- /dev/null +++ b/src/CoreBundle/Controller/Backend/MetaModelController.php @@ -0,0 +1,114 @@ + + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\Controller\Backend; + +use Contao\CoreBundle\Exception\AccessDeniedException; +use Contao\CoreBundle\Framework\ContaoFramework; +use Contao\CoreBundle\Menu\BackendMenuBuilder; +use ContaoCommunityAlliance\DcGeneral\Factory\DcGeneralFactoryService; +use ContaoCommunityAlliance\Translator\TranslatorInterface; +use MetaModels\ViewCombination\ViewCombination; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Twig\Environment as TwigEnvironment; + +final class MetaModelController +{ + use DcGeneralControllerTrait; + + /** + * The constructor. + * + * @param BackendMenuBuilder $builder The menu builder. + */ + public function __construct( + private readonly BackendMenuBuilder $builder + ) { + } + + /** + * @param Request $request The request. + * @param TwigEnvironment $twig The twig environment. + * @param DcGeneralFactoryService $factoryFactory The DCG factory + * @param EventDispatcherInterface $dispatcher The event dispatcher. + * @param TranslatorInterface $translator The translator. + * @param ContaoFramework $framework The Contao framework + * + * @return Response + */ + public function __invoke( + Request $request, + TwigEnvironment $twig, + DcGeneralFactoryService $factoryFactory, + EventDispatcherInterface $dispatcher, + TranslatorInterface $translator, + ContaoFramework $framework, + ViewCombination $viewCombination, + ): Response { + $containerName = (string) $request->query->get('table', ''); + if ('' === $containerName) { + $containerName = (string) ($request->attributes->get('_route_params', [])['tableName'] ?? ''); + } + $combination = $viewCombination->getCombination($containerName); + if (null === $combination) { + throw new AccessDeniedException('Permission denied to access back end module "' . $containerName . '".'); + } + $inputScreenId = $combination['dca_id'] ?? ''; + $controllerResult = $this->bootDcGeneralAndProcess( + $request, + $containerName, + $factoryFactory, + $dispatcher, + $translator, + $framework + ); + $headline = $this->determineHeadline($containerName, $inputScreenId, $translator); + + return new Response( + $twig->render( + '@MetaModelsCore/Backend/be_config.html.twig', + [ + 'headline' => $headline, + 'body' => $controllerResult, + 'stylesheets' => ['bundles/metamodelscore/css/style.css'] + ] + ) + ); + } + + /** + * Generate headline. + * + * @param string $containerName The container. + * @param string $inputScreenId The input screen id. + * @param TranslatorInterface $translator The translator. + * + * @return string + */ + private function determineHeadline( + string $containerName, + string $inputScreenId, + TranslatorInterface $translator + ): string { + return $translator->translate('backend-module.' . $inputScreenId . '.headline', $containerName); + } +} diff --git a/src/CoreBundle/Controller/Backend/SupportMetaModelsController.php b/src/CoreBundle/Controller/Backend/SupportMetaModelsController.php index 9335e1c90..7eef890e2 100644 --- a/src/CoreBundle/Controller/Backend/SupportMetaModelsController.php +++ b/src/CoreBundle/Controller/Backend/SupportMetaModelsController.php @@ -89,20 +89,20 @@ public function __invoke() 'stylesheets' => [ 'bundles/metamodelscore/css/supportscreen.css' ], - 'headline' => $this->translator->trans('MOD.support_metamodels.0', [], 'contao_modules'), + 'headline' => $this->translator->trans('menu.label', [], 'metamodels_support'), 'sub_headline' => - $this->translator->trans('MSC.metamodels_support.main_headline', [], 'contao_default'), + $this->translator->trans('main_headline', [], 'metamodels_support'), 'head_contributor' => - $this->translator->trans('MSC.metamodels_support.contributor_headline', [], 'contao_default'), - 'purpose' => $this->translator->trans('MSC.metamodels_support.purpose', [], 'contao_default'), + $this->translator->trans('contributor_headline', [], 'metamodels_support'), + 'purpose' => $this->translator->trans('purpose', [], 'metamodels_support'), 'other_donations' => - $this->translator->trans('MSC.metamodels_support.other_donations', [], 'contao_default'), + $this->translator->trans('other_donations', [], 'metamodels_support'), 'main_text' => - $this->translator->trans('MSC.metamodels_support.main_text', [], 'contao_default'), + $this->translator->trans('main_text', [], 'metamodels_support'), 'help_headline' => - $this->translator->trans('MSC.metamodels_support.help_headline', [], 'contao_default'), + $this->translator->trans('help_headline', [], 'metamodels_support'), 'help_text' => - $this->translator->trans('MSC.metamodels_support.help_text', [], 'contao_default'), + $this->translator->trans('help_text', [], 'metamodels_support'), 'github_contributors' => $this->getJsonFile($this->github), 'transifex_contributors' => $this->getJsonFile($this->transifex) ] diff --git a/src/CoreBundle/Controller/ContentElement/ItemListController.php b/src/CoreBundle/Controller/ContentElement/ItemListController.php index 080460bf9..f73870b28 100644 --- a/src/CoreBundle/Controller/ContentElement/ItemListController.php +++ b/src/CoreBundle/Controller/ContentElement/ItemListController.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Ingolf Steinhardt * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -99,7 +99,7 @@ protected function getResponse(Template $template, ContentModel $model, Request */ private function getBackendWildcard(ContentModel $model): Response { - $name = $this->translator->trans('CTE.' . $this->getType() . '.0', [], 'contao_modules'); + $name = $this->translator->trans($this->getType(), [], 'metamodels_wildcard'); $href = $this->router->generate( 'contao_backend', ['do' => 'article', 'table' => 'tl_content', 'act' => 'edit', 'id' => $model->id] diff --git a/src/CoreBundle/Controller/FrontendModule/ItemListController.php b/src/CoreBundle/Controller/FrontendModule/ItemListController.php index c26cee486..c5f4f0839 100644 --- a/src/CoreBundle/Controller/FrontendModule/ItemListController.php +++ b/src/CoreBundle/Controller/FrontendModule/ItemListController.php @@ -81,7 +81,7 @@ public function __invoke( */ protected function getBackendWildcard(ModuleModel $module): Response { - $name = $this->translator->trans('FMD.' . $this->getType() . '.0', [], 'contao_modules'); + $name = $this->translator->trans($this->getType(), [], 'metamodels_wildcard'); $href = $this->router->generate( 'contao_backend', ['do' => 'themes', 'table' => 'tl_module', 'act' => 'edit', 'id' => $module->id] diff --git a/src/CoreBundle/Controller/ListControllerTrait.php b/src/CoreBundle/Controller/ListControllerTrait.php index 9832684a9..6c0359785 100644 --- a/src/CoreBundle/Controller/ListControllerTrait.php +++ b/src/CoreBundle/Controller/ListControllerTrait.php @@ -432,13 +432,14 @@ private function getWildcardInfoText(Model $model, string $href, string $name): // Add CSS file. $GLOBALS['TL_CSS'][] = 'bundles/metamodelscore/css/style.css'; - // Retrieve name of MetaModels. + // Retrieve name of MetaModel. $infoTemplate = '
    %s: %s
    '; $metaModel = $this->factory->getMetaModel($metaModelName); assert($metaModel instanceof IMetaModel); - $header = $name . ': ' . $metaModel->getName(); + + $header = $metaModel->getName(); if ($href) { $header .= \sprintf( ' (ID: %3$s)', @@ -447,11 +448,11 @@ private function getWildcardInfoText(Model $model, string $href, string $name): (string) $model->id ); } - $infoText = \sprintf( + $infoText = '### ' . $name . ' ###' . \sprintf( $infoTemplate, - $this->translator->trans('MSC.mm_be_info_name.1', [], 'contao_default'), - $this->translator->trans('MSC.mm_be_info_name.0', [], 'contao_default'), - $header + $this->translator->trans('mm_be_info_name.description', [], 'metamodels_wildcard'), + $this->translator->trans('mm_be_info_name.label', [], 'metamodels_wildcard'), + $header, ); // Retrieve name of filter. @@ -469,14 +470,14 @@ private function getWildcardInfoText(Model $model, string $href, string $name): if (null !== $infoFi) { $infoText .= \sprintf( $infoTemplate, - $this->translator->trans('MSC.mm_be_info_filter.1', [], 'contao_default'), - $this->translator->trans('MSC.mm_be_info_filter.0', [], 'contao_default'), + $this->translator->trans('mm_be_info_filter.description', [], 'metamodels_wildcard'), + $this->translator->trans('mm_be_info_filter.label', [], 'metamodels_wildcard'), $infoFi . $infoFiPa ); } } - // Retrieve name of rendersetting. + // Retrieve name of render setting. /** @psalm-suppress UndefinedMagicPropertyFetch */ if ($model->metamodel_rendersettings) { $infoRs = $this->renderSettingFactory @@ -485,8 +486,8 @@ private function getWildcardInfoText(Model $model, string $href, string $name): if (null !== $infoRs) { $infoText .= \sprintf( $infoTemplate, - $this->translator->trans('MSC.mm_be_info_render_setting.1', [], 'contao_default'), - $this->translator->trans('MSC.mm_be_info_render_setting.0', [], 'contao_default'), + $this->translator->trans('mm_be_info_render_setting.description', [], 'metamodels_wildcard'), + $this->translator->trans('mm_be_info_render_setting.label', [], 'metamodels_wildcard'), $infoRs ); } diff --git a/src/CoreBundle/DependencyInjection/CompilerPass/PrepareTranslatorPass.php b/src/CoreBundle/DependencyInjection/CompilerPass/PrepareTranslatorPass.php new file mode 100644 index 000000000..be83bc0ba --- /dev/null +++ b/src/CoreBundle/DependencyInjection/CompilerPass/PrepareTranslatorPass.php @@ -0,0 +1,47 @@ + + * @copyright 2012-2024 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +declare(strict_types=1); + +namespace MetaModels\CoreBundle\DependencyInjection\CompilerPass; + +use MetaModels\CoreBundle\Translator\MetaModelTranslatorConfigurator; +use Symfony\Bundle\FrameworkBundle\Translation\Translator; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +final class PrepareTranslatorPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + $definition = $container->getDefinition('translator.default'); + if (Translator::class !== $definition->getClass()) { + return; + } + $previousConfigurator = $definition->getConfigurator(); + $definition->setConfigurator(new Reference(MetaModelTranslatorConfigurator::class)); + if (null !== $previousConfigurator) { + $container->getDefinition(MetaModelTranslatorConfigurator::class)->setArgument( + '$previous', + $previousConfigurator + ); + } + } +} diff --git a/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php b/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php index 74ae196d4..1aa37c4f7 100644 --- a/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php +++ b/src/CoreBundle/DependencyInjection/MetaModelsCoreExtension.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Sven Baumann * @author Ingolf Steinhardt * @author Richard Henkenjohann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -133,7 +133,7 @@ public function getConfiguration(array $config, ContainerBuilder $container) */ private function buildCacheService(ContainerBuilder $container, array $config): void { - // if cache disabled, swap it out with the dummy cache. + // If cache disabled, swap it out with the dummy cache. if (!$config['enable_cache']) { $cache = $container->getDefinition('metamodels.cache_internal'); $cache->setClass(ArrayAdapter::class); diff --git a/src/CoreBundle/EventListener/BackendNavigationListener.php b/src/CoreBundle/EventListener/BackendNavigationListener.php index 590445e9c..93c240aeb 100644 --- a/src/CoreBundle/EventListener/BackendNavigationListener.php +++ b/src/CoreBundle/EventListener/BackendNavigationListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -14,25 +14,34 @@ * @author Christian Schiffler * @author Richard Henkenjohann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener; -use Contao\BackendUser; use Contao\CoreBundle\Event\MenuEvent; -use Contao\StringUtil; +use Knp\Menu\FactoryInterface; +use Knp\Menu\ItemInterface; use MetaModels\ViewCombination\ViewCombination; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; +use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Contracts\Translation\TranslatorInterface; +use function array_key_exists; +use function array_map; +use function in_array; +use function is_array; + /** * This registers the backend navigation of MetaModels. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class BackendNavigationListener { @@ -71,6 +80,13 @@ class BackendNavigationListener */ private RouterInterface $router; + /** + * The session. + * + * @var Session + */ + private Session $session; + /** * Create a new instance. * @@ -79,19 +95,22 @@ class BackendNavigationListener * @param ViewCombination $viewCombination The view combination. * @param TokenStorageInterface $tokenStorage The token storage. * @param RouterInterface $router The router. + * @param Session $session The session. */ public function __construct( TranslatorInterface $translator, RequestStack $requestStack, ViewCombination $viewCombination, TokenStorageInterface $tokenStorage, - RouterInterface $router + RouterInterface $router, + Session $session, ) { $this->requestStack = $requestStack; $this->translator = $translator; $this->viewCombination = $viewCombination; $this->tokenStorage = $tokenStorage; $this->router = $router; + $this->session = $session; } /** @@ -123,31 +142,28 @@ public function __invoke(MenuEvent $event): void $this->addBackendCss(); - $userRights = $this->extractUserRights($user); - $isAdmin = \in_array('ROLE_ADMIN', $user->getRoleNames(), true); + $isAdmin = in_array('ROLE_ADMIN', $user->getRoleNames(), true); - $metaModelsNode = $tree->getChild('metamodels'); - if (null !== $metaModelsNode && ($isAdmin || isset($userRights['support_metamodels']))) { - $node = $factory - ->createItem('support_screen') - ->setUri($this->router->generate('metamodels.support_screen')) - ->setLabel($this->translator->trans('MOD.support_metamodels.0', [], 'contao_modules')) - ->setLinkAttribute('title', $this->translator->trans('MOD.support_metamodels.1', [], 'contao_modules')) - ->setLinkAttribute('class', 'support_screen') - ->setCurrent('metamodels.support_screen' === $request->attributes->get('_route')); + $metaModelsNode = $this->getRootNode($tree, $factory); - $metaModelsNode->addChild($node); + $names = array_map(static fn(ItemInterface $item): string => $item->getName(), $metaModelsNode->getChildren()); + + // Show MetaModels config only for Admins. + if ($isAdmin) { + $metaModelsNode->addChild($configNode = $this->buildConfigNode($factory, $request)); + array_unshift($names, $configNode->getName()); } - $locale = $request->getLocale(); - foreach ($this->viewCombination->getStandalone() as $metaModelName => $screen) { - $moduleName = 'metamodel_' . $metaModelName; - if (!$isAdmin && !isset($userRights[$moduleName])) { - continue; - } + $metaModelsNode->reorderChildren($names); + + $currentMetaModel = ''; + if ($request->attributes->get('_route') === 'metamodels.metamodel') { + $currentMetaModel = (string) (($request->attributes->get('_route_params', []))['tableName'] ?? ''); + } - $sectionNode = $tree->getChild($screen['meta']['backendsection']); - if (null === $sectionNode) { + foreach ($this->viewCombination->getStandalone() as $metaModelName => $screen) { + if (null === $sectionNode = $this->getSectionNode($factory, $tree, $screen['meta']['backendsection'])) { + // Rien ne vas plus. continue; } @@ -155,70 +171,232 @@ public function __invoke(MenuEvent $event): void $node = $factory ->createItem($item) - ->setUri($this->router->generate('contao_backend', ['do' => $item])) - ->setLabel($this->extractLanguageValue($screen['label'], $locale)) - ->setLinkAttribute('title', $this->extractLanguageValue($screen['description'], $locale)) + ->setUri($this->router->generate('metamodels.metamodel', ['tableName' => $metaModelName])) + ->setLabel('inputscreen.' . $screen['meta']['id'] . '.menu.label') + ->setExtra('translation_domain', $metaModelName) + ->setLinkAttribute( + 'title', + $this->translator->trans( + 'inputscreen.' . $screen['meta']['id'] . '.menu.description', + [], + $metaModelName + ) + ) ->setLinkAttribute('class', $item) - ->setCurrent( - ($request->attributes->get('_route') === 'contao_backend') && ($request->query->get('do') === $item) - ); + ->setCurrent($currentMetaModel === $metaModelName); $sectionNode->addChild($node); } + + if ($isAdmin) { + $node = $factory + ->createItem('support_screen') + ->setUri($this->router->generate('metamodels.support_screen')) + ->setLabel('menu.label') + ->setExtra('translation_domain', 'metamodels_support') + ->setLinkAttribute('title', $this->translator->trans('menu.description', [], 'metamodels_support')) + ->setLinkAttribute('class', 'support_screen') + ->setCurrent('metamodels.support_screen' === $request->attributes->get('_route')); + + $metaModelsNode->addChild($node); + } } /** - * Extract the permissions from the Contao backend user. + * Add the CSS files for the backend. * - * @param TokenInterface $token The token. + * @return void * - * @return array + * @SuppressWarnings(PHPMD.Superglobals) + * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - private function extractUserRights(TokenInterface $token): array + private function addBackendCss(): void { - $beUser = $token->getUser(); - if (!($beUser instanceof BackendUser)) { - return []; - } + // BE group icon. + $GLOBALS['TL_CSS']['metamodels'] = 'bundles/metamodelscore/css/be_logo_svg.css'; + } - $allowedModules = $beUser->modules; - switch (true) { - case \is_string($allowedModules): - $allowedModules = StringUtil::deserialize($allowedModules, true); - break; - case null === $allowedModules: - $allowedModules = []; - break; - default: + /** + * Get root node. + * + * @param ItemInterface $tree The tree. + * @param FactoryInterface $factory The factory. + * + * @return ItemInterface + */ + private function getRootNode(ItemInterface $tree, FactoryInterface $factory): ItemInterface + { + $names = + $this->getChildNamesFromTree($tree); + $insertPos = (int) array_search('accounts', $names, true) + 1; + $metaModelsNode = $tree->getChild('metamodels'); + if (null === $metaModelsNode) { + $metaModelsNode = $factory->createItem('metamodels'); + $tree->addChild($metaModelsNode); } - return \array_flip($allowedModules); + $metaModelsNode + ->setLabel('menuGroup.metamodels.label') + ->setExtra('translation_domain', 'metamodels_navigation'); + + $this->updateCollapsedState($metaModelsNode); + + // Resort if already existing. + $names = array_values(array_filter($names, static fn(string $name): bool => 'metamodels' !== $name)); + + array_splice($names, $insertPos, 0, 'metamodels'); + $tree->reorderChildren($names); + + return $metaModelsNode; } /** - * Extract the language value. + * Generate build config. * - * @param string[] $values The values. - * @param string $locale The current locale. + * @param FactoryInterface $factory The factory. + * @param Request $request The request. * - * @return string + * @return ItemInterface */ - private function extractLanguageValue(array $values, string $locale): string + private function buildConfigNode(FactoryInterface $factory, Request $request): ItemInterface { - return \html_entity_decode(($values[$locale] ?? $values[''])); + $configNode = $factory->createItem('metamodels'); + + $configNode + ->setUri($this->router->generate('metamodels.configuration')) + ->setLabel('menu.metamodels.label') + ->setExtra('translation_domain', 'metamodels_navigation') + ->setLinkAttribute('title', $this->translator->trans('menu.metamodels.title', [], 'metamodels_navigation')) + ->setLinkAttribute('class', 'metamodel_config') + ->setCurrent('metamodels.configuration' === $request->attributes->get('_route')); + + return $configNode; } /** - * Add the CSS files for the backend. + * Update collapsed state of navigation groups. + * + * @param ItemInterface $metaModelsNode * * @return void + */ + private function updateCollapsedState(ItemInterface $metaModelsNode): void + { + $nodeName = $metaModelsNode->getName(); + $sessionBag = $this->session->getBag('contao_backend'); + $status = ($sessionBag instanceof AttributeBagInterface) ? $sessionBag->get('backend_modules') : []; + $isCollapsed = ($status[$nodeName] ?? 1) < 1; + $path = $this->router->generate('contao_backend'); + + $metaModelsNode + ->setLinkAttribute('class', 'group-' . $nodeName) + ->setLinkAttribute( + 'onclick', + "return AjaxRequest.toggleNavigation(this, '" . $nodeName . "', '" . $path . "')" + ) + ->setLinkAttribute('aria-controls', $nodeName) + ->setChildrenAttribute('id', $nodeName) + ->setLinkAttribute( + 'title', + $this->translator->trans('MSC.' . ($isCollapsed ? 'expand' : 'collapse') . 'Node', [], 'contao_default') + ) + ->setLinkAttribute('aria-expanded', $isCollapsed ? 'false' : 'true'); + + if ($isCollapsed) { + $metaModelsNode->setAttribute('class', 'collapsed'); + } + + $request = $this->requestStack->getCurrentRequest(); + if (null === $request) { + return; + } + + $uri = $this->router->generate( + 'contao_backend', + [ + 'do' => $request->query->get('do'), + 'mtg' => $nodeName, + 'ref' => $request->attributes->get('_contao_referer_id') + ] + ); + + $metaModelsNode->setUri($uri); + } + + /** + * Get section node. + * + * @param FactoryInterface $factory The factory. + * @param ItemInterface $tree The item interface. + * @param string $backendSection The backend section. + * + * @return ItemInterface|null * * @SuppressWarnings(PHPMD.Superglobals) - * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ - private function addBackendCss(): void + private function getSectionNode( + FactoryInterface $factory, + ItemInterface $tree, + string $backendSection + ): ?ItemInterface { + if (null !== $sectionNode = $tree->getChild($backendSection)) { + return $sectionNode; + } + + // Somehow it disappeared - try to generate it via BE_MOD. + if (!array_key_exists($backendSection, $GLOBALS['BE_MOD'])) { + return null; + } + $navigation = array_keys($GLOBALS['BE_MOD']); + // Keep child names before adding the new child. + $namesInMenu = $this->getChildNamesFromTree($tree); + $sectionNode = $factory->createItem($backendSection); + $tree->addChild($sectionNode); + $sectionNode + ->setLabel($this->getLabelForSection($backendSection)) + ->setExtra('translation_domain', false); + + $this->updateCollapsedState($sectionNode); + + // Search the position in the already existing menu by starting at offset in BE_MOD and walking up to the start. + $start = (int) array_search($backendSection, $navigation, true); + while (0 <= --$start) { + /** @psalm-suppress InvalidArrayOffset */ + if (in_array($navigation[$start], $namesInMenu, true)) { + array_splice($namesInMenu, $start + 1, 0, [$backendSection]); + break; + } + } + // If we did not find a position in existing menu, append at the end. + if (!in_array($backendSection, $namesInMenu)) { + $namesInMenu[] = $backendSection; + } + $tree->reorderChildren($namesInMenu); + + return $sectionNode; + } + + /** + * @param ItemInterface $tree + * + * @return list + */ + private function getChildNamesFromTree(ItemInterface $tree): array { - // BE group icon. - $GLOBALS['TL_CSS']['metamodels'] = 'bundles/metamodelscore/css/be_logo_svg.css'; + return array_values( + array_map(static fn(ItemInterface $item): string => $item->getName(), $tree->getChildren()) + ); + } + + /** @SuppressWarnings(PHPMD.Superglobals) */ + public function getLabelForSection(string $backendSection): string + { + /** @var null|list|string $langValue */ + $langValue = $GLOBALS['TL_LANG']['MOD'][$backendSection] ?? null; + if (is_array($langValue)) { + return $langValue[0] ?? $backendSection; + } + + return $langValue ?? $backendSection; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbMetaModelListener.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbMetaModelListener.php index 5cf1c42e7..a996ab0d7 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbMetaModelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbMetaModelListener.php @@ -51,7 +51,7 @@ protected function wantToHandle(GetBreadcrumbEvent $event) protected function getBreadcrumbElements(EnvironmentInterface $environment, BreadcrumbStore $elements) { $elements->push( - 'contao/main.php?do=metamodels', + 'contao/metamodels', 'tl_metamodel', 'bundles/metamodelscore/images/backend/logo.png' ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStore.php b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStore.php index 1bc98a253..2e73cab3e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStore.php +++ b/src/CoreBundle/EventListener/DcGeneral/Breadcrumb/BreadcrumbStore.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -25,6 +25,11 @@ use MetaModels\CoreBundle\Assets\IconBuilder; use Symfony\Contracts\Translation\TranslatorInterface; +use function array_key_exists; +use function str_replace; +use function str_starts_with; +use function ucfirst; + /** * The breadcrumb store. */ @@ -35,35 +40,35 @@ class BreadcrumbStore * * @var array */ - private $elements = []; + private array $elements = []; /** * The icon builder. * * @var IconBuilder */ - private $iconBuilder; + private IconBuilder $iconBuilder; /** * The translator. * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * List of "current" ids. * * @var string[] */ - private $idList = []; + private array $idList = []; /** * The current URI. * * @var string */ - private $uri; + private string $uri; /** * Create a new instance. @@ -145,19 +150,19 @@ public function getUri(): string } /** - * Get for a table the human readable name or a fallback. + * Get for a table the human-readable name or a fallback. * * @param string $table Name of table. * - * @return string The human readable name. + * @return string The human-readable name. */ public function getLabel($table): string { - if (strpos($table, 'tl_') !== 0) { + if (!str_starts_with($table, 'tl_')) { return $table; } $shortTable = str_replace('tl_', '', $table); - $label = $this->translator->trans('BRD.' . $shortTable, [], 'contao_default'); + $label = $this->translator->trans($shortTable, [], 'metamodels_navigation'); if ($label === $shortTable) { $shortTable = str_replace('tl_metamodel_', '', $table); return ucfirst($shortTable) . ' %s'; diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php index e17c44f60..8dbf8db1d 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/CommandBuilder.php @@ -33,7 +33,6 @@ use MetaModels\CoreBundle\Assets\IconBuilder; use MetaModels\DcGeneral\DataDefinition\IMetaModelDataDefinition; use MetaModels\DcGeneral\Events\MetaModel\BuildMetaModelOperationsEvent; -use MetaModels\Helper\LocaleUtil; use MetaModels\IFactory; use MetaModels\IMetaModel; use MetaModels\ViewCombination\ViewCombination; @@ -138,14 +137,14 @@ protected function build(IMetaModelDataDefinition $container) ); } - $this->container = $container; + $this->container = $container; $inputScreen = $this->viewCombination->getScreen($container->getName()); if (null === $inputScreen) { return; } $this->addEditMultipleCommand($view); $this->parseModelOperations($view); - $this->container = null; + $this->container = null; if ($this->dispatcher->hasListeners(BuildMetaModelOperationsEvent::NAME)) { // @codingStandardsIgnoreStart @@ -180,9 +179,9 @@ private function addEditMultipleCommand(Contao2BackendViewDefinitionInterface $v $commands = $view->getGlobalCommands(); $command = new SelectCommand(); $command - ->setName('all') - ->setLabel('MSC.all.0') - ->setDescription('MSC.all.1'); + ->setName('editAll') + ->setLabel('editAll.label') + ->setDescription('editAll.description'); $parameters = $command->getParameters(); $parameters['act'] = 'select'; @@ -214,10 +213,8 @@ private function parseModelOperations(Contao2BackendViewDefinitionInterface $vie ['act' => 'delete'], 'delete.svg', [ - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $this->translator->trans('MSC.deleteConfirm', [], 'contao_default') - ) + 'attributes' => + 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ] ); $this->createCommand($collection, 'show', ['act' => 'show'], 'show.svg'); @@ -235,18 +232,14 @@ private function parseModelOperations(Contao2BackendViewDefinitionInterface $vie // Check if we have some children. foreach ($this->viewCombination->getChildrenOf($this->container->getName()) as $tableName => $screen) { - $metaModel = $this->factory->getMetaModel($tableName); - assert($metaModel instanceof IMetaModel); - $caption = $this->getChildModelCaption($metaModel, $screen); - $this->createCommand( $collection, 'edit_' . $tableName, ['table' => $tableName], $this->iconBuilder->getBackendIcon($screen['meta']['backendicon']), [ - 'label' => $caption[0], - 'description' => $caption[1], + 'label' => 'metamodel_edit_as_child.' . $tableName . '.label', + 'description' => 'metamodel_edit_as_child.' . $tableName . '.description', 'idparam' => 'pid' ] ); @@ -254,7 +247,7 @@ private function parseModelOperations(Contao2BackendViewDefinitionInterface $vie } /** - * Build a command into the the command collection. + * Build a command into the command collection. * * @param CommandCollectionInterface $collection The command collection. * @param string $operationName The operation name. @@ -280,14 +273,14 @@ private function createCommand( } if (!$command->getLabel()) { - $command->setLabel($operationName . '.0'); + $command->setLabel($operationName . '.label'); if (isset($extraValues['label'])) { $command->setLabel($extraValues['label']); } } if (!$command->getDescription()) { - $command->setDescription($operationName . '.1'); + $command->setDescription($operationName . '.description'); if (isset($extraValues['description'])) { $command->setDescription($extraValues['description']); } @@ -335,38 +328,4 @@ private function getCommandInstance(CommandCollectionInterface $collection, stri return $command; } - - /** - * Create the caption text for the child model. - * - * @param IMetaModel $metaModel The child model. - * @param array $screen The input screen. - * - * @return array - * - * @SuppressWarnings(PHPMD.Superglobals) - * @SuppressWarnings(PHPMD.CamelCaseVariableName) - */ - private function getChildModelCaption(IMetaModel $metaModel, array $screen): array - { - $caption = [ - '', - \sprintf( - $GLOBALS['TL_LANG']['MSC']['metamodel_edit_as_child']['label'], - $metaModel->getName() - ) - ]; - - foreach ($screen['label'] as $langCode => $label) { - // @deprecated usage of TL_LANGUAGE - remove for Contao 5.0. - if (!empty($label) && $langCode === LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'])) { - $caption = [ - $screen['description'][$langCode], - $label - ]; - } - } - - return $caption; - } } diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php index 2619ce470..b233a41ef 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/Contao2BackendViewDefinitionBuilder.php @@ -184,9 +184,13 @@ private function parseListing(): void { assert($this->definition instanceof Contao2BackendViewDefinitionInterface); assert($this->metaModel instanceof IMetaModel); - assert(\is_array($this->inputScreen)); + if (null === $this->inputScreen) { + return; + } + $listing = $this->definition->getListingConfig(); + if (null === $listing->getRootLabel()) { $listing->setRootLabel($this->metaModel->get('name')); } diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php index 51cbf7de8..5c1593083 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PaletteBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -112,8 +112,9 @@ protected function build(IMetaModelDataDefinition $container) ->setName('default') ->setCondition(new DefaultPaletteCondition()); + $prefix = 'inputscreen.' . $inputScreen['meta']['id'] . '.'; foreach ($inputScreen['legends'] as $legendName => $legendInfo) { - $legend = new Legend($legendName); + $legend = new Legend($prefix . $legendName); $legend->setInitialVisibility(!$legendInfo['hide']); $palette->addLegend($legend); @@ -191,10 +192,7 @@ private function createProperty( $chain = new PropertyConditionChain(); $paletteProperty->setVisibleCondition($chain); $chain->addCondition( - new BooleanCondition( - !((isset($extra['doNotShow']) && $extra['doNotShow']) - || (isset($extra['hideInput']) && $extra['hideInput'])) - ) + new BooleanCondition(!(bool) ($extra['doNotShow'] ?? false) || !(bool) ($extra['hideInput'] ?? false)) ); if (null !== $condition) { diff --git a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php index 507b820a3..e18983089 100644 --- a/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php +++ b/src/CoreBundle/EventListener/DcGeneral/DefinitionBuilder/PropertyDefinitionBuilder.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -151,8 +151,8 @@ private function buildProperty( array $propInfo ): void { $property = $this->getOrCreateProperty($definition, $attribute->getColName()); - $this->setLabel($property, $propInfo, $attribute); - $this->setDescription($property, $propInfo); + $this->setLabel($property); + $this->setDescription($property); $this->setDefaultValue($property, $propInfo); $this->setExcluded($property, $propInfo); $this->setSearchable($property, $propInfo); @@ -188,47 +188,30 @@ private function getOrCreateProperty(PropertiesDefinitionInterface $definition, * Set the label in the property. * * @param PropertyInterface $property The property definition. - * @param array $propInfo The property info array. - * @param IAttribute $attribute The attribute. * * @return void */ - private function setLabel(PropertyInterface $property, array $propInfo, IAttribute $attribute): void + private function setLabel(PropertyInterface $property): void { if ($property->getLabel()) { return; } - if (!isset($propInfo['label'])) { - $property->setLabel($attribute->getName()); - - return; - } - $lang = $propInfo['label']; - if (\is_array($lang)) { - $property->setLabel(reset($lang)); - $property->setDescription(next($lang)); - - return; - } - - $property->setLabel($lang); + $property->setLabel($property->getName() . '.label'); } /** * Set the description in the property. * * @param PropertyInterface $property The property definition. - * @param array $propInfo The property info array. * * @return void */ - private function setDescription(PropertyInterface $property, array $propInfo): void + private function setDescription(PropertyInterface $property): void { - if ($property->getDescription() || !isset($propInfo['description'])) { + if ($property->getDescription()) { return; } - - $property->setDescription($propInfo['description']); + $property->setDescription($property->getName() . '.description'); } /** diff --git a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php index 776b7663e..d25e151b7 100644 --- a/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php +++ b/src/CoreBundle/EventListener/DcGeneral/EnvironmentPopulator/TranslatorPopulator.php @@ -21,15 +21,16 @@ namespace MetaModels\CoreBundle\EventListener\DcGeneral\EnvironmentPopulator; -use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents; -use ContaoCommunityAlliance\Contao\Bindings\Events\System\LoadLanguageFileEvent; +use Contao\System; use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; use ContaoCommunityAlliance\Translator\StaticTranslator; +use ContaoCommunityAlliance\Translator\SymfonyTranslatorBridge; use ContaoCommunityAlliance\Translator\TranslatorChain; use ContaoCommunityAlliance\Translator\TranslatorInterface; use MetaModels\Helper\LocaleUtil; use MetaModels\ViewCombination\ViewCombination; +use Symfony\Contracts\Translation\TranslatorInterface as SymfonyTranslator; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** @@ -39,30 +40,18 @@ class TranslatorPopulator { use MetaModelPopulatorTrait; - /** - * The event dispatcher. - * - * @var EventDispatcherInterface - */ - private EventDispatcherInterface $dispatcher; - - /** - * The view combination. - * - * @var ViewCombination - */ - private ViewCombination $viewCombination; - /** * Create a new instance. * * @param EventDispatcherInterface $dispatcher The event dispatcher. * @param ViewCombination $viewCombination The view combination. + * @param SymfonyTranslator $translator The translator. */ - public function __construct(EventDispatcherInterface $dispatcher, ViewCombination $viewCombination) - { - $this->dispatcher = $dispatcher; - $this->viewCombination = $viewCombination; + public function __construct( + private EventDispatcherInterface $dispatcher, + private ViewCombination $viewCombination, + private SymfonyTranslator $translator + ) { } /** @@ -87,23 +76,11 @@ protected function populate(EnvironmentInterface $environment) } else { $translatorChain = $translator; } + $translatorChain->add(new SymfonyTranslatorBridge($this->translator)); $translatorChain->add($translator = new StaticTranslator()); - - // Map the tl_metamodel_item domain over to this domain. - $this->dispatcher->dispatch( - new LoadLanguageFileEvent('tl_metamodel_item'), - ContaoEvents::SYSTEM_LOAD_LANGUAGE_FILE - ); - $dataDefinition = $environment->getDataDefinition(); assert($dataDefinition instanceof ContainerInterface); - $definitionName = $dataDefinition->getName(); - $this->mapTranslations( - $GLOBALS['TL_LANG']['tl_metamodel_item'], - $definitionName, - $translator - ); if (null === $inputScreen = $this->viewCombination->getScreen($definitionName)) { return; diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php index b47145107..5e57b2e0f 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeRendererListener.php @@ -64,9 +64,9 @@ public function modelToLabel(ModelToLabelEvent $event)
    ' ) ->setArgs([ - $translator->translate('error_unknown_attribute.0', 'tl_metamodel_attribute'), + $translator->translate('error_unknown_attribute.label', 'tl_metamodel_attribute'), $type, - $translator->translate('error_unknown_attribute.1', 'tl_metamodel_attribute', [$type]), + $translator->translate('error_unknown_attribute.description', 'tl_metamodel_attribute', [$type]), ]); return; diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSchemaManagerHintListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSchemaManagerHintListener.php index fc2921b34..ff56056dd 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSchemaManagerHintListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/AttributeSchemaManagerHintListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,7 @@ * * @package MetaModels/core * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -70,12 +70,6 @@ public function handle(PreEditModelEvent $event): void return; } - Message::addInfo( - $this->translator->trans( - 'tl_metamodel_attribute.hint_schema_manager', - [], - 'contao_tl_metamodel_attribute' - ) - ); + Message::addInfo($this->translator->trans('hint_schema_manager', [], 'tl_metamodel_attribute')); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php index 5d3f3d274..6d673daf2 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/ColNameValidationListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -85,14 +85,15 @@ public function handle(EncodePropertyValueFromWidgetEvent $event): void $this->tableManipulator->checkColumnName($columnName); } catch (InvalidColumnNameException $exception) { throw new \RuntimeException( - \sprintf( - $translator->translate( - 'ERR.' . ($this->tableManipulator->isSystemColumn($columnName) - ? 'systemColumn' - : 'invalidColumnName') - ), - $columnName, - $metaModel->getTableName() + $translator->translate( + 'ERR.' . ($this->tableManipulator->isSystemColumn($columnName) + ? 'systemColumn' + : 'invalidColumnName'), + 'tl_metamodel_attribute', + [ + '%col_name%' => $columnName, + '%table_name%' => $metaModel->getTableName() + ] ), 0, $exception @@ -102,10 +103,13 @@ public function handle(EncodePropertyValueFromWidgetEvent $event): void $colNames = \array_keys($metaModel->getAttributes()); if (\in_array($columnName, $colNames)) { throw new \RuntimeException( - \sprintf( - $translator->translate('ERR.columnExists'), - $columnName, - $metaModel->getTableName() + $translator->translate( + 'ERR.columnExists', + 'tl_metamodel_attribute', + [ + '%col_name%' => $columnName, + '%table_name%' => $metaModel->getTableName() + ] ) ); } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/NameAndDescriptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/NameAndDescriptionListener.php index 79b79e2b4..caadfddda 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/NameAndDescriptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Attribute/NameAndDescriptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Stefan Heimes * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -32,6 +32,9 @@ use MetaModels\IFactory; use Symfony\Contracts\Translation\TranslatorInterface; +use function in_array; +use function unserialize; + /** * This class provides the attribute type names. */ @@ -42,7 +45,7 @@ class NameAndDescriptionListener extends BaseListener * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * Create a new instance. @@ -71,7 +74,7 @@ public function __construct( */ public function decodeValue(DecodePropertyValueForWidgetEvent $event) { - if (!($this->wantToHandle($event) && \in_array($event->getProperty(), ['name', 'description']))) { + if (!($this->wantToHandle($event) && in_array($event->getProperty(), ['name', 'description']))) { return; } @@ -90,7 +93,7 @@ public function decodeValue(DecodePropertyValueForWidgetEvent $event) */ public function encodeValue(EncodePropertyValueFromWidgetEvent $event) { - if (!($this->wantToHandle($event) && \in_array($event->getProperty(), ['name', 'description']))) { + if (!($this->wantToHandle($event) && in_array($event->getProperty(), ['name', 'description']))) { return; } $metaModel = $this->getMetaModelByModelPid($event->getModel()); @@ -108,7 +111,7 @@ public function encodeValue(EncodePropertyValueFromWidgetEvent $event) */ public function buildWidget(BuildWidgetEvent $event) { - if (!($this->wantToHandle($event) && \in_array($event->getProperty()->getName(), ['name', 'description']))) { + if (!($this->wantToHandle($event) && in_array($event->getProperty()->getName(), ['name', 'description']))) { return; } @@ -118,8 +121,8 @@ public function buildWidget(BuildWidgetEvent $event) $event->getEnvironment(), $event->getProperty(), $metaModel, - $this->translator->trans('tl_metamodel_attribute.name_langcode', [], 'contao_tl_metamodel_attribute'), - $this->translator->trans('tl_metamodel_attribute.name_value', [], 'contao_tl_metamodel_attribute'), + 'name_langcode', + 'name_value', false, StringUtil::deserialize($event->getModel()->getProperty($event->getProperty()->getName()), true) ); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/BackendSectionOptionListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/BackendSectionOptionListener.php index c6f8a60c9..b3fc1af91 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/BackendSectionOptionListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/BackendSectionOptionListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -14,21 +14,36 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table\Dca; +use Contao\Controller; +use Contao\CoreBundle\Framework\ContaoFramework; +use Contao\CoreBundle\Menu\BackendMenuBuilder; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use Knp\Menu\ItemInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +use function array_diff; +use function array_keys; /** * This provides the backend section options. */ class BackendSectionOptionListener { + public function __construct( + private BackendMenuBuilder $builder, + private TranslatorInterface $translator, + private ContaoFramework $framework, + ) { + } + /** * Retrieve a list of all backend sections, like "content", "system" etc. * @@ -51,6 +66,26 @@ public function handle(GetPropertyOptionsEvent $event) return; } - $event->setOptions(\array_keys($GLOBALS['BE_MOD'])); + $options = []; + foreach ($this->getMenu()->getChildren() as $option) { + $label = $option->getLabel(); + if (false !== $domain = $option->getExtra('translation_domain')) { + $label = $this->translator->trans($label, $option->getExtra('translation_params') ?? [], $domain); + } + + $options[$option->getName()] = $label; + } + + $event->setOptions($options); + } + + private function getMenu(): ItemInterface + { + // Work around legacy Contao code - Menu builder loads via global lang array instead of translator. + /** @psalm-suppress InternalMethod - Class ContaoFramework is internal, not the getAdapter() method. */ + $contaoController = $this->framework->getAdapter(Controller::class); + $contaoController->loadLanguageFile('modules'); + + return $this->builder->buildMainMenu(); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php index e2f5a8d41..74358c1b7 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/Dca/RenderModeHintListener.php @@ -75,11 +75,7 @@ public function handle(BuildWidgetEvent $event) if ('hierarchical' === $model->getProperty('rendermode')) { Message::addInfo( - $this->translator->trans( - 'tl_metamodel_dca.hint_rendermode_hierarchical', - [], - 'contao_tl_metamodel_dca' - ) + $this->translator->trans('hint_rendermode_hierarchical', [], 'tl_metamodel_dca') ); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php index d71ef9133..2dded529e 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableMandatoryListener.php @@ -92,11 +92,7 @@ public function handle(BuildWidgetEvent $event) if ($attribute->get('isunique')) { Message::addInfo( - $this->translator->trans( - 'tl_metamodel_dcasetting.mandatory_for_unique_attr', - [], - 'contao_tl_metamodel_dcasetting' - ) + $this->translator->trans('mandatory_for_unique_attr', [], 'tl_metamodel_dcasetting') ); $extra = $event->getProperty()->getExtra(); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php index 0bb5568dd..78228858d 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/DisableReadOnlyListener.php @@ -93,11 +93,7 @@ public function handle(BuildWidgetEvent $event) if ($attribute->get('force_alias')) { Message::addInfo( - $this->translator->trans( - 'tl_metamodel_dcasetting.readonly_for_force_alias', - [], - 'contao_tl_metamodel_dcasetting' - ) + $this->translator->trans('readonly_for_force_alias', [], 'tl_metamodel_dcasetting') ); $extra = $event->getProperty()->getExtra(); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php index 488551d61..4dcb4aa8c 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/EditMaskSubHeadlineListener.php @@ -114,7 +114,7 @@ public function __invoke(GetEditMaskSubHeadlineEvent $event): void // Translate language key and add headline part. $subHeadline = - $this->translator->trans('tl_metamodel_item.editRecord', [0 => $headlineAdd], 'contao_tl_metamodel_item'); + $this->translator->trans('editRecord', ['%item%' => $headlineAdd], $metaModelName); $event->setHeadline($subHeadline); } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php index 8aea94cfd..16e7e87ba 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/ModelToLabelListener.php @@ -160,7 +160,7 @@ private function drawAttribute(ModelToLabelEvent $event) $name, // unique attributes are automatically mandatory. (bool) $model->getProperty('mandatory') || $isUnique - ? ' [' . $this->trans('mandatory.0') . ']' + ? ' [' . $this->trans('mandatory.label') . ']' : '', $model->getProperty('tl_class') ? \sprintf('[%s]', $model->getProperty('tl_class')) : '' ]); @@ -197,7 +197,7 @@ private function drawLegend(ModelToLabelEvent $event)
    %s%s
    ') ->setArgs([ $model->getProperty('published') ? 'published' : 'unpublished', - $this->trans('dcatypes.legend'), + $this->translator->trans('dcatypes.legend', [], 'tl_metamodel_dcasetting'), $legend, $model->getProperty('legendhide') ? ':hide' : '' ]); @@ -212,6 +212,6 @@ private function drawLegend(ModelToLabelEvent $event) */ private function trans($key) { - return $this->translator->trans('tl_metamodel_dcasetting.' . $key, [], 'contao_tl_metamodel_dcasetting'); + return $this->translator->trans($key, [], 'tl_metamodel_dcasetting'); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/SetVisibilityConditionIconListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/SetVisibilityConditionIconListener.php index 21f1a8c6c..b9374b923 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/SetVisibilityConditionIconListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSetting/SetVisibilityConditionIconListener.php @@ -27,7 +27,6 @@ use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\View\CommandInterface; use Contao\Image; use Contao\StringUtil; -use MetaModels\IMetaModel; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** @@ -82,9 +81,9 @@ public function handle(GetOperationButtonEvent $event): void $command->getName(), $event->getHref() ?? '', StringUtil::specialchars( - \sprintf($command->getDescription(), $model->getID()) + \sprintf($event->getTitle(), $model->getID()) ), - $this->renderImageAsHtml($event, $icon, $command->getLabel()) + $this->renderImageAsHtml($event, $icon, $event->getLabel()) ); $event->setHtml($button); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php index 913f3840e..0d3cf22f8 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/ModelToLabelListener.php @@ -93,28 +93,28 @@ public function handle(ModelToLabelEvent $event) $type = $model->getProperty('type'); $parameterValue = (\is_array($model->getProperty('value')) ? \implode(', ', $model->getProperty('value')) - : $model->getProperty('value')); - - $name = $this->translator->trans( - 'tl_metamodel_dcasetting_condition.conditionnames.' . $type, - [], - 'contao_tl_metamodel_dcasetting_condition' + : $model->getProperty('value') ); + $name = $this->translator->trans('conditionnames.' . $type, [], 'tl_metamodel_dcasetting_condition'); + + $params = [ + '%icon%' => $this->iconBuilder->getBackendIconImageTag( + 'bundles/metamodelscore/images/icons/filter_default.png', + $name, + '', + 'bundles/metamodelscore/images/icons/filter_default.png' + ), + '%name%' => $name, + '%attribute%' => $attribute ? $attribute->getName() : '' . $model->getProperty('attr_id'), + '%value%' => $parameterValue, + '%comment%' => '' !== ($comment = $model->getProperty('comment')) ? '
    ' . $comment : '', + ]; + /** @psalm-suppress InvalidArgument */ $event - ->setLabel($this->getLabelText($type)) - ->setArgs([ - $this->iconBuilder->getBackendIconImageTag( - 'bundles/metamodelscore/images/icons/filter_default.png', - $name, - '', - 'bundles/metamodelscore/images/icons/filter_default.png' - ), - $name, - $attribute ? $attribute->getName() : '' . $model->getProperty('attr_id'), - $parameterValue - ]); + ->setLabel($this->getLabelText($type, $params)) + ->setArgs(array_values($params)); } /** @@ -136,25 +136,18 @@ protected function wantToHandle(AbstractEnvironmentAwareEvent $event) /** * Retrieve the label text for a condition setting or the default one. * - * @param string $type The type of the element. + * @param string $type The type of the element. + * @param array $params The params. * * @return string */ - private function getLabelText($type) + private function getLabelText(string $type, array $params): string { - $label = $this->translator->trans( - 'tl_metamodel_dcasetting_condition.typedesc.' . $type, - [], - 'contao_tl_metamodel_dcasetting_condition' - ); + $label = $this->translator->trans('typedesc.' . $type, $params, 'tl_metamodel_dcasetting_condition'); - if ($label === 'tl_metamodel_dcasetting_condition.typedesc.' . $type) { - $label = $this->translator->trans( - 'tl_metamodel_dcasetting_condition.typedesc._default_', - [], - 'contao_tl_metamodel_dcasetting_condition' - ); - if ($label === 'tl_metamodel_dcasetting_condition.typedesc._default_') { + if ($label === 'typedesc.' . $type) { + $label = $this->translator->trans('typedesc._default_', $params, 'tl_metamodel_dcasetting_condition'); + if ($label === 'typedesc._default_') { return $type; } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/TypeOptionsListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/TypeOptionsListener.php index caf51b690..d8baa556c 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/TypeOptionsListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSettingCondition/TypeOptionsListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -39,7 +39,7 @@ class TypeOptionsListener extends AbstractConditionFactoryUsingListener * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * Create a new instance. @@ -79,11 +79,8 @@ public function handle(GetPropertyOptionsEvent $event) $options = []; foreach ($this->conditionFactory->getTypeNames() as $condition) { - $options[$condition] = $this->translator->trans( - 'tl_metamodel_dcasetting_condition.conditionnames.' . $condition, - [], - 'contao_tl_metamodel_dcasetting_condition' - ); + $options[$condition] = + $this->translator->trans('conditionnames.' . $condition, [], 'tl_metamodel_dcasetting_condition'); } $event->setOptions($options); diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/ModelToLabelListener.php index ecee9d311..4c771d4b6 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DcaSortGroup/ModelToLabelListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -76,7 +76,7 @@ public function handle(ModelToLabelEvent $event) sprintf( '%s [%s]', $event->getLabel(), - $this->translator->trans('MSC.fallback', [], 'contao_default') + $this->translator->trans('fallback', [], 'metamodels_default') ) ); } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/DeleteOperationButtonListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/DeleteOperationButtonListener.php new file mode 100755 index 000000000..e72766218 --- /dev/null +++ b/src/CoreBundle/EventListener/DcGeneral/Table/DeleteOperationButtonListener.php @@ -0,0 +1,122 @@ + + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\EventListener\DcGeneral\Table; + +use ContaoCommunityAlliance\DcGeneral\Contao\RequestScopeDeterminator; +use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetOperationButtonEvent; +use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\View\CommandInterface; +use ContaoCommunityAlliance\DcGeneral\Event\AbstractEnvironmentAwareEvent; +use Symfony\Contracts\Translation\TranslatorInterface; + +use function assert; +use function in_array; +use function str_starts_with; + +/** + * This provides the attribute name options. + */ +class DeleteOperationButtonListener +{ + public function __construct( + private readonly RequestScopeDeterminator $scopeDeterminator, + private readonly TranslatorInterface $translator + ) { + } + + /** + * Update the delete button attributes for MetaModels tables. + * + * @param GetOperationButtonEvent $event The event. + * + * @return void + */ + public function handle(GetOperationButtonEvent $event) + { + if (!$this->wantToHandle($event)) { + return; + } + + $model = $event->getModel(); + assert($model instanceof ModelInterface); + + $attributes = $event->getAttributes(); + + + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + $event->setAttributes( + 'data-msg-confirm="' . $this->translator->trans( + 'delete.confirm', + [ + '%id%' => $model->getID() + ], + $dataDefinition->getName() + ) . '" ' + . $attributes + ); + } + + /** + * Test if the event is for the correct table and in backend scope. + * + * @param AbstractEnvironmentAwareEvent $event The event to test. + * + * @return bool + */ + protected function wantToHandle(AbstractEnvironmentAwareEvent $event) + { + /** @var GetOperationButtonEvent $event */ + $command = $event->getCommand(); + assert($command instanceof CommandInterface); + + if ('delete' !== $command->getName()) { + return false; + } + + if (!$this->scopeDeterminator->currentScopeIsBackend()) { + return false; + } + + $dataDefinition = $event->getEnvironment()->getDataDefinition(); + assert($dataDefinition instanceof ContainerInterface); + + return str_starts_with($dataDefinition->getName(), 'mm_') + || in_array( + $dataDefinition->getName(), + [ + 'tl_metamodel', + 'tl_metamodel_attribute', + 'tl_metamodel_dca', + 'tl_metamodel_dca_sortgroup', + 'tl_metamodel_dcasetting', + 'tl_metamodel_dcasetting_condition', + 'tl_metamodel_filter', + 'tl_metamodel_filtersetting', + 'tl_metamodel_rendersetting', + 'tl_metamodel_rendersettings', + 'tl_metamodel_searchable_pages', + ] + ); + } +} diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php index fe7897979..8c9451abd 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/FilterSetting/AbstractFilterSettingTypeRenderer.php @@ -152,11 +152,13 @@ abstract protected function getTypes(); protected function getLabelComment(ModelInterface $model, TranslatorInterface $translator) { if ($model->getProperty('comment')) { - return \sprintf( - $translator->translate('typedesc._comment_', 'tl_metamodel_filtersetting'), - StringUtil::specialchars($model->getProperty('comment')) + return $translator->translate( + 'typedesc._comment_', + 'tl_metamodel_filtersetting', + ['%comment%' => StringUtil::specialchars($model->getProperty('comment'))] ); } + return ''; } @@ -262,16 +264,21 @@ protected function getLabelParametersWithAttributeAndUrlParam( return [ $this->getLabelImage($model), $this->getLabelText($translator, $model), - \sprintf( - $translator->translate('typedesc._attribute_', 'tl_metamodel_filtersetting'), - $attributeColumnName, - $attributeName + $translator->translate( + 'typedesc._attribute_', + 'tl_metamodel_filtersetting', + ['%colName%' => $attributeColumnName, '%name%' => $attributeName], ), $this->getLabelComment($model, $translator), - \sprintf( - $translator->translate('typedesc._url_', 'tl_metamodel_filtersetting'), - ($model->getProperty('urlparam') ? $model->getProperty('urlparam') : $attributeColumnName) - ) + $translator->translate( + 'typedesc._url_', + 'tl_metamodel_filtersetting', + [ + '%urlparam%' => ($model->getProperty('urlparam') + ? $model->getProperty('urlparam') + : $attributeColumnName) + ] + ), ]; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelSchemaManagerHintListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelSchemaManagerHintListener.php index 4131e8f3c..9b6cfd17f 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelSchemaManagerHintListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelSchemaManagerHintListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,7 @@ * * @package MetaModels/core * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -61,12 +61,6 @@ public function handle(PreEditModelEvent $event): void return; } - Message::addInfo( - $this->translator->trans( - 'tl_metamodel.hint_schema_manager', - [], - 'contao_tl_metamodel' - ) - ); + Message::addInfo($this->translator->trans('hint_schema_manager', [], 'tl_metamodel')); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php index 91411b630..33bd8edaa 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/ModelToLabelListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -81,8 +81,7 @@ public function handle(ModelToLabelEvent $event): void $model = $event->getModel(); $tableName = $model->getProperty('tableName'); - $count = '?'; - $transId = 'tl_metamodel.itemFormatCount.0'; + $count = -1; if (!empty($tableName) && $this->connection->createSchemaManager()->tablesExist([$tableName])) { $count = $this->connection ->createQueryBuilder() @@ -90,17 +89,6 @@ public function handle(ModelToLabelEvent $event): void ->from($tableName, 't') ->executeQuery() ->fetchOne(); - - switch ($count) { - case 0: - $transId = 'tl_metamodel.itemFormatCount.0'; - break; - case 1: - $transId = 'tl_metamodel.itemFormatCount.1'; - break; - default: - $transId = 'tl_metamodel.itemFormatCount.2:'; - } } // Keep the previous label. @@ -119,7 +107,7 @@ public function handle(ModelToLabelEvent $event): void $image, $label, $tableName, - $this->translator->trans($transId, [$count], 'contao_tl_metamodel') + $this->translator->trans('itemFormatCount.label', ['%count%' => $count], 'tl_metamodel') ]); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php index 75c5d3c00..e0027934f 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/MetaModel/TableNamePrefixingListener.php @@ -87,8 +87,11 @@ public function handle(EncodePropertyValueFromWidgetEvent $event): void // See #49 (We can no longer find the correct issue number... :(). $tableName = \strtolower($event->getValue()); + $translator = $event->getEnvironment()->getTranslator(); + assert($translator instanceof TranslatorInterface); + if ('' === $tableName) { - throw new \RuntimeException('Table name not given'); + throw new \RuntimeException($translator->translate('ERR.tableNameNotGiven', 'tl_metamodel')); } // Force mm_ prefix. @@ -96,9 +99,6 @@ public function handle(EncodePropertyValueFromWidgetEvent $event): void $tableName = 'mm_' . $tableName; } - $translator = $event->getEnvironment()->getTranslator(); - assert($translator instanceof TranslatorInterface); - // New model, ensure the table does not exist. if (!$event->getModel()->getId()) { $this->checkTableName($tableName, $translator); @@ -123,14 +123,16 @@ private function checkTableName(string $tableName, TranslatorInterface $translat $this->tableManipulator->checkTablename($tableName); } catch (InvalidTableNameException $exception) { throw new \RuntimeException( - \sprintf($translator->translate('ERR.invalidTableName'), $tableName), + $translator->translate('ERR.invalidTableName', 'tl_metamodel', ['%table_name%' => $tableName]), $exception->getCode(), $exception ); } $model = $this->factory->getMetaModel($tableName); if (null !== $model) { - throw new \RuntimeException(\sprintf($translator->translate('ERR.tableExists'), $tableName)); + throw new \RuntimeException( + $translator->translate('ERR.tableExists', 'tl_metamodel', ['%table_name%' => $tableName]) + ); } } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php index 11a5bc032..850215805 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSetting/ModelToLabelListener.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2022 The MetaModels team. + * (c) 2012-2024 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 Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -40,21 +40,21 @@ class ModelToLabelListener extends AbstractListener * * @var IAttributeFactory */ - private $attributeFactory; + private IAttributeFactory $attributeFactory; /** * The icon builder. * * @var IconBuilder */ - private $iconBuilder; + private IconBuilder $iconBuilder; /** * The translator. * * @var TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; /** * Create a new instance. @@ -110,7 +110,7 @@ public function handle(ModelToLabelEvent $event) $name = $attribute->getName(); $colName = $attribute->getColName(); } else { - $type = $this->trans('error_unknown_id', [$model->getProperty('attr_id')]); + $type = $this->trans('error_unknown_id', ['%id%' => $model->getProperty('attr_id')]); $image = $this->iconBuilder->getBackendIconImageTag('bundles/metamodelscore/images/icons/fields.png'); $variant = ''; $name = $this->trans('error_unknown_attribute'); @@ -137,17 +137,12 @@ public function handle(ModelToLabelEvent $event) * Translate a key. * * @param string $key The key to translate. - * * @param array $params The parameters. * * @return string */ - private function trans($key, $params = []) + private function trans(string $key, array $params = []): string { - return $this->translator->trans( - 'tl_metamodel_rendersettings.' . $key, - $params, - 'contao_tl_metamodel_rendersettings' - ); + return $this->translator->trans($key, $params, 'tl_metamodel_rendersettings'); } } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php index dfe0708c3..0efaac7be 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/JumpToListener.php @@ -178,18 +178,23 @@ public function buildWidget(BuildWidgetEvent $event) /** @psalm-suppress DeprecatedMethod */ if ($metaModel->isTranslated()) { + /** @psalm-suppress DeprecatedMethod */ + $fallback = $metaModel->getFallbackLanguage(); + $arrLanguages = []; + $rowClasses = []; /** @psalm-suppress DeprecatedMethod */ foreach ((array) $metaModel->getAvailableLanguages() as $strLangCode) { $arrLanguages[$strLangCode] = $this->translator ->trans('LNG.' . $strLangCode, [], 'contao_languages'); + $rowClasses[] = ($strLangCode === $fallback) ? 'fallback_language' : 'normal_language'; } - asort($arrLanguages); $extra['minCount'] = \count($arrLanguages); $extra['maxCount'] = \count($arrLanguages); - $extra['columnFields']['langcode']['options'] = $arrLanguages; + $extra['columnFields']['langcode']['options'] = $arrLanguages; + $extra['columnFields']['langcode']['eval']['rowClasses'] = $rowClasses; } else { $extra['minCount'] = 1; $extra['maxCount'] = 1; @@ -197,9 +202,9 @@ public function buildWidget(BuildWidgetEvent $event) $extra['columnFields']['langcode']['options'] = [ 'xx' => $this->translator ->trans( - 'tl_metamodel_rendersettings.jumpTo_allLanguages', + 'jumpTo_allLanguages', [], - 'contao_tl_metamodel_rendersettings' + 'tl_metamodel_rendersettings' ) ]; } diff --git a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/LanguageCodeWizardListener.php b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/LanguageCodeWizardListener.php index 04ca987f5..c9db4b37b 100644 --- a/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/LanguageCodeWizardListener.php +++ b/src/CoreBundle/EventListener/DcGeneral/Table/RenderSettings/LanguageCodeWizardListener.php @@ -92,7 +92,7 @@ public function pagePicker(ManipulateWidgetEvent $event) $urlEvent = new GenerateHtmlEvent( 'pickpage.svg', - $translator->translate('MSC.pagepicker'), + $translator->translate('pagePicker', 'dc-general'), 'style="vertical-middle:top;cursor:pointer"' ); @@ -106,7 +106,7 @@ public function pagePicker(ManipulateWidgetEvent $event) ->set('name', $event->getWidget()->name) ->set('popupUrl', $pickerUrl) ->set('html', ' ' . (string) $urlEvent->getHtml()) - ->set('label', $event->getProperty()->getLabel()[1]) + ->set('label', $translator->translate($event->getProperty()->getLabel(), $dataDefinition->getName())) ->set('id', $event->getWidget()->id); $event->getWidget()->wizard = $template->parse(); diff --git a/src/CoreBundle/EventListener/UserListener.php b/src/CoreBundle/EventListener/UserListener.php index 61970ad3a..a180ca03e 100644 --- a/src/CoreBundle/EventListener/UserListener.php +++ b/src/CoreBundle/EventListener/UserListener.php @@ -119,6 +119,7 @@ public function onKernelRequest(RequestEvent $event) */ private function buildBackendModules(&$localMenu) { + return; foreach ($this->viewCombination->getStandalone() as $metaModelName => $screen) { $section = $screen['meta']['backendsection']; if (!isset($localMenu[$section])) { diff --git a/src/CoreBundle/MetaModelsCoreBundle.php b/src/CoreBundle/MetaModelsCoreBundle.php index 6a1bb7069..2f2619730 100644 --- a/src/CoreBundle/MetaModelsCoreBundle.php +++ b/src/CoreBundle/MetaModelsCoreBundle.php @@ -25,6 +25,7 @@ use MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectFactoriesPass; use MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectSchemaGeneratorsPass; use MetaModels\CoreBundle\DependencyInjection\CompilerPass\CollectSchemaManagersPass; +use MetaModels\CoreBundle\DependencyInjection\CompilerPass\PrepareTranslatorPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; @@ -44,5 +45,6 @@ public function build(ContainerBuilder $container): void $container->addCompilerPass(new CollectSchemaGeneratorsPass()); $container->addCompilerPass(new CollectSchemaManagersPass()); $container->addCompilerPass(new CollectDoctrineSchemaGeneratorsPass()); + $container->addCompilerPass(new PrepareTranslatorPass()); } } diff --git a/src/CoreBundle/Resources/config/dc-general/environment-populator.yml b/src/CoreBundle/Resources/config/dc-general/environment-populator.yml index 41a1cf2bb..bcf4016b5 100644 --- a/src/CoreBundle/Resources/config/dc-general/environment-populator.yml +++ b/src/CoreBundle/Resources/config/dc-general/environment-populator.yml @@ -32,6 +32,7 @@ services: arguments: - "@event_dispatcher" - "@metamodels.view_combination" + - "@translator" tags: - name: kernel.event_listener event: dc-general.factory.populate-environment diff --git a/src/CoreBundle/Resources/config/dc-general/listener.yml b/src/CoreBundle/Resources/config/dc-general/listener.yml index b9a3f4dea..b8f349f08 100644 --- a/src/CoreBundle/Resources/config/dc-general/listener.yml +++ b/src/CoreBundle/Resources/config/dc-general/listener.yml @@ -48,3 +48,12 @@ services: - name: kernel.event_listener event: dc-general.view.contao2backend.get-paste-root-button method: handleRoot + + MetaModels\CoreBundle\EventListener\DcGeneral\Table\DeleteOperationButtonListener: + arguments: + - "@cca.dc-general.scope-matcher" + - "@translator" + tags: + - name: kernel.event_listener + event: dc-general.view.contao2backend.get-operation-button + method: handle diff --git a/src/CoreBundle/Resources/config/dc-general/table/tl_dca.yml b/src/CoreBundle/Resources/config/dc-general/table/tl_dca.yml index 3f40d2fec..bb5a08dce 100644 --- a/src/CoreBundle/Resources/config/dc-general/table/tl_dca.yml +++ b/src/CoreBundle/Resources/config/dc-general/table/tl_dca.yml @@ -1,6 +1,10 @@ services: metamodels.dc_general.table.tl_metamodel_dca.backend_section_options: class: MetaModels\CoreBundle\EventListener\DcGeneral\Table\Dca\BackendSectionOptionListener + arguments: + - '@contao.menu.backend_builder' + - '@translator' + - '@contao.framework' tags: - name: kernel.event_listener event: dc-general.view.contao2backend.get-property-options diff --git a/src/CoreBundle/Resources/config/hooks.yml b/src/CoreBundle/Resources/config/hooks.yml index 3f92b9c1a..684bc41e2 100644 --- a/src/CoreBundle/Resources/config/hooks.yml +++ b/src/CoreBundle/Resources/config/hooks.yml @@ -19,6 +19,7 @@ services: - '@database_connection' - '@metamodels.template_list' - '@request_stack' + - '@translator' public: true MetaModels\CoreBundle\Contao\Hooks\ModuleCallback: @@ -30,6 +31,7 @@ services: - '@database_connection' - '@metamodels.template_list' - '@request_stack' + - '@translator' public: true MetaModels\CoreBundle\EventListener\GetSearchablePagesListener: diff --git a/src/CoreBundle/Resources/config/listeners.yml b/src/CoreBundle/Resources/config/listeners.yml index ded769c9f..d5959e8e7 100644 --- a/src/CoreBundle/Resources/config/listeners.yml +++ b/src/CoreBundle/Resources/config/listeners.yml @@ -81,6 +81,7 @@ services: - '@metamodels.view_combination' - '@security.token_storage' - '@router' + - '@session' tags: - { name: kernel.event_listener } diff --git a/src/CoreBundle/Resources/config/routing.yml b/src/CoreBundle/Resources/config/routing.yml index 296521506..e786c10b8 100644 --- a/src/CoreBundle/Resources/config/routing.yml +++ b/src/CoreBundle/Resources/config/routing.yml @@ -9,3 +9,19 @@ metamodels.support_screen: metamodels.rendersetting.add_all: path: /contao/metamodels/rendersetting/add-all/{metaModel}/{renderSetting} defaults: { _controller: metamodels.controller.rendersetting.add_all, _scope: backend, _token_check: true } + +metamodels.configuration: + path: /contao/metamodels + defaults: + _controller: MetaModels\CoreBundle\Controller\Backend\ConfigurationController + _scope: backend + _dcg_referer_update: true + _token_check: true + +metamodels.metamodel: + path: /contao/metamodel/{tableName} + defaults: + _controller: MetaModels\CoreBundle\Controller\Backend\MetaModelController + _scope: backend + _dcg_referer_update: true + _token_check: true diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index 6062f0181..25ca2647c 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -1,6 +1,10 @@ parameters: metamodels.managed-schema-type-names: [] services: + _defaults: + bind: + $translator: '@cca.translator.contao_translator' + MetaModels\IFactory: '@metamodels.factory' MetaModels\Filter\Setting\IFilterSettingFactory: '@metamodels.filter_setting_factory' MetaModels\Render\Setting\IRenderSettingFactory: '@metamodels.render_setting_factory' @@ -74,6 +78,7 @@ services: - "@database_connection" - "%contao.resources_paths%" - "%kernel.project_dir%" + - "@translator" metamodels.contao_input: class: Contao\Input @@ -142,6 +147,14 @@ services: parent: metamodels.controller.abstract.add_all tags: ['controller.service_arguments'] + MetaModels\CoreBundle\Controller\Backend\ConfigurationController: + tags: ['controller.service_arguments'] + + MetaModels\CoreBundle\Controller\Backend\MetaModelController: + arguments: + - '@contao.menu.backend_builder' + tags: ['controller.service_arguments'] + metamodels.controller.support_screen: class: MetaModels\CoreBundle\Controller\Backend\SupportMetaModelsController arguments: @@ -285,10 +298,20 @@ services: - "@contao.image.picture_factory" - "@session" + MetaModels\CoreBundle\Translator\MetaModelTranslatorConfigurator: + arguments: + $factory: '@metamodels.factory' + $cache: '@metamodels.cache_internal' + MetaModels\CoreBundle\Translator\Translator: decorates: 'contao.translation.translator' arguments: - '@MetaModels\CoreBundle\Translator\Translator.inner' MetaModels\CoreBundle\Translator\MetaModelTranslationLoader: + arguments: + $baseTranslator: '@contao.translation.translator' + $factory: '@metamodels.factory' + $viewCombination: '@metamodels.view_combination' + $builder: '@metamodels.view_combination.input_screen_information_builder' tags: [ { name: translation.loader, alias: 'metamodels' } ] diff --git a/src/CoreBundle/Resources/contao/config/config.php b/src/CoreBundle/Resources/contao/config/config.php index 268f55429..53f711b94 100644 --- a/src/CoreBundle/Resources/contao/config/config.php +++ b/src/CoreBundle/Resources/contao/config/config.php @@ -26,46 +26,10 @@ * @filesource */ -// Preserve values by extensions but insert as first entry after 'system'. -$arrOld = isset($GLOBALS['BE_MOD']['metamodels']) ? $GLOBALS['BE_MOD']['metamodels'] : array(); -unset($GLOBALS['BE_MOD']['metamodels']); -\Contao\ArrayUtil::arrayInsert( - $GLOBALS['BE_MOD'], - (array_search('accounts', array_keys($GLOBALS['BE_MOD'])) + 1), - array - ( - 'metamodels' => array_replace_recursive( - array - ( - 'metamodels' => array - ( - 'tables' => array - ( - 'tl_metamodel', - 'tl_metamodel_attribute', - 'tl_metamodel_filter', - 'tl_metamodel_filtersetting', - 'tl_metamodel_rendersettings', - 'tl_metamodel_rendersetting', - 'tl_metamodel_dca_sortgroup', - 'tl_metamodel_dca', - 'tl_metamodel_dcasetting', - 'tl_metamodel_dca_combine', - 'tl_metamodel_dcasetting_condition', - 'tl_metamodel_searchable_pages' - ), - 'icon' => 'bundles/metamodelscore/images/backend/logo.png', - 'callback' => 'MetaModels\BackendIntegration\Module' - ) - ), - // Append all previous data here. - $arrOld - ) - ) -); +$container = \Contao\System::getContainer(); // @deprecated Use the config parameter metamodels.system_columns instead. -$GLOBALS['METAMODELS_SYSTEM_COLUMNS'] = \Contao\System::getContainer()->getParameter('metamodels.system_columns'); +$GLOBALS['METAMODELS_SYSTEM_COLUMNS'] = $container->getParameter('metamodels.system_columns'); // Front-end modules. $GLOBALS['FE_MOD']['metamodels']['metamodels_frontendfilter'] = 'MetaModels\FrontendIntegration\Module\Filter'; @@ -86,10 +50,10 @@ array('MetaModels\FrontendIntegration\FrontendFilter', 'generateClearAll'); // Add cache only if dir defined in container (and therefore we are using the cache). -if ($cacheDir = \Contao\System::getContainer()->getParameter('metamodels.cache_dir')) { +if ($cacheDir = $container->getParameter('metamodels.cache_dir')) { // We need to translate the cache dir - otherwise the backend view is distorted. See \Contao\PurgeData::run(). $GLOBALS['TL_PURGE']['folders']['metamodels']['affected'] = [str_replace( - \Contao\System::getContainer()->getParameter('kernel.cache_dir') . '/', + $container->getParameter('kernel.cache_dir') . '/', '%s/', $cacheDir )]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_content.php b/src/CoreBundle/Resources/contao/dca/tl_content.php old mode 100644 new mode 100755 diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel.php index 99ffe2c3f..5a1b0921f 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,7 +21,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Cliff Parnitzky - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -314,72 +314,80 @@ ], 'global_operations' => [ 'all' => [ - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'all.label', + 'description' => 'all.description', + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ], ], 'operations' => [ 'edit' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['editheader'], - 'href' => 'act=edit', - 'icon' => 'edit.svg', + 'label' => 'editheader.label', + 'description' => 'editheader.description', + 'href' => 'act=edit', + 'icon' => 'edit.svg', ], 'cut' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['cut'], - 'href' => 'act=paste&mode=cut', - 'icon' => 'cut.svg' + 'label' => 'cut.label', + 'description' => 'cut.description', + 'href' => 'act=paste&mode=cut', + 'icon' => 'cut.svg' ], 'delete' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['tl_metamodel']['deleteConfirm'] ?? '' - ) + 'label' => 'delete.label', + 'description' => 'delete.description', + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ], 'show' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' + 'label' => 'show.label', + 'description' => 'show.description', + 'href' => 'act=show', + 'icon' => 'show.svg' ], 'fields' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['fields'], - 'href' => 'table=tl_metamodel_attribute', - 'icon' => 'bundles/metamodelscore/images/icons/fields.png', - 'idparam' => 'pid' + 'label' => 'fields.label', + 'description' => 'fields.description', + 'href' => 'table=tl_metamodel_attribute', + 'icon' => 'bundles/metamodelscore/images/icons/fields.png', + 'idparam' => 'pid' ], 'rendersettings' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['rendersettings'], - 'href' => 'table=tl_metamodel_rendersettings', - 'icon' => 'bundles/metamodelscore/images/icons/rendersettings.png', - 'idparam' => 'pid' + 'label' => 'rendersettings.label', + 'description' => 'rendersettings.description', + 'href' => 'table=tl_metamodel_rendersettings', + 'icon' => 'bundles/metamodelscore/images/icons/rendersettings.png', + 'idparam' => 'pid' ], 'dca' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['dca'], - 'href' => 'table=tl_metamodel_dca', - 'icon' => 'bundles/metamodelscore/images/icons/dca.png', - 'idparam' => 'pid' + 'label' => 'dca.label', + 'description' => 'dca.description', + 'href' => 'table=tl_metamodel_dca', + 'icon' => 'bundles/metamodelscore/images/icons/dca.png', + 'idparam' => 'pid' ], 'searchable_pages' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['searchable_pages'], - 'href' => 'table=tl_metamodel_searchable_pages', - 'icon' => 'bundles/metamodelscore/images/icons/searchable_pages.png', - 'idparam' => 'pid' + 'label' => 'searchable_pages.label', + 'description' => 'searchable_pages.description', + 'href' => 'table=tl_metamodel_searchable_pages', + 'icon' => 'bundles/metamodelscore/images/icons/searchable_pages.png', + 'idparam' => 'pid' ], 'filter' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['filter'], - 'href' => 'table=tl_metamodel_filter', - 'icon' => 'bundles/metamodelscore/images/icons/filter.png', - 'idparam' => 'pid' + 'label' => 'filter.label', + 'description' => 'filter.description', + 'href' => 'table=tl_metamodel_filter', + 'icon' => 'bundles/metamodelscore/images/icons/filter.png', + 'idparam' => 'pid' ], 'dca_combine' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['dca_combine'], - 'href' => 'table=tl_metamodel_dca_combine&act=edit', - 'icon' => 'bundles/metamodelscore/images/icons/dca_combine.png', - 'idparam' => 'pid' + 'label' => 'dca_combine.label', + 'description' => 'dca_combine.description', + 'href' => 'table=tl_metamodel_dca_combine&act=edit', + 'icon' => 'bundles/metamodelscore/images/icons/dca_combine.png', + 'idparam' => 'pid' ], ] ], @@ -407,41 +415,46 @@ ], 'fields' => [ 'id' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['id'], - 'sql' => 'int(10) unsigned NOT NULL auto_increment' + 'label' => 'id.label', + 'description' => 'id.description', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'tstamp' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['tstamp'], - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'tstamp.label', + 'description' => 'tstamp.description', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['sorting'], - 'sorting' => true, - 'flag' => 11, - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'sorting.label', + 'description' => 'sorting.description', + 'sorting' => true, + 'flag' => 11, + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'name' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['name'], - 'sorting' => true, - 'flag' => 3, - 'length' => 1, - 'exclude' => true, - 'inputType' => 'text', - 'search' => true, - 'eval' => [ + 'label' => 'name.label', + 'description' => 'name.description', + 'sorting' => true, + 'flag' => 3, + 'length' => 1, + 'exclude' => true, + 'inputType' => 'text', + 'search' => true, + 'eval' => [ 'mandatory' => true, 'maxlength' => 255, 'tl_class' => 'w50' ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], 'tableName' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['tableName'], - 'sorting' => true, - 'exclude' => true, - 'inputType' => 'text', - 'search' => true, - 'eval' => [ + 'label' => 'tableName.label', + 'description' => 'tableName.description', + 'sorting' => true, + 'exclude' => true, + 'inputType' => 'text', + 'search' => true, + 'eval' => [ 'mandatory' => true, 'maxlength' => 64, 'doNotCopy' => true, @@ -449,65 +462,72 @@ // Hide at overrideAll. 'doNotOverrideMultiple' => true ], - 'sql' => "varchar(64) NOT NULL default ''" + 'sql' => "varchar(64) NOT NULL default ''" ], 'translated' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['translated'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'translated.label', + 'description' => 'translated.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'clr w50 cbx m12', 'submitOnChange' => true ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'languages' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['languages'], - 'exclude' => true, - 'inputType' => 'multiColumnWizard', - 'eval' => + 'label' => 'languages.label', + 'description' => 'languages.description', + 'exclude' => true, + 'inputType' => 'multiColumnWizard', + 'eval' => [ - 'tl_class' => 'clr w50', - 'columnFields' => [ + 'useTranslator' => true, + 'tl_class' => 'clr w50', + 'columnFields' => [ 'langcode' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['languages_langcode'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'languages_langcode.label', + 'description' => 'languages_langcode.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'style' => 'width:100%;', 'chosen' => 'true' ], ], 'isfallback' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['languages_isfallback'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'languages_isfallback.label', + 'description' => 'languages_isfallback.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'style' => 'width:100%;', ], ], ], ], - 'sql' => 'text NULL' + 'sql' => 'text NULL' ], 'varsupport' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['varsupport'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'varsupport.label', + 'description' => 'varsupport.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'clr w50' ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'localeterritorysupport' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel']['localeterritorysupport'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'localeterritorysupport.label', + 'description' => 'localeterritorysupport.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12', 'submitOnChange' => true ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], ], ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php index a75add074..729e8fb08 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_attribute.php @@ -175,37 +175,39 @@ ], 'global_operations' => [ 'all' => [ - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'all.label', + 'description' => 'all.description', + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ] ], 'operations' => [ 'edit' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['edit'], - 'href' => 'act=edit', - 'icon' => 'edit.svg' + 'label' => 'edit.label', + 'description' => 'edit.description', + 'href' => 'act=edit', + 'icon' => 'edit.svg' ], 'cut' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['cut'], - 'href' => 'act=paste&mode=cut', - 'icon' => 'cut.svg', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'cut.label', + 'description' => 'cut.description', + 'href' => 'act=paste&mode=cut', + 'icon' => 'cut.svg', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ], 'delete' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['tl_metamodel_attribute']['deleteConfirm'] ?? '' - ) + 'label' => 'delete.label', + 'description' => 'delete.description', + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ], 'show' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' + 'label' => 'show.label', + 'description' => 'show.description', + 'href' => 'act=show', + 'icon' => 'show.svg' ], ] ], @@ -228,8 +230,6 @@ 'isvariant', 'isunique' ], - 'metamodeloverview' => [], - 'backenddisplay' => [], ], // Default palette for MetaModelAttributeSimple derived types. // WARNING: even though it is empty, we have to keep it as otherwise @@ -249,27 +249,28 @@ // Fields. 'fields' => [ 'id' => [ - 'label' => 'id.0', + 'label' => 'id.label', 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'label' => 'pid.0', + 'label' => 'pid.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'label' => 'sorting.0', + 'label' => 'sorting.label', 'sorting' => true, 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'label' => 'tstamp.0', + 'label' => 'tstamp.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'type' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['type'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'type.label', + 'description' => 'type.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'includeBlankOption' => true, 'doNotSaveEmpty' => true, 'alwaysSave' => true, @@ -278,60 +279,65 @@ 'tl_class' => 'w50', 'chosen' => true ], - 'filter' => true, - 'search' => true, - 'sql' => "varchar(64) NOT NULL default ''" + 'filter' => true, + 'search' => true, + 'sql' => "varchar(64) NOT NULL default ''" ], 'name' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['name'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'name.label', + 'description' => 'name.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'tl_class' => 'clr' ], - 'search' => true, - 'sql' => 'text NULL' + 'search' => true, + 'sql' => 'text NULL' ], 'description' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['description'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'description.label', + 'description' => 'description.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'tl_class' => 'clr' ], - 'sql' => 'text NULL' + 'sql' => 'text NULL' ], // AVOID: doNotCopy => true, as child records won't be copied when copy metamodel. 'colname' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['colname'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'colname.label', + 'description' => 'colname.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'mandatory' => true, 'maxlength' => 64, 'tl_class' => 'w50', // Hide at overrideAll. 'doNotOverrideMultiple' => true ], - 'search' => true, - 'sql' => "varchar(64) NOT NULL default ''" + 'search' => true, + 'sql' => "varchar(64) NOT NULL default ''" ], 'isvariant' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['isvariant'], - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'isvariant.label', + 'description' => 'isvariant.description', + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12' ], - 'filter' => true, - 'sql' => "char(1) NOT NULL default ''" + 'filter' => true, + 'sql' => "char(1) NOT NULL default ''" ], 'isunique' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['isunique'], - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'isunique.label', + 'description' => 'isunique.description', + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12' ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], ] ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php index e212c9a16..f8da7c337 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,7 +21,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Cliff Parnitzky - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -98,7 +98,6 @@ ], ], ], - [ 'from' => 'tl_metamodel_dca', 'to' => 'tl_metamodel_dcasetting', @@ -132,48 +131,52 @@ ], 'global_operations' => [ 'all' => [ - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'all.label', + 'description' => 'all.description', + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ], ], 'operations' => [ 'edit' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['edit'], - 'href' => 'act=edit', - 'icon' => 'edit.svg', + 'label' => 'edit.label', + 'description' => 'edit.description', + 'href' => 'act=edit', + 'icon' => 'edit.svg', ], 'copy' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['copy'], - 'href' => 'act=copy', - 'icon' => 'copy.svg', + 'label' => 'copy.label', + 'description' => 'copy.description', + 'href' => 'act=copy', + 'icon' => 'copy.svg', ], 'delete' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['tl_metamodel_dca']['deleteConfirm'] ?? '' - ) + 'label' => 'delete.label', + 'description' => 'delete.description', + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ], 'show' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' + 'label' => 'show.label', + 'description' => 'show.description', + 'href' => 'act=show', + 'icon' => 'show.svg' ], 'groupsort_settings' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['groupsort_settings'], - 'href' => 'table=tl_metamodel_dca_sortgroup', - 'icon' => 'bundles/metamodelscore/images/icons/dca_groupsortsettings.png', - 'idparam' => 'pid' + 'label' => 'groupsort_settings.label', + 'description' => 'groupsort_settings.description', + 'href' => 'table=tl_metamodel_dca_sortgroup', + 'icon' => 'bundles/metamodelscore/images/icons/dca_groupsortsettings.png', + 'idparam' => 'pid' ], 'settings' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['settings'], - 'href' => 'table=tl_metamodel_dcasetting', - 'icon' => 'bundles/metamodelscore/images/icons/dca_setting.png', - 'idparam' => 'pid' + 'label' => 'settings.label', + 'description' => 'settings.description', + 'href' => 'table=tl_metamodel_dcasetting', + 'icon' => 'bundles/metamodelscore/images/icons/dca_setting.png', + 'idparam' => 'pid' ], ] ], @@ -223,141 +226,156 @@ ], 'fields' => [ 'id' => [ - 'label' => 'id.0', + 'label' => 'id.label', 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'label' => 'pid.0', + 'label' => 'pid.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'label' => 'sorting.0', + 'label' => 'sorting.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'label' => 'tstamp.0', + 'label' => 'tstamp.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'name' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['name'], - 'exclude' => true, - 'search' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'name.label', + 'description' => 'name.description', + 'exclude' => true, + 'search' => true, + 'inputType' => 'text', + 'eval' => [ 'mandatory' => true, 'maxlength' => 255, 'tl_class' => 'w50' ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], 'rendertype' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendertype'], - 'inputType' => 'select', - 'default' => 'standalone', - 'reference' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendertypes'], - 'eval' => [ + 'label' => 'rendertype.label', + 'description' => 'rendertype.description', + 'inputType' => 'select', + 'default' => 'standalone', + 'reference' => [ + 'standalone' => 'rendertypes.standalone', + 'ctable' => 'rendertypes.ctable', + ], + 'eval' => [ 'tl_class' => 'w50', 'submitOnChange' => true, 'includeBlankOption' => true ], - 'sql' => "varchar(10) NOT NULL default ''" + 'sql' => "varchar(10) NOT NULL default ''" ], 'ptable' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['ptable'], - 'inputType' => 'select', - 'eval' => [ + 'label' => 'ptable.label', + 'description' => 'ptable.description', + 'inputType' => 'select', + 'eval' => [ 'tl_class' => 'w50', 'includeBlankOption' => true, 'chosen' => true ], - 'sql' => "varchar(64) NOT NULL default ''" + 'sql' => "varchar(64) NOT NULL default ''" ], 'rendermode' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermode'], - 'inputType' => 'select', - 'default' => 'flat', - 'eval' => [ + 'label' => 'rendermode.label', + 'description' => 'rendermode.description', + 'inputType' => 'select', + 'default' => 'flat', + 'eval' => [ 'tl_class' => 'w50', 'submitOnChange' => true ], - 'sql' => "varchar(12) NOT NULL default ''" + 'sql' => "varchar(12) NOT NULL default ''" ], 'showColumns' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['showColumns'], - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'showColumns.label', + 'description' => 'showColumns.description', + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 m12 cbx' ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'backendsection' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['backendsection'], - 'exclude' => true, - 'inputType' => 'select', - 'default' => 'metamodels', - 'reference' => &$GLOBALS['TL_LANG']['MOD'], - 'eval' => + 'label' => 'backendsection.label', + 'description' => 'backendsection.description', + 'exclude' => true, + 'inputType' => 'select', + 'default' => 'metamodels', + 'eval' => [ 'includeBlankOption' => true, 'valign' => 'top', 'chosen' => true, 'tl_class' => 'w50' ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], 'backendicon' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['backendicon'], - 'exclude' => true, - 'inputType' => 'fileTree', - 'eval' => [ + 'label' => 'backendicon.label', + 'description' => 'backendicon.description', + 'exclude' => true, + 'inputType' => 'fileTree', + 'eval' => [ 'fieldType' => 'radio', 'files' => true, 'filesOnly' => true, 'extensions' => 'jpg,jpeg,gif,png,tif,tiff,svg', 'tl_class' => 'clr' ], - 'sql' => 'blob NULL' + 'sql' => 'blob NULL' ], 'backendcaption' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['backendcaption'], - 'exclude' => true, - 'inputType' => 'multiColumnWizard', - 'eval' => [ - 'tl_class' => 'clr', - 'columnFields' => [ + 'label' => 'backendcaption.label', + 'description' => 'backendcaption.description', + 'exclude' => true, + 'inputType' => 'multiColumnWizard', + 'eval' => [ + 'useTranslator' => true, + 'tl_class' => 'clr', + 'columnFields' => [ 'langcode' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['becap_langcode'], - 'exclude' => true, - 'inputType' => 'select', - 'options' => $this->getLanguages(), - 'eval' => [ + 'label' => 'becap_langcode.label', + 'description' => 'becap_langcode.description', + 'exclude' => true, + 'inputType' => 'select', + 'options' => $this->getLanguages(), + 'eval' => [ 'tl_class' => '', 'style' => 'width:400px', 'chosen' => 'true' ] ], 'label' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['becap_label'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'becap_label.label', + 'description' => 'becap_label.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'style' => 'width:100%', ] ], 'description' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['becap_description'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'becap_description.label', + 'description' => 'becap_description.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'style' => 'width:100%', ] ], ], ], - 'sql' => 'text NULL' + 'sql' => 'text NULL' ], 'panelLayout' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['panelLayout'], + 'label' => 'panelLayout.label', + 'description' => 'panelLayout.description', 'exclude' => true, 'inputType' => 'text', 'default' => 'limit', @@ -370,40 +388,44 @@ 'sql' => 'blob NULL' ], 'iseditable' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['iseditable'], - 'inputType' => 'checkbox', - 'default' => 1, - 'eval' => [ + 'label' => 'iseditable.label', + 'description' => 'iseditable.description', + 'inputType' => 'checkbox', + 'default' => 1, + 'eval' => [ 'tl_class' => 'w50 cbx', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'iscreatable' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['iscreatable'], - 'inputType' => 'checkbox', - 'default' => 1, - 'eval' => [ + 'label' => 'iscreatable.label', + 'description' => 'iscreatable.description', + 'inputType' => 'checkbox', + 'default' => 1, + 'eval' => [ 'tl_class' => 'w50 cbx', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'isdeleteable' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['isdeleteable'], - 'inputType' => 'checkbox', - 'default' => 1, - 'eval' => [ + 'label' => 'isdeleteable.label', + 'description' => 'isdeleteable.description', + 'inputType' => 'checkbox', + 'default' => 1, + 'eval' => [ 'tl_class' => 'clr w50 cbx', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'subheadline' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca']['subheadline'], - 'inputType' => 'text', - 'eval' => [ + 'label' => 'subheadline.label', + 'description' => 'subheadline.description', + 'inputType' => 'text', + 'eval' => [ 'maxlength' => 255, 'tl_class' => 'w50' ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php index ca4cac19c..8af295dbd 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_combine.php @@ -39,7 +39,7 @@ ] ], 'dca_config' => [ - 'data_provider' => [ + 'data_provider' => [ 'default' => [ 'class' => 'ContaoCommunityAlliance\DcGeneral\Data\TableRowsAsRecordsDataProvider', 'source' => 'tl_metamodel_dca_combine', @@ -49,15 +49,15 @@ ], 'childCondition' => [ [ - 'from' => 'tl_metamodel', - 'to' => 'tl_metamodel_dca_combine', - 'setOn' => [ + 'from' => 'tl_metamodel', + 'to' => 'tl_metamodel_dca_combine', + 'setOn' => [ [ 'to_field' => 'pid', 'from_field' => 'id', ], ], - 'filter' => [ + 'filter' => [ [ 'local' => 'pid', 'remote' => 'id', @@ -75,28 +75,30 @@ ], 'fields' => [ 'id' => [ - 'label' => 'id.0', - 'sql' => 'int(10) unsigned NOT NULL auto_increment' + 'label' => 'id.label', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'label' => 'pid.0', - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'pid.label', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'label' => 'sorting.0', - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'sorting.label', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'label' => 'tstamp.0', - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'tstamp.label', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'rows' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['dca_combiner'], - 'exclude' => true, - 'inputType' => 'multiColumnWizard', - 'eval' => [ - 'tl_class' => 'dca_combine', - 'columnFields' => [ + 'label' => 'dca_combiner.label', + 'description' => 'dca_combiner.description', + 'exclude' => true, + 'inputType' => 'multiColumnWizard', + 'eval' => [ + 'useTranslator' => true, + 'tl_class' => 'dca_combine', + 'columnFields' => [ 'id' => [ 'label' => null, 'exclude' => true, @@ -107,10 +109,11 @@ ] ], 'fe_group' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['fe_group'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'fe_group.label', + 'description' => 'fe_group.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'includeBlankOption' => true, 'blankOptionLabel' => '*', 'style' => 'width:100%', @@ -118,10 +121,11 @@ ], ], 'be_group' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['be_group'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'be_group.label', + 'description' => 'be_group.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'includeBlankOption' => true, 'blankOptionLabel' => '*', 'style' => 'width:100%', @@ -129,21 +133,23 @@ ], ], 'view_id' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['view_id'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => + 'label' => 'view_id.label', + 'description' => 'view_id.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ - 'includeBlankOption' => true, - 'style' => 'width:100%', - 'chosen' => 'true' + 'includeBlankOption' => true, + 'style' => 'width:100%', + 'chosen' => 'true' ], ], 'dca_id' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['dca_id'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => + 'label' => 'dca_id.label', + 'description' => 'dca_id.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'includeBlankOption' => true, 'style' => 'width:100%', @@ -154,18 +160,22 @@ ], ], 'fe_group' => [ + 'label' => 'fe_group.label', // keep signed as anonymous are -1 - 'sql' => "int(10) NOT NULL default '0'" + 'sql' => "int(10) NOT NULL default '0'" ], 'be_group' => [ + 'label' => 'be_group.label', // keep signed as admins are -1 - 'sql' => "int(10) NOT NULL default '0'" + 'sql' => "int(10) NOT NULL default '0'" ], 'view_id' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'view_id.label', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'dca_id' => [ - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'dca_id.label', + 'sql' => "int(10) unsigned NOT NULL default '0'" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php index a62c732c3..12972a234 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dca_sortgroup.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,7 +17,7 @@ * @author Richard Henkenjohann * @author Ingolf Steinhardt * @author Cliff Parnitzky - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -105,39 +105,42 @@ ], 'global_operations' => [ 'all' => [ - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'all.label', + 'description' => 'all.description', + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ], ], 'operations' => [ 'edit' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['edit'], - 'href' => 'act=edit', - 'icon' => 'edit.svg', + 'label' => 'edit.label', + 'description' => 'edit.description', + 'href' => 'act=edit', + 'icon' => 'edit.svg', ], 'copy' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['copy'], - 'href' => 'act=copy', - 'icon' => 'copy.svg', + 'label' => 'copy.label', + 'description' => 'copy.description', + 'href' => 'act=copy', + 'icon' => 'copy.svg', ], 'delete' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['deleteConfirm'] ?? '' - ) + 'label' => 'delete.label', + 'description' => 'delete.description', + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ], 'show' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' + 'label' => 'show.label', + 'description' => 'show.description', + 'href' => 'act=show', + 'icon' => 'show.svg' ], 'toggle' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['toggle'], + 'label' => 'toggle.label', + 'description' => 'toggle.description', 'icon' => 'visible.svg', 'toggleProperty' => 'published' ] @@ -179,109 +182,130 @@ ], 'fields' => [ 'id' => [ - 'label' => 'id.0', + 'label' => 'id.label', 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'label' => 'pid.0', + 'label' => 'pid.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'label' => 'sorting.0', + 'label' => 'sorting.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'label' => 'tstamp.0', + 'label' => 'tstamp.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], + 'published' => [ + 'label' => 'published.label', + 'default' => 1, + 'sql' => "char(1) NOT NULL default '1'" + ], 'name' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['name'], - 'exclude' => true, - 'search' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'name.label', + 'description' => 'name.description', + 'exclude' => true, + 'search' => true, + 'inputType' => 'text', + 'eval' => [ 'mandatory' => true, 'maxlength' => 255, 'tl_class' => 'w50' ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], 'isdefault' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['isdefault'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'isdefault.label', + 'description' => 'isdefault.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 m12 cbx', 'fallback' => true ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'ismanualsort' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['ismanualsort'], - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'ismanualsort.label', + 'description' => 'ismanualsort.description', + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx', 'submitOnChange' => true ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'rendersort' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendersort'], - 'exclude' => true, - 'inputType' => 'select', - 'options' => ['asc', 'desc'], - 'eval' => [ + 'label' => 'rendersort.label', + 'description' => 'rendersort.description', + 'exclude' => true, + 'inputType' => 'select', + 'options' => ['asc', 'desc'], + 'eval' => [ 'tl_class' => 'w50', ], - 'reference' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendersortdirections'], - 'sql' => "varchar(10) NOT NULL default 'asc'" + 'reference' => [ + 'asc' => 'rendersortdirections.asc', + 'desc' => 'rendersortdirections.desc', + ], + 'sql' => "varchar(10) NOT NULL default 'asc'" ], 'rendersortattr' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendersortattr'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'rendersortattr.label', + 'description' => 'rendersortattr.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'tl_class' => 'w50 clr', 'chosen' => true ], - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'rendergrouptype' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptype'], - 'exclude' => true, - 'inputType' => 'select', - 'options' => ['none', 'char', 'digit', 'day', 'weekday', 'week', 'month', 'year'], - 'default' => 'none', - 'eval' => [ + 'label' => 'rendergrouptype.label', + 'description' => 'rendergrouptype.description', + 'exclude' => true, + 'inputType' => 'select', + 'options' => ['none', 'char', 'digit', 'day', 'weekday', 'week', 'month', 'year'], + 'default' => 'none', + 'eval' => [ 'tl_class' => 'w50 clr', 'submitOnChange' => true ], - 'reference' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptypes'], - 'sql' => "varchar(10) NOT NULL default 'none'" + 'reference' => [ + 'none' => 'rendergrouptypes.none', + 'char' => 'rendergrouptypes.char', + 'digit' => 'rendergrouptypes.digit', + 'day' => 'rendergrouptypes.day', + 'weekday' => 'rendergrouptypes.weekday', + 'week' => 'rendergrouptypes.week', + 'month' => 'rendergrouptypes.month', + 'year' => 'rendergrouptypes.year', + ], + 'sql' => "varchar(10) NOT NULL default 'none'" ], 'rendergroupattr' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergroupattr'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'rendergroupattr.label', + 'description' => 'rendergroupattr.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'tl_class' => 'w50', 'chosen' => true ], - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'rendergrouplen' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouplen'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'rendergrouplen.label', + 'description' => 'rendergrouplen.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'tl_class' => 'w50', 'rgxp' => 'digit' ], - 'sql' => "int(10) unsigned NOT NULL default '1'" - ], - 'published' => [ - 'default' => 1, - 'sql' => "char(1) NOT NULL default '1'" + 'sql' => "int(10) unsigned NOT NULL default '1'" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php index 54d654468..1b3375841 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting.php @@ -138,52 +138,57 @@ ], 'global_operations' => [ 'addall' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['addall'], - 'class' => 'header_add_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'addall.label', + 'description' => 'addall.description', + 'class' => 'header_add_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ], 'all' => [ - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'all.label', + 'description' => 'all.description', + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ], ], 'operations' => [ 'edit' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['edit'], - 'href' => 'act=edit', - 'icon' => 'edit.svg' + 'label' => 'edit.label', + 'description' => 'edit.description', + 'href' => 'act=edit', + 'icon' => 'edit.svg' ], 'cut' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['cut'], - 'href' => 'act=paste&mode=cut', - 'icon' => 'cut.svg' + 'label' => 'cut.label', + 'description' => 'cut.description', + 'href' => 'act=paste&mode=cut', + 'icon' => 'cut.svg' ], 'delete' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['deleteConfirm'] ?? '' - ) + 'label' => 'delete.label', + 'description' => 'delete.description', + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ], 'show' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' + 'label' => 'show.label', + 'description' => 'show.description', + 'href' => 'act=show', + 'icon' => 'show.svg' ], 'toggle' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['toggle'], + 'label' => 'toggle.label', + 'description' => 'toggle.description', 'icon' => 'visible.svg', 'toggleProperty' => 'published', ], 'conditions' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['conditions'], - 'href' => 'table=tl_metamodel_dcasetting_condition', - 'icon' => 'bundles/metamodelscore/images/icons/dca_condition.png', - 'idparam' => 'pid' + 'label' => 'conditions.label', + 'description' => 'conditions.description', + 'href' => 'table=tl_metamodel_dcasetting_condition', + 'icon' => 'bundles/metamodelscore/images/icons/dca_condition.png', + 'idparam' => 'pid' ], ] ], @@ -246,43 +251,49 @@ ], 'fields' => [ 'id' => [ - 'label' => 'id.0', + 'label' => 'id.label', 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'label' => 'pid.0', + 'label' => 'pid.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'label' => 'sorting.0', + 'label' => 'sorting.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'label' => 'tstamp.0', + 'label' => 'tstamp.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'published' => [ + 'label' => 'published.label', 'default' => 1, 'sql' => "char(1) NOT NULL default '1'" ], 'dcatype' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['dcatype'], - 'exclude' => true, - 'inputType' => 'select', - 'options' => ['attribute', 'legend'], - 'reference' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['dcatypes'], - 'eval' => [ + 'label' => 'dcatype.label', + 'description' => 'dcatype.description', + 'exclude' => true, + 'inputType' => 'select', + 'options' => ['attribute', 'legend'], + 'reference' => [ + 'legend' => 'dcatypes.legend', + 'attribute' => 'dcatypes.attribute', + ], + 'eval' => [ 'tl_class' => 'w50', 'includeBlankOption' => true, 'submitOnChange' => true, ], - 'sql' => "varchar(10) NOT NULL default ''" + 'sql' => "varchar(10) NOT NULL default ''" ], 'attr_id' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['attr_id'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'attr_id.label', + 'description' => 'attr_id.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'tl_class' => 'w50', 'doNotSaveEmpty' => true, 'alwaysSave' => true, @@ -290,10 +301,11 @@ 'mandatory' => true, 'submitOnChange' => true, ], - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tl_class' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['tl_class'], + 'label' => 'tl_class.label', + 'description' => 'tl_class.description', 'exclude' => true, 'inputType' => 'text', 'default' => 'w50', @@ -305,185 +317,208 @@ 'sql' => ['type' => 'string', 'length' => 64, 'default' => 'w50'] ], 'be_template' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['be_template'], - 'exclude' => true, - 'inputType' => 'select', - 'sql' => 'varchar(255) NOT NULL default \'\'', - 'eval' => [ + 'label' => 'be_template.label', + 'description' => 'be_template.description', + 'exclude' => true, + 'inputType' => 'select', + 'sql' => 'varchar(255) NOT NULL default \'\'', + 'eval' => [ 'includeBlankOption' => true, 'tl_class' => 'clr w50', 'chosen' => 'true' ] ], 'legendhide' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['legendhide'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'legendhide.label', + 'description' => 'legendhide.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12' ], - 'sql' => "varchar(5) NOT NULL default ''" + 'sql' => "varchar(5) NOT NULL default ''" ], 'legendtitle' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['legendtitle'], - 'exclude' => true, - 'eval' => [ + 'label' => 'legendtitle.label', + 'description' => 'legendtitle.description', + 'exclude' => true, + 'eval' => [ 'tl_class' => 'clr' ], - 'sql' => 'text NULL' + 'sql' => 'text NULL' ], 'mandatory' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['mandatory'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'mandatory.label', + 'description' => 'mandatory.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'alwaysSave' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['alwaysSave'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'alwaysSave.label', + 'description' => 'alwaysSave.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'filterable' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['filterable'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'filterable.label', + 'description' => 'filterable.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'searchable' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['searchable'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'searchable.label', + 'description' => 'searchable.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'chosen' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['chosen'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'chosen.label', + 'description' => 'chosen.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12' ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'allowHtml' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['allowHtml'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => + 'label' => 'allowHtml.label', + 'description' => 'allowHtml.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'preserveTags' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['preserveTags'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'preserveTags.label', + 'description' => 'preserveTags.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'decodeEntities' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['decodeEntities'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'decodeEntities.label', + 'description' => 'decodeEntities.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'rte' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rte'], - 'exclude' => true, - 'inputType' => 'select', - 'default' => 'tinyMCE', - 'eval' => [ + 'label' => 'rte.label', + 'description' => 'rte.description', + 'exclude' => true, + 'inputType' => 'select', + 'default' => 'tinyMCE', + 'eval' => [ 'tl_class' => 'w50', 'includeBlankOption' => true, ], - 'sql' => "varchar(64) NOT NULL default 'tinyMCE'" + 'sql' => "varchar(64) NOT NULL default 'tinyMCE'" ], 'rows' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rows'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => + 'label' => 'rows.label', + 'description' => 'rows.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'tl_class' => 'w50', 'rgxp' => 'digit' ], - 'sql' => "int(10) NOT NULL default '0'" + 'sql' => "int(10) NOT NULL default '0'" ], 'cols' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['cols'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'cols.label', + 'description' => 'cols.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'tl_class' => 'w50', 'rgxp' => 'digit' ], - 'sql' => "int(10) NOT NULL default '0'" + 'sql' => "int(10) NOT NULL default '0'" ], 'trailingSlash' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash'], - 'exclude' => true, - 'inputType' => 'select', - 'options' => [0, 1, 2], - 'default' => 2, - 'reference' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash_options'], - 'eval' => [ + 'label' => 'trailingSlash.label', + 'description' => 'trailingSlash.description', + 'exclude' => true, + 'inputType' => 'select', + 'options' => [0, 1, 2], + 'default' => 2, + 'reference' => [ + '0' => 'trailingSlash_options.0', + '1' => 'trailingSlash_options.1', + '2' => 'trailingSlash_options.2', + ], + 'eval' => [ 'tl_class' => 'clr w50', ], - 'sql' => "char(1) NOT NULL default '2'" + 'sql' => "char(1) NOT NULL default '2'" ], 'spaceToUnderscore' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['spaceToUnderscore'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'spaceToUnderscore.label', + 'description' => 'spaceToUnderscore.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'includeBlankOption' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['includeBlankOption'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'default' => '1', - 'eval' => [ + 'label' => 'includeBlankOption.label', + 'description' => 'includeBlankOption.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'default' => '1', + 'eval' => [ 'tl_class' => 'clr w50 cbx m12', ], - 'sql' => "char(1) NOT NULL default '1'" + 'sql' => "char(1) NOT NULL default '1'" ], 'submitOnChange' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['submitOnChange'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'submitOnChange.label', + 'description' => 'submitOnChange.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'clr w50 cbx m12', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'readonly' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['readonly'], - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'readonly.label', + 'description' => 'readonly.description', + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx m12', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php index ba57b1c59..b0f6c31ce 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_dcasetting_condition.php @@ -27,7 +27,8 @@ $GLOBALS['TL_DCA']['tl_metamodel_dcasetting_condition'] = [ 'config' => [ 'dataContainer' => General::class, - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['list_label'], + 'label' => 'list_label.label', + 'description' => 'list_label.description', 'switchToEdit' => false, 'enableVersioning' => false, 'sql' => [ @@ -154,45 +155,49 @@ ], 'global_operations' => [ 'all' => [ - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'all.label', + 'description' => 'all.description', + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ] ], 'operations' => [ 'edit' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['edit'], - 'href' => 'act=edit', - 'icon' => 'edit.svg' + 'label' => 'edit.label', + 'description' => 'edit.description', + 'href' => 'act=edit', + 'icon' => 'edit.svg' ], 'copy' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['copy'], - 'href' => 'act=copy', - 'icon' => 'copy.svg' + 'label' => 'copy.label', + 'description' => 'copy.description', + 'href' => 'act=copy', + 'icon' => 'copy.svg' ], 'cut' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['cut'], - 'href' => 'act=paste&mode=cut', - 'icon' => 'cut.svg', - 'attributes' => 'onclick="Backend.getScrollOffset()"', + 'label' => 'cut.label', + 'description' => 'cut.description', + 'href' => 'act=paste&mode=cut', + 'icon' => 'cut.svg', + 'attributes' => 'onclick="Backend.getScrollOffset()"', ], 'delete' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['deleteConfirm'] ?? '' - ) + 'label' => 'delete.label', + 'description' => 'delete.description', + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ], 'show' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' + 'label' => 'show.label', + 'description' => 'show.description', + 'href' => 'act=show', + 'icon' => 'show.svg' ], 'toggle' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['toggle'], + 'label' => 'toggle.label', + 'description' => 'toggle.description', 'icon' => 'visible.svg', 'toggleProperty' => 'enabled', ] @@ -235,29 +240,31 @@ ], 'fields' => [ 'id' => [ - 'label' => 'id.0', + 'label' => 'id.label', 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'label' => 'pid.0', + 'label' => 'pid.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'label' => 'sorting.0', + 'label' => 'sorting.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'label' => 'tstamp.0', + 'label' => 'tstamp.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'settingId' => [ // Keep this empty but keep it here! // needed for act=copy in DC_Table, as otherwise the fid value will not be copied. - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['fid'], - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'fid.label', + 'description' => 'fid.description', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'type' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['type'], + 'label' => 'type.label', + 'description' => 'type.description', 'exclude' => true, 'inputType' => 'select', 'eval' => [ @@ -274,30 +281,33 @@ 'sql' => "varchar(255) NOT NULL default ''" ], 'enabled' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['enabled'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'default' => 1, - 'eval' => [ + 'label' => 'enabled.label', + 'description' => 'enabled.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'default' => 1, + 'eval' => [ 'alwaysSave' => true, 'tl_class' => 'w50 m12 cbx', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'comment' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['comment'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'comment.label', + 'description' => 'comment.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'tl_class' => 'clr long' ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], 'attr_id' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['attr_id'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'attr_id.label', + 'description' => 'attr_id.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'doNotSaveEmpty' => true, 'alwaysSave' => true, 'submitOnChange' => true, @@ -306,19 +316,20 @@ 'tl_class' => 'w50', 'chosen' => true ], - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'value' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['value'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'value.label', + 'description' => 'value.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'alwaysSave' => true, 'includeBlankOption' => true, 'tl_class' => 'w50', 'chosen' => true ], - 'sql' => 'blob NULL' + 'sql' => 'blob NULL' ], ] ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php index 4583933bf..9161a567b 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filter.php @@ -27,7 +27,7 @@ use ContaoCommunityAlliance\DcGeneral\DC\General; $GLOBALS['TL_DCA']['tl_metamodel_filter'] = [ - 'config' => [ + 'config' => [ 'dataContainer' => General::class, 'switchToEdit' => false, 'enableVersioning' => false, @@ -38,8 +38,7 @@ ], ], ], - - 'dca_config' => [ + 'dca_config' => [ 'data_provider' => [ 'default' => [ 'source' => 'tl_metamodel_filter' @@ -97,9 +96,8 @@ ], ], ], - - 'list' => [ - 'sorting' => [ + 'list' => [ + 'sorting' => [ 'mode' => 4, 'fields' => [ 'name' @@ -110,52 +108,50 @@ ], 'flag' => 1, ], - - 'label' => [ + 'label' => [ 'fields' => [ 'name' ], 'format' => '%s' ], - 'global_operations' => [ 'all' => [ - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'all.label', + 'description' => 'all.description', + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ] ], - - 'operations' => [ + 'operations' => [ 'edit' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['edit'], - 'href' => 'act=edit', - 'icon' => 'edit.svg' + 'label' => 'edit.label', + 'description' => 'edit.description', + 'href' => 'act=edit', + 'icon' => 'edit.svg' ], 'delete' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['tl_metamodel_filter']['deleteConfirm'] ?? '' - ) + 'label' => 'delete.label', + 'description' => 'delete.description', + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ], 'show' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' + 'label' => 'show.label', + 'description' => 'show.description', + 'href' => 'act=show', + 'icon' => 'show.svg' ], 'settings' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['settings'], - 'href' => 'table=tl_metamodel_filtersetting', - 'idparam' => 'pid', - 'icon' => 'bundles/metamodelscore/images/icons/filter_setting.png', + 'label' => 'settings.label', + 'description' => 'settings.description', + 'href' => 'table=tl_metamodel_filtersetting', + 'idparam' => 'pid', + 'icon' => 'bundles/metamodelscore/images/icons/filter_setting.png', ], ] ], - 'metapalettes' => [ 'default' => [ 'title' => [ @@ -163,30 +159,30 @@ ] ], ], - - 'fields' => [ + 'fields' => [ 'id' => [ - 'label' => 'id.0', + 'label' => 'id.label', 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'label' => 'pid.0', + 'label' => 'pid.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'label' => 'tstamp.0', + 'label' => 'tstamp.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'name' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filter']['name'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'name.label', + 'description' => 'name.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'mandatory' => true, 'maxlength' => 255, 'tl_class' => 'w50' ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], ] ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php index 411c92156..9fa4e1d74 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_filtersetting.php @@ -30,7 +30,8 @@ $GLOBALS['TL_DCA']['tl_metamodel_filtersetting'] = [ 'config' => [ 'dataContainer' => General::class, - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['list_label'], + 'label' => 'list_label.label', + 'description' => 'list_label.description', 'switchToEdit' => false, 'enableVersioning' => false, 'sql' => [ @@ -146,45 +147,49 @@ ], 'global_operations' => [ 'all' => [ - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'all.label', + 'description' => 'all.description', + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ] ], 'operations' => [ 'edit' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['edit'], - 'href' => 'act=edit', - 'icon' => 'edit.svg' + 'label' => 'edit.label', + 'description' => 'edit.description', + 'href' => 'act=edit', + 'icon' => 'edit.svg' ], 'copy' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['copy'], - 'href' => 'act=copy', - 'icon' => 'copy.svg' + 'label' => 'copy.label', + 'description' => 'copy.description', + 'href' => 'act=copy', + 'icon' => 'copy.svg' ], 'cut' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['cut'], - 'href' => 'act=paste&mode=cut', - 'icon' => 'cut.svg', - 'attributes' => 'onclick="Backend.getScrollOffset()"', + 'label' => 'cut.label', + 'description' => 'cut.description', + 'href' => 'act=paste&mode=cut', + 'icon' => 'cut.svg', + 'attributes' => 'onclick="Backend.getScrollOffset()"', ], 'delete' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['deleteConfirm'] ?? '' - ) + 'label' => 'delete.label', + 'description' => 'delete.description', + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ], 'show' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' + 'label' => 'show.label', + 'description' => 'show.description', + 'href' => 'act=show', + 'icon' => 'show.svg' ], 'toggle' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['toggle'], + 'label' => 'toggle.label', + 'description' => 'toggle.description', 'icon' => 'visible.svg', 'toggleProperty' => 'enabled', ] @@ -255,33 +260,35 @@ ], 'fields' => [ 'id' => [ - 'label' => 'id.0', + 'label' => 'id.label', 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'label' => 'pid.0', + 'label' => 'pid.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'label' => 'sorting.0', + 'label' => 'sorting.label', 'sorting' => true, 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'label' => 'tstamp.0', + 'label' => 'tstamp.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'fid' => [ // Keep this empty but keep it here! // needed for act=copy in DC_Table, as otherwise the fid value will not be copied. - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['fid'], - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'fid.label', + 'description' => 'fid.description', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'type' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['type'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'type.label', + 'description' => 'type.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'doNotSaveEmpty' => true, 'alwaysSave' => true, 'submitOnChange' => true, @@ -290,31 +297,34 @@ 'tl_class' => 'w50', 'chosen' => true ], - 'sql' => "varchar(64) NOT NULL default ''" + 'sql' => "varchar(64) NOT NULL default ''" ], 'enabled' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['enabled'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'default' => 1, - 'eval' => [ + 'label' => 'enabled.label', + 'description' => 'enabled.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'default' => 1, + 'eval' => [ 'alwaysSave' => true, 'tl_class' => 'w50 m12 cbx', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'comment' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['comment'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => ['tl_class' => 'clr long'], - 'sql' => "varchar(255) NOT NULL default ''" + 'label' => 'comment.label', + 'description' => 'comment.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => ['tl_class' => 'clr long'], + 'sql' => "varchar(255) NOT NULL default ''" ], 'attr_id' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['attr_id'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'attr_id.label', + 'description' => 'attr_id.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'doNotSaveEmpty' => true, 'alwaysSave' => true, 'submitOnChange' => true, @@ -323,60 +333,66 @@ 'tl_class' => 'w50', 'chosen' => true ], - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'all_langs' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['all_langs'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'all_langs.label', + 'description' => 'all_langs.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'alwaysSave' => true, 'tl_class' => 'w50 m12 cbx', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'items' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['items'], - 'exclude' => true, - 'inputType' => 'textarea', - 'eval' => [ + 'label' => 'items.label', + 'description' => 'items.description', + 'exclude' => true, + 'inputType' => 'textarea', + 'eval' => [ 'doNotSaveEmpty' => true, 'alwaysSave' => true, 'mandatory' => true, ], - 'sql' => 'text NULL' + 'sql' => 'text NULL' ], 'urlparam' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['urlparam'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'urlparam.label', + 'description' => 'urlparam.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'tl_class' => 'w50', ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], 'predef_param' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['predef_param'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'predef_param.label', + 'description' => 'predef_param.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'alwaysSave' => true, 'tl_class' => 'w50 m12 cbx', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'fe_widget' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['fe_widget'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'fe_widget.label', + 'description' => 'fe_widget.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'alwaysSave' => true, 'tl_class' => 'w50 m12 cbx', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'customsql' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['customsql'], + 'label' => 'customsql.label', + 'description' => 'customsql.description', 'exclude' => true, 'inputType' => 'textarea', 'default' => 'SELECT id FROM {{table}} @@ -393,145 +409,162 @@ 'sql' => 'text NULL' ], 'allow_empty' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['allow_empty'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'allow_empty.label', + 'description' => 'allow_empty.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'alwaysSave' => true, 'tl_class' => 'w50 m12 cbx', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'stop_after_match' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['stop_after_match'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'stop_after_match.label', + 'description' => 'stop_after_match.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'alwaysSave' => true, 'tl_class' => 'w50 cbx', ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'label' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['label'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'label.label', + 'description' => 'label.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'tl_class' => 'clr w50', ], - 'sql' => 'blob NULL' + 'sql' => 'blob NULL' ], 'template' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['template'], - 'default' => 'mm_filteritem_default', - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'template.label', + 'description' => 'template.description', + 'default' => 'mm_filteritem_default', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'tl_class' => 'w50', 'chosen' => true ], - 'sql' => "varchar(64) NOT NULL default ''" + 'sql' => "varchar(64) NOT NULL default ''" ], 'blankoption' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['blankoption'], - 'exclude' => true, - 'default' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'blankoption.label', + 'description' => 'blankoption.description', + 'exclude' => true, + 'default' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'clr w50 m12 cbx', ], - 'sql' => "char(1) NOT NULL default '1'" + 'sql' => "char(1) NOT NULL default '1'" ], 'onlyused' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['onlyused'], - 'exclude' => true, - 'default' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'onlyused.label', + 'description' => 'onlyused.description', + 'exclude' => true, + 'default' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 m12 cbx', 'submitOnChange' => true, ], - 'sql' => "char(1) NOT NULL default '0'" + 'sql' => "char(1) NOT NULL default '1'" ], 'onlypossible' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['onlypossible'], - 'exclude' => true, - 'default' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'onlypossible.label', + 'description' => 'onlypossible.description', + 'exclude' => true, + 'default' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 m12 cbx', ], - 'sql' => "char(1) NOT NULL default '0'" + 'sql' => "char(1) NOT NULL default '1'" ], 'skipfilteroptions' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['skipfilteroptions'], - 'exclude' => true, - 'default' => false, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'skipfilteroptions.label', + 'description' => 'skipfilteroptions.description', + 'exclude' => true, + 'default' => false, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 m12 cbx', ], - 'sql' => "char(1) NOT NULL default '0'" + 'sql' => "char(1) NOT NULL default ''" ], 'defaultid' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['defaultid'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'defaultid.label', + 'description' => 'defaultid.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'tl_class' => 'clr w50', 'includeBlankOption' => true ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], 'hide_label' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['hide_label'], - 'exclude' => true, - 'default' => false, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'hide_label.label', + 'description' => 'hide_label.description', + 'exclude' => true, + 'default' => false, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 m12 cbx', ], - 'sql' => "char(1) NOT NULL default '0'" + 'sql' => "char(1) NOT NULL default '0'" ], 'label_as_blankoption' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['label_as_blankoption'], - 'exclude' => true, - 'default' => false, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'label_as_blankoption.label', + 'description' => 'label_as_blankoption.description', + 'exclude' => true, + 'default' => false, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 m12 cbx', ], - 'sql' => "char(1) NOT NULL default '0'" + 'sql' => "char(1) NOT NULL default '0'" ], 'apply_sorting' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['apply_sorting'], - 'exclude' => true, - 'inputType' => 'select', - 'options' => ['natsort_asc', 'natsort_desc'], - 'reference' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['sorting_directions'], - 'eval' => [ + 'label' => 'apply_sorting.label', + 'description' => 'apply_sorting.description', + 'exclude' => true, + 'inputType' => 'select', + 'options' => ['natsort_asc', 'natsort_desc'], + 'reference' => [ + 'natsort_asc' => 'sorting_directions.natsort_asc', + 'natsort_desc' => 'sorting_directions.natsort_desc', + ], + 'eval' => [ 'tl_class' => 'w50', 'includeBlankOption' => true ], - 'sql' => ['type' => 'string', 'length' => '24', 'notnull' => false, 'default' => ''] + 'sql' => ['type' => 'string', 'length' => '24', 'notnull' => false, 'default' => ''] ], 'cssID' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['cssID'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'cssID.label', + 'description' => 'cssID.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'multiple' => true, 'size' => 2, 'tl_class' => 'clr w50' ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], 'placeholder' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['placeholder'], - 'exclude' => true, - 'inputType' => 'text', - 'sql' => 'varchar(255) NOT NULL default \'\'', - 'eval' => ['tl_class' => 'w50'] + 'label' => 'placeholder.label', + 'description' => 'placeholder.description', + 'exclude' => true, + 'inputType' => 'text', + 'sql' => 'varchar(255) NOT NULL default \'\'', + 'eval' => ['tl_class' => 'w50'] ] ] ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php index 8354e1e4b..d59a381c3 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_item.php @@ -47,7 +47,6 @@ 'tstamp' ], ], - 'label' => [ 'fields' => [ ], @@ -56,16 +55,16 @@ ], 'fields' => [ 'id' => [ - 'label' => 'id.0', + 'label' => 'id.label', ], 'pid' => [ - 'label' => 'pid.0', + 'label' => 'pid.label', ], 'sorting' => [ - 'label' => 'sorting.0', + 'label' => 'sorting.label', ], 'tstamp' => [ - 'label' => 'tstamp.0', + 'label' => 'tstamp.label', ] ] ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php index 1aa22e2ea..250f6df22 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersetting.php @@ -121,43 +121,47 @@ ], 'global_operations' => [ 'addall' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall'], - 'class' => 'header_add_all rendersetting_add_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'addall.label', + 'description' => 'addall.description', + 'class' => 'header_add_all rendersetting_add_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ], 'all' => [ - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'all.label', + 'description' => 'all.description', + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ] ], 'operations' => [ 'edit' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit'], - 'href' => 'act=edit', - 'icon' => 'edit.svg' + 'label' => 'edit.label', + 'description' => 'edit.description', + 'href' => 'act=edit', + 'icon' => 'edit.svg' ], 'cut' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['cut'], - 'icon' => 'cut.svg' + 'label' => 'cut.label', + 'description' => 'cut.description', + 'icon' => 'cut.svg' ], 'delete' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['deleteConfirm'] ?? '' - ) + 'label' => 'delete.label', + 'description' => 'delete.description', + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ], 'show' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' + 'label' => 'show.label', + 'description' => 'show.description', + 'href' => 'act=show', + 'icon' => 'show.svg' ], 'toggle' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle'], + 'label' => 'toggle.label', + 'description' => 'toggle.description', 'icon' => 'visible.svg', 'toggleProperty' => 'enabled', ] @@ -180,26 +184,27 @@ // Fields. 'fields' => [ 'id' => [ - 'label' => 'id.0', + 'label' => 'id.label', 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'label' => 'pid.0', + 'label' => 'pid.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'sorting' => [ - 'label' => 'sorting.0', + 'label' => 'sorting.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'label' => 'tstamp.0', + 'label' => 'tstamp.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'attr_id' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'attr_id.label', + 'description' => 'attr_id.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'doNotSaveEmpty' => true, 'alwaysSave' => true, 'submitOnChange' => true, @@ -208,32 +213,36 @@ 'chosen' => true, 'tl_class' => 'w50' ], - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'template' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'template.label', + 'description' => 'template.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'tl_class' => 'w50', 'chosen' => true, 'includeBlankOption' => true, ], - 'sql' => "varchar(64) NOT NULL default ''" + 'sql' => "varchar(64) NOT NULL default ''" ], 'additional_class' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['additional_class'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'additional_class.label', + 'description' => 'additional_class.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'tl_class' => 'w50', 'maxlength' => 64, ], - 'sql' => "varchar(64) NOT NULL default ''" + 'sql' => "varchar(64) NOT NULL default ''" ], 'enabled' => [ - 'default' => 1, - 'sql' => "char(1) NOT NULL default ''" + 'label' => 'enabled.label', + 'description' => 'enabled.description', + 'default' => 1, + 'sql' => "char(1) NOT NULL default ''" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php index 3b4618a4b..636114838 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_rendersettings.php @@ -124,43 +124,46 @@ ], 'global_operations' => [ 'all' => [ - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'all.label', + 'description' => 'all.description', + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ] ], 'operations' => [ 'edit' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['edit'], - 'href' => 'act=edit', - 'icon' => 'edit.svg' + 'label' => 'edit.label', + 'description' => 'edit.description', + 'href' => 'act=edit', + 'icon' => 'edit.svg' ], 'copy' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['copy'], - 'href' => 'act=copy', - 'icon' => 'copy.svg' + 'label' => 'copy.label', + 'description' => 'copy.description', + 'href' => 'act=copy', + 'icon' => 'copy.svg' ], 'delete' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['deleteConfirm'] ?? '' - ) + 'label' => 'delete.label', + 'description' => 'delete.description', + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ], 'show' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' + 'label' => 'show.label', + 'description' => 'show.description', + 'href' => 'act=show', + 'icon' => 'show.svg' ], 'settings' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['settings'], - 'href' => 'table=tl_metamodel_rendersetting', - 'icon' => 'bundles/metamodelscore/images/icons/rendersetting.png', - 'idparam' => 'pid' + 'label' => 'settings.label', + 'description' => 'settings.description', + 'href' => 'table=tl_metamodel_rendersetting', + 'icon' => 'bundles/metamodelscore/images/icons/rendersetting.png', + 'idparam' => 'pid' ], ] ], @@ -189,109 +192,122 @@ ], 'fields' => [ 'id' => [ - 'label' => 'id.0', - 'sql' => 'int(10) unsigned NOT NULL auto_increment' + 'label' => 'id.label', + 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'label' => 'pid.0', - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'pid.label', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'label' => 'tstamp.0', - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'label' => 'tstamp.label', + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'name' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['name'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'name.label', + 'description' => 'name.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'mandatory' => true, 'maxlength' => 255, 'tl_class' => 'w50' ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], 'hideEmptyValues' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['hideEmptyValues'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'hideEmptyValues.label', + 'description' => 'hideEmptyValues.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx' ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'hideLabels' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['hideLabels'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'hideLabels.label', + 'description' => 'hideLabels.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'tl_class' => 'w50 cbx' ], - 'sql' => "char(1) NOT NULL default ''" + 'sql' => "char(1) NOT NULL default ''" ], 'template' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['template'], - 'default' => 'metamodel_prerendered', - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'template.label', + 'description' => 'template.description', + 'default' => 'metamodel_prerendered', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'includeBlankOption' => true, 'tl_class' => 'w50', 'mandatory' => true, 'chosen' => true ], - 'sql' => "varchar(64) NOT NULL default ''" + 'sql' => "varchar(64) NOT NULL default ''" ], 'format' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['format'], - 'exclude' => true, - 'inputType' => 'select', - 'options' => [ + 'label' => 'format.label', + 'description' => 'format.description', + 'exclude' => true, + 'inputType' => 'select', + 'options' => [ 'html5', 'text' ], - 'reference' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['formatOptions'], - 'eval' => [ + 'reference' => [ + 'html5' => 'formatOptions.html5', + 'text' => 'formatOptions.text', + ], + 'eval' => [ 'includeBlankOption' => true, 'tl_class' => 'w50', 'chosen' => true ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], 'jumpTo' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo'], + 'label' => 'jumpTo.label', + 'description' => 'jumpTo.description', 'exclude' => true, 'minCount' => 1, 'maxCount' => 1, 'disableSorting' => '1', 'inputType' => 'multiColumnWizard', 'eval' => [ - 'dragAndDrop' => false, - 'hideButtons' => true, - 'style' => 'width:100%;', - 'tl_class' => 'clr clx', - 'columnFields' => [ + 'useTranslator' => true, + 'dragAndDrop' => false, + 'hideButtons' => true, + 'style' => 'width:100%;', + 'tl_class' => 'clr clx', + 'columnFields' => [ 'langcode' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo_language'], - 'exclude' => true, - 'inputType' => 'justtextoption', - 'eval' => [ + 'label' => 'jumpTo_language.label', + 'description' => 'jumpTo_language.description', + 'exclude' => true, + 'inputType' => 'justtextoption', + 'eval' => [ 'valign' => 'center' ] ], 'value' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo_page'], - 'exclude' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'jumpTo_page.label', + 'description' => 'jumpTo_page.description', + 'exclude' => true, + 'inputType' => 'text', + 'eval' => [ 'style' => 'width:90%;' ] ], 'filter' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo_filter'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'jumpTo_filter.label', + 'description' => 'jumpTo_filter.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'style' => 'width:100%;', 'includeBlankOption' => true, 'chosen' => true @@ -302,64 +318,72 @@ 'sql' => 'blob NULL' ], 'additionalCss' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['additionalCss'], - 'exclude' => true, - 'inputType' => 'multiColumnWizard', - 'eval' => [ - 'style' => 'width:100%;', - 'tl_class' => 'w50', - 'columnFields' => [ + 'label' => 'additionalCss.label', + 'description' => 'additionalCss.description', + 'exclude' => true, + 'inputType' => 'multiColumnWizard', + 'eval' => [ + 'useTranslator' => true, + 'style' => 'width:100%;', + 'tl_class' => 'w50', + 'columnFields' => [ 'file' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['file'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'file.label', + 'description' => 'file.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'style' => 'width:100%;', 'chosen' => true, 'includeBlankOption' => true ] ], 'published' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['publish'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'publish.label', + 'description' => 'publish.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'style' => 'width:40px;' ] ], ] ], - 'sql' => 'blob NULL' + 'sql' => 'blob NULL' ], 'additionalJs' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['additionalJs'], - 'exclude' => true, - 'inputType' => 'multiColumnWizard', - 'eval' => [ - 'style' => 'width:100%;', - 'tl_class' => 'w50', - 'columnFields' => [ + 'label' => 'additionalJs.label', + 'description' => 'additionalJs.description', + 'exclude' => true, + 'inputType' => 'multiColumnWizard', + 'eval' => [ + 'useTranslator' => true, + 'style' => 'width:100%;', + 'tl_class' => 'w50', + 'columnFields' => [ 'file' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['file'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'file.label', + 'description' => 'file.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'style' => 'width:100%;', 'chosen' => true, 'includeBlankOption' => true ] ], 'published' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['publish'], - 'exclude' => true, - 'inputType' => 'checkbox', - 'eval' => [ + 'label' => 'publish.label', + 'description' => 'publish.description', + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => [ 'style' => 'width:40px;' ] ], ] ], - 'sql' => 'blob NULL' + 'sql' => 'blob NULL' ], ], ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php b/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php index d4a5ea3d9..1124a2683 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php +++ b/src/CoreBundle/Resources/contao/dca/tl_metamodel_searchable_pages.php @@ -87,39 +87,42 @@ ], 'global_operations' => [ 'all' => [ - 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], - 'href' => 'act=select', - 'class' => 'header_edit_all', - 'attributes' => 'onclick="Backend.getScrollOffset();"' + 'label' => 'all.label', + 'description' => 'all.description', + 'href' => 'act=select', + 'class' => 'header_edit_all', + 'attributes' => 'onclick="Backend.getScrollOffset();"' ], ], 'operations' => [ 'edit' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['edit'], - 'href' => 'act=edit', - 'icon' => 'edit.svg', + 'label' => 'edit.label', + 'description' => 'edit.description', + 'href' => 'act=edit', + 'icon' => 'edit.svg', ], 'copy' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['copy'], - 'href' => 'act=copy', - 'icon' => 'copy.svg', + 'label' => 'copy.label', + 'description' => 'copy.description', + 'href' => 'act=copy', + 'icon' => 'copy.svg', ], 'delete' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['delete'], - 'href' => 'act=delete', - 'icon' => 'delete.svg', - 'attributes' => sprintf( - 'onclick="if (!confirm(\'%s\')) return false; Backend.getScrollOffset();"', - $GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['deleteConfirm'] ?? '' - ) + 'label' => 'delete.label', + 'description' => 'delete.description', + 'href' => 'act=delete', + 'icon' => 'delete.svg', + 'attributes' => 'onclick="if (!confirm(this.dataset.msgConfirm)) return false; Backend.getScrollOffset();"', ], 'show' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['show'], - 'href' => 'act=show', - 'icon' => 'show.svg' + 'label' => 'show.label', + 'description' => 'show.description', + 'href' => 'act=show', + 'icon' => 'show.svg' ], 'toggle' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'], + 'label' => 'toggle.label', + 'description' => 'toggle.description', 'icon' => 'visible.svg', 'toggleProperty' => 'published' ] @@ -139,71 +142,78 @@ ], 'fields' => [ 'id' => [ - 'label' => 'id.0', + 'label' => 'id.label', 'sql' => 'int(10) unsigned NOT NULL auto_increment' ], 'pid' => [ - 'label' => 'pid.0', + 'label' => 'pid.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'tstamp' => [ - 'label' => 'tstamp.0', + 'label' => 'tstamp.label', 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'name' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['name'], - 'exclude' => true, - 'search' => true, - 'inputType' => 'text', - 'eval' => [ + 'label' => 'name.label', + 'description' => 'name.description', + 'exclude' => true, + 'search' => true, + 'inputType' => 'text', + 'eval' => [ 'mandatory' => true, 'maxlength' => 255, 'tl_class' => 'w50' ], - 'sql' => "varchar(255) NOT NULL default ''" + 'sql' => "varchar(255) NOT NULL default ''" ], 'filter' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['filter'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'filter.label', + 'description' => 'filter.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'includeBlankOption' => true, 'chosen' => true, 'submitOnChange' => true, 'tl_class' => 'clr w50', ], - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'filterparams' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['filterparams'], - 'exclude' => true, - 'inputType' => 'mm_subdca', - 'eval' => [ + 'label' => 'filterparams.label', + 'description' => 'filterparams.description', + 'exclude' => true, + 'inputType' => 'mm_subdca', + 'eval' => [ 'tl_class' => 'clr m12', 'flagfields' => [ 'use_get' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['filterparams'], - 'inputType' => 'checkbox' + 'label' => 'filterparams.label', + 'description' => 'filterparams.description', + 'inputType' => 'checkbox' ], ], ], - 'sql' => 'longblob NULL' + 'sql' => 'longblob NULL' ], 'rendersetting' => [ - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['rendersetting'], - 'exclude' => true, - 'inputType' => 'select', - 'eval' => [ + 'label' => 'rendersetting.label', + 'description' => 'rendersetting.description', + 'exclude' => true, + 'inputType' => 'select', + 'eval' => [ 'includeBlankOption' => true, 'mandatory' => true, 'chosen' => true, 'tl_class' => 'w50', ], - 'sql' => "int(10) unsigned NOT NULL default '0'" + 'sql' => "int(10) unsigned NOT NULL default '0'" ], 'published' => [ - 'default' => 1, - 'sql' => "char(1) NOT NULL default '1'" + 'label' => 'published.label', + 'description' => 'published.description', + 'default' => 1, + 'sql' => "char(1) NOT NULL default '1'" ] ] ]; diff --git a/src/CoreBundle/Resources/contao/dca/tl_module.php b/src/CoreBundle/Resources/contao/dca/tl_module.php old mode 100644 new mode 100755 diff --git a/src/CoreBundle/Resources/contao/dca/tl_user_group.php b/src/CoreBundle/Resources/contao/dca/tl_user_group.php index 8e9b389f6..6f29615da 100644 --- a/src/CoreBundle/Resources/contao/dca/tl_user_group.php +++ b/src/CoreBundle/Resources/contao/dca/tl_user_group.php @@ -17,7 +17,18 @@ * @filesource */ -use MetaModels\CoreBundle\Contao\Hooks\FixupUserGroupModules; +use ContaoCommunityAlliance\DcGeneral\Contao\Callback\Callbacks; -$GLOBALS['TL_DCA']['tl_user_group']['fields']['modules']['options_callback'] = - [FixupUserGroupModules::class, 'fixupModules']; +$prefCallback = $GLOBALS['TL_DCA']['tl_user_group']['fields']['alexf']['options_callback'] ?? null; +// Filter all MetaModels tables from user group permissions - only Admins MUST edit MetaModels. +$GLOBALS['TL_DCA']['tl_user_group']['fields']['alexf']['options_callback'] = +static function () use ($prefCallback): array { + $options = (null === $prefCallback) ? [] : Callbacks::call($prefCallback); + foreach (\array_keys($options) as $tableName) { + if (str_starts_with($tableName, 'tl_metamodel')) { + unset($options[$tableName]); + } + } + + return $options; +}; diff --git a/src/CoreBundle/Resources/contao/languages/da/default.php b/src/CoreBundle/Resources/contao/languages/da/default.php deleted file mode 100644 index 76e07c5f2..000000000 --- a/src/CoreBundle/Resources/contao/languages/da/default.php +++ /dev/null @@ -1,80 +0,0 @@ -Hilfe-Website finden Sie als Leitfaden zu MetaModels das Handbuch, alle Support-Kanäle, Videos und unseren Newsletter-Service.


    Direkter Link zum MetaModels Handbuch...'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['main_headline'] = 'Bitte unterstützen Sie uns!'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['main_text'] = 'Als Entwickler dieses Projektes erhalten wir keine Vergütung für unsere Arbeit. Ein Großteil unserer wertvollen Zeit widmen wir dem MetaModels-Projekt. Jede Spende an das MetaModels-Projekt würde es uns ermöglichen, während unserer regulären Arbeitszeit an dem Projekt zu arbeiten, was die Entwicklung erheblich beschleunigen würde. Deshalb bitten wir um eine Unterstützung für das MetaModels-Projekt.

    Wir garantieren, dass Spendengelder nur für dieses Projekt ausgegeben werden. Sollten Sie spezielle Wünsche oder Anforderungen haben, können Sie gerne ein Mitglied unseres Teamsanfragen, das Ihnen gerne weiterhilft.


    Ein großes Dankeschön an alle bestehenden Supporter und Sponsoren. Bitte beachten Sie unsere Spendenseite. Ein solches umfangreiches Open Source Projekt konnten wir ohne die Unterstützung der Community nicht realisieren.

    Mehr Infos'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['other_donations'] = 'Für Spenden besuchen Sie auch unsere Fundraisings oder beachten Sie Spenden für das Handbuch.'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['purpose'] = 'Verwendungszweck'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_filter']['0'] = 'Fi'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_filter']['1'] = 'Filtern'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_name']['0'] = 'MM'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_name']['1'] = 'MetaModel'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting']['0'] = 'Rs'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting']['1'] = 'Render-Einstellung'; -$GLOBALS['TL_LANG']['MSC']['noItemsMsg'] = 'Ihre Suche lieferte keine passenden Ergebnisse.'; -$GLOBALS['TL_LANG']['MSC']['no_theme'] = 'Globaler Gültigkeitsbereich '; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['filter']['0'] = 'Filtersets'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['limit']['0'] = 'Limitierung'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['search']['0'] = 'Suche'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['sort']['0'] = 'Sortierung'; -$GLOBALS['TL_LANG']['MSC']['random'] = 'Zufällig'; -$GLOBALS['TL_LANG']['MSC']['template_in_theme'] = '%s (%s)'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clr']['0'] = 'clr'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clr']['1'] = 'Hebt alle Floats auf.'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clx']['0'] = 'clx'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clx']['1'] = 'Entfernt die Voreinstellung "overflow:hidden". Bitte gemeinsam mit "clr" verwenden.'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['long']['0'] = 'long'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['long']['1'] = 'Sorgt dafür, dass das Eingabefeld zwei Spalten umfasst.'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['m12']['0'] = 'm12'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['m12']['1'] = 'Fügt dem Element einen oberen Abstand von 12 Pixeln hinzu (z.B. für einzelne Checkboxen).'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50']['0'] = 'w50'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50']['1'] = 'Setzt die Feldbreite auf 50% und floatet das Element (float:left).'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50x']['0'] = 'w50x'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50x']['1'] = 'Entfernt die Voreinstellung für eine feste Höhe. Bitte gemeinsam mit "w50" verwenden.'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['wizard']['0'] = 'wizard'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['wizard']['1'] = 'Verkürzt das Eingabefeld, damit genug Platz für den Wizard (z.B. einen Date Picker) ist.'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['action_add'] = '+'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['action_remove'] = '-'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['clear_all'] = 'Alle Filter zurücksetzen'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'] = 'Nicht filtern'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['no_combinations'] = '(Keine passenden Kombinationen gefunden.)'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['select_all'] = 'Alles auswählen'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['submit'] = 'Filtern'; - diff --git a/src/CoreBundle/Resources/contao/languages/de/explain.php b/src/CoreBundle/Resources/contao/languages/de/explain.php deleted file mode 100644 index 2862d23d5..000000000 --- a/src/CoreBundle/Resources/contao/languages/de/explain.php +++ /dev/null @@ -1,102 +0,0 @@ - - Es ist erforderlich, dass diese Abfrage mindestens eine Spalte mit dem Namen "id" zurückgibt.
    - Es ist nicht möglich, Berechnungen aus dem SQL an die Liste zu übergeben.
    - Die Deklaration der Spaltennamen sollte mit dem Tabellenalias als Präfix eingegeben werden, z.B. t.name.'; -$GLOBALS['TL_LANG']['XPL']['customsql']['1']['0'] = 'Beispiel 1
    Einfache Abfrage'; -$GLOBALS['TL_LANG']['XPL']['customsql']['1']['1'] = '
    SELECT t.id FROM mm_mymetamodel AS t WHERE t.page_id=1
    - Damit werden alle IDs aus der Tabelle mm_mymetamodel ausgewählt, mit page_id=1 - '; -$GLOBALS['TL_LANG']['XPL']['customsql']['2']['0'] = 'Beispiel 2
    Tabellennamen einsetzen'; -$GLOBALS['TL_LANG']['XPL']['customsql']['2']['1'] = '
    SELECT t.id FROM {{table}} AS t WHERE t.page_id=1
    - Dies ist lediglich dasselbe wie in Beispiel 1, aber der Tabellenname des aktuellen MetaModel - (z.B.: das mm_mymetamodel von oben) wird in die Abfrage eingefügt.'; -$GLOBALS['TL_LANG']['XPL']['customsql']['3']['0'] = 'Inserttags'; -$GLOBALS['TL_LANG']['XPL']['customsql']['3']['1'] = 'Insert-Tags werden unterstützt. Bitte beachten, dass nicht alle Tags für alle Ausgaben verfügbar sein können. Falls eine Filtereinstellung wie zum Beispiel {{page::id}} benutzt wird, dann ist der Insert-Tag nur für einen Seitenaufruf im Frontend und nicht für einen RRS-Feed verfügbar.'; -$GLOBALS['TL_LANG']['XPL']['customsql']['4']['0'] = 'Sichere Inserttags'; -$GLOBALS['TL_LANG']['XPL']['customsql']['4']['1'] = 'Sichere Insert-Tags funktionieren wie normale Insert-Tags. Allerdings werden die Werte in der Abfrage escaped.
    Eine unbedachte Nutzung kann daher zu unerwarteten Ergebnissen führen.
    Die Notation für sichere Insert-Tags ist wie folgt:
    {{secure::page::id}}
    '; -$GLOBALS['TL_LANG']['XPL']['customsql']['5']['0'] = 'Parameterquellen'; -$GLOBALS['TL_LANG']['XPL']['customsql']['5']['1'] = 'Parameterquellen sind nach diesem Muster aufgebaut:
    {{param::[source]?[query string]}}
    Eine Quelle kann bestehen aus
    • get - HTTP GET Query-String
    • post - HTTP POST Feldern
    • session - einem beliebigen Feld aus der Contao-Session
    • filter - einen beliebigen ausgeführten Filterparameter (um Filterparameter zwischen Filtereinstellungen zu teilen).
    Der Abfragestring wird wie ein normaler HTTP-Query-String als "name=wert"-Paar aufgebaut kann mit dem Zeichen & kombiniert werden und muss mindestens das Feld \'name\' enthalten. Einer oder mehrere der folgenden optionalen Schlüsselwörter können zusätzlich benutzt werden;
    • default - der zu benutzende Standardwert falls kein anderer zur Verfügung steht
    • aggregate - entweder "list" oder "set"
    • key - auf 1 setzen um den Schlüssel eines Array auszulesen (benötigt "aggregate").
    • recursive - auf 1 setzen um Arrays rekursiv auszulesen (benötigt "aggregate").
    '; -$GLOBALS['TL_LANG']['XPL']['customsql']['6']['0'] = 'Beispiel 3
    -Komplexe Filter, Parameter und Quellen nutzen'; -$GLOBALS['TL_LANG']['XPL']['customsql']['6']['1'] = '
    SELECT t.id
    -    FROM {{table}} AS t
    -    WHERE t.catname={{param::get?name=category&default=defaultcat}}
    -

    - Dies ist dasselbe wie in Beispiel 2, aber jetzt verwenden wir einen Parameter aus dem "query"-String. -

    -

    - bei der Beispiel-URL wie diese: "http://example.org/list/category/demo.html"
    - wäre das Query: "SELECT t.id FROM mm_demo AS t WHERE t.catname=\'demo\'" -

    -

    - Ist die URL: "http://example.org/list.html",
    - wäre das Query: "SELECT t.id FROM mm_demo AS t WHERE t.catname=\'defaultcat\'" -

    - '; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['0']['0'] = 'Panel-Optionen'; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['0']['1'] = 'Fügen Sie eine oder mehrere Panel-Optionen hinzu und trennen Sie diese mit einem Komma (= Freiraum) oder Semikolon (= neue Zeile), z. B. "filter;search;sort,limit".'; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['1']['0'] = 'Panel-Optionen zum Kopieren'; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['1']['1'] = 'filter;search;sort,limit'; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['2']['0'] = 'Filtern'; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['2']['1'] = 'Zeige Filter in der Listendarstellung'; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['3']['0'] = 'Suche'; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['3']['1'] = 'Zeige Suche in der Listendarstellung'; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['4']['0'] = 'Sortierung'; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['4']['1'] = 'Zeige Sortierung in der Listendarstellung'; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['5']['0'] = 'Limit'; -$GLOBALS['TL_LANG']['XPL']['dca_panellayout']['5']['1'] = 'Zeige Limit in der Listendarstellung'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['0']['0'] = 'Eigenschaftswert ist gleich ...'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['0']['1'] = 'Die Bedingung ist erfüllt, wenn der Attributwert gleich dem festgelegten Wert ist. Als Attribute können diejenigen mit Einfachauswahl wie z.B. Select oder Checkbox ausgewählt werden.'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['1']['0'] = 'Eigenschaftswert beinhaltet ...'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['1']['1'] = 'Die Bedingung ist erfüllt, wenn ein beliebiger Attributwert gleich dem jeweils festgelegten Wert ist (Schnittmenge bzw. ODER). Als Attribute können diejenigen mit Mehrfachauswahl wie z.B. Tags ausgewählt werden.'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['2']['0'] = 'Eigenschaft ist sichtbar ...'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['2']['1'] = 'Die Bedingung ist erfüllt, wenn alle Bedingungen für ein ausgewähltes Attribut erfüllt sind. Mit anderen Worten, das Attribut ist sichtbar, und nur dann, wenn das ausgewählte (oder "referenzierte") Attribut auch sichtbar ist. Mit diesem Bedingungstyp erspart man sich das Duplizieren von erstellten Ansichtsbedingungen eines Attributs.'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['3']['0'] = 'ODER'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['3']['1'] = 'Eine beliebige Bedingung muss erfüllt sein.'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['4']['0'] = 'UND'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['4']['1'] = 'Alle Bedingungen müssen erfüllt sein.'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['5']['0'] = 'NICHT'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['5']['1'] = 'Kehrt das Ergebnis einer vorgegebenen Bedingung um.'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['0']['0'] = 'Die CSS-Klasse für das Eingabewidget setzen'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['0']['1'] = 'Legen Sie eine oder mehrere der folgenden CSS-Klassen fest, um das Layout des Widgets wie "clr w50" zu definieren.'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['1']['0'] = 'CSS-Klassen zum Kopieren'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['1']['1'] = 'clr clx w50 w50x m12 wizard long'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['2']['0'] = 'clr'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['2']['1'] = 'Hebt alle Floats auf.'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['3']['0'] = 'clx'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['3']['1'] = 'Entfernt die Voreinstellung "overflow:hidden". Bitte gemeinsam mit "clr" verwenden.'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['4']['0'] = 'w50'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['4']['1'] = 'Setzt die Feldbreite auf 50% und floated links (float:left).'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['5']['0'] = 'w50x'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['5']['1'] = 'Entfernt die Voreinstellung für eine feste Höhe. Bitte gemeinsam mit "w50" verwenden.'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['6']['0'] = 'm12'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['6']['1'] = 'Fügt dem Element einen oberen Abstand von 12 Pixeln hinzu (z.B. für einzelne Checkboxen).'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['7']['0'] = 'wizard'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['7']['1'] = 'Verkürzt das Eingabefeld, damit genug Platz für den Wizard (z.B. einen Date Picker) ist.'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['8']['0'] = 'long'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['8']['1'] = 'Setzt das Feld auf 100% Breite.'; - diff --git a/src/CoreBundle/Resources/contao/languages/de/modules.php b/src/CoreBundle/Resources/contao/languages/de/modules.php deleted file mode 100644 index dfd63cf1a..000000000 --- a/src/CoreBundle/Resources/contao/languages/de/modules.php +++ /dev/null @@ -1,25 +0,0 @@ -/orderDir/.html\' oder per GET-Parameter überschrieben werden.'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_sort_param_type']['0'] = 'URL-Typ für Parameter'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_sort_param_type']['1'] = 'Bitte wählen Sie den Typ der URL Parameter als Slug (key/value) oder GET (key=value).'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_sortby']['0'] = 'Sortieren nach'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_sortby']['1'] = 'Bitte wählen Sie eine Reihenfolge für die Sortierung aus.'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_sortby_direction']['0'] = 'Sortierreihenfolge'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_sortby_direction']['1'] = 'In aufsteigender oder absteigender Reihenfolge'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_use_limit']['0'] = 'Offset und Limit für die Auflistung verwenden'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_use_limit']['1'] = 'Auswählen, falls Sie die Anzahl anzuzeigender Items begrenzen möchten. Diese Einstellung ist beipielsweise nützlich, wenn Sie nur die ersten 500 Items anzeigen möchten, oder falls Sie alle Items anzeigen und dabei die ersten 10 überspringen wollen. Eine voreingestellte Paginierung bleibt dabei erhalten.'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_use_parameters']['0'] = 'Parameter aktivieren'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_use_parameters']['1'] = 'Sie können die Parameterliste aktivieren, um Ihre eigenen Parameter einzustellen.'; -$GLOBALS['TL_LANG']['tl_content']['mm_config_legend'] = 'MetaModel-Einstellungen'; -$GLOBALS['TL_LANG']['tl_content']['mm_filter_legend'] = 'MetaModel-Filter'; -$GLOBALS['TL_LANG']['tl_content']['mm_meta_legend'] = 'Suchmaschinen-Optimierung'; -$GLOBALS['TL_LANG']['tl_content']['mm_pagination_legend'] = 'MetaModel Paginierung'; -$GLOBALS['TL_LANG']['tl_content']['mm_parameters_legend'] = 'Parameter-Einstellungen'; -$GLOBALS['TL_LANG']['tl_content']['mm_rendering_legend'] = 'MetaModel Render-Einstellung'; -$GLOBALS['TL_LANG']['tl_content']['mm_sorting_legend'] = 'MetaModel Sortierung'; - diff --git a/src/CoreBundle/Resources/contao/languages/de/tl_form_field.php b/src/CoreBundle/Resources/contao/languages/de/tl_form_field.php deleted file mode 100644 index 504f575ee..000000000 --- a/src/CoreBundle/Resources/contao/languages/de/tl_form_field.php +++ /dev/null @@ -1,28 +0,0 @@ -Hinweis: Diese Option wird automatisch gesetzt, wenn in der Attributkonfiguration "Eindeutige Werte" ausgewählt wurde.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['mandatory_for_unique_attr'] = 'Eindeutige (unique) Attribute sind automatisch Pflichtfelder (Einstellung nicht änderbar).'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['name_langcode'] = 'Sprache'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['name_value'] = 'Legenden-Titel'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['new']['0'] = 'Neu'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['new']['1'] = 'Neue Einstellung erstellen.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['overview_legend'] = 'Filtern und Suchen in der Backend-Liste'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pasteafter']['0'] = 'Neue Einstellung oben anlegen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pasteafter']['1'] = 'Neue Einstellung nach Element ID %s anlegen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pastenew']['0'] = 'Neue Einstellung oben anlegen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pastenew']['1'] = 'Neues Einstellung nach dem Element ID %s anlegen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['presentation_legend'] = 'Anzeigeoptionen des Widgets'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['preserveTags']['0'] = 'Alle HTML-Tags nicht encodieren'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['preserveTags']['1'] = 'Falls angewählt, werden keine HTML-Tags encodiert.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['readonly']['0'] = 'Nur lesen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['readonly']['1'] = 'Wenn aktiviert, erlaubt das Feld nur das Lesen und kann nicht geändert werden.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['readonly_for_force_alias'] = 'Attribute mit "Neuerstellung erzwingen" sind automatisch "nur lesend" (Einstellung nicht änderbar).'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rows']['0'] = 'Zeilen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rows']['1'] = 'Anzahl der Zeilen, die für longtext / table Widget verwendet werden.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rte']['0'] = 'Richtext-Editor aktivieren'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rte']['1'] = 'Wählen Sie eine Voreinstellung für den Richtext-Editor aus, die für dieses Feld benutzt werden soll (falls vorhanden).'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['searchable']['0'] = 'Suchbar'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['searchable']['1'] = 'Auswählen, falls dieses Attribut für die Suche im Backend zur Verfügung stehen soll.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['show']['0'] = 'Einstellungsdetails'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['show']['1'] = 'Zeige Details der Einstellung ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['spaceToUnderscore']['0'] = 'Leerzeichen durch Unterstriche ersetzen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['spaceToUnderscore']['1'] = 'Falls diese Option angewählt ist, werden Leerzeichen durch Unterstriche ersetzt.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['submitOnChange']['0'] = 'Absenden bei Änderungen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['submitOnChange']['1'] = 'Wenn aktiv, wird das Formular bei Änderungen eines Feldwertes abgesendet.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['template']['0'] = 'Angepasstes Template für die Ausgabe'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['template']['1'] = 'Wählen Sie das Template aus, das für das gewählte Attribut verwendet werden soll. Gültige Dateinamen für das Template beginnen mit "mm_<typ>", wobei <typ> für den Typ steht.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['title_legend'] = 'Typ'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['tl_class']['0'] = 'Backend-Klasse'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['tl_class']['1'] = 'Hier können Sie eine oder mehrere Backend-Klassen festlegen.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['toggle']['0'] = 'Wechseln'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['toggle']['1'] = 'Umschaltung des Status der Einstellung ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash']['0'] = 'Führende \'/\' bearbeiten'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash']['1'] = 'Hier können Sie angeben, wie führende \'/\' behandelt werden sollen.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash_options']['0'] = 'Schrägstrich beim Speichern entfernen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash_options']['1'] = 'Schrägstrich beim Speichern hinzufügen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash_options']['2'] = 'Nichts tun'; - diff --git a/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_dcasetting_condition.php b/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_dcasetting_condition.php deleted file mode 100644 index 633915bcd..000000000 --- a/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_dcasetting_condition.php +++ /dev/null @@ -1,70 +0,0 @@ -%s
    für Attribut %s (Parameter: %s)'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['typedesc']['conditionand'] = '%s %s
    alle Bedingungen müssen erfüllt sein.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['typedesc']['conditionnot'] = '%s %s
    kehrt das Ergebnis der vorgegebenen Bedingung um.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['typedesc']['conditionor'] = '%s %s
    eine beliebige Bedingung muss erfüllt sein.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['value']['0'] = 'Wert'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['value']['1'] = 'Bitte wählen Sie einen eigenen Wert aus.'; - diff --git a/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_filter.php b/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_filter.php deleted file mode 100644 index ba1f4e4ab..000000000 --- a/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_filter.php +++ /dev/null @@ -1,35 +0,0 @@ -[%s, "%s"]'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['_comment_'] = '
    %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['_default_'] = '%1$s %2$s%3$s%5$s%4$s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['_url_'] = ' (URL: %s)'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['conditionand'] = '%1$s %2$s%4$s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['conditionor'] = '%1$s %2$s%4$s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['fefilter'] = '%1$s %2$s %3$s%4$s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['simplelookup'] = '%1$s %2$s%3$s%5$s%4$s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typenames']['conditionand'] = 'UND-Bedingung (AND)'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typenames']['conditionor'] = 'ODER-Bedingung (OR)'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typenames']['customsql'] = 'Eigenes SQL'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typenames']['idlist'] = 'Vordefinierter Satz von Items'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typenames']['simplelookup'] = 'Einfache Abfrage'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['urlparam']['0'] = 'URL-Parameter'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['urlparam']['1'] = 'Geben Sie den URL-Parameter an, der dem ausgewählten Attribut zugeordnet werden soll. Der "auto_item"-Parameter kann ebenfalls verwendet werden. Diese Einstellung ist nützlich um Aliase zu verwenden.'; - diff --git a/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_item.php b/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_item.php deleted file mode 100644 index 0e4bb78e4..000000000 --- a/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_item.php +++ /dev/null @@ -1,52 +0,0 @@ -%s [%s]'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addAll_activate'] = 'Hinzugefügte Attribute aktivieren.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addAll_addsuccess'] = 'Das Attribut "%s" [%s] wurde der Render-Einstellung hinzugefügt.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addAll_alreadycontained'] = 'Das Attribut "%s" [%s] ist bereits in der Render-Einstellung vorhanden.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addAll_willadd'] = 'Fügt das Attribut "%s" [%s] den Render-Einstellung hinzu.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['0'] = 'Alle hinzufügen'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['1'] = 'Alle Attribute der Render-Einstellung hinzufügen.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['additional_class']['0'] = 'Eigene CSS-Klasse'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['additional_class']['1'] = 'Eingabe einer CSS-Klasse, wenn diese mit dem Attribut ausgegeben werden soll.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['advanced_legend'] = 'Erweitern'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['0'] = 'Attribut'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['1'] = 'Attribut, auf das sich diese Einstellung bezieht.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['copy']['0'] = 'Render-Einstellung kopieren'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['copy']['1'] = 'Kopieren Sie die Render-Einstellung ID %s.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['cut']['0'] = 'Render-Einstellung ausschneiden'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['cut']['1'] = 'Ausschneiden der Render-Einstellung ID %s.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['delete']['0'] = 'Render-Einstellung löschen'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['delete']['1'] = 'Löschen Sie die Render-Einstellung ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit']['0'] = 'Einstellung bearbeiten'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit']['1'] = 'Render-Einstellung ID %s bearbeiten.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['0'] = 'Neu'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['1'] = 'Neue Einstellung erstellen.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['pastenew']['0'] = 'Neue Einstellung oben erstellen'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['pastenew']['1'] = 'Neues Einstellung nach Render-Einstellung ID %s anlegen'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['show']['0'] = 'Details der Render-Einstellung'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['show']['1'] = 'Anzeige Details der Render-Einstellung ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['0'] = 'Angepasstes Template für die Ausgabe'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['1'] = 'Wählen Sie das Template aus, das für das gewählte Attribut verwendet werden soll. Gültige Dateinamen für das Template beginnen mit "mm_<typ>", wobei <typ> für den Typ steht.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['title_legend'] = 'Typ'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle']['0'] = 'Wechseln'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle']['1'] = 'Umschaltung des Status für die Render-Einstellung ID %s.'; - diff --git a/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_rendersettings.php deleted file mode 100644 index bba6b80ea..000000000 --- a/src/CoreBundle/Resources/contao/languages/de/tl_metamodel_rendersettings.php +++ /dev/null @@ -1,75 +0,0 @@ -/orderDir/.html\' oder per GET-Parameter überschrieben werden.'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_sort_param_type']['0'] = 'URL-Typ für Parameter'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_sort_param_type']['1'] = 'Bitte geben Sie den Typ der URL-Parameter als Slug (key/value) oder GET (key=value) an.'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_sortby']['0'] = 'Sortieren nach'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_sortby']['1'] = 'Bitte wählen Sie eine Reihenfolge für die Sortierung aus.'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_sortby_direction']['0'] = 'Sortierreihenfolge'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_sortby_direction']['1'] = 'In aufsteigender oder absteigender Reihenfolge'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_use_limit']['0'] = 'Offset und Limit für die Auflistung verwenden'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_use_limit']['1'] = 'Auswählen, falls Sie die Anzahl anzuzeigender Datensätze begrenzen möchten. Diese Einstellung ist beispielsweise nützlich, wenn Sie nur die ersten 500 Datensätze anzeigen möchten, oder falls Sie alle Datensätze anzeigen und dabei die ersten 10 überspringen wollen. Eine voreingestellte Paginierung bleibt dabei erhalten.'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_use_parameters']['0'] = 'Parameter aktivieren'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_use_parameters']['1'] = 'Sie können die Parameterliste aktivieren, um Ihre eigenen Parameter einzustellen.'; -$GLOBALS['TL_LANG']['tl_module']['mm_config_legend'] = 'MetaModel-Einstellungen'; -$GLOBALS['TL_LANG']['tl_module']['mm_filter_legend'] = 'MetaModel-Filter'; -$GLOBALS['TL_LANG']['tl_module']['mm_meta_legend'] = 'Suchmaschinen-Optimierung'; -$GLOBALS['TL_LANG']['tl_module']['mm_pagination_legend'] = 'MetaModel Paginierung'; -$GLOBALS['TL_LANG']['tl_module']['mm_parameters_legend'] = 'Parameter-Einstellungen'; -$GLOBALS['TL_LANG']['tl_module']['mm_rendering_legend'] = 'MetaModel Render-Einstellung'; -$GLOBALS['TL_LANG']['tl_module']['mm_sorting_legend'] = 'MetaModel Sortierung'; - diff --git a/src/CoreBundle/Resources/contao/languages/de/tl_syncCto_database.php b/src/CoreBundle/Resources/contao/languages/de/tl_syncCto_database.php deleted file mode 100644 index ef6246bd8..000000000 --- a/src/CoreBundle/Resources/contao/languages/de/tl_syncCto_database.php +++ /dev/null @@ -1,23 +0,0 @@ -απλό ερώτημα '; -$GLOBALS['TL_LANG']['XPL']['customsql']['2']['0'] = 'Παραδειγμα 2
    εισαγωγη ονοματος ταμπελας'; -$GLOBALS['TL_LANG']['XPL']['customsql']['3']['0'] = 'Εισαγωγη ετικετων'; -$GLOBALS['TL_LANG']['XPL']['customsql']['4']['0'] = 'Ασφαλης εισαγωγη ετικετων'; -$GLOBALS['TL_LANG']['XPL']['customsql']['5']['0'] = 'Πηγες παραμετρων
    '; -$GLOBALS['TL_LANG']['XPL']['customsql']['6']['0'] = 'Παραδειγμα 3
    χρησιμοποιηση φιλτρων των παραμετρων πηγων'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['3']['0'] = 'OR'; - diff --git a/src/CoreBundle/Resources/contao/languages/el/modules.php b/src/CoreBundle/Resources/contao/languages/el/modules.php deleted file mode 100644 index 437f62dae..000000000 --- a/src/CoreBundle/Resources/contao/languages/el/modules.php +++ /dev/null @@ -1,26 +0,0 @@ -%s [%s]'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['0'] = 'Προσθηκη ολων'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['1'] = ' -Προσθέστε όλα τα χαρακτηριστικά για να καταστήσει τη ρύθμιση '; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['advanced_legend'] = 'Προσαρμογη'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['0'] = ' Χαρακτηριστικο'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['1'] = 'Χαρακτηριστικό που η ρύθμιση αυτή το αφορά.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit']['0'] = 'Επεξεργασια ρυθμισης'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['0'] = 'Νεος τυπος'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['1'] = 'Δημιουργια νεας ρυθμισης'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['0'] = 'Προσαρμοσμένο πρότυπο που θα χρησιμοποιηθεί για την παραγωγή '; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['1'] = 'Επιλέξτε το πρότυπο που πρέπει να χρησιμοποιηθεί για την επιλεγμένη ιδιότητα. Ισχύει για αρχεία προτύπων αρχίζουν με "mm_<type>" όπου το όνομα του τύπου τίθεται για <type>'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['title_legend'] = 'Τυπος'; - diff --git a/src/CoreBundle/Resources/contao/languages/el/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/languages/el/tl_metamodel_rendersettings.php deleted file mode 100644 index 0160600de..000000000 --- a/src/CoreBundle/Resources/contao/languages/el/tl_metamodel_rendersettings.php +++ /dev/null @@ -1,64 +0,0 @@ - * @author David Molineus * @author Sven Baumann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -$GLOBALS['TL_LANG']['CTE']['metamodels'] = 'MetaModel elements'; -$GLOBALS['TL_LANG']['CTE']['metamodel_content'][0] = 'MetaModel list'; -$GLOBALS['TL_LANG']['CTE']['metamodel_content'][1] = +$GLOBALS['TL_LANG']['CTE']['metamodels'] = 'MetaModels elements'; +$GLOBALS['TL_LANG']['CTE']['metamodel_content'][0] = 'MetaModels list'; +$GLOBALS['TL_LANG']['CTE']['metamodel_content'][1] = 'Adds a list of MetaModel items to the article.'; -$GLOBALS['TL_LANG']['CTE']['metamodels_frontendfilter'][0] = 'MetaModel frontend filter'; -$GLOBALS['TL_LANG']['CTE']['metamodels_frontendfilter'][1] = +$GLOBALS['TL_LANG']['CTE']['metamodels_frontendfilter'][0] = 'MetaModels frontend filter'; +$GLOBALS['TL_LANG']['CTE']['metamodels_frontendfilter'][1] = 'Adds a frontend filter for a MetaModel.'; -$GLOBALS['TL_LANG']['CTE']['metamodels_frontendclearall'][0] = 'MetaModel clear all'; -$GLOBALS['TL_LANG']['CTE']['metamodels_frontendclearall'][1] = +$GLOBALS['TL_LANG']['CTE']['metamodels_frontendclearall'][0] = 'MetaModels clear all'; +$GLOBALS['TL_LANG']['CTE']['metamodels_frontendclearall'][1] = 'Adds a clear all for all frontend filter.'; -$GLOBALS['TL_LANG']['MSC']['metamodel_filtersetting']['editRecord'] = - 'Edit filter setting %%s for filter "%s" in MetaModel "%s"'; -$GLOBALS['TL_LANG']['MSC']['metamodel_filtersetting']['label'] = 'Filter "%s" in MetaModel "%s"'; -$GLOBALS['TL_LANG']['MSC']['metamodel_rendersetting']['editRecord'] = - 'Edit attribute setting %%s for render setting "%s" in MetaModel "%s"'; -$GLOBALS['TL_LANG']['MSC']['metamodel_rendersetting']['label'] = - 'Render setting "%s" in MetaModel "%s"'; -$GLOBALS['TL_LANG']['BRD']['metamodel'] = 'MetaModels'; -$GLOBALS['TL_LANG']['BRD']['metamodel_attribute'] = 'Attributes of "%s"'; -$GLOBALS['TL_LANG']['BRD']['metamodel_rendersettings'] = 'All render setting of "%s"'; -$GLOBALS['TL_LANG']['BRD']['metamodel_rendersetting'] = 'Render settings in "%s"'; -$GLOBALS['TL_LANG']['BRD']['metamodel_dca_sortgroup'] = 'Sorting and grouping in "%s"'; -$GLOBALS['TL_LANG']['BRD']['metamodel_dca'] = 'All input screens of "%s"'; -$GLOBALS['TL_LANG']['BRD']['metamodel_dcasetting'] = 'Input screens in "%s"'; -$GLOBALS['TL_LANG']['BRD']['metamodel_dca_combine'] = - 'Input screen and render setting combination for "%s"'; -$GLOBALS['TL_LANG']['BRD']['metamodel_dcasetting_condition'] = - 'Visibility conditions for attribute "%s"'; -$GLOBALS['TL_LANG']['BRD']['metamodel_filter'] = 'All filter of "%s"'; -$GLOBALS['TL_LANG']['BRD']['metamodel_filtersetting'] = 'Filter settings in "%s"'; -$GLOBALS['TL_LANG']['BRD']['metamodel_searchable_pages'] = 'All indexes of "%s"'; -$GLOBALS['TL_LANG']['MSC']['metamodel_edit_as_child']['label'] = 'Edit "%s" for item %%s'; -$GLOBALS['TL_LANG']['MSC']['metamodels_sorting'] = 'Sorting'; -$GLOBALS['TL_LANG']['MSC']['random'] = 'Random'; -$GLOBALS['TL_LANG']['MSC']['template_in_theme'] = '%s (%s)'; -$GLOBALS['TL_LANG']['MSC']['no_theme'] = 'global scope'; -$GLOBALS['TL_LANG']['MSC']['noItemsMsg'] = - 'There are no items matching your search.'; -$GLOBALS['TL_LANG']['MSC']['details'] = 'Details'; -$GLOBALS['TL_LANG']['MSC']['field_label'] = '%s:'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50'][0] = 'w50'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50'][1] = - 'Set the field width to 50% and float it (float:left).'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50x'][0] = 'w50x'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50x'][1] = - 'Remove only the annoying fixed height, please use it together with "w50".'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clr'][0] = 'clr'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clr'][1] = 'Clear all floats.'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clx'][0] = 'clx'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clx'][1] = - 'Remove only the annoying overflow hidden, please use it together with "clr".'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['m12'][0] = 'm12'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['m12'][1] = - 'Add a 12 pixel top margin to the element (used for single checkboxes).'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['wizard'][0] = 'wizard'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['wizard'][1] = - 'Shorten the input field so there is enough room for the wizard button (e.g. date picker fields).'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['long'][0] = 'long'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['long'][1] = - 'Make the text input field span two columns.'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['search'][0] = 'Search'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['search'][1] = ''; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['sort'][0] = 'Sort'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['sort'][1] = ''; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['filter'][0] = 'Filter'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['filter'][1] = ''; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['limit'][0] = 'Limit'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['limit'][1] = ''; -$GLOBALS['TL_LANG']['ERR']['no_attribute_extension'] = - 'Please install at least one attribute extension! MetaModels without attributes do not make sense.'; -$GLOBALS['TL_LANG']['ERR']['activate_extension'] = - 'Please activate the required extension "%s" (%s)'; -$GLOBALS['TL_LANG']['ERR']['install_extension'] = - 'Please install the required extension "%s" (%s)'; -$GLOBALS['TL_LANG']['ERR']['columnExists'] = - 'There is already an attribute with the given column name.'; -$GLOBALS['TL_LANG']['ERR']['no_palette'] = - 'Attempt to access the MetaModel "%s" without input screen for current user %s.'; -$GLOBALS['TL_LANG']['ERR']['no_view'] = - 'Attempt to access the MetaModel "%s" without view for user %s.'; -$GLOBALS['TL_LANG']['ERR']['invalidTableName'] = 'The table name "%s" is invalid.'; -$GLOBALS['TL_LANG']['ERR']['invalidColumnName'] = - 'The column name "%s" is invalid.'; -$GLOBALS['TL_LANG']['ERR']['systemColumn'] = - 'The column name "%s" is reserved for system use.'; -$GLOBALS['TL_LANG']['ERR']['tableDoesNotExist'] = 'Table "%s" does not exist.'; -$GLOBALS['TL_LANG']['ERR']['tableExists'] = 'Table "%s" already exists.'; -$GLOBALS['TL_LANG']['ERR']['columnDoesNotExist'] = - 'Column "%s" does not exist on table "%s".'; -$GLOBALS['TL_LANG']['ERR']['columnExists'] = - 'Column "%s" already exists on table "%s".'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['submit'] = 'Filter'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'] = 'No filtering'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['select_all'] = 'Select all'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['clear_all'] = 'Clear all filter'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['action_add'] = '+'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['action_remove'] = '-'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['no_combinations'] = + +$GLOBALS['TL_LANG']['metamodels_frontendfilter']['submit'] = 'Filter'; +$GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'] = 'No filtering'; +$GLOBALS['TL_LANG']['metamodels_frontendfilter']['select_all'] = 'Select all'; +$GLOBALS['TL_LANG']['metamodels_frontendfilter']['clear_all'] = 'Clear all filter'; +$GLOBALS['TL_LANG']['metamodels_frontendfilter']['action_add'] = '+'; +$GLOBALS['TL_LANG']['metamodels_frontendfilter']['action_remove'] = '-'; +$GLOBALS['TL_LANG']['metamodels_frontendfilter']['no_combinations'] = ' (No matching combinations found.)'; -$GLOBALS['TL_LANG']['MSC']['metamodel_filtersettings_parameter']['simplelookup'][0] = 'Filter value for attribute "%s"'; -$GLOBALS['TL_LANG']['MSC']['metamodel_filtersettings_parameter']['simplelookup'][1] = ''; -$GLOBALS['TL_LANG']['MSC']['orderMetaModelListByAscending'] = - 'Sort by %s in ascending order'; -$GLOBALS['TL_LANG']['MSC']['orderMetaModelListByDescending'] = - 'Sort by %s in descending order'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['main_headline'] = 'We are calling for your help!'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['purpose'] = 'Purpose'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['other_donations'] = - 'For donations check also our - - fundraisings or consider - - donating for the manual.'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['contributor_headline'] = - 'Thanks to these users for tickets, suggestions and translations'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_name'][0] = 'MM'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_name'][1] = 'MetaModel'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_filter'][0] = 'Fi'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_filter'][1] = 'Filter'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting'][0] = 'Rs'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting'][1] = 'Rendersetting'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['contributor_link'] = 'See contributors at github...'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['main_text'] = - 'As the developers of this project, we receive no compensation for our work. - Much of our valuable time is freely given to the MetaModels project. Any - donations towards the MetaModels project would allow us to work on the - project during our working hours, speeding up development significantly. -

    We guarantee to spend any donations only on this project. - If you have any specific requirements or features requests, you are free - to hire a member from our team, who will gladly - help you.

    A big thanks to all our existing supporters and - sponsors. Please consider joining our list of sponsors. We could not - create such a popular open source project without the support of the - community.

    More informations'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['help_headline'] = - 'Help for your MetaModels projects'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['help_text'] = - 'On our help - website as guide to MetaModels you can find the manual, all support - channels, videos tutorials and our newsletter service.

    - - Direct link to the MetaModels manual...'; -$GLOBALS['TL_LANG']['METAMODELS_SYSTEM_COLUMNS']['id'] = 'ID'; -$GLOBALS['TL_LANG']['METAMODELS_SYSTEM_COLUMNS']['pid'] = 'PID'; -$GLOBALS['TL_LANG']['METAMODELS_SYSTEM_COLUMNS']['sorting'] = 'Sorting'; -$GLOBALS['TL_LANG']['METAMODELS_SYSTEM_COLUMNS']['tstamp'] = 'Timestamp'; -$GLOBALS['TL_LANG']['METAMODELS_SYSTEM_COLUMNS']['vargroup'] = 'Vargroup'; -$GLOBALS['TL_LANG']['METAMODELS_SYSTEM_COLUMNS']['varbase'] = 'Varbase'; -$GLOBALS['TL_LANG']['METAMODELS_SYSTEM_COLUMNS']['meta'] = 'Metafields'; -$GLOBALS['TL_LANG']['METAMODELS_SYSTEM_COLUMNS']['attributes'] = 'Attributes'; diff --git a/src/CoreBundle/Resources/contao/languages/en/explain.php b/src/CoreBundle/Resources/contao/languages/en/explain.php old mode 100644 new mode 100755 diff --git a/src/CoreBundle/Resources/contao/languages/en/modules.php b/src/CoreBundle/Resources/contao/languages/en/modules.php old mode 100644 new mode 100755 index 7f8c7fcbe..38e3500c7 --- a/src/CoreBundle/Resources/contao/languages/en/modules.php +++ b/src/CoreBundle/Resources/contao/languages/en/modules.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2018 The MetaModels team. + * (c) 2012-2024 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,8 @@ * @subpackage Core * @author Christian Schiffler * @author Sven Baumann - * @copyright 2012-2018 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -22,11 +23,6 @@ /** * Back end modules */ -$GLOBALS['TL_LANG']['MOD']['metamodels'][0] = 'MetaModels'; -$GLOBALS['TL_LANG']['MOD']['metamodels'][1] = - 'The MetaModels extension allows you to create own data models.'; -$GLOBALS['TL_LANG']['MOD']['support_metamodels'][0] = 'Support MetaModels'; -$GLOBALS['TL_LANG']['MOD']['support_metamodels'][1] = 'Support information for the MetaModels extension.'; $GLOBALS['TL_LANG']['FMD']['metamodels'][0] = 'MetaModels'; $GLOBALS['TL_LANG']['FMD']['metamodels'][1] = 'The MetaModels extension allows you to create own data models.'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_content.php b/src/CoreBundle/Resources/contao/languages/en/tl_content.php old mode 100644 new mode 100755 index d0c553bde..5ca272516 --- a/src/CoreBundle/Resources/contao/languages/en/tl_content.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_content.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -42,7 +42,7 @@ 'Please specify the offset value (i.e. 10 to skip the first 10 items).'; $GLOBALS['TL_LANG']['tl_content']['metamodel_limit'][0] = 'Maximum number of items'; $GLOBALS['TL_LANG']['tl_content']['metamodel_limit'][1] = - 'Please enter the maximum number of items. Enter 0 to show all items and therefore disable the pagination.'; + 'Please enter the maximum number of items - enter 0 to show all items.'; $GLOBALS['TL_LANG']['tl_content']['metamodel_sortby'][0] = 'Order by'; $GLOBALS['TL_LANG']['tl_content']['metamodel_sortby'][1] = 'Please choose the sort order.'; @@ -87,9 +87,9 @@ $GLOBALS['TL_LANG']['tl_content']['metamodel_page_param_type'][0] = 'URL-Type for pagination'; $GLOBALS['TL_LANG']['tl_content']['metamodel_page_param_type'][1] = 'Please specify the type of URL parameters als slug (key/value) or GET (key=value).'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_maxpaginationlinks'][0] = +$GLOBALS['TL_LANG']['tl_content']['metamodel_maxpaginationlinks'][0] = 'Maximum number of pagination links'; -$GLOBALS['TL_LANG']['tl_content']['metamodel_maxpaginationlinks'][1] = +$GLOBALS['TL_LANG']['tl_content']['metamodel_maxpaginationlinks'][1] = 'Please enter the maximum number pagination links. Enter 0 to show the default value from Contao e.g. 7.'; $GLOBALS['TL_LANG']['tl_content']['metamodel_pagination'][0] = 'Custom template to use for pagination'; @@ -116,7 +116,7 @@ $GLOBALS['TL_LANG']['tl_content']['metamodel_fef_id'][1] = 'Set ID as own postfix for "FORM_SUBMIT" value e.g. to use redirect and another filter -' . ' in which case the value must be the same. '; -$GLOBALS['TL_LANG']['tl_content']['metamodel_fef_urlfragment'][0] = 'URL fragment'; +$GLOBALS['TL_LANG']['tl_content']['metamodel_fef_urlfragment'][0] = 'URL fragment'; $GLOBALS['TL_LANG']['tl_content']['metamodel_fef_urlfragment'][1] = 'Add URL fragment to jump to anchor or id.'; $GLOBALS['TL_LANG']['tl_content']['metamodel_fef_params'][0] = 'Attributes'; @@ -154,11 +154,3 @@ $GLOBALS['TL_LANG']['tl_content']['metamodel_meta_description'][0] = 'Meta Description'; $GLOBALS['TL_LANG']['tl_content']['metamodel_meta_description'][1] = 'Set this attribute as the meta-description of the page.'; -$GLOBALS['TL_LANG']['tl_content']['editmetamodel'][0] = 'Edit MetaModel'; -$GLOBALS['TL_LANG']['tl_content']['editmetamodel'][1] = 'Edit the MetaModel ID %s.'; -$GLOBALS['TL_LANG']['tl_content']['editrendersetting'][0] = 'Edit rendersetting'; -$GLOBALS['TL_LANG']['tl_content']['editrendersetting'][1] = - 'Edit the render setting ID %s.'; -$GLOBALS['TL_LANG']['tl_content']['editfiltersetting'][0] = 'Edit filtersetting'; -$GLOBALS['TL_LANG']['tl_content']['editfiltersetting'][1] = - 'Edit the filter setting ID %s.'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_form_field.php b/src/CoreBundle/Resources/contao/languages/en/tl_form_field.php old mode 100644 new mode 100755 diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_maintenance.php b/src/CoreBundle/Resources/contao/languages/en/tl_maintenance.php old mode 100644 new mode 100755 diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php deleted file mode 100644 index 68f0edf53..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel.php +++ /dev/null @@ -1,93 +0,0 @@ - - * @author Christian de la Haye - * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -$GLOBALS['TL_LANG']['tl_metamodel']['id'][0] = 'Id'; -$GLOBALS['TL_LANG']['tl_metamodel']['id'][1] = 'Id of the MetaModel'; -$GLOBALS['TL_LANG']['tl_metamodel']['name'][0] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel']['name'][1] = 'MetaModel name.'; -$GLOBALS['TL_LANG']['tl_metamodel']['tstamp'][0] = 'Revision date'; -$GLOBALS['TL_LANG']['tl_metamodel']['tstamp'][1] = 'Date and time of the latest revision'; -$GLOBALS['TL_LANG']['tl_metamodel']['tableName'][0] = 'Table name'; -$GLOBALS['TL_LANG']['tl_metamodel']['tableName'][1] = 'Name of database table to store items to.'; -$GLOBALS['TL_LANG']['tl_metamodel']['mode'][0] = 'Parent list mode'; -$GLOBALS['TL_LANG']['tl_metamodel']['mode'][1] = 'Mode to use for parent/child relationship.'; -$GLOBALS['TL_LANG']['tl_metamodel']['translated'][0] = 'Translation'; -$GLOBALS['TL_LANG']['tl_metamodel']['translated'][1] = - 'Check if this MetaModel shall support translation/multilingualism.'; -$GLOBALS['TL_LANG']['tl_metamodel']['languages'][0] = 'Languages to provide for translation'; -$GLOBALS['TL_LANG']['tl_metamodel']['languages'][1] = - 'Specify all languages that shall be available for translation.'; -$GLOBALS['TL_LANG']['tl_metamodel']['languages_langcode'][0] = 'Language'; -$GLOBALS['TL_LANG']['tl_metamodel']['languages_langcode'][1] = 'Select the languages you want to provide.'; -$GLOBALS['TL_LANG']['tl_metamodel']['languages_isfallback'][0] = 'Fallback language'; -$GLOBALS['TL_LANG']['tl_metamodel']['languages_isfallback'][1] = 'Check the language that shall be used as fallback.'; -$GLOBALS['TL_LANG']['tl_metamodel']['varsupport'][0] = 'Variant support'; -$GLOBALS['TL_LANG']['tl_metamodel']['varsupport'][1] = - 'Check if this MetaModel shall support variants of items.'; -$GLOBALS['TL_LANG']['tl_metamodel']['localeterritorysupport'][0] = 'Locale territory support'; -$GLOBALS['TL_LANG']['tl_metamodel']['localeterritorysupport'][1] = - 'Check if this MetaModel shall support language territory at locale.'; -$GLOBALS['TL_LANG']['tl_metamodel']['sorting'][0] = 'Sorting'; -$GLOBALS['TL_LANG']['tl_metamodel']['sorting'][1] = 'Sorting order of items.'; -$GLOBALS['TL_LANG']['tl_metamodel']['title_legend'] = 'Name and table'; -$GLOBALS['TL_LANG']['tl_metamodel']['translated_legend'] = 'Translation'; -$GLOBALS['TL_LANG']['tl_metamodel']['advanced_legend'] = 'Advanced settings'; -$GLOBALS['TL_LANG']['tl_metamodel']['new'][0] = 'New MetaModel'; -$GLOBALS['TL_LANG']['tl_metamodel']['new'][1] = 'Create a new MetaModel.'; -$GLOBALS['TL_LANG']['tl_metamodel']['edit'][0] = 'Manage items'; -$GLOBALS['TL_LANG']['tl_metamodel']['edit'][1] = 'Manage items of MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['copy'][0] = 'Copy MetaModel definition'; -$GLOBALS['TL_LANG']['tl_metamodel']['copy'][1] = 'Copy definition of MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['delete'][0] = 'Delete MetaModel'; -$GLOBALS['TL_LANG']['tl_metamodel']['delete'][1] = 'Delete MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['show'][0] = 'MetaModel details'; -$GLOBALS['TL_LANG']['tl_metamodel']['show'][1] = 'Show details of MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['editheader'][0] = 'Edit MetaModel'; -$GLOBALS['TL_LANG']['tl_metamodel']['editheader'][1] = 'Edit the MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['fields'][0] = 'Define attributes'; -$GLOBALS['TL_LANG']['tl_metamodel']['fields'][1] = 'Define attributes for MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['filter'][0] = 'Define filters'; -$GLOBALS['TL_LANG']['tl_metamodel']['filter'][1] = 'Define filters for MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['rendersettings'][0] = 'Define render settings'; -$GLOBALS['TL_LANG']['tl_metamodel']['rendersettings'][1] = 'Define render settings for MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['dca'][0] = 'Define input screens'; -$GLOBALS['TL_LANG']['tl_metamodel']['dca'][1] = 'Define input screens for MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['dca_combine'][0] = 'Define input/output combinations'; -$GLOBALS['TL_LANG']['tl_metamodel']['dca_combine'][1] = - 'Define input/output combinations for MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['cut'][0] = 'Move MetaModel'; -$GLOBALS['TL_LANG']['tl_metamodel']['cut'][1] = 'Define the order of your MetaModels.'; -$GLOBALS['TL_LANG']['tl_metamodel']['searchable_pages'][0] = 'Define search settings'; -$GLOBALS['TL_LANG']['tl_metamodel']['searchable_pages'][1] = 'Define search settings for MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['pastenew'][0] = 'Add new at the top'; -$GLOBALS['TL_LANG']['tl_metamodel']['pastenew'][1] = 'Add new after MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['pasteafter'][0] = 'Create new MetaModel'; -$GLOBALS['TL_LANG']['tl_metamodel']['pasteafter'][1] = 'Create new after MetaModel ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel']['itemFormatCount']['0'] = '%s items'; -$GLOBALS['TL_LANG']['tl_metamodel']['itemFormatCount']['1'] = '%s item'; -$GLOBALS['TL_LANG']['tl_metamodel']['itemFormatCount']['2:'] = '%s items'; -$GLOBALS['TL_LANG']['tl_metamodel']['deleteConfirm'] = 'Do you really want to delete MetaModel ID %s?'; - -$GLOBALS['TL_LANG']['tl_metamodel']['hint_schema_manager'] = - 'After creating an model, the database must be migrated (console, Contao Manager) -' . - ' even if the table name is changed. When changing the table name, the user data itself must be transferred.'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php deleted file mode 100644 index 88ab281c7..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_attribute.php +++ /dev/null @@ -1,73 +0,0 @@ - - * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['type'][0] = 'Attribute type'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['type'][1] = - 'Select the type of this attribute. ' . - 'WARNING: if you change this, all existing data within this attribute will be deleted.'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['name'][0] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['name'][1] = 'Human readable name'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['description'][0] = 'Description'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['description'][1] = 'Human readable description'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['colname'][0] = 'Column name'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['colname'][1] = - 'Internal reference name for this attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['isvariant'][0] = 'Enable variant override'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['isvariant'][1] = - 'Check this, if you want variants within the MetaModel to override the parent item\'s value'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['isunique'][0] = 'Unique values'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['isunique'][1] = - 'Check this, if you want to ensure that each value only occurs once'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['name_langcode'] = 'Language'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['name_value'] = 'Description'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['title_legend'] = - 'Type, naming and base attribute configuration'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['advanced_legend'] = 'Advanced settings'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['new'][0] = 'New attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['new'][1] = 'Create new attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['pastenew'][0] = 'New attribute after this Attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['pastenew'][1] = 'New attribute after this Attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['edit'][0] = 'Edit attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['edit'][1] = 'Edit attribute ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['cut'][0] = 'Cut attribute definition'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['cut'][1] = 'Cut definition of attribute ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['copy'][0] = 'Copy attribute definition'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['copy'][1] = 'Copy definition of attribute ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['delete'][0] = 'Delete attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['delete'][1] = 'Delete attribute ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['show'][0] = 'Attribute details'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['show'][1] = 'Show details of attribute ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['editheader'][0] = 'Edit attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['editheader'][1] = 'Edit the attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['pastenew'][0] = 'Add new at the top'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['pastenew'][1] = 'Add new after attribute ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['pasteafter'][0] = 'Create new attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['pasteafter'][1] = 'Create new after attribute ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['error_unknown_attribute'][0] = 'Unknown attribute!'; -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['error_unknown_attribute'][1] = - 'Extension missing? The attribute type "%s" is not installed.'; - -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['deleteConfirm'] = 'Do you really want to delete attribute ID %s?'; - -$GLOBALS['TL_LANG']['tl_metamodel_attribute']['hint_schema_manager'] = - 'After creating an attribute, the database must be migrated (console, Contao Manager) -' . - ' even if the column name is changed. When changing the column name, the user data itself must be transferred.'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php deleted file mode 100644 index 3f9a4d42f..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca.php +++ /dev/null @@ -1,106 +0,0 @@ - - * @author Ingolf Steinhardt - * @author Sven Baumann - * @copyright 2012-2023 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -$GLOBALS['TL_LANG']['tl_metamodel_dca']['name'][0] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['name'][1] = 'Name of the input screen.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['tstamp'][0] = 'Revision date'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['tstamp'][1] = 'Date and time of the latest revision.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendertype'][0] = 'Integration'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendertype'][1] = 'Select the desired type of integration.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermode'][0] = 'Render mode'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermode'][1] = 'Select the desired render mode.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['ptable'][0] = 'Parent table name'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['ptable'][1] = - 'Name of the database table that shall be referred to as parent table.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['showColumns'][0] = 'Use column based layout'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['showColumns'][1] = - 'If selected a table header will be generated with column names.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['backendsection'][0] = 'Backend section'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['backendsection'][1] = - 'Select the desired backend section where you want the MetaModel appear. ' . - 'For models that shall be edited by end users, the "content" section most likely will be appropriate.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['backendicon'][0] = 'Backend icon'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['backendicon'][1] = - 'Select the desired backend icon.' . - 'This icon will get used to draw an image in the parent list if you have a integration as child table.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['backendcaption'][0] = 'Backend caption'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['backendcaption'][1] = - 'The text you specify in here, will get used as the label and description text in the backend menu.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['becap_langcode'][0] = 'Language'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['becap_langcode'][1] = 'Select the languages you want to provide.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['becap_label'][0] = 'Label text'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['becap_label'][1] = - 'The text you specify in here, will get used as the menu label in the backend menu.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['becap_description'][0] = 'Description text'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['becap_description'][1] = - 'The text you specify in here, will get used as the description (hover title) in the backend menu.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['panelLayout'][0] = 'Panel layout'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['panelLayout'][1] = - 'Separate panel options with comma (= space) and semicolon (= new line) like "filter;search;sort,limit".'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['panelpicker'] = 'Panelpicker'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['use_limitview'][0] = 'View limitation'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['use_limitview'][1] = 'Activate the view limitation.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['limit_rendersetting'][0] = 'Limit the render setting'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['limit_rendersetting'][1] = 'Choose between front end or backend.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['iseditable'][0] = 'Allow editing of items'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['iseditable'][1] = - 'If checked, this input screen allows the editing of items.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['iscreatable'][0] = 'Allow creating of items'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['iscreatable'][1] = - 'If checked, this input screen allows the creating of items.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['isdeleteable'][0] = 'Allow deleting of items'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['isdeleteable'][1] = - 'If checked, this input screen allows the deleting of items.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['title_legend'] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['view_legend'] = 'View settings'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['backend_legend'] = 'Backend integration'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['display_legend'] = 'Data display settings'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['permissions_legend'] = 'Data manipulation permissions'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['new'][0] = 'New input screen'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['new'][1] = 'Create new input screen'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['edit'][0] = 'Edit input screen'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['edit'][1] = 'Edit the input screen ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['copy'][0] = 'Copy input screen definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['copy'][1] = 'Copy definition of input screen ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['delete'][0] = 'Delete input screen'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['delete'][1] = 'Delete input screen ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['show'][0] = 'Input screen details'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['show'][1] = 'Show details of input screen ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['settings'][0] = 'Input screen settings'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['settings'][1] = 'Edit the settings of input screen ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['groupsort_settings'][0] = 'Grouping and sorting'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['groupsort_settings'][1] = - 'Edit the grouping and sorting settings of input screen ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['subheadline'][0] = 'Additions to the mask-heading'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['subheadline'][1] = - 'The field can be used to adapt the heading of the mask at edit and replaces the output of the ID.' . - 'You can use simple tokens e.g. ##model_name##, ##model_firstname## [##model_id##]'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendertypes']['standalone'] = 'Standalone'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendertypes']['ctable'] = 'As child table'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermodes']['flat'] = 'Flat'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermodes']['parented'] = 'Parented'; -$GLOBALS['TL_LANG']['tl_metamodel_dca']['rendermodes']['hierarchical'] = 'Hierarchical'; - -$GLOBALS['TL_LANG']['tl_metamodel_dca']['hint_rendermode_hierarchical'] = - 'When using the "Hierarchical" render mode, the current sort must be enable to "Manual sorting" as default.'; - -$GLOBALS['TL_LANG']['tl_metamodel_dca']['deleteConfirm'] = 'Do you really want to delete input screen ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_combine.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_combine.php deleted file mode 100644 index 2f611a1b5..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_combine.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['dca_combiner_legend'] = 'Combination configuration'; - -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['dca_combiner'][0] = 'Permissions for input screen and views'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['dca_combiner'][1] = - 'For selected frontend user group (if any) and selected backend user group (if any) use the selected palette and ' . - 'the selected view.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['fe_group'][0] = 'Frontend group'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['fe_group'][1] = - 'The frontend user group the combination applies to; * is \'catch all\'.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['be_group'][0] = 'Backend group'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['be_group'][1] = - 'The backend user group the combination applies to; * is \'catch all\'.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['dca_id'][0] = 'The input screen'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['dca_id'][1] = 'The input screen the combination applies to.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['view_id'][0] = 'The render setting'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['view_id'][1] = 'The view the combination applies to.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['sysadmin'] = 'Administrator'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_combine']['anonymous'] = 'Anonymous'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php deleted file mode 100644 index 83f33b642..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dca_sortgroup.php +++ /dev/null @@ -1,90 +0,0 @@ - - * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -/** - * Fields - */ -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['name'][0] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['name'][1] = 'Name of the sorting group.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['tstamp'][0] = 'Revision date'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['tstamp'][1] = - 'Date and time of the latest revision.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['isdefault'][0] = 'Is default'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['isdefault'][1] = - 'Determines that this input screen shall be used as default for the parenting MetaModel.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendermode'][0] = 'Render mode'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendermode'][1] = 'Select the desired render mode.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['becap_langcode'][0] = 'Language'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['becap_langcode'][1] = - 'Select the languages you want to provide.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['becap_label'][0] = 'Label text'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['becap_label'][1] = - 'The text you specify in here, will get used as the menu label in the backend menu.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['becap_description'][0] = 'Description text'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['becap_description'][1] = - 'The text you specify in here, will get used as the description (hover title) in the backend menu.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptype'][0] = 'Grouping type'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptype'][1] = - 'The grouping type to use in the item view.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergroupattr'][0] = 'Grouping attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergroupattr'][1] = - 'The attribute to use for grouping in the item view.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouplen'][0] = 'Grouping length'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouplen'][1] = - 'The amount of characters to use for grouping.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendersortattr'][0] = 'Sorting attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendersortattr'][1] = 'The attribute to sort by.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendersort'][0] = 'Sorting direction'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendersort'][1] = 'The sorting direction.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['ismanualsort'][0] = 'Enable manual sorting'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['ismanualsort'][1] = - 'If this is enabled, the user will be able to perform manual sorting.'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['title_legend'] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['display_legend'] = 'Data display settings'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['new'][0] = 'New definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['new'][1] = 'Create new definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['edit'][0] = 'Edit definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['edit'][1] = 'Edit the definition ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['copy'][0] = 'Copy definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['copy'][1] = 'Copy the definition ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'][0] = 'Delete definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['delete'][1] = 'Delete the definition ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][0] = 'Definition details'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['show'][1] = 'Show details of definition ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['toggle'][0] = 'Toggle'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['toggle'][1] = - 'Toggle the state of definition ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][0] = 'Definition settings'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['settings'][1] = - 'Edit the settings of definition ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptypes']['none'] = 'Do not group '; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptypes']['char'] = 'Group by initial letter(s)'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptypes']['digit'] = 'Group by numeric order'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptypes']['day'] = 'Group by day of date'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptypes']['weekday'] = 'Group by weekday of date'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptypes']['week'] = 'Group by week of year'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptypes']['month'] = 'Group by month of date'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendergrouptypes']['year'] = 'Group by year of date'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendersortdirections']['asc'] = 'Ascending'; -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['rendersortdirections']['desc'] = 'Descending'; - -$GLOBALS['TL_LANG']['tl_metamodel_dca_sortgroup']['deleteConfirm'] = 'Do you really want to delete definition ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php deleted file mode 100644 index ca0a9afe9..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting.php +++ /dev/null @@ -1,145 +0,0 @@ - - * @author Cliff Parnitzky - * @author Ingolf Steinhardt - * @author Sven Baumann - * @copyright 2012-2023 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -/** - * Fields - */ - -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['dcatype'][0] = 'Type'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['dcatype'][1] = 'Select the attribute type.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['attr_id'][0] = 'Attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['attr_id'][1] = 'Attribute this setting relates to.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['template'][0] = 'Custom template to use for generating'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['template'][1] = - 'Select the template that shall be used for the selected attribute. ' . - 'Valid template files start with "mm_<type>" where the type name is put for <type>'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['tl_class'][0] = 'Backend class'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['tl_class'][1] = - 'Here you can set backend class(es). Open the wizard for an overview of the classes.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['be_template'][0] = 'Template at backend'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['be_template'][1] = - 'You can chose own template for widget in backend - add file in root folder of template.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['legendhide'][0] = 'Collapse section'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['legendhide'][1] = 'Collapse the section by default.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['legendtitle'][0] = 'Legend title'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['legendtitle'][1] = 'Here you can enter the legend title.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['name_langcode'] = 'Language'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['name_value'] = 'Legend title'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['mandatory'][0] = 'Mandatory'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['mandatory'][1] = 'Check if this attribute shall be ' . - 'mandatory. -
    NOTE: This will be implicitely active on if you selected "Unique values" in the attribute configuration.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['alwaysSave'][0] = 'Always save'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['alwaysSave'][1] = - 'If true the field will always be saved, even if its value has not changed.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['chosen'][0] = 'Chosen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['chosen'][1] = 'Enable Chosen graphical select widget.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['filterable'][0] = 'Filterable'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['filterable'][1] = - 'Check if this attribute shall be available for backend filtering.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['searchable'][0] = 'Searchable'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['searchable'][1] = - 'Check if this attribute shall be available for backend search.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['allowHtml'][0] = 'Do not encode allowed html tags.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['allowHtml'][1] = - 'If you select this, allowed HTML tags from system settings will not be encoded.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['preserveTags'][0] = 'Do not encode all html tags.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['preserveTags'][1] = - 'If you select this, no HTML tags will be encoded.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['decodeEntities'][0] = 'Decode HTML entities.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['decodeEntities'][1] = - 'If you select this, all HTML entities will be decoded. Note that HTML entities are always decoded if "Do not encode allowed html tags" is true.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rte'][0] = 'Enable richtext editor on this'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rte'][1] = - 'Select the rich text configuration that shall be used on this field (if any).'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rows'][0] = 'Rows'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rows'][1] = - 'Amount of rows to use for longtext/table widget.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['cols'][0] = 'Columns'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['cols'][1] = - 'Amount of colums to use for longtext/table widget'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash'][0] = 'Trailing slash handling'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash'][1] = - 'Here you can specify how trailing slashes shall be handled'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['spaceToUnderscore'][0] = 'Replace spaces with underscore'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['spaceToUnderscore'][1] = - 'If true any whitespace character will be replaced by an underscore.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['includeBlankOption'][0] = 'Include blank option'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['includeBlankOption'][1] = - 'if true a blank option will be added to the options which allows to define a "no item selected" option.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['readonly'][0] = 'Read only'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['readonly'][1] = - 'If true a the widget will be read only and may not be changed.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['submitOnChange'][0] = 'Submit on change'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['submitOnChange'][1] = - 'If active the form will be submitted when the field value changes.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['title_legend'] = 'Type'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['presentation_legend'] = 'Widget appearance related options'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['functions_legend'] = 'Functionality related options'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['overview_legend'] = - 'Filtering and searching in the backend list'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['backend_legend'] = 'Backend'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['config_legend'] = 'Configuration'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['advanced_legend'] = 'Advanced'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['new'][0] = 'New'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['new'][1] = 'Create new setting.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['edit'][0] = 'Edit setting'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['edit'][1] = 'Edit the setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['cut'][0] = 'Cut setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['cut'][1] = 'Cut the setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['copy'][0] = 'Copy setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['copy'][1] = 'Copy the setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['delete'][0] = 'Delete setting'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['delete'][1] = 'Delete the setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['conditions'][0] = 'Manage visibility conditions'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['conditions'][1] = - 'Manage the visibility conditions of property ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['show'][0] = 'Setting details'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['show'][1] = 'Show details of setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['toggle'][0] = 'Toggle'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['toggle'][1] = 'Toggle the state of setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['addall'][0] = 'Add all'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['addall'][1] = 'Add all attributes to input screen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pastenew'][0] = 'Add new at the top'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pastenew'][1] = 'Add new after setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pasteafter'][0] = 'Create new setting at the top'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pasteafter'][1] = 'Create new after setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['dcatypes']['legend'] = 'Legend'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['dcatypes']['attribute'] = 'Attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash_options']['0'] = 'Strip slash on save'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash_options']['1'] = 'Add slash on save'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash_options']['2'] = 'Do nothing'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['addAll_willadd'] = - 'Will add the attribute "%s" [%s, "%s"] to the input screen.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['addAll_alreadycontained'] = - 'Attribute "%s" [%s, "%s"] is already contained in input screen.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['addAll_addsuccess'] = - 'Added the attribute "%s" [%s, "%s"] to the input screen.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['addAll_activate'] = 'Add new settings enabled.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['addAll_tlclass'] = 'Set backend class.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['mandatory_for_unique_attr'] = - 'Unique attribues are automatically mandatory (this is not changable).'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['readonly_for_force_alias'] = - 'Attribues with force alias are automatically readonly (this is not changable).'; - -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['deleteConfirm'] = 'Do you really want to delete setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting_condition.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting_condition.php deleted file mode 100644 index 703ed8719..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_dcasetting_condition.php +++ /dev/null @@ -1,110 +0,0 @@ - - * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -/** - * Legends - */ -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['list_label'] = - 'Visibility conditons'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['basic_legend'] = - 'Basic configuration'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['config_legend'] = - 'Condition configuration'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['type'][0] = 'Type'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['type'][1] = - 'Select the condition type.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['enabled'][0] = 'Enabled'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['enabled'][1] = - 'Check to enable this condition.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['comment'][0] = 'Comment'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['comment'][1] = - 'Enter a comment to describe the purpose of this condition.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['attr_id'][0] = - 'Attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['attr_id'][1] = - 'Select the attribute to use for this condition.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['value'][0] = 'Value'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['value'][1] = - 'Please select the desired value.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['new'][0] = 'New'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['new'][1] = - 'Create new setting.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['edit'][0] = - 'Edit setting'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['edit'][1] = - 'Edit the setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['cut'][0] = - 'Cut setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['cut'][1] = - 'Cut the setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['copy'][0] = - 'Copy setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['copy'][1] = - 'Copy the setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['delete'][0] = - 'Delete setting'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['delete'][1] = - 'Delete the setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['conditions'][0] = - 'Manage conditions'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['conditions'][1] = - 'Manage the conditions of property ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['show'][0] = - 'Setting details'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['show'][1] = - 'Show details of setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['toggle'][0] = 'Toggle'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['toggle'][1] = - 'Toggle the state of setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['addall'][0] = 'Add all'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['addall'][1] = - 'Add all attributes to input screen'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['pastenew'][0] = - 'Add new at the top'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['pastenew'][1] = - 'Add new after setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['pasteafter'][1] = - 'Create new after setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['pasteinto'][0] = - 'Create new setting at the top'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['pasteinto'][1] = - 'Create new at the top of setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['conditionnames']['conditionpropertyvalueis'] = - 'Attribute value is...'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['conditionnames']['conditionpropertycontainanyof'] = - 'Attribute values contain any of...'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['conditionnames']['conditionpropertyvisible'] = - 'Is attribute visible...'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['conditionnames']['conditionor'] = 'OR'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['conditionnames']['conditionand'] = 'AND'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['conditionnames']['conditionnot'] = 'NOT'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['typedesc']['_default_'] = - '%s %s
    for attribute %s (Parameter: %s)'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['typedesc']['conditionor'] = - '%s %s
    any sub conditions must be fulfilled'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['typedesc']['conditionand'] = - '%s %s
    all sub conditions must be fulfilled'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['typedesc']['conditionnot'] = - '%s %s
    invert the result of the contained condition'; - -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['deleteConfirm'] = - 'Do you really want to delete setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filter.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filter.php deleted file mode 100644 index 3ae002946..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filter.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -$GLOBALS['TL_LANG']['tl_metamodel_filter']['name'][0] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['name'][1] = 'Filter setting name.'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['tstamp'][0] = 'Revision date'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['tstamp'][1] = 'Date and time of the latest revision.'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['title_legend'] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['pastenew'][0] = 'New'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['pastenew'][1] = 'Create a new filter setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['editheader'][0] = 'Edit'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['editheader'][1] = 'Edit MetaModel'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['new'][0] = 'New'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['new'][1] = 'Create new filter setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['edit'][0] = 'Edit setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['edit'][1] = 'Edit the filter setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['copy'][0] = 'Copy filter setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['copy'][1] = 'Copy the filter setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['delete'][0] = 'Delete filter setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['delete'][1] = 'Delete the filter setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['show'][0] = 'Filter setting details'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['show'][1] = 'Show details of filter setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['settings'][0] = 'Define attribute settings'; -$GLOBALS['TL_LANG']['tl_metamodel_filter']['settings'][1] = 'Define attribute settings for filter setting ID %s'; - -$GLOBALS['TL_LANG']['tl_metamodel_filter']['deleteConfirm'] = 'Do you really want to delete filter setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filtersetting.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filtersetting.php deleted file mode 100644 index dcc972a7d..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_filtersetting.php +++ /dev/null @@ -1,157 +0,0 @@ - - * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -/** - * Fields - */ -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['list_label'] = 'Filter settings'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['fid'][0] = 'Parent collection'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['fid'][1] = - 'The collection of filter settings, this setting belongs to.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['type'][0] = 'Type'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['type'][1] = 'The type of this setting.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['enabled'][0] = 'Enabled'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['enabled'][1] = 'Enable this filter setting.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['comment'][0] = 'Comment'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['comment'][1] = - 'A short comment for describing the purpose of this filter setting.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['attr_id'][0] = 'Attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['attr_id'][1] = - 'Attribute this setting relates to.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['all_langs'][0] = 'Search all languages'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['all_langs'][1] = - 'Check if you want to perform the lookup language independant. ' . - 'If this is not checked, only the current active language will be searched.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['allow_empty'][0] = 'Allow empty value'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['allow_empty'][1] = - 'Check if you want to allow this filter value to be emtpy, if checked and the parameter holds an empty value, ' . - 'this filter rule will behave as if it was not defined.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['stop_after_match'][0] = 'Stop after first match'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['stop_after_match'][1] = - 'Check if you want this filter setting to stop executing its child rules after the first subset returned matches.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['urlparam'][0] = 'URL parameter'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['urlparam'][1] = - 'The URL parameter that shall get mapped to the selected attribute. ' . - 'The special "auto_item" parameter can also be used, this is especially useful for alias columns.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['predef_param'][0] = 'Static parameter'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['predef_param'][1] = - 'Check if you want to be able to set the value of this parameter in the parenting list ' . - '(modules, content elements, etc.).'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['fe_widget'][0] = 'Provide Frontend widget'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['fe_widget'][1] = - 'Check if you want to display a filter widget in the Frontend.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['customsql'][0] = 'Custom SQL Query'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['customsql'][1] = - 'The SQL query that shall be executed, insert tags are supported.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['label'][0] = 'Label'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['label'][1] = - 'Show label instead of attribute name.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['template'][0] = 'Template'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['template'][1] = - 'Sub template for this filter element. Standard: form widget.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['blankoption'][0] = 'Empty option'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['blankoption'][1] = - 'Show empty options in filter widget.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['onlyused'][0] = 'Assigned values only'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['onlyused'][1] = - 'Show only options, that are assigned somewhere in the MetaModel.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['onlypossible'][0] = 'Remaining values only'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['onlypossible'][1] = - 'Show only options, that are still assigned somewhere after the actual filter is set.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['skipfilteroptions'][0] = - 'Ignore this filter for the remaining values'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['skipfilteroptions'][1] = - 'If activate the filter will return all options without itself in the filter rules.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['hide_label'][0] = - 'Hide label in filter widget'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['hide_label'][1] = - 'If active, the label is not output.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['label_as_blankoption'][0] = - 'Use label as blank option'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['label_as_blankoption'][1] = - 'If active, the label output as blank option.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['apply_sorting'][0] = 'Sorting'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['apply_sorting'][1] = - 'Please enter sorting of values in filter widget.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['cssID'][0] = 'CSS ID/class'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['cssID'][1] = - 'Here you can set an ID and one or more classes.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['placeholder'][0] = 'Placeholder'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['placeholder'][1] = - 'Show this text as long as the field is empty.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['sorting_directions']['natsort_asc'] = 'Natural sorting (ASC)'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['sorting_directions']['natsort_desc'] = 'Natural sorting (DESC)'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['defaultid'][0] = 'Default'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['defaultid'][1] = - 'Default value for selection.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['title_legend'] = 'Type'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['config_legend'] = 'Configuration'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['fefilter_legend'] = 'Frontend filter'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['new'][0] = 'New'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['new'][1] = 'Create new setting.'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['edit'][0] = 'Edit setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['edit'][1] = 'Edit the filter setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['copy'][0] = - 'Copy filter setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['copy'][1] = 'Copy the filter setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['cut'][0] = - 'Cut filter setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['cut'][1] = 'Cut the filter setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['delete'][0] = 'Delete filter setting'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['delete'][1] = 'Delete the filter setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['show'][0] = 'Filter setting details'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['show'][1] = - 'Show details of filter setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['toggle'][0] = 'Toggle'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['toggle'][1] = 'Toggle the state of setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['pastenew'][0] = 'Add new at the top'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['pastenew'][1] = 'Add new after setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['pasteafter'][1] = - 'Create new after setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['pasteinto'][0] = - 'Create new setting at the top'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['pasteinto'][1] = - 'Create new at the top of setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typenames']['idlist'] = 'Predefined set of items'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typenames']['simplelookup'] = 'Simple lookup'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typenames']['customsql'] = 'Custom SQL'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typenames']['conditionor'] = 'OR condition'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typenames']['conditionand'] = 'AND condition'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['_attribute_'] = ' [%s, "%s"]'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['_url_'] = ' (URL: %s)'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['_comment_'] = '
    %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['_default_'] = - '%1$s %2$s%3$s%5$s%4$s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['simplelookup'] = - '%1$s %2$s%3$s%5$s%4$s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['fefilter'] = - '%1$s %2$s %3$s%4$s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['conditionor'] = - '%1$s %2$s%4$s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['typedesc']['conditionand'] = - '%1$s %2$s%4$s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['items'][0] = 'Items'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['items'][1] = - 'Please enter the IDs of the items for filtering as comma-separated list.'; - -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['deleteConfirm'] = - 'Do you really want to delete filter setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_item.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_item.php deleted file mode 100644 index e060cca8f..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_item.php +++ /dev/null @@ -1,57 +0,0 @@ - - * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -$GLOBALS['TL_LANG']['tl_metamodel_item']['new'][0] = 'New item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['new'][1] = 'Create new item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['edit'][0] = 'Edit item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['edit'][1] = 'Edit item ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['copy'][0] = 'Copy item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['copy'][1] = 'Copy item ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['createvariant'][0] = 'New variant'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['createvariant'][1] = 'Create a new variant of item ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['cut'][0] = 'Move item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['cut'][1] = 'Move item ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['delete'][0] = 'Delete item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['delete'][1] = 'Delete item ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['show'][0] = 'Item details'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['show'][1] = 'Show details of item ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['editheader'][0] = 'Edit item type'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['editheader'][1] = 'Edit the item type'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['pasteafter'][0] = 'Create new item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['pasteafter'][1] = 'Create a new item after item ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['pasteinto'][0] = 'Create new item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['pasteinto'][1] = 'Create a new item in item ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['pastenew'][0] = 'Add new at the top'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['pastenew'][1] = 'Add new item after item ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['varbase'][0] = 'Is variant base'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['varbase'][1] = - 'Check this if you want to make this the base for the current variant group'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['editRecord'] = 'Edit item %s'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['newRecord'] = 'Create a new item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['sorting'][0] = 'Sorting'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['sorting'][1] = 'The manual sorting'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['id'][0] = 'ID of the item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['id'][1] = 'The id of the item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['pid'][0] = 'Parent item id'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['pid'][1] = 'The id of the parent item'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['tstamp'][0] = 'Revision date'; -$GLOBALS['TL_LANG']['tl_metamodel_item']['tstamp'][1] = 'The date when the item revision was created'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersetting.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersetting.php deleted file mode 100644 index ced2a7268..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersetting.php +++ /dev/null @@ -1,63 +0,0 @@ - - * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2022 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id'][0] = 'Attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id'][1] = 'Attribute this setting relates to.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template'][0] = 'Custom template to use for generating'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template'][1] = - 'Select the template that shall be used for the selected attribute. ' . - 'Valid template files start with "mm_<type>" where the type name is put for <type>'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['additional_class'][0] = 'Custom CSS class'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['additional_class'][1] = - 'Enter any CSS classes that you want get added to the output of this attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['title_legend'] = 'Type'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['advanced_legend'] = 'Advanced'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new'][0] = 'New'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new'][1] = 'Create new setting'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit'][0] = 'Edit setting'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit'][1] = 'Edit render setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['cut'][0] = 'Cut render setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['cut'][1] = 'Cut the render setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['copy'][0] = 'Copy render setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['copy'][1] = 'Copy the render setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['delete'][0] = 'Delete render setting'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['delete'][1] = 'Delete the render setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['show'][0] = 'Render setting details'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['show'][1] = 'Show details of render setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle'][0] = 'Toggle'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle'][1] = - 'Toggle the state of render setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall'][0] = 'Add all'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall'][1] = 'Add all attributes to render setting'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['pastenew'][0] = 'Add new at the top'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['pastenew'][1] = 'Add new after render setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_filtersetting']['row'] = '%s %s [%s]'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addAll_willadd'] = - 'Will add attribute "%s" [%s] to rendersetting.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addAll_alreadycontained'] = - 'Attribute "%s" [%s] already in rendersetting.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addAll_addsuccess'] = - 'Added attribute "%s" [%s] to rendersetting.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addAll_activate'] = 'Add new settings enabled.'; - -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['deleteConfirm'] = - 'Do you really want to render filter setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersettings.php deleted file mode 100644 index d9f247b07..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_rendersettings.php +++ /dev/null @@ -1,85 +0,0 @@ - - * @author Ingolf Steinhardt - * @author Sven Baumann - * @copyright 2012-2022 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['title_legend'] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['general_legend'] = 'General settings'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['expert_legend'] = 'Expert settings'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpto_legend'] = 'Frontend jump-to settings'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['additional_legend'] = 'Additional files'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['name'][0] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['name'][1] = 'Setting name.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['template'][0] = 'Template'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['template'][1] = - 'The template to use to render the items.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['format'][0] = 'Output format'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['format'][1] = - 'Define the output format. Leave empty to use the format used by current page.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['formatOptions']['html5'] = 'HTML5'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['formatOptions']['text'] = 'Text'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo'][0] = 'JumpTo page'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo'][1] = - 'The page that shall be used as "show details" urls. Note that the detailed URL params will get generated by the ' . - 'filter setting that is currently in use.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo_allLanguages'] = 'All languages'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo_language'][0] = 'Language'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo_language'][1] = 'The language for the jump to page.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo_page'][0] = 'Jump to page'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo_page'][1] = 'The page to use for detail links.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo_filter'][0] = 'Filter settings'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['jumpTo_filter'][1] = - 'The filter settings that define how the target (the reader/lister on the detail page) will filter the items.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['hideEmptyValues'][0] = 'Hide empty values'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['hideEmptyValues'][1] = - 'Hide empty values in backend and frontend.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['hideLabels'][0] = 'Hide labels'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['hideLabels'][1] = - 'Hide all labels in backend and frontend.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['additionalCss'][0] = 'Additional css files'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['additionalCss'][1] = - 'Choose this, if you want to include additional css files.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['additionalJs'][0] = 'Additional javascript files'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['additionalJs'][1] = - 'Choose this, if you want to include additional javascript files.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['file'] = 'File'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['publish'] = 'Publish'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['new'][0] = 'New'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['new'][1] = 'Create new setting'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['edit'][0] = 'Edit setting'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['edit'][1] = 'Edit the setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['copy'][0] = 'Copy setting definition'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['copy'][1] = 'Copy the setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['delete'][0] = 'Delete setting'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['delete'][1] = 'Delete the setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['show'][0] = 'Filter details'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['show'][1] = 'Show details of setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['settings'][0] = 'Define attribute settings'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['settings'][1] = - 'Define attribute settings for setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['pastenew'][0] = 'Add new at the top'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['pastenew'][1] = 'Add new after setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['pasteafter'][0] = 'Create new setting at the top'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['pasteafter'][1] = 'Create new after setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['error_unknown_id'] = 'unknown ID: %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['error_unknown_attribute'] = 'unknown attribute'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['error_unknown_column'] = 'unknown column'; - -$GLOBALS['TL_LANG']['tl_metamodel_rendersettings']['deleteConfirm'] = 'Do you really want to render setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_searchable_pages.php b/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_searchable_pages.php deleted file mode 100644 index 3faeef908..000000000 --- a/src/CoreBundle/Resources/contao/languages/en/tl_metamodel_searchable_pages.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @author Tim Becker - * @author Ingolf Steinhardt - * @author Sven Baumann - * @copyright 2012-2018 The MetaModels team. - * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['name'][0] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['name'][1] = 'Name of the searchable page setting'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['tstamp'][0] = 'Revision date'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['tstamp'][1] = 'Date and time of the latest revision.'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['rendersetting'][0] = 'Rendersetting'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['rendersetting'][1] = - 'Choose the rendersetting which will be used for the search rendering.'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['filter'][0] = 'Filtersetting'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['filter'][1] = - 'Choose the filtersetting which will be used for the search rendering.'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['filterparams'][0] = 'Filter parameter override'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['filterparams'][1] = 'Filter parameter override'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['title_legend'] = 'Name'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['general_legend'] = 'General settings'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['new'][0] = 'New searchable page'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['new'][1] = 'Create new searchable page setting'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['edit'][0] = 'Edit searchable page'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['edit'][1] = 'Edit the searchable page setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['copy'][0] = 'Copy searchable page'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['copy'][1] = - 'Copy definition of searchable page setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['delete'][0] = 'Delete searchable page'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['delete'][1] = 'Delete searchable page setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['show'][0] = 'Searchable page setting details'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['show'][1] = - 'Show details of searchable page setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][0] = 'Toggle'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['toggle'][1] = - 'Toggle the state of searchable page setting ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['settings'][0] = 'Searchable page settings'; -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['settings'][1] = - 'Edit the settings of searchable page setting ID %s'; - -$GLOBALS['TL_LANG']['tl_metamodel_searchable_pages']['deleteConfirm'] = - 'Do you really want to searchable page setting ID %s?'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_module.php b/src/CoreBundle/Resources/contao/languages/en/tl_module.php old mode 100644 new mode 100755 index abceb32d3..0caf3b184 --- a/src/CoreBundle/Resources/contao/languages/en/tl_module.php +++ b/src/CoreBundle/Resources/contao/languages/en/tl_module.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Christian Schiffler * @author Sven Baumann * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -41,7 +41,7 @@ 'Please specify the offset value (i.e. 10 to skip the first 10 items).'; $GLOBALS['TL_LANG']['tl_module']['metamodel_limit'][0] = 'Maximum number of items'; $GLOBALS['TL_LANG']['tl_module']['metamodel_limit'][1] = - 'Please enter the maximum number of items. Enter 0 to show all items and therefore disable the pagination.'; + 'Please enter the maximum number of items - enter 0 to show all items.'; $GLOBALS['TL_LANG']['tl_module']['metamodel_sortby'][0] = 'Order by'; $GLOBALS['TL_LANG']['tl_module']['metamodel_sortby'][1] = 'Please choose the sort order.'; $GLOBALS['TL_LANG']['tl_module']['metamodel_sortby_direction'][0] = 'Order by direction'; @@ -84,9 +84,9 @@ $GLOBALS['TL_LANG']['tl_module']['metamodel_page_param_type'][0] = 'URL-Type for pagination'; $GLOBALS['TL_LANG']['tl_module']['metamodel_page_param_type'][1] = 'Please specify the type of URL parameters als slug (key\value) or GET (key=value).'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_maxpaginationlinks'][0] = +$GLOBALS['TL_LANG']['tl_module']['metamodel_maxpaginationlinks'][0] = 'Maximum number of pagination links'; -$GLOBALS['TL_LANG']['tl_module']['metamodel_maxpaginationlinks'][1] = +$GLOBALS['TL_LANG']['tl_module']['metamodel_maxpaginationlinks'][1] = 'Please enter the maximum number pagination links. Enter 0 to show the default value from Contao e.g. 7.'; $GLOBALS['TL_LANG']['tl_module']['metamodel_pagination'][0] = 'Custom template to use for pagination'; @@ -149,9 +149,3 @@ $GLOBALS['TL_LANG']['tl_module']['metamodel_meta_description'][0] = 'Meta Description'; $GLOBALS['TL_LANG']['tl_module']['metamodel_meta_description'][1] = 'Set this attribute as the meta-description of the page.'; -$GLOBALS['TL_LANG']['tl_module']['editmetamodel'][0] = 'Edit MetaModel'; -$GLOBALS['TL_LANG']['tl_module']['editmetamodel'][1] = 'Edit the MetaModel ID %s.'; -$GLOBALS['TL_LANG']['tl_module']['editrendersetting'][0] = 'Edit render setting'; -$GLOBALS['TL_LANG']['tl_module']['editrendersetting'][1] = 'Edit the render setting ID %s.'; -$GLOBALS['TL_LANG']['tl_module']['editfiltersetting'][0] = 'Edit filter setting'; -$GLOBALS['TL_LANG']['tl_module']['editfiltersetting'][1] = 'Edit the filter setting ID %s.'; diff --git a/src/CoreBundle/Resources/contao/languages/en/tl_syncCto_database.php b/src/CoreBundle/Resources/contao/languages/en/tl_syncCto_database.php old mode 100644 new mode 100755 diff --git a/src/CoreBundle/Resources/contao/languages/et/default.php b/src/CoreBundle/Resources/contao/languages/et/default.php deleted file mode 100644 index e0669a075..000000000 --- a/src/CoreBundle/Resources/contao/languages/et/default.php +++ /dev/null @@ -1,62 +0,0 @@ -lihtne päring'; -$GLOBALS['TL_LANG']['XPL']['customsql']['3']['0'] = 'Sisesta silte'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['0']['0'] = 'Omaduse väärtus on...'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['2']['0'] = 'Kas omadus on nähtav...'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['3']['0'] = 'VÕI'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['4']['0'] = 'JA'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['5']['0'] = 'EI'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['2']['0'] = 'clr'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['3']['0'] = 'clx'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['4']['0'] = 'w50'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['5']['0'] = 'w50x'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['6']['0'] = 'm12'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['7']['0'] = 'juhendaja'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['8']['0'] = 'Pikk'; - diff --git a/src/CoreBundle/Resources/contao/languages/et/modules.php b/src/CoreBundle/Resources/contao/languages/et/modules.php deleted file mode 100644 index 8bfe53a98..000000000 --- a/src/CoreBundle/Resources/contao/languages/et/modules.php +++ /dev/null @@ -1,19 +0,0 @@ -requête plaine'; -$GLOBALS['TL_LANG']['XPL']['customsql']['2']['0'] = 'Example 2
    insert tablename'; -$GLOBALS['TL_LANG']['XPL']['customsql']['3']['0'] = 'Balises d\'insertion'; -$GLOBALS['TL_LANG']['XPL']['customsql']['4']['0'] = 'Sécuriser les balises'; -$GLOBALS['TL_LANG']['XPL']['customsql']['5']['0'] = 'Source des paramètres
    '; -$GLOBALS['TL_LANG']['XPL']['customsql']['6']['0'] = 'Example 3
    Utilise des sources de paramètres de filtre complexe'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['3']['0'] = 'OR'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['2']['0'] = 'clr'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['2']['1'] = 'Effacer tous les flottants'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['3']['0'] = 'clx'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['3']['1'] = 'Enlever seulement le débordement caché ennuyeux, à utiliser avec "clr".'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['4']['0'] = 'w50'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['4']['1'] = 'Définir la largeur du champ à 50% et son type de flottant (float:left).'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['5']['0'] = 'w50x'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['5']['1'] = 'Retirer seulement la hauteur fixe ennuyeuse, à utiliser avec "w50".'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['6']['0'] = 'm12'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['6']['1'] = 'Ajoute 12 pixels à la marge haute de l\'élément (utilisé pour les cases à cocher simples).'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['7']['0'] = 'wizard'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['7']['1'] = 'Raccourcir le champ de saisie de sorte qu\'il y ait assez de place pour le bouton Assistant (ex : champ sélecteur de date).'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['8']['0'] = 'long'; - diff --git a/src/CoreBundle/Resources/contao/languages/fr/modules.php b/src/CoreBundle/Resources/contao/languages/fr/modules.php deleted file mode 100644 index 8a2bb18e0..000000000 --- a/src/CoreBundle/Resources/contao/languages/fr/modules.php +++ /dev/null @@ -1,25 +0,0 @@ -"auto_item" peut aussi être utilisé, spécialement pour les alias de colonnes.'; - diff --git a/src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_item.php b/src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_item.php deleted file mode 100644 index 854d39d51..000000000 --- a/src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_item.php +++ /dev/null @@ -1,46 +0,0 @@ -%s [%s]'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['0'] = 'Ajouter tout'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['1'] = 'Ajouter tout les attributs au paramètre de rendu'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['advanced_legend'] = 'Avancé'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['0'] = 'Attribut'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['1'] = 'l\'attribut auquel ce paramètre se réfère.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit']['0'] = 'Éditer le paramètre'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['0'] = 'Nouveau'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['1'] = 'Créer nouveau paramètre'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['0'] = 'Modèle personnalisé à utiliser pour la production'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['1'] = 'Sélectionner le modèle qui doit être utilisé pour l\'attribut sélectionné. les fichiers modèle valides commencent par "mm_<type>" où le nom type est mis pour <type>'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['title_legend'] = 'Type'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle']['0'] = 'Basculer'; - diff --git a/src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_rendersettings.php deleted file mode 100644 index 9a3529884..000000000 --- a/src/CoreBundle/Resources/contao/languages/fr/tl_metamodel_rendersettings.php +++ /dev/null @@ -1,65 +0,0 @@ -query semplice'; -$GLOBALS['TL_LANG']['XPL']['customsql']['2']['0'] = 'Esempio 2
    Riferimento nome tabella'; -$GLOBALS['TL_LANG']['XPL']['customsql']['3']['0'] = 'Insert tags'; -$GLOBALS['TL_LANG']['XPL']['customsql']['4']['0'] = 'Secure insert tags'; -$GLOBALS['TL_LANG']['XPL']['customsql']['5']['0'] = 'Sorgente dei parametri'; -$GLOBALS['TL_LANG']['XPL']['customsql']['6']['0'] = 'Esempio 3
    Utilizzo di filtri di sorgenti parametri complessi '; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['3']['0'] = 'OR'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['2']['0'] = 'clr'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['2']['1'] = 'Elimina tutti i floats.'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['3']['0'] = 'clx'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['3']['1'] = 'Rimuove solo l\'overflow hidden fastidioso. Si prega di utilizzare insieme con "clr".'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['4']['0'] = 'w50'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['4']['1'] = 'Imposta la larghezza del campo al 50% e con float (float:left)'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['5']['0'] = 'w50x'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['5']['1'] = 'Rimuove solo l\'altezza fissa fastidiosa. Si prega di utilizzare insieme con "w50".'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['6']['0'] = 'm12'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['6']['1'] = 'Aggiungi 12 pixel al top margin dell\'elemento (utilizzato per i checkbox singoli)'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['7']['0'] = 'assistente'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['7']['1'] = 'Accorciare il campo di input per permettere di avere un pulsante di aiuto sul campo (esempio nei campi data per far comparire il calendario)'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['8']['0'] = 'lungo'; - diff --git a/src/CoreBundle/Resources/contao/languages/it/modules.php b/src/CoreBundle/Resources/contao/languages/it/modules.php deleted file mode 100644 index cb9b5cea1..000000000 --- a/src/CoreBundle/Resources/contao/languages/it/modules.php +++ /dev/null @@ -1,25 +0,0 @@ -"auto_item" può essere utilizzato, questo è particolarmente utile come alias delle colonne.'; - diff --git a/src/CoreBundle/Resources/contao/languages/it/tl_metamodel_item.php b/src/CoreBundle/Resources/contao/languages/it/tl_metamodel_item.php deleted file mode 100644 index 76163960c..000000000 --- a/src/CoreBundle/Resources/contao/languages/it/tl_metamodel_item.php +++ /dev/null @@ -1,46 +0,0 @@ -%s [%s]'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['0'] = 'Aggiungi tutti'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['1'] = 'Aggiungi tutti gli attributi nelle impostazioni del render'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['advanced_legend'] = 'Avanzato'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['0'] = 'Attributo'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['1'] = 'Attributo a cui questa impostazione si riferisce.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit']['0'] = 'Modifica l\'impostazione'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['0'] = 'Nuovo'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['1'] = 'Crea una nuova impostazione'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['0'] = 'Template personalizzato da utilizzare per la generazione'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['1'] = 'Selezionare il template che deve essere utilizzato per l\'attributo selezionato. Il nome del template deve iniziare con "mm_<type>" dove il nome del tipo deve essere inserito al posto di <type>'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['title_legend'] = 'Tipo'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle']['0'] = 'Toggle'; - diff --git a/src/CoreBundle/Resources/contao/languages/it/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/languages/it/tl_metamodel_rendersettings.php deleted file mode 100644 index 5c9667f2c..000000000 --- a/src/CoreBundle/Resources/contao/languages/it/tl_metamodel_rendersettings.php +++ /dev/null @@ -1,65 +0,0 @@ -dumonda simpla'; -$GLOBALS['TL_LANG']['XPL']['customsql']['2']['0'] = 'Exempel 2
    inserir num da tabella'; -$GLOBALS['TL_LANG']['XPL']['customsql']['3']['0'] = 'Insert-tags'; -$GLOBALS['TL_LANG']['XPL']['customsql']['4']['0'] = 'Insert-tags segirs'; -$GLOBALS['TL_LANG']['XPL']['customsql']['5']['0'] = 'Funtaunas da parameters
    '; -$GLOBALS['TL_LANG']['XPL']['customsql']['6']['0'] = 'Exempel 3
    utilisar funtaunas da parameters cumplexas'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['3']['0'] = 'OR'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['2']['0'] = 'clr'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['2']['1'] = 'Annular tut ils floats.'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['3']['0'] = 'clx'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['3']['1'] = 'Allontanar l\'overflow zuppentà mulestus. Utilisar ensemen cun "clr".'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['4']['0'] = 'w50'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['4']['1'] = 'Definir la ladezza dal champ a 50% e laschar circumdar (float:left).'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['5']['0'] = 'w50x'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['5']['1'] = 'Allontanar la autezza fixa mulestusa. Utilisar ensemen cun "w50".'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['6']['0'] = 'm12'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['6']['1'] = 'Agiuntar sura a l\'element in ur da 12 pixels (vegn utilisà per chaschettas da controlla singulas).'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['7']['0'] = 'assistent'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['7']['1'] = 'Scursanir il champ d\'endataziun per ch\'i haja avunda plaz per in buttun d\'assistenza (p.ex. champs da tscherner la data).'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['8']['0'] = 'long'; - diff --git a/src/CoreBundle/Resources/contao/languages/rm/modules.php b/src/CoreBundle/Resources/contao/languages/rm/modules.php deleted file mode 100644 index 0a8eed86a..000000000 --- a/src/CoreBundle/Resources/contao/languages/rm/modules.php +++ /dev/null @@ -1,26 +0,0 @@ -"auto_item" po era vegnir utilisà, quai è specialmain practic per colonnas dad alias.'; - diff --git a/src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_item.php b/src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_item.php deleted file mode 100644 index d626876ee..000000000 --- a/src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_item.php +++ /dev/null @@ -1,46 +0,0 @@ -%s [%s]'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['0'] = 'Agiuntar tuts'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['1'] = 'Agiuntar tut ils attributs a la configuraziun da visualisar'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['advanced_legend'] = 'Avanzà'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['0'] = 'Attribut'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['1'] = 'Attribut che vegn definì da questa configuraziun.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit']['0'] = 'Modifitgar la configuraziun'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['0'] = 'Nov'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['1'] = 'Crear ina nova configuraziun'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['0'] = 'Template persunalisà per generar'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['1'] = 'Tscherna il template che duai vegnir utilisà per l\'attribut tschernì. Datotecas da template validas cumenzan cun "mm_<type>", e <type> stat per il tip.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['title_legend'] = 'Tip'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle']['0'] = 'Activar/deactivar'; - diff --git a/src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_rendersettings.php deleted file mode 100644 index 34911d36e..000000000 --- a/src/CoreBundle/Resources/contao/languages/rm/tl_metamodel_rendersettings.php +++ /dev/null @@ -1,65 +0,0 @@ - веб-сайте - в разделе "Помощь" в качестве справочника по MetaModels - вы можете найти руководство, все каналы поддержки, - видеоуроки и нашу рассылку новостей.

    - - Прямая ссылка на руководство MetaModels...'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['main_headline'] = 'Мы просим оказать нам помощь!'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['main_text'] = 'Как разработчики этого проекта, мы не получаем никакой компенсации - за нашу работу. Значительная часть нашего ценного свободного - времени предоставляется проекту MetaModels. Любые пожертвования - на проект MetaModels позволят нам работать над проектом в рабочее - время, значительно ускоряя разработку. -

    Мы гарантируем, что потратим любые пожертвования - только на этот проект. Если у вас есть какие-либо конкретные - требования или пожелания, вы можете нанять члена - нашей команды, который с радостью поможет вам.

      - Большое спасибо всем нашим существующим сторонникам и - спонсорам.. Пожалуйста, подумайте о присоединении к нашему - списку спонсоров. Мы не смогли бы создать такой популярный проект - с открытым исходным кодом без поддержки сообщества.

    - Больше информации'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['other_donations'] = 'Для пожертвований проверьте также наш - - поиск финансирования или рассмотрите - - пожертвование для авторов.'; -$GLOBALS['TL_LANG']['MSC']['metamodels_support']['purpose'] = 'Цель'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_filter']['0'] = 'Фи'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_filter']['1'] = 'Фильтр'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_name']['0'] = 'MM'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_name']['1'] = 'MetaModel'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting']['0'] = 'Нв'; -$GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting']['1'] = 'Настройка визуализации'; -$GLOBALS['TL_LANG']['MSC']['noItemsMsg'] = 'Нет элементов, соответствующих вашему запросу.'; -$GLOBALS['TL_LANG']['MSC']['no_theme'] = 'global scope'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['filter']['0'] = 'Фильтр'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['limit']['0'] = 'Лимит'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['search']['0'] = 'Поиск'; -$GLOBALS['TL_LANG']['MSC']['panelLayout']['sort']['0'] = 'Сортировка'; -$GLOBALS['TL_LANG']['MSC']['random'] = 'Случайный'; -$GLOBALS['TL_LANG']['MSC']['template_in_theme'] = '%s (%s)'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clr']['0'] = 'clr'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clr']['1'] = 'Очистить все floats.'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clx']['0'] = 'clx'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['clx']['1'] = 'Чтобы удалить только раздражающее переполнение, используйте его вместе с «clr».'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['long']['0'] = 'длинный'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['long']['1'] = 'Сделать поле ввода текста двумя столбцами.'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['m12']['0'] = 'm12'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['m12']['1'] = 'Добавьте верхний край 12 пикселей к элементу (используется для отдельных флажков).'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50']['0'] = 'w50'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50']['1'] = 'Установите ширину поля на 50% и поместите ее (float: left).'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50x']['0'] = 'w50x'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['w50x']['1'] = 'Чтобы удалить только раздражающую фиксированную высоту, используйте ее вместе с «w50».'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['wizard']['0'] = 'мастер'; -$GLOBALS['TL_LANG']['MSC']['tl_class']['wizard']['1'] = 'Сократите поле ввода, чтобы было достаточно места для кнопки мастера (например, поля выбора даты).'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['action_add'] = '+'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['action_remove'] = '-'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['clear_all'] = 'Очистить все фильтры'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'] = 'Без фильтрации'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['no_combinations'] = '(Комбинаций соответствия не найдено.)'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['select_all'] = 'Выбрать все'; -$GLOBALS['TL_LANG']['metamodels_frontendfilter']['submit'] = 'Фильтр'; - diff --git a/src/CoreBundle/Resources/contao/languages/ru/explain.php b/src/CoreBundle/Resources/contao/languages/ru/explain.php deleted file mode 100644 index b59647516..000000000 --- a/src/CoreBundle/Resources/contao/languages/ru/explain.php +++ /dev/null @@ -1,85 +0,0 @@ -простой запрос'; -$GLOBALS['TL_LANG']['XPL']['customsql']['2']['0'] = 'Пример 2
    вставка имени таблицы'; -$GLOBALS['TL_LANG']['XPL']['customsql']['3']['0'] = 'Вставка тегов'; -$GLOBALS['TL_LANG']['XPL']['customsql']['3']['1'] = 'Вставка тегов поддерживается, но имейте в виду, что не все теги могут - быть доступны когда используется параметр фильтра - (например, {{page::id}} доступен только при использовании - с передней страницы, а не из RSS-каналов).'; -$GLOBALS['TL_LANG']['XPL']['customsql']['4']['0'] = 'Безопасная вставка тегов'; -$GLOBALS['TL_LANG']['XPL']['customsql']['4']['1'] = 'Безопасные теги вставки похожи на теги простой вставки, но их значение ускользает в запросе.
    - Поэтому, возможно, вам лучше использовать безопасный эквивалент, если вы точно не знаете, что делаете.
    - Обозначения: -
    {{secure::page::id}}
    '; -$GLOBALS['TL_LANG']['XPL']['customsql']['5']['0'] = 'Параметр источников'; -$GLOBALS['TL_LANG']['XPL']['customsql']['5']['1'] = 'Источники параметров имеют нормальную компоновку: -
    {{param::[source]?[query string]}}
    - Где источником может быть любой из: -
      -
    • get - строка запроса HTTP GET
    • -
    • post - HTTP POST поля
    • -
    • cookie - HTTP COOKIE значения
    • -
    • session - любое поле в the Contao сессии
    • -
    • filter - любой из переданных параметров фильтра (для обмена параметрами между настройками фильтра).
    • -
    • container - имя вызываемой службы в контейнере службы MetaModels (для этого требуется дополнительное PHP-кодирование с вашей стороны).
    • -
    - Строка запроса построена как обычная строка запроса HTTP как пары «имя = значение», которые объединены с помощью символа & char и должны содержать по крайней мере поле «имя». - Можно использовать одну или несколько следующих дополнительных клавиш: -
      -
    • default - значение по умолчанию для использования, если нет доступного значения.
    • -
    • aggregate - либо «список», либо «набор».
    • -
    • key - установить 1, чтобы прочитать ключ массивов (требуется совокупность с «set»).
    • -
    • recursive - устанавливается в 1 для чтения рекурсивных массивов (требуется совокупность с «set»).
    • -
    • service - имя службы для извлечения (требуется источник «service»).
    • -
    - '; -$GLOBALS['TL_LANG']['XPL']['customsql']['6']['0'] = 'Пример 3
    использовать сложный фильтр параметров источников'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['0']['0'] = 'Значение атрибута...'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['0']['1'] = 'Условие выполняется, когда значение атрибута равно заданному значению.'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['1']['0'] = 'Значения атрибута содержат любое из...'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['1']['1'] = 'Условие выполняется, когда любое из значений атрибута соответствует хотя бы одному из указанных значений (установить пересечение).'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['2']['0'] = 'Является ли атрибут видимым...'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['2']['1'] = 'Условие выполняется, когда выполняется условие указанного атрибута. Другими словами, атрибут отображается, если и только если указанный атрибут также виден.'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['3']['0'] = 'ИЛИ'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['3']['1'] = 'Любое дополнительное условие должно быть выполнено.'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['4']['0'] = 'И'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['4']['1'] = 'Все вспомогательные условия должны быть выполнены.'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['5']['0'] = 'НЕ'; -$GLOBALS['TL_LANG']['XPL']['dcasetting_condition']['5']['1'] = 'Инвертировать результат содержащегося условия.'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['2']['0'] = 'clr'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['2']['1'] = 'Очистить все floats.'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['3']['0'] = 'clx'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['3']['1'] = 'Чтобы удалить только раздражающее переполнение, используйте его вместе с «clr».'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['4']['0'] = 'w50'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['4']['1'] = 'Установите ширину поля на 50% и поместите ее (float: left).'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['5']['0'] = 'w50x'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['5']['1'] = 'Чтобы удалить только раздражающую фиксированную высоту, используйте ее вместе с «w50».'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['6']['0'] = 'm12'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['6']['1'] = 'Добавьте верхний край 12 пикселей к элементу (используется для отдельных флажков).'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['7']['0'] = 'мастер'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['7']['1'] = 'Сократите поле ввода, чтобы было достаточно места для кнопки мастера (например, поля выбора даты).'; -$GLOBALS['TL_LANG']['XPL']['tl_class']['8']['0'] = 'длинный'; - diff --git a/src/CoreBundle/Resources/contao/languages/ru/modules.php b/src/CoreBundle/Resources/contao/languages/ru/modules.php deleted file mode 100644 index 9035f46aa..000000000 --- a/src/CoreBundle/Resources/contao/languages/ru/modules.php +++ /dev/null @@ -1,26 +0,0 @@ -ПРИМЕЧАНИЕ: Это будет неявно активным, если вы выбрали «Уникальные значения» в конфигурации атрибута.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['mandatory_for_unique_attr'] = 'Уникальные атрибуты автоматически обязательны (это невозможно изменить).'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['name_langcode'] = 'Язык'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['name_value'] = 'Название легенды'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['new']['0'] = 'Новый'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['new']['1'] = 'Создать новую настройку'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pasteafter']['0'] = 'Создать новую настройку сверху'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pasteafter']['1'] = 'Создать новый после настройки ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pastenew']['0'] = 'Добавить новый сверху'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['pastenew']['1'] = 'Добавить новый после настройки ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['presentation_legend'] = 'Связанные параметры внешнего вида виджета'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['preserveTags']['0'] = 'Не кодировать все теги html.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['preserveTags']['1'] = 'Если вы выберете это, HTML-теги не будут закодированы.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['readonly']['0'] = 'Только чтение'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['readonly']['1'] = 'Если истина, виджет будет доступен только для чтения и не может быть изменен.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['readonly_for_force_alias'] = 'Атрибуты с принудительным псевдонимом автоматически считываются (это невозможно изменить).'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rows']['0'] = 'Строки'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rows']['1'] = 'Количество строк для виджета longtext/table.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rte']['0'] = 'Включить редактор расширенного текста'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['rte']['1'] = 'Выберите конфигурацию расширенного текста, которая будет использоваться в этом поле (если есть).'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['searchable']['0'] = 'Поисковый'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['searchable']['1'] = 'Выберите, если этот атрибут должен быть доступен для поиска в панели управления.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['show']['0'] = 'Детали настроек'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['show']['1'] = 'Показать детали настроек ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['spaceToUnderscore']['0'] = 'Заменять пробелы на подчеркивания'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['spaceToUnderscore']['1'] = 'Если истина, любой пробел будет заменен подчеркиванием.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['submitOnChange']['0'] = 'Отправить по изменению'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['submitOnChange']['1'] = 'Если активно, форма будет отправлена ​​при изменении значения поля.'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['template']['0'] = 'Пользовательские шаблоны для генерации'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['template']['1'] = 'Выберите шаблон, который должен использоваться для выбранного атрибута. Названия шаблонов начинаются с "mm_<type>", где название типа ставится для <type>'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['title_legend'] = 'Тип'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['tl_class']['0'] = 'Класс панели управления'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['toggle']['0'] = 'Переключить'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['toggle']['1'] = 'Переключить состояние настройки ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash']['0'] = 'Обработка замыкающего слеша'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash']['1'] = 'Здесь вы можете указать, как обрабатывать конечные слеши'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash_options']['0'] = 'Сбросить косую черту при сохранении'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash_options']['1'] = 'Добавить косую черту при сохранении'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['trailingSlash_options']['2'] = 'Ничего не делать'; - diff --git a/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_dcasetting_condition.php b/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_dcasetting_condition.php deleted file mode 100644 index de055910b..000000000 --- a/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_dcasetting_condition.php +++ /dev/null @@ -1,59 +0,0 @@ -%s
    для атрибута %s (Параметр: %s)'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['typedesc']['conditionand'] = '%s %s
    все вспомогательные условия должны быть выполнены'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['typedesc']['conditionnot'] = '%s %s
    инвертировать результат содержащегося условия'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['typedesc']['conditionor'] = '%s %sлюбые условия должны быть выполнены'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['value']['0'] = 'Значение'; -$GLOBALS['TL_LANG']['tl_metamodel_dcasetting_condition']['value']['1'] = 'Выберите нужное значение.'; - diff --git a/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_filter.php b/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_filter.php deleted file mode 100644 index 8a107a3bb..000000000 --- a/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_filter.php +++ /dev/null @@ -1,35 +0,0 @@ -"auto_item", что особенно полезно для столбцов псевдонимов.'; - diff --git a/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_item.php b/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_item.php deleted file mode 100644 index 769878dd6..000000000 --- a/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_item.php +++ /dev/null @@ -1,52 +0,0 @@ -%s [%s]'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addAll_activate'] = 'Добавить новые настройки.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['0'] = 'Добавить все'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['addall']['1'] = 'Добавить все атрибуты к настройкам визуализации'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['additional_class']['0'] = 'Пользовательский CSS-класс'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['additional_class']['1'] = 'Введите все классы CSS, которые вы хотите добавить в вывод этого атрибута'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['advanced_legend'] = 'Дополнительно'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['0'] = 'Атрибут'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['attr_id']['1'] = 'Атрибут этой настройки относится к.'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['copy']['0'] = 'Копировать настройки визуализации определения'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['copy']['1'] = 'Копировать настройки визуализации ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['cut']['0'] = 'Вырезать настройки визуализации определения'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['cut']['1'] = 'Вырезать настройки визуализации ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['delete']['0'] = 'Удалить настройки визуализации'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['delete']['1'] = 'Удалить настройки визуализации ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit']['0'] = 'Редактировать настройки'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['edit']['1'] = 'Изменить настройки визуализации ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['0'] = 'Новый'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['new']['1'] = 'Создать новую настройку'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['pastenew']['0'] = 'Добавить новый сверху'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['pastenew']['1'] = 'Добавить новый после настройки визуализации ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['show']['0'] = 'Настройки визуализации деталей'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['show']['1'] = 'Показать детали визуализации настроек ID %s'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['0'] = 'Пользовательские шаблоны для генерации'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['template']['1'] = 'Выберите шаблон, который должен использоваться для выбранного атрибута. Имена шаблонов начинаются с "mm_<type>" где имя типа ставится для <type>'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['title_legend'] = 'Тип'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle']['0'] = 'Переключить'; -$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['toggle']['1'] = 'Переключить состояние настройки визуализации ID %s'; - diff --git a/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_rendersettings.php b/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_rendersettings.php deleted file mode 100644 index 4073e95c9..000000000 --- a/src/CoreBundle/Resources/contao/languages/ru/tl_metamodel_rendersettings.php +++ /dev/null @@ -1,73 +0,0 @@ - - backBt ?>
    diff --git a/src/CoreBundle/Resources/contao/templates/be_detectedproblems.html5 b/src/CoreBundle/Resources/contao/templates/be_detectedproblems.html5 index ac55ab6cc..8bba835ea 100644 --- a/src/CoreBundle/Resources/contao/templates/be_detectedproblems.html5 +++ b/src/CoreBundle/Resources/contao/templates/be_detectedproblems.html5 @@ -1,5 +1,5 @@ diff --git a/src/CoreBundle/Resources/contao/templates/metamodel_prerendered.html5 b/src/CoreBundle/Resources/contao/templates/metamodel_prerendered.html5 index a5e96c815..d89969706 100644 --- a/src/CoreBundle/Resources/contao/templates/metamodel_prerendered.html5 +++ b/src/CoreBundle/Resources/contao/templates/metamodel_prerendered.html5 @@ -1,3 +1,6 @@ +get('translator'); +?> data)): ?>
    @@ -6,18 +9,14 @@ block('item'); ?>
    - $strName): ?> - getFormat()][$field]) - && ($strValue = $arrItem[$this->getFormat()][$field]) - || (isset($arrItem['text'][$field]) && ($strValue = $arrItem['text'][$field])))): ?> + $name): ?> + getFormat()][$field] ?? null)) + || (null !== ($value = $arrItem['text'][$field] ?? null))): ?>
    view->get('hideLabels')): ?> -
    +
    trans('field_label', ['%field_label%' => $name], 'metamodels_list') ?>
    -
    +
    diff --git a/src/CoreBundle/Resources/contao/templates/metamodel_prerendered.text b/src/CoreBundle/Resources/contao/templates/metamodel_prerendered.text index ad78c65c3..c12497fbd 100644 --- a/src/CoreBundle/Resources/contao/templates/metamodel_prerendered.text +++ b/src/CoreBundle/Resources/contao/templates/metamodel_prerendered.text @@ -1,13 +1,14 @@ get('translator'); $hideLabels = $this->view->get('hideLabels'); if (count($this->data)) { foreach ($this->data as $item) { foreach ($item['attributes'] as $field => $name) { - if ((isset($item['text'][$field]) && ($value = $item['text'][$field]))) { + if (null !== ($value = $arrItem['text'][$field] ?? null)) { if (!$hideLabels) { - echo sprintf($GLOBALS['TL_LANG']['MSC']['field_label'], $name) . ' '; + echo trim($translator->trans('field_label', ['%field_label%' => $name], 'metamodels_list')) . ' '; } echo $value . PHP_EOL; } diff --git a/src/CoreBundle/Resources/contao/templates/metamodel_unrendered.html5 b/src/CoreBundle/Resources/contao/templates/metamodel_unrendered.html5 index df6ecc00d..ea8d295b0 100644 --- a/src/CoreBundle/Resources/contao/templates/metamodel_unrendered.html5 +++ b/src/CoreBundle/Resources/contao/templates/metamodel_unrendered.html5 @@ -1,20 +1,20 @@ +get('translator'); +?> items->getCount()): ?>
    items->parseAll($this->getFormat(), $this->view) as $arrItem): ?> block('item'); ?>
    - items->getItem()->getMetaModel()->getAttributes() as $field => $objAttribute): ?> - getFormat()][$field]) - || ($strValue = $arrItem['text'][$field])): ?> + items->getItem()->getMetaModel()->getAttributes() as $field => $attribute): ?> + getFormat()][$field] ?? null)) + || (null !== ($value = $arrItem['text'][$field] ?? null))): ?>
    view->get('hideLabels')): ?> -
    getName() - ) ?>
    +
    trans('field_label', ['%field_label%' => $attribute->getName()], 'metamodels_list') ?>
    -
    +
    diff --git a/src/CoreBundle/Resources/contao/templates/metamodel_unrendered.text b/src/CoreBundle/Resources/contao/templates/metamodel_unrendered.text index 4607e29ea..ff3fd4997 100644 --- a/src/CoreBundle/Resources/contao/templates/metamodel_unrendered.text +++ b/src/CoreBundle/Resources/contao/templates/metamodel_unrendered.text @@ -1,4 +1,5 @@ get('translator'); $hideLabels = $this->view->get('hideLabels'); @@ -7,7 +8,7 @@ if ($this->items->getCount()) { foreach ($item['attributes'] as $field => $attribute) { if ((isset($item['text'][$field]) && ($value = $item['text'][$field]))) { if (!$hideLabels) { - echo sprintf($GLOBALS['TL_LANG']['MSC']['field_label'], $attribute->getName()) . ' '; + echo trim($translator->trans('field_label', ['%field_label%' => $attribute->getName()], 'metamodels_list')) . ' '; } echo $value . PHP_EOL; } diff --git a/src/CoreBundle/Resources/contao/templates/mm_actionbutton.html5 b/src/CoreBundle/Resources/contao/templates/mm_actionbutton.html5 index 3dc69aaef..7ea5f73c8 100644 --- a/src/CoreBundle/Resources/contao/templates/mm_actionbutton.html5 +++ b/src/CoreBundle/Resources/contao/templates/mm_actionbutton.html5 @@ -1,5 +1,5 @@ action['html'])): ?> - action['class'] ?? null): ?> class="action['class'] ?? ''; ?>"action['title'] ?? null): ?> title="action['title']; ?>"action['attribute'] ?? ''; ?>>action['label']; ?> + action['class'] ?? null): ?> class="action['class'] ?? '' ?>"action['title'] ?? null): ?> title="action['title'] ?>"action['attribute'] ?? '' ?>>action['label'] ?> action['html'] ?> diff --git a/src/CoreBundle/Resources/contao/templates/mm_clearall_default.html5 b/src/CoreBundle/Resources/contao/templates/mm_clearall_default.html5 index e54c3183f..b8572b63f 100644 --- a/src/CoreBundle/Resources/contao/templates/mm_clearall_default.html5 +++ b/src/CoreBundle/Resources/contao/templates/mm_clearall_default.html5 @@ -1,6 +1,6 @@
    cssID ?>style): ?> style="style ?>"> - +
    diff --git a/src/CoreBundle/Resources/contao/templates/mm_pagination.html5 b/src/CoreBundle/Resources/contao/templates/mm_pagination.html5 index 373001b81..1c55caedf 100644 --- a/src/CoreBundle/Resources/contao/templates/mm_pagination.html5 +++ b/src/CoreBundle/Resources/contao/templates/mm_pagination.html5 @@ -1,5 +1,5 @@ get('translator'); +$translator = \Contao\System::getContainer()->get('translator'); $paginationFragment = $this->paginationFragment ? '#' . $this->paginationFragment : ''; ?> diff --git a/src/CoreBundle/Resources/public/css/style.css b/src/CoreBundle/Resources/public/css/style.css index 6543da192..34c266dd2 100644 --- a/src/CoreBundle/Resources/public/css/style.css +++ b/src/CoreBundle/Resources/public/css/style.css @@ -44,7 +44,7 @@ color: #8ab858; margin: 6px 0; padding-left: 24px; - background: url("../../../../themes/flexible/images/palOpen.gif") 3px center no-repeat; + background: url("/system/themes/flexible/icons/navcol.svg") 3px center no-repeat; } .mm_problem_display { diff --git a/src/CoreBundle/Resources/public/scss/style.scss b/src/CoreBundle/Resources/public/scss/style.scss index b6280f785..8eb1c77c3 100644 --- a/src/CoreBundle/Resources/public/scss/style.scss +++ b/src/CoreBundle/Resources/public/scss/style.scss @@ -23,7 +23,7 @@ $icon_fields: url('../images/icons/fields.png'); $icon_dca_add: url('../images/icons/dca_add.png'); $icon_rendersettings_add: url('../images/icons/rendersettings_add.png'); -$icon_pal_open: url('../../../../themes/default/images/palOpen.gif'); +$icon_pal_open: url('/system/themes/flexible/icons/navcol.svg'); $icon_filter_setting: url('../images/icons/filter_settings.png'); $icon_locale: url('../images/icons/locale.png'); diff --git a/src/CoreBundle/Resources/translations/metamodels_default.en.xlf b/src/CoreBundle/Resources/translations/metamodels_default.en.xlf new file mode 100644 index 000000000..3db199390 --- /dev/null +++ b/src/CoreBundle/Resources/translations/metamodels_default.en.xlf @@ -0,0 +1,16 @@ + + + + + + global scope + + + default + + + %template% (%themes%) + + + + diff --git a/src/CoreBundle/Resources/translations/metamodels_filter.en.xlf b/src/CoreBundle/Resources/translations/metamodels_filter.en.xlf new file mode 100644 index 000000000..a4c91a2b7 --- /dev/null +++ b/src/CoreBundle/Resources/translations/metamodels_filter.en.xlf @@ -0,0 +1,13 @@ + + + + + + Filter value for attribute "%id%" + + + + + + + diff --git a/src/CoreBundle/Resources/translations/metamodels_list.en.xlf b/src/CoreBundle/Resources/translations/metamodels_list.en.xlf new file mode 100644 index 000000000..10c98b6a7 --- /dev/null +++ b/src/CoreBundle/Resources/translations/metamodels_list.en.xlf @@ -0,0 +1,25 @@ + + + + + + Sorting + + + Random + + + Id + + + %field_label%: + + + There are no items matching your search. + + + Details + + + + diff --git a/src/CoreBundle/Resources/translations/metamodels_navigation.en.xlf b/src/CoreBundle/Resources/translations/metamodels_navigation.en.xlf new file mode 100644 index 000000000..b588d11f3 --- /dev/null +++ b/src/CoreBundle/Resources/translations/metamodels_navigation.en.xlf @@ -0,0 +1,53 @@ + + + + + + MetaModels + + + MetaModels + + + The MetaModels extension allows you to create own data models. + + + MetaModels + + + Attributes of "%s" + + + All render setting of "%s" + + + Render settings in "%s" + + + Sorting and grouping in "%s" + + + All input screens of "%s" + + + Input screens in "%s" + + + Input screen and render setting combination for "%s" + + + Visibility conditions for attribute "%s" + + + All filter of "%s" + + + Filter settings in "%s" + + + All indexes of "%s" + + + + diff --git a/src/CoreBundle/Resources/translations/metamodels_support.en.xlf b/src/CoreBundle/Resources/translations/metamodels_support.en.xlf new file mode 100644 index 000000000..82d1902dc --- /dev/null +++ b/src/CoreBundle/Resources/translations/metamodels_support.en.xlf @@ -0,0 +1,62 @@ + + + + + + Support MetaModels + + + Support information for the MetaModels extension. + + + As the developers of this project, we receive no compensation for our work. + Much of our valuable time is freely given to the MetaModels project. Any + donations towards the MetaModels project would allow us to work on the + project during our working hours, speeding up development significantly. + <br /><br /> We guarantee to spend any donations only on this project. + If you have any specific requirements or features requests, you are free + to hire a member from our <a target="_blank" + href="https://now.metamodel.me/en/about/team">team</a>, who will gladly + help you.<br /><br />A big thanks to all our <a target="_blank" + href="https://now.metamodel.me/en/supporters">existing supporters and + sponsors</a>. Please consider joining our list of sponsors. We could not + create such a popular open source project without the support of the + community.<br /><br /><a target="_blank" + href="https://now.metamodel.me/en/supporters/donate">More informations</a> + + + + We are calling for your help! + + + Thanks to these users for tickets, suggestions and translations + + + Purpose + + + For donations check also our + <a target="_blank" href="https://now.metamodel.me/en/supporters/fundraising"> + fundraisings</a> or consider + <a target="_blank" href="https://now.metamodel.me/en/supporters/donate"> + donating for the manual</a>. + + + + Help for your MetaModels projects + + + On our <a target="_blank" href="https://now.metamodel.me/en/help">help + website as guide to MetaModels</a> you can find the manual, all support + channels, videos tutorials and our newsletter service.<br /><br /> + <a target="_blank" href="https://metamodels.readthedocs.io/en/latest/"> + Direct link to the MetaModels manual...</a> + + + + See contributors at github... + + + + diff --git a/src/CoreBundle/Resources/translations/metamodels_wildcard.en.xlf b/src/CoreBundle/Resources/translations/metamodels_wildcard.en.xlf new file mode 100644 index 000000000..ed5fabc8a --- /dev/null +++ b/src/CoreBundle/Resources/translations/metamodels_wildcard.en.xlf @@ -0,0 +1,41 @@ + + + + + + MM + + + MetaModel + + + Fi + + + Filter + + + Rs + + + Rendersetting + + + MetaModels elements + + + MetaModels list + + + MetaModels list + + + MetaModels frontend filter + + + MetaModels clear all + + + + diff --git a/src/CoreBundle/Resources/translations/mm_testselecttags.en.metamodels b/src/CoreBundle/Resources/translations/mm_testselecttags.en.metamodels deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/CoreBundle/Resources/translations/modules.en.xlf b/src/CoreBundle/Resources/translations/modules.en.xlf new file mode 100644 index 000000000..b7f0c549a --- /dev/null +++ b/src/CoreBundle/Resources/translations/modules.en.xlf @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/CoreBundle/Resources/translations/tl_content.en.xlf b/src/CoreBundle/Resources/translations/tl_content.en.xlf new file mode 100644 index 000000000..d179d01c0 --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_content.en.xlf @@ -0,0 +1,25 @@ + + + + + + Edit MetaModel + + + Edit the MetaModel ID %id%. + + + Edit render setting + + + Edit the render setting ID %id%. + + + Edit filter setting + + + Edit the filter setting ID %id%. + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel.en.xlf new file mode 100644 index 000000000..0c3471345 --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel.en.xlf @@ -0,0 +1,243 @@ + + + + + + All MetaModels + + + New MetaModel + + + Create a new MetaModel + + + Edit multiple + + + Edit multiple elements at once + + + Create a new element at the top + + + Create a new element after element ID %id% + + + Paste at the top + + + Paste after element ID %id% + + + Go back + + + Back to the previous page + + + Show the details of record %id% + + + Id + + + Id of the MetaModel + + + Name + + + MetaModel name. + + + Revision date + + + Date and time of the latest revision + + + Table name + + + Name of database table to store items to. + + + Parent list mode + + + Mode to use for parent/child relationship. + + + Translation + + + Check if this MetaModel shall support translation/multilingualism. + + + Languages to provide for translation + + + Specify all languages that shall be available for translation. + + + Language + + + Select the languages you want to provide. + + + Fallback language + + + Check the language that shall be used as fallback. + + + Variant support + + + Check if this MetaModel shall support variants of items. + + + Locale territory support + + + Check if this MetaModel shall support language territory at locale. + + + Sorting + + + Sorting order of items. + + + Name and table + + + Translation + + + Advanced settings + + + Cancel + + + Cancel multiple processing. + + + Manage items + + + Manage items of MetaModel ID %id% + + + Copy MetaModel definition + + + Copy definition of MetaModel ID %id% + + + Delete MetaModel + + + Delete MetaModel ID %id% + + + Do you really want to delete element ID %id%? + + + MetaModel details + + + Show details of MetaModel ID %id% + + + Edit MetaModel + + + Edit the MetaModel ID %id% + + + Define attributes + + + Define attributes for MetaModel ID %id% + + + Define filters + + + Define filters for MetaModel ID %id% + + + Define render settings + + + Define render settings for MetaModel ID %id% + + + Define input screens + + + Define input screens for MetaModel ID %id% + + + Define input/output combinations + + + Define input/output combinations for MetaModel ID %id% + + + Move MetaModel + + + Define the order of your MetaModels. + + + Define search settings + + + Define search settings for MetaModel ID %id% + + + {-1} Table does not exist, run migration!| {0} No items|{1} 1 item|[2,Inf[ %count% items + + + Do you really want to delete MetaModel ID %id%? + + + After creating a model, the database must be migrated (console, Contao Manager) - even if the table + name is changed. When changing the table name, the user data itself must be transferred. + + + + Create a new item + + + Edit record %id% + + + Save + + + Save and close + + + Save and new + + + Save and go back + + + The table name is not given or empty. + + + The table name "%table_name%" is invalid. + + + Table "%table_name%" already exists. + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_attribute.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_attribute.en.xlf new file mode 100644 index 000000000..a1578ab14 --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_attribute.en.xlf @@ -0,0 +1,192 @@ + + + + + + All attributes + + + Id + + + Pid + + + Sorting + + + Revision date + + + New attribute + + + Create a new attribute + + + Edit multiple + + + Edit multiple elements at once + + + Create a new element at the top + + + Create a new element after element ID %id% + + + Paste at the top + + + Paste after element ID %id% + + + Go back + + + Back to the previous page + + + Attribute type + + + Select the type of this attribute. WARNING: if you change this, all existing data within this attribute + will be deleted. + + + + Name + + + Human readable name + + + Description + + + Human readable description + + + Column name + + + Internal reference name for this attribute + + + Enable variant override + + + Check this, if you want variants within the MetaModel to override the parent item's value + + + Unique values + + + Check this, if you want to ensure that each value only occurs once + + + Language + + + Description + + + Type, naming and base attribute configuration + + + Advanced settings + + + Edit attribute + + + Cancel + + + Cancel multiple processing. + + + Edit attribute ID %id% + + + Cut attribute definition + + + Cut definition of attribute ID %id% + + + Copy attribute definition + + + Copy definition of attribute ID %id% + + + Delete attribute + + + Delete attribute ID %id% + + + Do you really want to delete element ID %id%? + + + Attribute details + + + Show details of attribute ID %id% + + + Edit attribute + + + Edit the attribute + + + Unknown attribute! + + + Extension missing? The attribute type "%id%" is not installed. + + + Do you really want to delete attribute ID %id%? + + + After creating an attribute, the database must be migrated (console, Contao Manager) - even if the + column name is changed. When changing the column name, the user data itself must be transferred. + + + + Create a new item + + + Edit record %id% + + + Show the details of record %id% + + + Save + + + Save and close + + + Save and new + + + Save and go back + + + Column "%col_name%" already exists on table "%table_name%". + + + The column name "%col_name%" is invalid. + + + The column name "%col_name%" is reserved for system use. + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_dca.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_dca.en.xlf new file mode 100644 index 000000000..7ab65aa0d --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_dca.en.xlf @@ -0,0 +1,284 @@ + + + + + + All input screens + + + Id + + + Pid + + + Sorting + + + New input screen + + + Create a new input screen + + + Edit multiple + + + Edit multiple elements at once + + + Create a new element at the top + + + Create a new element after element ID %id% + + + Paste at the top + + + Paste after element ID %id% + + + Save + + + Save and close + + + Save and new + + + Save and go back + + + Go back + + + Back to the previous page + + + Show the details of record %id% + + + Edit record %id% + + + Edit MetaModel + + + Edit the MetaModel ID %id% + + + Name + + + Name of the input screen. + + + Revision date + + + Date and time of the latest revision. + + + Integration + + + Select the desired type of integration. + + + Render mode + + + Select the desired render mode. + + + Parent table name + + + Name of the database table that shall be referred to as parent table. + + + Use column based layout + + + If selected a table header will be generated with column names. + + + Backend section + + + Select the desired backend section where you want the MetaModel appear. For models that shall be edited + by end users, the "content" section most likely will be appropriate. + + + + Backend icon + + + Select the desired backend icon.This icon will get used to draw an image in the parent list if you have + a integration as child table. + + + + Backend caption + + + The text you specify in here, will get used as the label and description text in the backend menu. + + + + Language + + + Select the languages you want to provide. + + + Label text + + + The text you specify in here, will get used as the menu label in the backend menu. + + + Description text + + + The text you specify in here, will get used as the description (hover title) in the backend menu. + + + + Panel layout + + + Separate panel options with comma (= space) and semicolon (= new line) like + "filter;search;sort,limit". + + + + Panelpicker + + + View limitation + + + Activate the view limitation. + + + Limit the render setting + + + Choose between front end or backend. + + + Allow editing of items + + + If checked, this input screen allows the editing of items. + + + Allow creating of items + + + If checked, this input screen allows the creating of items. + + + Allow deleting of items + + + If checked, this input screen allows the deleting of items. + + + Name + + + View settings + + + Backend integration + + + Data display settings + + + Data manipulation permissions + + + Edit input screen + + + Edit the input screen ID %id% + + + Copy input screen definition + + + Copy definition of input screen ID %id% + + + Delete input screen + + + Delete input screen ID %id% + + + Do you really want to delete element ID %id%? + + + Input screen details + + + Show details of input screen ID %id% + + + Input screen settings + + + Edit the settings of input screen ID %id% + + + Grouping and sorting + + + Edit the grouping and sorting settings of input screen ID %id% + + + Additions to the mask-heading + + + The field can be used to adapt the heading of the mask at edit and replaces the output of the ID.You can + use simple tokens e.g. ##model_name##, ##model_firstname## [##model_id##] + + + + Standalone + + + As child table + + + Flat + + + Parented + + + Hierarchical + + + When using the "Hierarchical" render mode, the current sort must be enable to "Manual sorting" as + default. + + + + Do you really want to delete input screen ID %id%? + + + Cancel + + + Cancel multiple processing. + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_dca_combine.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_dca_combine.en.xlf new file mode 100644 index 000000000..4e9fe501c --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_dca_combine.en.xlf @@ -0,0 +1,73 @@ + + + + + + All input/output combinations + + + Save + + + Save and close + + + Save and new + + + Save and go back + + + Go back + + + Back to the previous page + + + Edit record %id% + + + Combination configuration + + + Permissions for input screen and views + + + For selected frontend user group (if any) and selected backend user group (if any) use the selected + palette and the selected view. + + + + Frontend group + + + The frontend user group the combination applies to; * is 'catch all'. + + + Backend group + + + The backend user group the combination applies to; * is 'catch all'. + + + Input screen + + + The input screen the combination applies to. + + + Render setting + + + The view the combination applies to. + + + Administrator + + + Anonymous + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_dca_sortgroup.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_dca_sortgroup.en.xlf new file mode 100644 index 000000000..77d4b05fe --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_dca_sortgroup.en.xlf @@ -0,0 +1,231 @@ + + + + + + All grouping and sorting settings + + + Id + + + Pid + + + Revision date + + + Sorting + + + Published + + + New Sorting and grouping + + + Create a new Sorting and grouping + + + Edit multiple + + + Edit multiple elements at once + + + Create a new element at the top + + + Create a new element after element ID %id% + + + Paste at the top + + + Paste after element ID %id% + + + Go back + + + Back to the previous page + + + Save + + + Save and close + + + Save and new + + + Save and go back + + + Edit record %id% + + + Name + + + Name of the sorting group. + + + Is default + + + Determines that this input screen shall be used as default for the parenting MetaModel. + + + Render mode + + + Select the desired render mode. + + + Language + + + Select the languages you want to provide. + + + Label text + + + The text you specify in here, will get used as the menu label in the backend menu. + + + Description text + + + The text you specify in here, will get used as the description (hover title) in the backend menu. + + + + Grouping type + + + The grouping type to use in the item view. + + + Grouping attribute + + + The attribute to use for grouping in the item view. + + + Grouping length + + + The amount of characters to use for grouping. + + + Sorting attribute + + + The attribute to sort by. + + + Sorting direction + + + The sorting direction. + + + Enable manual sorting + + + If this is enabled, the user will be able to perform manual sorting. + + + Name + + + Data display settings + + + Edit definition + + + Edit the definition ID %id% + + + Copy definition + + + Copy the definition ID %id% + + + Delete definition + + + Delete the definition ID %id% + + + Do you really want to delete element ID %id%? + + + Definition details + + + Show details of definition ID %id% + + + Toggle + + + Toggle the state of definition ID %id% + + + Definition settings + + + Edit the settings of definition ID %id% + + + Do not group + + + Group by initial letter(s) + + + Group by numeric order + + + Group by day of date + + + Group by weekday of date + + + Group by week of year + + + Group by month of date + + + Group by year of date + + + Ascending + + + Descending + + + Do you really want to delete definition ID %id%? + + + Show the details of record %id% + + + Cancel + + + Cancel multiple processing. + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.en.xlf new file mode 100644 index 000000000..fca38de04 --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting.en.xlf @@ -0,0 +1,335 @@ + + + + + + All input screen settings + + + Id + + + Pid + + + Sorting + + + Revision date + + + Published + + + New attribute or legend + + + Add a new attribute or legend for input mask + + + Edit multiple + + + Edit multiple elements at once + + + Create a new element at the top + + + Create a new element after element ID %id% + + + Paste at the top + + + Paste after element ID %id% + + + Go back + + + Back to the previous page + + + Save and close + + + Continue + + + Select all + + + Cancel + + + Cancel multiple processing. + + + Type + + + Select the attribute type. + + + Attribute + + + Attribute this setting relates to. + + + Custom template to use for generating + + + Select the template that shall be used for the selected attribute. Valid template files start with "mm_&lt;type&gt;" + where the type name is put for &lt;type&gt; + + + + Backend class + + + Here you can set backend class(es). Open the wizard for an overview of the classes. + + + Template at backend + + + You can chose own template for widget in backend - add file in root folder of template. + + + Collapse section + + + Collapse the section by default. + + + Legend title + + + Here you can enter the legend title. + + + Language + + + Legend title + + + Mandatory + + + Check if this attribute shall be mandatory. + <br />NOTE: This will be implicitely active on if you selected "Unique values" in the attribute + configuration. + + + + Always save + + + If true the field will always be saved, even if its value has not changed. + + + Chosen + + + Enable Chosen graphical select widget. + + + Filterable + + + Check if this attribute shall be available for backend filtering. + + + Searchable + + + Check if this attribute shall be available for backend search. + + + Do not encode allowed html tags. + + + If you select this, allowed HTML tags from system settings will not be encoded. + + + Do not encode all html tags. + + + If you select this, no HTML tags will be encoded. + + + Decode HTML entities. + + + If you select this, all HTML entities will be decoded. Note that HTML entities are always decoded if "Do + not encode allowed html tags" is true. + + + + Enable richtext editor on this + + + Select the rich text configuration that shall be used on this field (if any). + + + Rows + + + Amount of rows to use for longtext/table widget. + + + Columns + + + Amount of colums to use for longtext/table widget + + + Trailing slash handling + + + Here you can specify how trailing slashes shall be handled + + + Replace spaces with underscore + + + If true any whitespace character will be replaced by an underscore. + + + Include blank option + + + if true a blank option will be added to the options which allows to define a &quot;no item selected&quot; + option. + + + + Read only + + + If true a the widget will be read only and may not be changed. + + + Submit on change + + + If active the form will be submitted when the field value changes. + + + Type + + + Widget appearance related options + + + Functionality related options + + + Filtering and searching in the backend list + + + Backend + + + Configuration + + + Advanced + + + Edit setting + + + Edit the setting ID %id% + + + Cut setting definition + + + Cut the setting ID %id% + + + Copy setting definition + + + Copy the setting ID %id% + + + Delete setting + + + Delete the setting ID %id% + + + Do you really want to delete element ID %id%? + + + Manage visibility conditions + + + Manage the visibility conditions of property ID %id% + + + Setting details + + + Show details of setting ID %id% + + + Toggle + + + Toggle the state of setting ID %id% + + + Add all + + + Add all attributes to input screen + + + Legend + + + Attribute + + + Strip slash on save + + + Add slash on save + + + Do nothing + + + Will add the attribute "%name%" [%type%, "%colName%"] to the input screen. + + + Attribute "%name%" [%type%, "%colName%"] is already contained in input screen. + + + Added the attribute "%name%" [%type%, "%colName%"] to the input screen. + + + Add new settings enabled. + + + Set backend class. + + + Unique attribues are automatically mandatory (this is not changable). + + + Attribues with force alias are automatically readonly (this is not changable). + + + Show the details of record %id% + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting_condition.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting_condition.en.xlf new file mode 100644 index 000000000..efbcc4020 --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_dcasetting_condition.en.xlf @@ -0,0 +1,192 @@ + + + + + + All input screen conditions + + + Id + + + Pid + + + Fid + + + Sorting + + + Revision date + + + New condition + + + Add a new visibility condition + + + Edit multiple + + + Edit multiple elements at once + + + Go back + + + Back to the previous page + + + Visibility conditons + + + Basic configuration + + + Condition configuration + + + Type + + + Select the condition type. + + + Enabled + + + Check to enable this condition. + + + Comment + + + Enter a comment to describe the purpose of this condition. + + + Attribute + + + Select the attribute to use for this condition. + + + Value + + + Please select the desired value. + + + Edit setting + + + Edit the setting ID %id% + + + Cut setting definition + + + Cut the setting ID %id% + + + Copy setting definition + + + Copy the setting ID %id% + + + Delete setting + + + Delete the setting ID %id% + + + Do you really want to delete element ID %id%? + + + Manage conditions + + + Manage the conditions of property ID %id% + + + Setting details + + + Show details of setting ID %id% + + + Toggle + + + Toggle the state of setting ID %id% + + + Add all + + + Add all attributes to input screen + + + Add new at the top + + + Add new after setting ID %id% + + + Create new after setting ID %id% + + + Create new after setting ID %id% + + + Create new setting at the top + + + Create new at the top of setting ID %id% + + + Attribute value is... + + + Attribute values contain any of... + + + Is attribute visible... + + + OR + + + AND + + + NOT + + + %icon% <strong>%name%</strong> - for attribute <em>%attribute%</em> (Parameter: %value%)%comment% + + + + %icon% <strong>%name%</strong> - any sub conditions must be fulfilled%comment% + + + %icon% <strong>%name%</strong> - all sub conditions must be fulfilled%comment% + + + %icon% <strong>%name%</strong> - invert the result of the contained condition%comment% + + + %icon% <strong>%attribute%</strong> value is %value%%comment% + + + Do you really want to delete setting ID %id%? + + + Show the details of record %id% + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_filter.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_filter.en.xlf new file mode 100644 index 000000000..11b2236d3 --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_filter.en.xlf @@ -0,0 +1,128 @@ + + + + + + All filters + + + Id + + + Pid + + + Save + + + Save and close + + + Save and new + + + Save and go back + + + Edit record %id% + + + Show the details of record %id% + + + New filter + + + Create a new filter + + + Edit multiple + + + Edit multiple elements at once + + + Create a new element at the top + + + Create a new element after element ID %id% + + + Paste at the top + + + Paste after element ID %id% + + + Go back + + + Back to the previous page + + + Name + + + Filter setting name. + + + Revision date + + + Date and time of the latest revision. + + + Name + + + Edit + + + Edit MetaModel + + + Edit setting + + + Edit the filter setting ID %id% + + + Copy filter setting + + + Copy the filter setting ID %id% + + + Delete filter setting + + + Delete the filter setting ID %id% + + + Do you really want to delete element ID %id%? + + + Filter setting details + + + Show details of filter setting ID %id% + + + Define attribute settings + + + Define attribute settings for filter setting ID %id% + + + Do you really want to delete filter setting ID %id%? + + + Cancel + + + Cancel multiple processing. + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_filtersetting.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_filtersetting.en.xlf new file mode 100644 index 000000000..e80af871a --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_filtersetting.en.xlf @@ -0,0 +1,339 @@ + + + + + + All filter settings + + + Id + + + Pid + + + Sorting + + + Revision date + + + New filter setting + + + Create a new filter setting + + + Edit multiple + + + Edit multiple elements at once + + + Create a new element at the top + + + Create a new element after element ID %id% + + + Paste at the top + + + Paste after element ID %id% + + + Create new setting at the top + + + Create new into setting ID %id% + + + Go back + + + Back to the previous page + + + Filter settings + + + Parent collection + + + The collection of filter settings, this setting belongs to. + + + Type + + + The type of this setting. + + + Enabled + + + Enable this filter setting. + + + Comment + + + A short comment for describing the purpose of this filter setting. + + + Attribute + + + Attribute this setting relates to. + + + Search all languages + + + Check if you want to perform the lookup language independant. If this is not checked, only the current + active language will be searched. + + + + Allow empty value + + + Check if you want to allow this filter value to be emtpy, if checked and the parameter holds an empty + value, this filter rule will behave as if it was not defined. + + + + Stop after first match + + + Check if you want this filter setting to stop executing its child rules after the first subset returned + matches. + + + + URL parameter + + + The URL parameter that shall get mapped to the selected attribute. The special <em>"auto_item"</em> + parameter can also be used, this is especially useful for alias columns. + + + + Static parameter + + + Check if you want to be able to set the value of this parameter in the parenting list (modules, content + elements, etc.). + + + + Provide Frontend widget + + + Check if you want to display a filter widget in the Frontend. + + + Custom SQL Query + + + The SQL query that shall be executed, insert tags are supported. + + + Label + + + Show label instead of attribute name. + + + Template + + + Sub template for this filter element. Standard: form widget. + + + Empty option + + + Show empty options in filter widget. + + + Assigned values only + + + Show only options, that are assigned somewhere in the MetaModel. + + + Remaining values only + + + Show only options, that are still assigned somewhere after the actual filter is set. + + + Ignore this filter for the remaining values + + + If activate the filter will return all options without itself in the filter rules. + + + Hide label in filter widget + + + If active, the label is not output. + + + Use label as blank option + + + If active, the label output as blank option. + + + Sorting + + + Please enter sorting of values in filter widget. + + + CSS ID/class + + + Here you can set an ID and one or more classes. + + + Placeholder + + + Show this text as long as the field is empty. + + + Natural sorting (ASC) + + + Natural sorting (DESC) + + + Default + + + Default value for selection. + + + Type + + + Configuration + + + Frontend filter + + + Edit setting + + + Edit the filter setting ID %id% + + + Copy filter setting definition + + + Copy the filter setting ID %id% + + + Cut filter setting definition + + + Cut the filter setting ID %id% + + + Delete filter setting + + + Delete the filter setting ID %id% + + + Do you really want to delete element ID %id%? + + + Filter setting details + + + Show details of filter setting ID %id% + + + Toggle + + + Toggle the state of setting ID %id% + + + Predefined set of items + + + Simple lookup + + + Custom SQL + + + OR condition + + + AND condition + + + <em>[%colName%, "%name%"]</em> + + + <em>(URL: %urlparam%)</em> + + + <br />%comment% + + + %1$s <strong>%2$s</strong> %3$s %5$s %4$s + + + %1$s <strong>%2$s</strong> %3$s %5$s %4$s + + + %1$s <strong>%2$s</strong> %3$s %4$s + + + %1$s <strong>%2$s</strong> %4$s + + + %1$s <strong>%2$s</strong> %4$s + + + Items + + + Please enter the IDs of the items for filtering as comma-separated list. + + + Do you really want to delete filter setting ID %id%? + + + Cancel + + + Cancel multiple processing. + + + Edit record %id% + + + Save + + + Save and close + + + Save and new + + + Save and go back + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_item.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_item.en.xlf new file mode 100644 index 000000000..56e1fb534 --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_item.en.xlf @@ -0,0 +1,150 @@ + + + + + + New item + + + Create new item + + + Edit item + + + Edit item ID %id% + + + Edit multiple + + + Edit multiple + + + Edit "%child_name%" + + + Edit "%child_name%" for item %id% + + + Copy item + + + Copy item ID %id% + + + New variant + + + Create a new variant of item ID %id% + + + Move item + + + Move item ID %id% + + + Delete item + + + Delete item ID %id% + + + Do you really want to delete element ID %id%? + + + Item details + + + Show details of item ID %id% + + + Edit item type + + + Edit the item type + + + Create new item + + + Create a new item after item ID %id% + + + Create new item + + + Create a new item in item ID %id% + + + Add new at the top + + + Add new item after item ID %id% + + + Is variant base + + + Check this if you want to make this the base for the current variant group + + + Edit item %item% + + + Create a new item + + + Sorting + + + The manual sorting + + + ID of the item + + + The id of the item + + + Parent item id + + + The id of the parent item + + + Revision date + + + The date when the item revision was created + + + Details + Used in the frontend for the "Details" link caption. + + + Show the details of record %id% + + + Go back + + + Back to the previous page + + + Save + + + Save and close + + + Save and new + + + Save and go back + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_rendersetting.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_rendersetting.en.xlf new file mode 100644 index 000000000..0bd355579 --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_rendersetting.en.xlf @@ -0,0 +1,178 @@ + + + + + + All render setting settings + + + Id + + + Pid + + + Revision date + + + Sorting + + + New attribute + + + Add a new attribute for render setting + + + Edit multiple + + + Edit multiple elements at once + + + Create a new element at the top + + + Create a new element after element ID %id% + + + Paste at the top + + + Paste after element ID %id% + + + Go back + + + Back to the previous page + + + Continue + + + Select all + + + Save + + + Save and close + + + Save and new + + + Save and go back + + + Edit record %id% + + + Attribute + + + Attribute this setting relates to. + + + Custom template to use for generating + + + Select the template that shall be used for the selected attribute. Valid template files start with "mm_&lt;type&gt;" + where the type name is put for &lt;type&gt; + + + + Custom CSS class + + + Enter any CSS classes that you want get added to the output of this attribute + + + Type + + + Advanced + + + Edit setting + + + Edit render setting ID %id% + + + Cut render setting definition + + + Cut the render setting ID %id% + + + Copy render setting definition + + + Copy the render setting ID %id% + + + Delete render setting + + + Delete the render setting ID %id% + + + Do you really want to delete element ID %id%? + + + Render setting details + + + Show details of render setting ID %id% + + + Toggle + + + Toggle the state of render setting ID %id% + + + Add all + + + Add all attributes to render setting + + + %id% <strong>%id%</strong> <em>[%id%]</em> + + + Will add the attribute "%name%" [%type%, "%colName%"] to the input screen. + + + Attribute "%name%" [%type%, "%colName%"] is already contained in input screen. + + + Added the attribute "%name%" [%type%, "%colName%"] to the input screen. + + + Add new settings enabled. + + + Do you really want to render filter setting ID %id%? + + + Enabled + + + Enable this filter setting. + + + Show the details of record %id% + + + Cancel + + + Cancel multiple processing. + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_rendersettings.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_rendersettings.en.xlf new file mode 100644 index 000000000..9649e9518 --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_rendersettings.en.xlf @@ -0,0 +1,225 @@ + + + + + + All render settings + + + Id + + + Pid + + + Revision date + + + New render setting + + + Create a new render setting + + + Edit multiple + + + Edit multiple elements at once + + + Create a new element at the top + + + Create a new element after element ID %id% + + + Paste at the top + + + Paste after element ID %id% + + + Go back + + + Back to the previous page + + + Edit MetaModel + + + Edit the MetaModel ID %id% + + + Name + + + General settings + + + Expert settings + + + Frontend jump-to settings + + + Additional files + + + Name + + + Setting name. + + + Template + + + The template to use to render the items. + + + Output format + + + Define the output format. Leave empty to use the format used by current page. + + + HTML5 + + + Text + + + JumpTo page + + + The page that shall be used as "show details" urls. Note that the detailed URL params will get generated + by the filter setting that is currently in use. + + + + All languages + + + Language + + + The language for the jump to page. + + + Jump to page + + + The page to use for detail links. + + + Filter settings + + + The filter settings that define how the target (the reader/lister on the detail page) will filter the + items. + + + + Hide empty values + + + Hide empty values in backend and frontend. + + + Hide labels + + + Hide all labels in backend and frontend. + + + Additional css files + + + Choose this, if you want to include additional css files. + + + Additional javascript files + + + Choose this, if you want to include additional javascript files. + + + File + + + Choose a file + + + Publish + + + Check to publish the file. + + + Edit setting + + + Edit the setting ID %id% + + + Copy setting definition + + + Copy the setting ID %id% + + + Delete setting + + + Delete the setting ID %id% + + + Do you really want to delete element ID %id%? + + + Filter details + + + Show details of setting ID %id% + + + Define attribute settings + + + Define attribute settings for setting ID %id% + + + Unknown ID: %id% + + + unknown attribute + + + Unknown column + + + Do you really want to render setting ID %id%? + + + Show the details of record %id% + + + Edit record %id% + + + Save + + + Save and close + + + Save and new + + + Save and go back + + + + diff --git a/src/CoreBundle/Resources/translations/tl_metamodel_searchable_pages.en.xlf b/src/CoreBundle/Resources/translations/tl_metamodel_searchable_pages.en.xlf new file mode 100644 index 000000000..c4384c0da --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_metamodel_searchable_pages.en.xlf @@ -0,0 +1,140 @@ + + + + + + All search settings + + + Id + + + Pid + + + New index + + + Create a new searchable page setting + + + Edit multiple + + + Edit multiple elements at once + + + Create a new element at the top + + + Create a new element after element ID %id% + + + Paste at the top + + + Paste after element ID %id% + + + Go back + + + Back to the previous page + + + Show the details of record %id% + + + Name + + + Name of the searchable page setting + + + Revision date + + + Date and time of the latest revision. + + + Rendersetting + + + Choose the rendersetting which will be used for the search rendering. + + + Filtersetting + + + Choose the filtersetting which will be used for the search rendering. + + + Filter parameter override + + + Filter parameter override + + + Name + + + General settings + + + Edit searchable page + + + Edit the searchable page setting ID %id% + + + Copy searchable page + + + Copy definition of searchable page setting ID %id% + + + Delete searchable page + + + Delete searchable page setting ID %id% + + + Do you really want to delete element ID %id%? + + + Searchable page setting details + + + Show details of searchable page setting ID %id% + + + Toggle + + + Toggle the state of searchable page setting ID %id% + + + Searchable page settings + + + Edit the settings of searchable page setting ID %id% + + + Searchable page settings + + + Published + + + Do you really want to render setting ID %id%? + + + Cancel + + + Cancel multiple processing. + + + + diff --git a/src/CoreBundle/Resources/translations/tl_modules.en.xlf b/src/CoreBundle/Resources/translations/tl_modules.en.xlf new file mode 100644 index 000000000..bc384cb5e --- /dev/null +++ b/src/CoreBundle/Resources/translations/tl_modules.en.xlf @@ -0,0 +1,25 @@ + + + + + + Edit MetaModel + + + Edit the MetaModel ID %id%. + + + Edit render setting + + + Edit the render setting ID %id%. + + + Edit filter setting + + + Edit the filter setting ID %id%. + + + + diff --git a/src/CoreBundle/Resources/views/Backend/add-all.html.twig b/src/CoreBundle/Resources/views/Backend/add-all.html.twig index 9005cd433..213bef4f9 100644 --- a/src/CoreBundle/Resources/views/Backend/add-all.html.twig +++ b/src/CoreBundle/Resources/views/Backend/add-all.html.twig @@ -12,7 +12,7 @@ {% block main %}
    diff --git a/src/CoreBundle/Resources/views/Backend/be_config.html.twig b/src/CoreBundle/Resources/views/Backend/be_config.html.twig new file mode 100644 index 000000000..40b0e1a14 --- /dev/null +++ b/src/CoreBundle/Resources/views/Backend/be_config.html.twig @@ -0,0 +1,15 @@ +{% extends "@MetaModelsCore/Backend/be_base.html.twig" %} + +{% block headline %} + {{ headline }} +{% endblock %} + +{% block error %} + {%- if error is defined -%} + {{- error -}} + {%- endif -%} +{% endblock %} + +{% block main %} +{{ body | raw }} +{% endblock %} diff --git a/src/CoreBundle/Translator/MetaModelTranslationLoader.php b/src/CoreBundle/Translator/MetaModelTranslationLoader.php index 45e2f356a..1dcc6eb34 100644 --- a/src/CoreBundle/Translator/MetaModelTranslationLoader.php +++ b/src/CoreBundle/Translator/MetaModelTranslationLoader.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,29 +12,249 @@ * * @package MetaModels/core * @author Christian Schiffler - * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\Translator; +use Doctrine\DBAL\Exception; +use MetaModels\Attribute\IInternal; +use MetaModels\IFactory; +use MetaModels\ITranslatedMetaModel; +use MetaModels\ViewCombination\InputScreenInformationBuilder; +use MetaModels\ViewCombination\ViewCombination; +use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Translation\Loader\LoaderInterface; use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\TranslatorBagInterface; + +use function is_array; +use function sprintf; final class MetaModelTranslationLoader implements LoaderInterface { - public function load($resource, $locale, $domain = 'messages') + /** + * The constructor. + * + * @param TranslatorBagInterface $baseTranslator The translator interface. + * @param IFactory $factory The factory. + * @param ViewCombination $viewCombination The view combination. + * @param InputScreenInformationBuilder $builder The input screen builder. + */ + public function __construct( + private readonly TranslatorBagInterface $baseTranslator, + private readonly IFactory $factory, + private readonly ViewCombination $viewCombination, + private readonly InputScreenInformationBuilder $builder, + ) { + } + + /** + * Load translation catalog. + * + * @param mixed $resource The resource. + * @param string $locale The locale. + * @param string $domain The domain + * + * @return MessageCatalogue + * @throws Exception + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function load($resource, string $locale, string $domain = 'messages'): MessageCatalogue { - dump($resource, $locale, $domain); + // Load tl_metamodel_item catalogue. + $base = $this->baseTranslator->getCatalogue($locale); + $catalog = new MessageCatalogue($locale); - if ($domain === 'mm_testselecttags') { - $catalog->set('mm_testselecttags.select_normal.0', 'Label !!!!', $domain); - $catalog->set('mm_testselecttags.select_normal.1', 'Description', $domain); + + foreach ($base->all('tl_metamodel_item') as $key => $value) { + $catalog->set($key, $value, $domain); + } + + $metaModel = $this->factory->getMetaModel($domain); + if (null === $metaModel) { + throw new NotFoundResourceException('Failed to load MetaModel: ' . $domain); + } + + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ + if ($metaModel instanceof ITranslatedMetaModel) { + $metaModel->selectLanguage($locale); + $mainLanguage = $metaModel->getMainLanguage(); + } elseif ($metaModel->isTranslated(false)) { + $mainLanguage = $metaModel->getFallbackLanguage() ?? 'en'; + } else { + // Untranslated MetaModel. + $mainLanguage = 'en'; + } + + // Attributes: + foreach ($metaModel->getAttributes() as $attribute) { + if ($attribute instanceof IInternal) { + continue; + } + $colName = $attribute->getColName(); + $name = $attribute->get('name') ?? $colName; + $description = $attribute->get('description') ?? ''; + $catalog->set( + sprintf('%1$s.label', $colName), + $this->extractLangString($name, $locale, $mainLanguage) ?? $colName, + $domain + ); + $catalog->set( + sprintf('%1$s.description', $colName), + $this->extractLangString($description, $locale, $mainLanguage) ?? '', + $domain + ); + } + + foreach ($this->builder->fetchAllInputScreensForTable($domain) as $inputScreen) { + $this->handleInputScreen($domain, $locale, $mainLanguage, $inputScreen, $catalog); + } + + // Check if we have some children - add child button translations then. + foreach ($this->viewCombination->getChildrenOf($domain) as $tableName => $inputScreen) { + $subMetaModel = $this->factory->getMetaModel($tableName); + if (null === $subMetaModel) { + continue; + } + $translationKey = 'metamodel_edit_as_child.' . $subMetaModel->getTableName(); + + if ( + 'metamodel_edit_as_child.label' !== + $baseValue = $catalog->get('metamodel_edit_as_child.label', $domain) + ) { + $catalog->set( + $translationKey . '.label', + strtr($baseValue, ['%child_name%' => $subMetaModel->getName()]), + $domain, + ); + } + if ( + 'metamodel_edit_as_child.description' !== + $baseValue = $catalog->get('metamodel_edit_as_child.description', $domain) + ) { + $catalog->set( + $translationKey . '.description', + strtr($baseValue, ['%child_name%' => $subMetaModel->getName()]), + $domain, + ); + } + + $this->setTranslationLabelAndDescription( + $domain, + $locale, + $mainLanguage, + $translationKey, + $inputScreen, + $catalog, + $tableName, + ); } - dump($catalog); return $catalog; } + + /** + * Handle input screen. + * + * @param string $domain The domain. + * @param string $locale The locale. + * @param string $mainLanguage The fallback language. + * @param array $inputScreen The input screen. + * @param MessageCatalogue $catalog The catalog. + * + * @return void + */ + private function handleInputScreen( + string $domain, + string $locale, + string $mainLanguage, + array $inputScreen, + MessageCatalogue $catalog + ): void { + $prefix = 'inputscreen.' . $inputScreen['meta']['id'] . '.'; + + foreach ($inputScreen['legends'] as $index => $legend) { + $value = $this->extractLangString($legend['label'], $locale, $mainLanguage) ?? ''; + // Suffix '_legend' due to EditMask in DcGeneral. + $catalog->set($prefix . $index . '_legend', $value, $domain); + } + + if ('standalone' === $inputScreen['meta']['rendertype']) { + $this->setTranslationLabelAndDescription( + $domain, + $locale, + $mainLanguage, + $prefix . 'menu', + $inputScreen, + $catalog, + $domain, + ); + } + } + + private function setTranslationLabelAndDescription( + string $domain, + string $locale, + string $mainLanguage, + string $prefix, + array $inputScreen, + MessageCatalogue $catalog, + string $headlineDomain + ): void { + $headlineKey = 'backend-module.' . $inputScreen['meta']['id'] . '.headline'; + $catalog->set($prefix . '.description', '', $domain); + if ('' !== $value = $this->extractLangString($inputScreen['description'], $locale, $mainLanguage) ?? '') { + $catalog->set($prefix . '.description', $value, $domain); + + $catalog->set($headlineKey, $value, $headlineDomain); + } + if ('' !== $value = $this->extractLangString($inputScreen['label'], $locale, $mainLanguage) ?? '') { + $catalog->set($prefix . '.label', $value, $domain); + if ($headlineKey === $catalog->get($headlineKey, $headlineDomain)) { + $catalog->set($headlineKey, $value, $headlineDomain); + } + } + } + + /** + * @param string|array $value The value. + * @param string $locale The locale. + * @param string $mainLocale The fallback language. + * + * @return string|null + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function extractLangString(string|array $value, string $locale, string $mainLocale): ?string + { + if (!is_array($value)) { + return $value; + } + + $fallback = null; + foreach ($value as $langCode => $string) { + if ($locale === $langCode && '' !== $string) { + return $string; + } + if ($mainLocale === $langCode && '' !== $string) { + $fallback = $string; + } + } + + if ('en' === $locale && null === $fallback && (null !== $default = ($value[''] ?? null))) { + return $default; + } + + return $fallback; + } } diff --git a/src/CoreBundle/Translator/MetaModelTranslatorConfigurator.php b/src/CoreBundle/Translator/MetaModelTranslatorConfigurator.php new file mode 100644 index 000000000..b70ed2490 --- /dev/null +++ b/src/CoreBundle/Translator/MetaModelTranslatorConfigurator.php @@ -0,0 +1,109 @@ + + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. + * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\CoreBundle\Translator; + +use MetaModels\IFactory; +use MetaModels\ITranslatedMetaModel; +use Psr\Cache\InvalidArgumentException; +use Symfony\Component\Translation\Translator as SymfonyTranslator; +use Symfony\Contracts\Cache\CacheInterface; + +/** @psalm-type TDomainList=iterable> */ +final class MetaModelTranslatorConfigurator +{ + /** @var callable|null */ + private $previous; + + /** + * The constructor. + * + * @param IFactory $factory The factory. + * @param CacheInterface $cache The cache. + * @param callable|null $previous The previous configurator. + */ + public function __construct( + private readonly IFactory $factory, + private readonly CacheInterface $cache, + $previous = null + ) { + if (null !== $previous && !is_callable($previous)) { + throw new \InvalidArgumentException('Passed value for previous must be callable or null'); + } + $this->previous = $previous; + } + + /** + * @param SymfonyTranslator $translator The translator. + * + * @return void + * + * @throws InvalidArgumentException + */ + public function __invoke(SymfonyTranslator $translator): void + { + // Apply previous configurator + if (null !== $this->previous) { + \call_user_func($this->previous, $translator); + } + + foreach ($this->fetchDomains() as $domain => $locales) { + foreach ($locales as $locale) { + $translator->addResource('metamodels', $domain, $locale, $domain); + } + } + } + + /** + * Obtain the domain names with their locales. + * + * @return TDomainList + * @throws InvalidArgumentException + */ + private function fetchDomains(): iterable + { + return $this->cache->get( + 'metamodels.translation-domains', + /** @return TDomainList */ + function (): iterable { + $result = []; + foreach ($this->factory->collectNames() as $metamodelName) { + $instance = $this->factory->getMetaModel($metamodelName); + if (!$instance instanceof ITranslatedMetaModel) { + $result[$metamodelName] = ['en']; + continue; + } + $locales = []; + foreach ($instance->getLanguages() as $language) { + $locales[] = $language; + } + // Fix: Always add 'en' to the language domains, even if user only set 'af_NA' by quick save. + if (!\in_array('en', $locales, true)) { + array_unshift($locales, 'en'); + } + + $result[$metamodelName] = $locales; + } + + return $result; + } + ); + } +} diff --git a/src/CoreBundle/Translator/Translator.php b/src/CoreBundle/Translator/Translator.php index b54fc51e9..33592e5ec 100644 --- a/src/CoreBundle/Translator/Translator.php +++ b/src/CoreBundle/Translator/Translator.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2019 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,30 +12,27 @@ * * @package MetaModels/core * @author Christian Schiffler - * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. + * @author Ingolf Steinhardt + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ namespace MetaModels\CoreBundle\Translator; +use Symfony\Component\Translation\MessageCatalogueInterface; use Symfony\Component\Translation\TranslatorBagInterface; -use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; use Symfony\Contracts\Translation\LocaleAwareInterface; use Symfony\Contracts\Translation\TranslatorInterface; -final class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface, LegacyTranslatorInterface +final class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface { - /** - * @var TranslatorInterface|TranslatorBagInterface|LegacyTranslatorInterface - */ - private $translator; + private TranslatorInterface&TranslatorBagInterface&LocaleAwareInterface $translator; /** * @internal Do not inherit from this class; decorate the "contao.translation.translator" service instead */ - public function __construct(TranslatorInterface $translator) + public function __construct(TranslatorInterface&TranslatorBagInterface&LocaleAwareInterface $translator) { $this->translator = $translator; } @@ -49,19 +46,14 @@ public function __construct(TranslatorInterface $translator) public function trans($id, array $parameters = [], $domain = null, $locale = null): string { // Cut off the contao_ prefix for mm_ domains as they are already loaded via symfony. - if (0 === strncmp($domain, 'contao_mm_', 10)) { + if (null !== $domain && 0 === strncmp($domain, 'contao_mm_', 10)) { $domain = substr($domain, 7); - dump('REDIRECTED TO: ' . $domain); } + // Forward to Contao translator return $this->translator->trans($id, $parameters, $domain, $locale); } - public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null): string - { - return $this->translator->transChoice($id, $number, $parameters, $domain, $locale); - } - public function setLocale($locale): void { $this->translator->setLocale($locale); @@ -72,7 +64,7 @@ public function getLocale(): string return $this->translator->getLocale(); } - public function getCatalogue($locale = null) + public function getCatalogue($locale = null): MessageCatalogueInterface { return $this->translator->getCatalogue($locale); } diff --git a/src/DcGeneral/Data/Driver.php b/src/DcGeneral/Data/Driver.php index c04b07436..e429bff67 100644 --- a/src/DcGeneral/Data/Driver.php +++ b/src/DcGeneral/Data/Driver.php @@ -566,8 +566,10 @@ public function getVersions($mixID, $onlyActive = false) */ public function isUniqueValue($field, $new, $primaryId = null) { - $attribute = $this->getMetaModel()?->getAttribute($field); - if ($attribute) { + $model = $this->getMetaModel(); + assert($model instanceof IMetaModel); + $attribute = $model->getAttribute($field); + if (null !== $attribute) { $matchingIds = $this ->prepareFilter( $this->getEmptyConfig()->setFilter( diff --git a/src/DcGeneral/Data/FilterBuilder.php b/src/DcGeneral/Data/FilterBuilder.php index 1c33e57cc..510be7cc6 100644 --- a/src/DcGeneral/Data/FilterBuilder.php +++ b/src/DcGeneral/Data/FilterBuilder.php @@ -49,6 +49,7 @@ * @psalm-type TFilter=TFilterANDOR|TFilterForProperty * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class FilterBuilder { @@ -147,7 +148,7 @@ private function getFilterForComparingOperator($attribute, IFilter $filter, $ope { switch ($operation['operation']) { case '=': - $filter->addFilterRule($this->buildSearchAttributeFilterRule($attribute, $operation['value'])); + $filter->addFilterRule($this->buildSearchAttributeFilterRule($attribute, (string) $operation['value'])); return; case '>': diff --git a/src/DcGeneral/Events/MetaModel/DuplicateModel.php b/src/DcGeneral/Events/MetaModel/DuplicateModel.php index 501c9d6e3..cbf69dbd3 100644 --- a/src/DcGeneral/Events/MetaModel/DuplicateModel.php +++ b/src/DcGeneral/Events/MetaModel/DuplicateModel.php @@ -61,9 +61,8 @@ public function handle(PreDuplicateModelEvent $event) $model = $event->getModel(); $metaModel = $this->factory->getMetaModel($model->getProviderName()); - assert($metaModel instanceof IMetaModel); - if (!$metaModel->hasVariants()) { + if (null === $metaModel || !$metaModel->hasVariants()) { return; } diff --git a/src/Dca/Helper.php b/src/Dca/Helper.php index e4ff6551a..3669256f3 100644 --- a/src/Dca/Helper.php +++ b/src/Dca/Helper.php @@ -26,6 +26,7 @@ namespace MetaModels\Dca; +use Contao\CoreBundle\Intl\Locales; use Contao\Folder; use Contao\StringUtil; use Contao\System; @@ -127,17 +128,35 @@ public static function encodeLangArray($varValue, IMetaModel $metaModel) * @param IMetaModel $metaModel The MetaModel to extract the languages from. * @param TranslatorInterface $translator The translator to use. * - * @return \string[] + * @return array */ private static function buildLanguageArray(IMetaModel $metaModel, TranslatorInterface $translator) { $languages = []; - /** @psalm-suppress DeprecatedMethod */ - foreach ((array) $metaModel->getAvailableLanguages() as $langCode) { - $languages[$langCode] = $translator->translate('LNG.' . $langCode, 'languages'); + if ($metaModel instanceof ITranslatedMetaModel) { + $intlLocales = System::getContainer()->get('contao.intl.locales'); + assert($intlLocales instanceof Locales); + $labels = $intlLocales->getLocales(); + foreach ($metaModel->getLanguages() as $langCode) { + $languages[$langCode] = $labels[$langCode]; + } + + return $languages; + } + + /** + * @psalm-suppress DeprecatedMethod + * @psalm-suppress TooManyArguments + */ + if ($metaModel->isTranslated(false)) { + /** @psalm-suppress DeprecatedMethod */ + foreach ((array) $metaModel->getAvailableLanguages() as $langCode) { + $languages[$langCode] = $translator->translate('LNG.' . $langCode, 'contao_languages'); + } + return $languages; } - return $languages; + throw new \RuntimeException('Should not end up here.'); } /** @@ -195,7 +214,7 @@ public static function prepareLanguageAwareWidget( $rowClasses = []; foreach (\array_keys($arrValues) as $langCode) { - $rowClasses[] = ($langCode == $fallback) ? 'fallback_language' : 'normal_language'; + $rowClasses[] = ($langCode === $fallback) ? 'fallback_language' : 'normal_language'; } $extra = $property->getExtra(); @@ -227,6 +246,7 @@ public static function prepareLanguageAwareWidget( ] ], ]; + $extra['useTranslator'] = true; $property ->setWidgetType('multiColumnWizard') diff --git a/src/Filter/Rules/SimpleQuery.php b/src/Filter/Rules/SimpleQuery.php index 434ae9b0d..589a24acf 100644 --- a/src/Filter/Rules/SimpleQuery.php +++ b/src/Filter/Rules/SimpleQuery.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,7 +15,7 @@ * @author Sven Baumann * @author Cliff Parnitzky * @author Ingolf Steinhardt - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -123,7 +123,7 @@ public function getMatchingIds() $matches = $this->connection->executeQuery($this->queryString, $this->params, $this->types); $ids = []; foreach ($matches->fetchAllAssociative() as $value) { - $ids[] = $value[$this->idColumn]; + $ids[] = (string) $value[$this->idColumn]; } return $ids; diff --git a/src/Filter/Rules/StaticIdList.php b/src/Filter/Rules/StaticIdList.php index fe4955c18..4a5b2ca23 100644 --- a/src/Filter/Rules/StaticIdList.php +++ b/src/Filter/Rules/StaticIdList.php @@ -32,14 +32,14 @@ class StaticIdList extends FilterRule /** * The static id list that shall be applied. * - * @var list + * @var list|null */ protected $arrIds = []; /** * Create a new FilterRule instance. * - * @param list $arrIds Static list of ids that shall be returned as matches. + * @param list|null $arrIds Static list of ids that shall be returned as matches. */ public function __construct($arrIds) { diff --git a/src/Filter/Setting/SimpleLookup.php b/src/Filter/Setting/SimpleLookup.php index b181b621f..09df3880d 100644 --- a/src/Filter/Setting/SimpleLookup.php +++ b/src/Filter/Setting/SimpleLookup.php @@ -3,7 +3,7 @@ /** * This file is part of MetaModels/core. * - * (c) 2012-2023 The MetaModels team. + * (c) 2012-2024 The MetaModels team. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,7 +16,7 @@ * @author Stefan Heimes * @author Ingolf Steinhardt * @author Sven Baumann - * @copyright 2012-2023 The MetaModels team. + * @copyright 2012-2024 The MetaModels team. * @license https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ @@ -24,6 +24,7 @@ namespace MetaModels\Filter\Setting; use Contao\StringUtil; +use Contao\System; use MetaModels\Attribute\IAttribute; use MetaModels\FrontendIntegration\FrontendFilterOptions; use MetaModels\IItem; @@ -33,6 +34,7 @@ use MetaModels\IMetaModel; use MetaModels\ITranslatedMetaModel; use MetaModels\Render\Setting\ICollection as IRenderSettings; +use Symfony\Contracts\Translation\TranslatorInterface; /** * Filter setting implementation performing a search for a value on a configured attribute. @@ -216,18 +218,16 @@ public function getParameterDCA() $arrOptions = $objAttribute->getFilterOptions(null, (bool) $this->get('onlyused')); + $translator = System::getContainer()->get('translator'); + assert($translator instanceof TranslatorInterface); + return [ (string) $this->getParamName() => [ - 'label' => [ - \sprintf( - $GLOBALS['TL_LANG']['MSC']['metamodel_filtersettings_parameter']['simplelookup'][0], - $objAttribute->getName() - ), - \sprintf( - $GLOBALS['TL_LANG']['MSC']['metamodel_filtersettings_parameter']['simplelookup'][1], - $objAttribute->getName() - ) - ], + 'label' => $translator->trans( + 'simplelookup.label', + ['%id%' => $objAttribute->getName()], + 'metamodels_filter' + ), 'inputType' => 'select', 'options' => $arrOptions, 'eval' => [ @@ -299,7 +299,7 @@ public function getParameterFilterWidgets( ), 'blankOptionLabel' => $this->get('label_as_blankoption') ? $this->getLabel() - : $GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'], + : $GLOBALS['TL_LANG']['metamodels_frontendfilter']['do_not_filter'] ?? '', 'colname' => $attribute->getColname(), 'urlparam' => $paramName, 'onlyused' => $this->get('onlyused'), diff --git a/src/FrontendIntegration/FrontendFilter.php b/src/FrontendIntegration/FrontendFilter.php index 70865b524..7b9d25845 100644 --- a/src/FrontendIntegration/FrontendFilter.php +++ b/src/FrontendIntegration/FrontendFilter.php @@ -443,7 +443,7 @@ protected function getFilters() 'filters' => $renderedWidgets, 'submit' => ($filterOptions->isAutoSubmit() ? '' - : $GLOBALS['TL_LANG']['metamodels_frontendfilter']['submit'] + : $GLOBALS['TL_LANG']['metamodels_frontendfilter']['submit'] ?? '' ) ]; } diff --git a/src/FrontendIntegration/MetaModelHybrid.php b/src/FrontendIntegration/MetaModelHybrid.php index e48d20272..13c3477dc 100644 --- a/src/FrontendIntegration/MetaModelHybrid.php +++ b/src/FrontendIntegration/MetaModelHybrid.php @@ -24,11 +24,8 @@ namespace MetaModels\FrontendIntegration; use Contao\BackendTemplate; -use Contao\ContentModel; use Contao\Database\Result; -use Contao\FormModel; use Contao\Hybrid; -use Contao\ModuleModel; use Contao\StringUtil; use Contao\System; use Doctrine\DBAL\Connection; @@ -37,6 +34,7 @@ use MetaModels\IMetaModelsServiceContainer; use MetaModels\MetaModelsServiceContainer; use Symfony\Component\HttpFoundation\Request; +use Symfony\Contracts\Translation\TranslatorInterface; /** * Base implementation of a MetaModel Hybrid element. @@ -196,7 +194,7 @@ public function generate() // Add CSS file. $GLOBALS['TL_CSS'][] = 'bundles/metamodelscore/css/style.css'; - // Retrieve name of MetaModels. + // Retrieve name of MetaModel. $infoTemplate = '
    %s: %s
    '; @@ -205,10 +203,13 @@ public function generate() $metaModel = $factory->getMetaModel($metaModelName); assert($metaModel instanceof IMetaModel); + $translator = System::getContainer()->get('translator'); + assert($translator instanceof TranslatorInterface); + $strInfo = \sprintf( $infoTemplate, - $GLOBALS['TL_LANG']['MSC']['mm_be_info_name'][1], - $GLOBALS['TL_LANG']['MSC']['mm_be_info_name'][0], + $translator->trans('mm_be_info_name.description', [], 'metamodels_wildcard'), + $translator->trans('mm_be_info_name.label', [], 'metamodels_wildcard'), $metaModel->getName() ); @@ -229,14 +230,14 @@ public function generate() if ($infoFi) { $strInfo .= \sprintf( $infoTemplate, - $GLOBALS['TL_LANG']['MSC']['mm_be_info_filter'][1], - $GLOBALS['TL_LANG']['MSC']['mm_be_info_filter'][0], + $translator->trans('mm_be_info_filter.description', [], 'metamodels_wildcard'), + $translator->trans('mm_be_info_filter.label', [], 'metamodels_wildcard'), \current($infoFi) ); } } - // Retrieve name of rendersetting. + // Retrieve name of render setting. if ($this->metamodel_rendersettings) { $infoRs = $database ->createQueryBuilder() @@ -251,8 +252,8 @@ public function generate() if ($infoRs) { $strInfo .= \sprintf( $infoTemplate, - $GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting'][1], - $GLOBALS['TL_LANG']['MSC']['mm_be_info_render_setting'][0], + $translator->trans('mm_be_info_render_setting.description', [], 'metamodels_wildcard'), + $translator->trans('mm_be_info_render_setting.label', [], 'metamodels_wildcard'), \current($infoRs) ); } diff --git a/src/Item.php b/src/Item.php index 343b73b1c..44d502e24 100644 --- a/src/Item.php +++ b/src/Item.php @@ -479,7 +479,7 @@ public function parseValue($strOutputFormat = 'text', $objSettings = null) $arrResult['actions']['jumpTo'] = [ 'href' => $jumpTo['url'], 'deep' => $jumpTo['deep'], - 'label' => $this->getCaptionText('details'), + 'label' => $jumpTo['label'], 'class' => 'details' ]; } @@ -597,40 +597,6 @@ public function varCopy() return $objNewItem; } - - /** - * Retrieve the translation string for the given lang key. - * - * In order to achieve the correct caption text, the function tries several translation strings sequentially. - * The first language key that is set will win, even if it is to be considered empty. - * - * This message is looked up in the following order: - * 1. $GLOBALS['TL_LANG']['MSC'][][][$langKey] - * 2. $GLOBALS['TL_LANG']['MSC'][][$langKey] - * 3. $GLOBALS['TL_LANG']['MSC'][$langKey] - * - * @param string $langKey The language key to retrieve. - * - * @return string - * - * @SuppressWarnings(PHPMD.Superglobals) - * @SuppressWarnings(PHPMD.CamelCaseVariableName) - */ - private function getCaptionText($langKey) - { - $tableName = $this->getMetaModel()->getTableName(); - if ( - isset($this->objView) - && isset($GLOBALS['TL_LANG']['MSC'][$tableName][$this->objView->get('id')][$langKey]) - ) { - return $GLOBALS['TL_LANG']['MSC'][$tableName][$this->objView->get('id')][$langKey]; - } elseif (isset($GLOBALS['TL_LANG']['MSC'][$tableName][$langKey])) { - return $GLOBALS['TL_LANG']['MSC'][$tableName][$langKey]; - } - - return $GLOBALS['TL_LANG']['MSC'][$langKey]; - } - /** * Create the CSS class for variant information. * diff --git a/src/ItemList.php b/src/ItemList.php index f11e9e5f0..a10de0b28 100644 --- a/src/ItemList.php +++ b/src/ItemList.php @@ -53,6 +53,7 @@ use RuntimeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Contracts\Translation\TranslatorInterface; use function array_key_exists; use function array_keys; @@ -1099,8 +1100,14 @@ private function getCaptionText(string $langKey): string ) { return $GLOBALS['TL_LANG']['MSC'][$tableName][$this->objView->get('id')][$langKey]; } + if (null !== ($caption = $GLOBALS['TL_LANG']['MSC'][$tableName][$langKey] ?? null)) { + return $caption; + } + + $translator = System::getContainer()->get('translator'); + assert($translator instanceof TranslatorInterface); - return ($GLOBALS['TL_LANG']['MSC'][$tableName][$langKey] ?? $GLOBALS['TL_LANG']['MSC'][$langKey]); + return $translator->trans($langKey, [], 'metamodels_list'); } /** diff --git a/src/Render/Setting/Collection.php b/src/Render/Setting/Collection.php index f55ee9fe0..13fe9e2cd 100644 --- a/src/Render/Setting/Collection.php +++ b/src/Render/Setting/Collection.php @@ -35,6 +35,7 @@ use MetaModels\IMetaModel; use MetaModels\ITranslatedMetaModel; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * Base implementation for render settings. @@ -188,10 +189,18 @@ public function getSettingNames() private function getJumpToLabel() { $tableName = $this->metaModel->getTableName(); + if ( + null !== ($label = ($GLOBALS['TL_LANG']['MSC'][$tableName][$this->get('id')]['details'] ?? + ($GLOBALS['TL_LANG']['MSC'][$tableName]['details'] ?? + ($GLOBALS['TL_LANG']['MSC']['details'] ?? null)))) + ) { + return $label; + } + + $translator = System::getContainer()->get('translator'); + assert($translator instanceof TranslatorInterface); - return ($GLOBALS['TL_LANG']['MSC'][$tableName][$this->get('id')]['details'] ?? - ($GLOBALS['TL_LANG']['MSC'][$tableName]['details'] ?? - $GLOBALS['TL_LANG']['MSC']['details'])); + return $translator->trans('details', [], $tableName); } /** diff --git a/src/ViewCombination/InputScreenInformationBuilder.php b/src/ViewCombination/InputScreenInformationBuilder.php index 66be513d9..620d1c9de 100644 --- a/src/ViewCombination/InputScreenInformationBuilder.php +++ b/src/ViewCombination/InputScreenInformationBuilder.php @@ -61,6 +61,35 @@ public function __construct(Connection $connection, IFactory $factory) $this->factory = $factory; } + /** + * Fetch information about all input screens. + * + * @return array + * + * @throws Exception + */ + public function fetchAllInputScreensForTable(string $tableName): array + { + $builder = $this->connection->createQueryBuilder(); + $screens = $builder + ->select('d.*') + ->from('tl_metamodel_dca', 'd') + ->leftJoin('d', 'tl_metamodel', 'm', 'm.id=d.pid') + ->where($builder->expr()->in('m.tableName', ':tableName')) + ->setParameter('tableName', $tableName) + ->orderBy('m.sorting') + ->executeQuery() + ->fetchAllAssociative(); + + $result = []; + foreach ($screens as $screen) { + $result[$screen['id']] = $this->prepareInputScreen($tableName, $screen); + // FIXME: simplify prepareInputScreen to not translate the values inline but define translation keys. + } + + return $result; + } + /** * Fetch information about an input screen. * @@ -117,7 +146,7 @@ private function prepareInputScreen(string $modelName, array $screen): array throw new \InvalidArgumentException('Could not retrieve MetaModel ' . $modelName); } $caption = ['' => $metaModel->getName()]; - $description = ['' => $metaModel->getName()]; + $description = ['' => '']; $fallback = null; /** * @psalm-suppress DeprecatedMethod diff --git a/tests/Data/FilterBuilderTest.php b/tests/Data/FilterBuilderTest.php index 053abe73f..155005769 100644 --- a/tests/Data/FilterBuilderTest.php +++ b/tests/Data/FilterBuilderTest.php @@ -160,7 +160,7 @@ public function testBuildSqlOnly() $filter = $builder->build(); - self::assertSame([0, 1, 2, 3], $filter->getMatchingIds()); + self::assertSame(['0', '1', '2', '3'], $filter->getMatchingIds()); } /** @@ -184,7 +184,7 @@ public function testIssue700() ->expects(self::once()) ->method('searchFor') ->with('*test*') - ->willReturn([0, 1, 2, 3]); + ->willReturn(['0', '1', '2', '3']); /** @var \MetaModels\Attribute\Base $attribute */ $metaModel->addAttribute($attribute); @@ -220,6 +220,6 @@ public function testIssue700() $filter = $builder->build(); - self::assertSame([0, 1, 2, 3], $filter->getMatchingIds()); + self::assertSame(['0', '1', '2', '3'], $filter->getMatchingIds()); } } diff --git a/tests/MetaModelsTest.php b/tests/MetaModelsTest.php index 689003076..4f91d560a 100644 --- a/tests/MetaModelsTest.php +++ b/tests/MetaModelsTest.php @@ -24,7 +24,6 @@ use Doctrine\DBAL\Query\Expression\ExpressionBuilder; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Result; -use Doctrine\DBAL\Statement; use MetaModels\MetaModel; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; From 08c603a302c460232130fd76dbf45eaaad9edeb0 Mon Sep 17 00:00:00 2001 From: Ingolf Steinardt Date: Wed, 15 May 2024 17:59:33 +0200 Subject: [PATCH 224/224] Update version of DCG --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5bfbeab09..09e923ccd 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "require": { "php": "^8.1", "ext-dom": "*", - "contao-community-alliance/dc-general": "^2.3", + "contao-community-alliance/dc-general": "^2.3.10", "contao-community-alliance/events-contao-bindings": "^4.13.1", "contao-community-alliance/meta-palettes": "^2.0.10", "contao-community-alliance/translator": "^2.4.2",