• Home
  • -
  • TYPO3: Extending the configuration module

TYPO3: Extending the configuration module

TYPO3 v11 comes with a new API to extend the configuration module (of EXT:lowlevel).

configuration module

Let's take a look at how to add our own entries there.

Extending the TYPO3 Configuration - Background

To extend the TYPO3 configuration modules, we need to write our own Configuration Provider. The Configuration Provider needs to implement ProviderInterface and has to be registered as lowlevel.configuration.module.provider by tagging it via the Services.yaml file.

Let's look at two implementations step by step:

Using the AbstractProvider

The TYPO3 Core comes with an abstract provider (\TYPO3\CMS\Lowlevel\ConfigurationModuleProvider\AbstractProvider) already implementing most of the methods needed. Our own class can extend the abstract and only has to implement the remaining getConfiguration() method.

I want to display the admin panel module configuration, so I'll add a class \Susanne\Site\ConfigurationModuleProvider\AdminPanelProvider with the following content:

<?php
declare(strict_types = 1);

namespace Susanne\Site\ConfigurationModuleProvider;

use TYPO3\CMS\Core\Service\DependencyOrderingService;
use TYPO3\CMS\Lowlevel\ConfigurationModuleProvider\AbstractProvider;

class AdminPanelProvider extends AbstractProvider
{
    private DependencyOrderingService $dependencyOrderingService;

    public function __construct(DependencyOrderingService $dependencyOrderingService)
    {
        $this->dependencyOrderingService = $dependencyOrderingService;
    }
    public function getConfiguration(): array
    {
        $modules = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] ?? [];
        return [
            'modules_raw' => $modules,
            'modules_ordered' => $this->dependencyOrderingService->orderByDependencies($modules)
        ];
    }
}

I now need to register this provider via the dependency injection configuration in Configuration/Services.yaml:

    Susanne\Site\ConfigurationModuleProvider\AdminPanelProvider:
        class: 'Susanne\Site\ConfigurationModuleProvider\AdminPanelProvider'
        tags:
            -   name: 'lowlevel.configuration.module.provider'
                identifier: 'adminPanelProvider'
                label: 'Admin Panel Module Configuration'
                before: 'beUserTsConfig'
                after: 'pagesTypes'

As you can see, the provider is tagged as lowlevel.configuration.module.provider. It needs an unique identifier which identifies this provider (used for example for ordering the providers). As we are using the abstract provider we also need to set the label directly in the Services.yaml (it may be a language file reference - in the example I used a simple label string for brevity). With the settings before and after we are able to control where in the module menu list our service is included.

After saving the file, make sure to fully clear the caches (via "Admin Tools" > "Maintenance") as we changed the dependency injection config.

Reloading the module shows our new entry which lists the admin panel configuration:

admin panel configuration module

Implementing the interface directly

If you want to have more control over your implementation you can also directly implement the ProviderInterface without using the abstract. Let's look at another example:

<?php
declare(strict_types = 1);

namespace Susanne\Site\ConfigurationModuleProvider;

use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Lowlevel\ConfigurationModuleProvider\ProviderInterface;

class SitesProvider implements ProviderInterface
{
    private string $identifier;
    private SiteFinder $siteFinder;

    public function __construct(SiteFinder $siteFinder)
    {
        $this->siteFinder = $siteFinder;
    }

    public function __invoke(array $attributes): ProviderInterface
    {
        $this->identifier = $attributes['identifier'];
        return $this;
    }

    public function getIdentifier(): string
    {
        return $this->identifier;
    }

    public function getLabel(): string
    {
        return 'Available Site Configurations';
    }

    public function getConfiguration(): array
    {
        $configuration = [];
        $sites = $this->siteFinder->getAllSites();
        foreach ($sites as $site) {
            $configuration[$site->getIdentifier()] = $site->getConfiguration();
        }
        return $configuration;
    }
}

with the following Configuration/Services.yaml:

    Susanne\Site\ConfigurationModuleProvider\SitesProvider:
        class: 'Susanne\Site\ConfigurationModuleProvider\SitesProvider'
        tags:
            - name: 'lowlevel.configuration.module.provider'
              identifier: 'sitesProvider'

This is a full implementation of the interface - as you can see, the label is now set directly in the provider class which gives you more control over it. In this case, we are using the site finder to fetch all site configurations and can now use the configuration module to look at the loaded configuration via a simple array browser.

site configuration module

More Info