heimrichhannot/contao-media-library-bundle

Add a Media Library to your Contao CMS Web Application.

Installs: 1 008

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 4

Forks: 0

Open Issues: 0

Type:contao-bundle

pkg:composer/heimrichhannot/contao-media-library-bundle

2.0.0-beta.25 2026-01-20 08:46 UTC

README

The Contao Media Library Bundle provides archive‑based management of media library items (such as images, videos, and files) and their downloadable files.

Features

  • Organize your media as objects in archives
  • Predefined media library item types: image, video, file
  • For image archives, define image sizes to automatically create downloads in desired formats and dimensions
  • Upload and edit media library items directly from the frontend with a form generator preset form-type
  • Add custom DCA fields to individual archives and their items
  • Integration with FLARE Bundle to list media libraries, e.g., in gallery views
  • Integration with Form Type Bundle to handle frontend form submissions with media library items
  • Optional: Integration with Codefog Tags Bundle to tag items
  • Optional: Integration with H & H Categories Bundle to categorize items
  • Optional: Integration with H & H Filecredits Bundle (private) to ease assignment of file credits to the files of items

Installation

Install the bundle via Composer and update the database afterwards.

composer require heimrichhannot/contao-media-library-bundle

Setup

  1. Create a media library archive and configure its settings.
  2. Create an entry in this archive.
  3. Optional: Manually add additional files or file variants.

Configuration

huh_media_library:
    # Default upload path for media library items when using the frontend form
    file_upload_path: 'files/media-library/##author##/##title##'

Editing and deleting products

Enable edit and delete functionality for media library items by turning on the corresponding options in the archive settings. Also verify that member (and/or member group) permissions are configured appropriately.

Editing items directly from the frontend

  1. Set up your custom upload and/or edit form in the form-generator using the supplied MediaLibraryType form-type.
    • You may use the identical form for both actions, uploading and editing, given that you want the same fields to be present.
    • Otherwise, create separate forms for each action or refer to the contao-form-type-bundle's documentation for information on how to modify a form programatically.
  2. Create an upload and/or edit page with a form content element configured to use the previously set up form. The page will then automatically assure that any accessing frontend member is authorized to upload or edit the individual media library item.
  3. In a flare reader template, you may use the below snippet to display an edit link for a media library item.
    • An endpoint for deleting items is road-mapped; full functionality is not available yet.
{% if is_granted('ml_item_edit', model) %}
    {% set pageEdit = archive.related('editJumpTo') %}
    {% if pageEdit %}
        <a href="{{ pageEdit.absoluteUrl }}?edit={{ model.id }}">edit</a>
    {% endif %}
{% endif %}

Developers

Events

Modify Palette

HeimrichHannot\MediaLibraryBundle\Event\ArchivePaletteEvent
HeimrichHannot\MediaLibraryBundle\Event\ItemPaletteEvent

Fired when the palette of an archive or item is generated. Can be used to add additional fields.

Backend Editing

HeimrichHannot\MediaLibraryBundle\Event\ArchiveEditEvent
HeimrichHannot\MediaLibraryBundle\Event\ItemEditEvent

Fired when an archive or item is edited, respectively. Can be used to modify the DCA or translations.

Custom Media Library Archive Types

Any class that extends HeimrichHannot\MediaLibraryBundle\ArchiveType\AbstractArchiveType will be automatically registered as a media library archive type and be available in the archive settings.

Minimal working Boilerplate

<?php # src/MediaLibrary/MyMediaLibraryArchive.php

namespace App\MediaLibrary;

use HeimrichHannot\MediaLibraryBundle\ArchiveType\AbstractArchiveType;

class MyMediaLibraryArchive extends AbstractArchiveType
{
    public const TYPE = 'app_myMlArchiveType';

    public static function getAlias(): string
    {
        return self::TYPE;
    }
}

Extended Example

<?php # src/MediaLibrary/MyMediaLibraryArchive.php

namespace App\MediaLibrary;

use HeimrichHannot\MediaLibraryBundle\ArchiveType\AbstractArchiveType;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;

class MyMediaLibraryArchive extends AbstractArchiveType
{
    public const TYPE = 'app_myMlArchiveType';

    public static function getAlias(): string
    {
        return self::TYPE;
    }

    /* ================ IMPLEMENT CONFIG METHODS ================ *\
     *  The following methods have default implementations in     *
     *  AbstractArchiveType, but can be overridden if necessary.  *
    \* ========================================================== */

    public function getItemPalette(ArchiveModel $archive, ItemModel $item): string
    {
        return parent::getItemPalette($archive, $item);
    }

    public function getArchivePalette(ArchiveModel $archive): string
    {
        return parent::getArchivePalette($archive);
    }

    public function supportsImageSizeDownloads(ArchiveModel $archive): bool
    {
        return parent::supportsImageSizeDownloads($archive);
    }

    /* ================ EXAMPLE EVENT LISTENERS  ================ *\
     *  The following methods are examples of event listeners     *
     *  that you can implement to customize the behavior of your  *
     *  media library archive types or even existing ones.        *
    \* ========================================================== */

    #[AsEventListener]
    public function alterTranslations(ItemEditEvent $event): void
    {
        if ($event->archiveType !== self::TYPE) {
            return;
        }

        $trans = &$GLOBALS['TL_LANG'][ItemModel::getTable()];
        $trans['file'] = ['Vorschaubild', 'Wählen Sie ein Thumbnail für das Archiv aus.'];
        $trans['addAdditionalFiles'] = ['Dateien zum Herunterladen anbieten', 'Bieten Sie Dateien zum Download an.'];
        $trans['additionalFiles'] = ['Herunterladbare Dateien auswählen', 'Hier können Sie die Dateien auswählen, die zum Download angeboten werden sollen.'];
    }

    #[AsEventListener]
    public function onItemPalette(ItemPaletteEvent $event): void
    {
        if ($event->archiveType !== self::TYPE) {
            return;
        }

        $event->prefix = PaletteManipulator::create()
            ->removeField('tags')
            ->removeField('text')
            ->applyToString($event->prefix);

        $event->suffix = '{details_legend},tags,text;' . $event->suffix;
    }
}