From 17a3b4b3305d875b371e1fdf3410752a7cb5a152 Mon Sep 17 00:00:00 2001 From: Marcel Brode Date: Fri, 6 Mar 2026 10:25:55 +0100 Subject: [PATCH 1/2] chore(media): Update media articles --- guides/plugins/plugins/content/media/index.md | 9 ++++++--- ...n-of-media-files-referenced-in-your-plugins.md | 15 ++++++++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/guides/plugins/plugins/content/media/index.md b/guides/plugins/plugins/content/media/index.md index c2bdb14392..8f4001b132 100644 --- a/guides/plugins/plugins/content/media/index.md +++ b/guides/plugins/plugins/content/media/index.md @@ -7,8 +7,11 @@ nav: # Media -Shopware Media offers the ability to add media file extensions and prevent the deletion of media files within the e-commerce platform. +The media subsystem in Shopware can be extended in several ways with plugins. +This section contains guides for common media extension points. -With the Media plugin, users can specify and configure new media file extensions. This allows businesses to define different types of media files, such as images, videos, or documents, that can be uploaded and used within the Shopware platform. +## Guides -Furthermore, the plugin helps prevent the deletion of media files that are not used in your application. +* [Prevent Deletion of Media Files Referenced in your Plugins](./prevent-deletion-of-media-files-referenced-in-your-plugins.md): Prevent your plugin's media references from being deleted by `media:delete-unused` if they are not represented by foreign keys. +* [Add Custom Media File Extension](./add-custom-file-extension.md): Allow additional file extensions and map them to the correct media type. +* [Remote Thumbnail Generation](./remote-thumbnail-generation.md): Use externally generated thumbnails instead of local thumbnail generation. diff --git a/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md b/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md index 9dc1f3be32..995e363a03 100644 --- a/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md +++ b/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md @@ -20,7 +20,7 @@ However, this does not cover all the possible cases, even for many internal Shop In order to fix the case of Media references that cannot be resolved without knowledge of the specific entity and its features, an extension point is provided via an event. -If you are developing an extension which references Media entities, and you cannot use foreign keys, this guide will detail how to prevent shopware deleting the Media entities your extension references. +If you are developing an extension which references Media entities, and you cannot use foreign keys, this guide explains how to prevent Shopware from deleting the Media entities your extension references. ## Prerequisites @@ -38,6 +38,9 @@ The remaining Media IDs will then be deleted by the `\Shopware\Core\Content\Medi Please note that this process is completed in small batches to maintain stability, so the event may be dispatched multiple times when an installation has many unused Media entities. +Before running the command in production, consider using `media:delete-unused --dry-run` to inspect candidates first. +If you need a machine-readable export, you can use `media:delete-unused --report` instead. + ## Adding a subscriber In this section, we're going to register a subscriber for the `\Shopware\Core\Content\Media\Event\UnusedMediaSearchEvent` event. @@ -79,7 +82,7 @@ class UnusedMediaSubscriber implements EventSubscriberInterface } ``` -You can use the method `getUnusedIds` of the `$event` variable to get the current an array of Media IDs scheduled for removal. +You can use the method `getUnusedIds` of the `$event` variable to get the current array of Media IDs scheduled for removal. You can use these IDs to query whatever storage your plugin uses to store references to Media entities, to check if they are currently used. @@ -103,15 +106,17 @@ private function getUsedMediaIds(array $idsToBeDeleted): array $usedMediaIds = $this->connection->fetchFirstColumn( $sql, - [$event->getUnusedIds()], + [$idsToBeDeleted], [ArrayParameterType::STRING] ); - return array_map(fn (string $ids) => json_decode($ids, true, \JSON_THROW_ON_ERROR), $usedMediaIds); + return array_merge( + ...array_map(fn (string $ids) => json_decode($ids, true, \JSON_THROW_ON_ERROR), $usedMediaIds) + ); } ``` -In the above example, `$this->connection` is an instance of `\Doctrine\DBAL\Connection` which can be injected in to your subscriber. +In the above example, `$this->connection` is an instance of `\Doctrine\DBAL\Connection` which can be injected into your subscriber. We use the MySQL JSON functions to query the table `my_slider_table`. We check if there are any references to the Media IDs from the event, in the `slider_config` column which is a JSON blob. The `JSON_EXTRACT` function looks into the `images` key of the data. We use the where condition in combination with the `JSON_OVERLAPS` function to only query rows that have references to the Media IDs we are interested in. From 7de1d99dfa66f7f9ed4616eefaa7d324bc81fde5 Mon Sep 17 00:00:00 2001 From: sushmangupta Date: Tue, 10 Mar 2026 16:27:10 +0100 Subject: [PATCH 2/2] Update text quality --- ...-media-files-referenced-in-your-plugins.md | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md b/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md index 995e363a03..2fa498a8b1 100644 --- a/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md +++ b/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md @@ -13,20 +13,20 @@ The ability to prevent Media entities from being deleted is available since Shop ## Overview -The Shopware CLI application provides a `media:delete-unused` command which deletes all media entities and their corresponding files which are not used in your application. +The Shopware CLI application provides a `media:delete-unused` command, which deletes all media entities and their corresponding files that are not used in your application. Not used means that it is not referenced by any other entity. This works well in the simple case that all your entity definitions store references to Media entities with correct foreign keys. -However, this does not cover all the possible cases, even for many internal Shopware features. For example the CMS entities store their configuration as JSON blobs with references to Media IDs stored in a nested data structure. +However, this does not cover all the possible cases, even for many internal Shopware features. For example, the CMS entities store their configuration as JSON blobs with references to Media IDs stored in a nested data structure. -In order to fix the case of Media references that cannot be resolved without knowledge of the specific entity and its features, an extension point is provided via an event. +To address cases where Media references cannot be resolved without knowledge of the specific entity and its features, an extension point is provided via an event. -If you are developing an extension which references Media entities, and you cannot use foreign keys, this guide explains how to prevent Shopware from deleting the Media entities your extension references. +If you are developing an extension that references Media entities, and you cannot use foreign keys, this guide explains how to prevent Shopware from deleting the Media entities your extension references. ## Prerequisites As most of our plugin guides, this guide was also built upon our [Plugin base guide](../../plugin-base-guide). Furthermore, you'll have to know about adding classes to the [Dependency injection](../../plugin-fundamentals/dependency-injection) container -and about using a subscriber in order to [Listen to events](../../plugin-fundamentals/listening-to-events). +and about using a subscriber to [Listen to events](../../plugin-fundamentals/listening-to-events). ## The deletion process @@ -84,13 +84,13 @@ class UnusedMediaSubscriber implements EventSubscriberInterface You can use the method `getUnusedIds` of the `$event` variable to get the current array of Media IDs scheduled for removal. -You can use these IDs to query whatever storage your plugin uses to store references to Media entities, to check if they are currently used. +You can use these IDs to query the storage your plugin uses to store references to Media entities and check whether they are currently in use. -If any of the IDs are used by your plugin, you can use the method `markAsUsed` of the `$event` variable to prevent the Media entities from being deleted. `markAsUsed` accepts an array of string IDs. +If your plugin uses any of the IDs, you can use the method `markAsUsed` of the `$event` variable to prevent the Media entities from being deleted. `markAsUsed` accepts an array of string IDs. -If your storage is a relational database such as MySQL you should, when possible, use direct database queries to check for references. This saves memory and CPU cycles by not loading unnecessary data. +If your storage is a relational database such as MySQL, you should, when possible, use direct database queries to check for references. This saves memory and CPU cycles by avoiding the loading of unnecessary data. -Imagine an extension which provides an image slider feature. An implementation of `getUsedMediaIds` might look something like the following: +Imagine an extension that provides an image slider feature. An implementation of `getUsedMediaIds` might look something like the following: ```php // /src/Subscriber/UnusedMediaSubscriber.php @@ -99,10 +99,10 @@ private function getUsedMediaIds(array $idsToBeDeleted): array $sql = <<connection->fetchFirstColumn( $sql, @@ -117,10 +117,10 @@ private function getUsedMediaIds(array $idsToBeDeleted): array ``` In the above example, `$this->connection` is an instance of `\Doctrine\DBAL\Connection` which can be injected into your subscriber. -We use the MySQL JSON functions to query the table `my_slider_table`. -We check if there are any references to the Media IDs from the event, in the `slider_config` column which is a JSON blob. The `JSON_EXTRACT` function looks into the `images` key of the data. We use the where condition in combination with the `JSON_OVERLAPS` function to only query rows that have references to the Media IDs we are interested in. +We use MySQL JSON functions to query the `my_slider_table` table. +We check whether there are any references to the Media IDs from the event in the `slider_config` column, which is a JSON blob. The `JSON_EXTRACT` function looks into the `images` key of the data. We use the WHERE condition in combination with the `JSON_OVERLAPS` function to query only rows that reference the Media IDs we are interested in. -Finally, we return all the IDs of Media which are used in the slider config so that they are not deleted. +Finally, we return all the IDs of Media used in the slider config so they are not deleted. Make sure to register your event subscriber to the [Dependency injection container](../../plugin-fundamentals/dependency-injection) by using the tag `kernel.event_subscriber`.