Feature: #109409 - Allow configuration of resources 

See forge#109409

Description 

Composer-managed TYPO3 

Until now, extensions could place public resources only in their Resources/Public folder. The folder name used to publish these extension resources was a non-configurable MD5 hash.

This feature introduces the possibility to configure resources explicitly. This includes additional public folders or files that are published into TYPO3's public/_assets folder, as well as non-public resource paths.

TYPO3 classic mode 

In TYPO3 classic mode, there is no visible change for extensions or the typo3/app package, since all files in extensions are already located within the document root. Restricting resources to the default locations in classic mode therefore mainly follows coding guidelines and keeps compatibility with Composer mode.

Configuring extensions 

Extensions can add Configuration/Resources.php to configure resources. This configuration is then added to the following default configuration:

EXT:core/Configuration/DefaultPackageResources.php
<?php

declare(strict_types=1);

use TYPO3\CMS\Core\Package\Package;
use TYPO3\CMS\Core\Package\Resource\Definition\PublicResourceDefinition;
use TYPO3\CMS\Core\Package\Resource\Definition\ResourceDefinition;

return static function (Package $package) {
    $resourceDefinitions = [
        new ResourceDefinition('Resources/Private'),
    ];
    if (is_dir($package->getPackagePath() . 'Resources/Public')) {
        $resourceDefinitions[] = new PublicResourceDefinition('Resources/Public');
    }
    return $resourceDefinitions;
};
Copied!

This means that, when using the system resources API (Feature: #107537 - System resource API for system file access and public URI generation), resource identifiers are only allowed to reference files or folders in Resources/Private and, if it exists, Resources/Public. It also means that, by default, Resources/Public in extensions will be published in the same way as before this change.

Example: publish an additional public folder 

EXT:my_extension/Configuration/Resources.php
<?php

declare(strict_types=1);

use TYPO3\CMS\Core\Package\Package;
use TYPO3\CMS\Core\Package\Resource\Definition\PublicResourceDefinition;
use TYPO3\CMS\Core\Package\Resource\Definition\ResourceDefinition;

return static function (Package $package) {
    return [
        new PublicResourceDefinition('Build/Public'),
    ];
};
Copied!

This will publish the Build/Public folder as well. The published folder name will be a hash unique to this folder.

Example: publish a single file only 

Instead of publishing a whole folder, a single file can be published:

EXT:my_extension/Configuration/Resources.php
<?php

declare(strict_types=1);

use TYPO3\CMS\Core\Package\Package;
use TYPO3\CMS\Core\Package\Resource\Definition\PublicFileDefinition;

return static function (Package $package) {
    return [
        new PublicFileDefinition(relativePath: 'Build/styles.css'),
        new PublicFileDefinition(
            relativePath: 'Build/components.css',
            publicPrefix: $package->getPackageKey() . '/custom/folder/my-components.css',
        ),
    ];
};
Copied!

This publishes the extension file Build/styles.css to a folder with a unique hash, which will then contain the file styles.css. Additionally, Build/components.css will be published to _assets/my_extension/custom/folder/my-components.css.

Example: use a fixed prefix in _assets 

By default, TYPO3 generates the public prefix automatically. A fixed prefix can be configured explicitly:

EXT:my_extension/Configuration/Resources.php
<?php

declare(strict_types=1);

use TYPO3\CMS\Core\Package\Package;
use TYPO3\CMS\Core\Package\Resource\Definition\PublicResourceDefinition;
use TYPO3\CMS\Core\Package\Resource\Definition\ResourceDefinition;

return static function (Package $package) {
    return [
        new PublicResourceDefinition(
            relativePath: 'Build/Public',
            publicPrefix: 'my-vendor/my-extension-build',
        ),
    ];
};
Copied!

This publishes resources from Build/Public to a stable location below public/_assets/my-vendor/my-extension-build.

Configuring the typo3/app package 

See the system resources API (Feature: #107537 - System resource API for system file access and public URI generation) for more information about what the typo3/app package represents.

To configure the typo3/app package, a config/system/resources.php file can be added.

If it is missing, the following default configuration is used:

EXT:core/Configuration/DefaultAppResources.php
<?php

declare(strict_types=1);

use TYPO3\CMS\Core\Package\Resource\Definition\PublicResourceDefinition;
use TYPO3\CMS\Core\Package\VirtualAppPackage;

return static function (VirtualAppPackage $package, string $relativePublicPath) {
    return [
        new PublicResourceDefinition(
            relativePath: $relativePublicPath . '_assets',
        ),
        new PublicResourceDefinition(
            relativePath: $relativePublicPath . 'uploads',
        ),
        new PublicResourceDefinition(
            relativePath: $relativePublicPath . 'typo3temp/assets',
        ),
    ];
};
Copied!

Closing notes 

For now, this change mainly affects public files and folders.

Impact 

If no resource configuration is added to extensions, this feature has no impact on a TYPO3 installation. If such a configuration exists, it extends the default configuration.