---
title: "MediaProcessor"
manual: "Handlebars"
version: "main"
permalink: "https://docs.typo3.org/permalink/cpsit/typo3-handlebars:developer-corner-media-processor@main"
source: "DeveloperCorner/MediaProcessor.rst"
rendered: "2026-09-29T09:05:57+00:00"
---

# MediaProcessor {#developer-corner-media-processor}

The [media](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:data-processor-media@main) data processor resolves a file
resource and hands it to whichever registered media processor's
`supports()` method matches it first — the built-in
`\CPSIT\Typo3Handlebars\DataProcessing\Media\ImageProcessor` is one such
implementation. Implement the interface yourself to support other resource
kinds (documents, videos, download links, ...) or to replace the built-in
image handling.

-   [The interface](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:the-interface@main)
-   [Implement a media processor](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:implement-a-media-processor@main)
-   [Typed configuration with ConfigurableProcessor](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:typed-configuration-with-configurableprocessor@main)

## The interface {#developer-corner-media-processor-interface}

-   **interface MediaProcessor**

    -   *Fully qualified name:* `\CPSIT\Typo3Handlebars\DataProcessing\Media\MediaProcessor`

    -   **process(contentObjectRenderer, resource, configuration = \[\])**

        Process the given resource and return the resulting array, which is
        stored under `media`'s `as` key, or merged
        recursively into the processed data if `as` is omitted.

        -   *param ContentObjectRenderer contentObjectRenderer:* The current content object renderer.
        -   *param resource:*

            The resolved resource — a core
            `ResourceInterface` or an Extbase `File`/`FileReference`.

        -   *param array configuration:* This processor's slice of `config.<name>`.
        -   *returntype:* array

    -   **supports(resource)**

        Return `true` if this processor can handle the given resource.
        Called for every registered media processor, in priority order, until
        one returns `true`.

        -   *param mixed resource:* The resolved resource, of unknown type.
        -   *returntype:* bool

## Implement a media processor {#developer-corner-media-processor-implement}

Implementations are auto-registered because the interface itself carries
`#[AutoconfigureTag('handlebars.media_processor')]`. The
`#[AsTaggedItem('<name>')]` attribute on the implementing class both
determines matching order among several processors (higher priority is tried
first, default 0, same as [PathProvider and VariableProvider](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:developer-corner-paths-and-variables@main)) and gives the processor its
`<name>`, i.e. the key under which `media` looks
up its `config.<name>` block.

**EXT:my_extension/Classes/DataProcessing/Media/DownloadProcessor.php**

```php
namespace Vendor\Extension\DataProcessing\Media;

use CPSIT\Typo3Handlebars\DataProcessing\Media\MediaProcessor;
use Symfony\Component\DependencyInjection\Attribute\AsTaggedItem;
use TYPO3\CMS\Core\Resource\AbstractFile;
use TYPO3\CMS\Core\Resource\ResourceInterface;
use TYPO3\CMS\Extbase\Domain\Model\File;
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;

#[AsTaggedItem('download')]
final readonly class DownloadProcessor implements MediaProcessor
{
    public function process(
        ContentObjectRenderer $contentObjectRenderer,
        ResourceInterface|File|FileReference $resource,
        array $configuration = [],
    ): array {
        return [
            'url' => $resource->getPublicUrl(),
            'label' => $configuration['label'] ?? $resource->getName(),
        ];
    }

    public function supports(mixed $resource): bool
    {
        return $resource instanceof AbstractFile && !$resource->isImage();
    }
}
```

With this registered, `config.download.label` becomes available
next to the built-in `config.image.*` options wherever
`media` is used.

## Typed configuration with ConfigurableProcessor {#developer-corner-media-processor-configurable}

Mapping `configuration` by hand, as above, is fine for a couple
of options. The built-in `ImageProcessor` instead extends the abstract
`\CPSIT\Typo3Handlebars\DataProcessing\Media\ConfigurableProcessor`,
which uses [cuyz/valinor](https://github.com/CuyZ/Valinor) to map the raw
configuration array onto a typed, immutable configuration object before
`processFile()` is called:

```php
/**
 * @extends ConfigurableProcessor<MyConfiguration>
 */
final class MyProcessor extends ConfigurableProcessor
{
    public function processFile(
        ContentObjectRenderer $contentObjectRenderer,
        ResourceInterface|File|FileReference $resource,
        Configuration $configuration,
    ): array {
        // $configuration is an instance of MyConfiguration
    }

    public function supports(mixed $resource): bool
    {
        // ...
    }

    protected function getConfigurationClass(): string
    {
        return MyConfiguration::class;
    }
}
```

`MyConfiguration` only needs to implement the empty marker interface
`\CPSIT\Typo3Handlebars\DataProcessing\Media\Configuration\Configuration`
and declare its accepted options as constructor-promoted properties — see
[ImageConfiguration](https://github.com/CPS-IT/handlebars/blob/main/Classes/DataProcessing/Media/Configuration/ImageConfiguration.php)
for reference.

> [!NOTE]
> **See also**
>
> [MediaProcessor](https://github.com/CPS-IT/handlebars/blob/main/Classes/DataProcessing/Media/MediaProcessor.php)
> interface source on GitHub.
