From 27b3ee49767aea6e59a1fe76139ad41ff5972050 Mon Sep 17 00:00:00 2001
From: Oliver Bartsch <bo@cedev.de>
Date: Wed, 20 Sep 2023 17:51:49 +0200
Subject: [PATCH] [BUGFIX] Inform about online media already exists
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

In case a user adds an online media asset,
which is already present in the target folder
a flash message now properly informs about
it instead of stating that the asset was
"added successfully".

Resolves: #101980
Releases: main, 12.4
Change-Id: Iae2bb05a22cc498a5f0bad1fa5e6723d0c2d99b1
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/81113
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Oliver Bartsch <bo@cedev.de>
Tested-by: Benni Mack <benni@typo3.org>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Oliver Bartsch <bo@cedev.de>
Reviewed-by: Benni Mack <benni@typo3.org>
---
 .../Controller/OnlineMediaController.php      | 46 +++++++++++++------
 .../OnlineMediaAlreadyExistsException.php     | 42 +++++++++++++++++
 .../Helpers/AbstractOEmbedHelper.php          | 20 ++++----
 .../Private/Language/locallang_core.xlf       |  3 ++
 4 files changed, 88 insertions(+), 23 deletions(-)
 create mode 100644 typo3/sysext/core/Classes/Resource/Exception/OnlineMediaAlreadyExistsException.php

diff --git a/typo3/sysext/backend/Classes/Controller/OnlineMediaController.php b/typo3/sysext/backend/Classes/Controller/OnlineMediaController.php
index 1ada7ffb2d00..058d399d0d3e 100644
--- a/typo3/sysext/backend/Classes/Controller/OnlineMediaController.php
+++ b/typo3/sysext/backend/Classes/Controller/OnlineMediaController.php
@@ -27,6 +27,7 @@ use TYPO3\CMS\Core\Localization\LanguageService;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Messaging\FlashMessageService;
 use TYPO3\CMS\Core\Resource\DefaultUploadFolderResolver;
+use TYPO3\CMS\Core\Resource\Exception\OnlineMediaAlreadyExistsException;
 use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperRegistry;
 use TYPO3\CMS\Core\Resource\ResourceFactory;
@@ -59,7 +60,13 @@ class OnlineMediaController
 
         if (!empty($url)) {
             $data = [];
-            $file = $this->addMediaFromUrl($url, $targetFolderIdentifier, $allowedExtensions);
+            try {
+                $file = $this->addMediaFromUrl($url, $targetFolderIdentifier, $allowedExtensions);
+            } catch (OnlineMediaAlreadyExistsException $e) {
+                // Ignore this exception since the endpoint is called e.g. in inline context, where the
+                // folder is not relevant and the same asset can be attached to a record multiple times.
+                $file = $e->getOnlineMedia();
+            }
             if ($file !== null) {
                 $data['file'] = $file->getUid();
             } else {
@@ -87,21 +94,34 @@ class OnlineMediaController
         foreach ($newMedia as $media) {
             if (!empty($media['url']) && !empty($media['target'])) {
                 $allowed = !empty($media['allowed']) ? GeneralUtility::trimExplode(',', $media['allowed']) : [];
-                $file = $this->addMediaFromUrl($media['url'], $media['target'], $allowed);
-                if ($file !== null) {
-                    $flashMessage = GeneralUtility::makeInstance(
-                        FlashMessage::class,
-                        $file->getName(),
-                        $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.new_media.added'),
-                        ContextualFeedbackSeverity::OK,
-                        true
-                    );
-                } else {
+                try {
+                    $file = $this->addMediaFromUrl($media['url'], $media['target'], $allowed);
+                    if ($file !== null) {
+                        $flashMessage = GeneralUtility::makeInstance(
+                            FlashMessage::class,
+                            $file->getName(),
+                            $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.new_media.added'),
+                            ContextualFeedbackSeverity::OK,
+                            true
+                        );
+                    } else {
+                        $flashMessage = GeneralUtility::makeInstance(
+                            FlashMessage::class,
+                            $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.error.invalid_url'),
+                            $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.error.new_media.failed'),
+                            ContextualFeedbackSeverity::ERROR,
+                            true
+                        );
+                    }
+                } catch (OnlineMediaAlreadyExistsException $e) {
                     $flashMessage = GeneralUtility::makeInstance(
                         FlashMessage::class,
-                        $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.error.invalid_url'),
+                        sprintf(
+                            $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.error.already_exists'),
+                            $e->getOnlineMedia()->getName()
+                        ),
                         $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.error.new_media.failed'),
-                        ContextualFeedbackSeverity::ERROR,
+                        ContextualFeedbackSeverity::WARNING,
                         true
                     );
                 }
diff --git a/typo3/sysext/core/Classes/Resource/Exception/OnlineMediaAlreadyExistsException.php b/typo3/sysext/core/Classes/Resource/Exception/OnlineMediaAlreadyExistsException.php
new file mode 100644
index 000000000000..cf2553e54be1
--- /dev/null
+++ b/typo3/sysext/core/Classes/Resource/Exception/OnlineMediaAlreadyExistsException.php
@@ -0,0 +1,42 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Core\Resource\Exception;
+
+use TYPO3\CMS\Core\Resource\Exception;
+use TYPO3\CMS\Core\Resource\File;
+
+/**
+ * Exception indicating that a online media asset is already present in the target folder
+ */
+class OnlineMediaAlreadyExistsException extends Exception
+{
+    public function __construct(
+        private readonly File $onlineMedia,
+        int $code = 0
+    ) {
+        parent::__construct(
+            sprintf('Online media asset "%s" does already exist in the target folder.', $onlineMedia->getName()),
+            $code
+        );
+    }
+
+    public function getOnlineMedia(): File
+    {
+        return $this->onlineMedia;
+    }
+}
diff --git a/typo3/sysext/core/Classes/Resource/OnlineMedia/Helpers/AbstractOEmbedHelper.php b/typo3/sysext/core/Classes/Resource/OnlineMedia/Helpers/AbstractOEmbedHelper.php
index cbd374ca45b0..0a135de68d9b 100644
--- a/typo3/sysext/core/Classes/Resource/OnlineMedia/Helpers/AbstractOEmbedHelper.php
+++ b/typo3/sysext/core/Classes/Resource/OnlineMedia/Helpers/AbstractOEmbedHelper.php
@@ -15,6 +15,7 @@
 
 namespace TYPO3\CMS\Core\Resource\OnlineMedia\Helpers;
 
+use TYPO3\CMS\Core\Resource\Exception\OnlineMediaAlreadyExistsException;
 use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\Folder;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -42,18 +43,17 @@ abstract class AbstractOEmbedHelper extends AbstractOnlineMediaHelper
     protected function transformMediaIdToFile($mediaId, Folder $targetFolder, $fileExtension)
     {
         $file = $this->findExistingFileByOnlineMediaId($mediaId, $targetFolder, $fileExtension);
-
+        if ($file !== null) {
+            throw new OnlineMediaAlreadyExistsException($file, 1695236851);
+        }
         // no existing file create new
-        if ($file === null) {
-            $oEmbed = $this->getOEmbedData($mediaId);
-            if (!empty($oEmbed['title'])) {
-                $fileName = $oEmbed['title'] . '.' . $fileExtension;
-            } else {
-                $fileName = $mediaId . '.' . $fileExtension;
-            }
-            $file = $this->createNewFile($targetFolder, $fileName, $mediaId);
+        $oEmbed = $this->getOEmbedData($mediaId);
+        if (!empty($oEmbed['title'])) {
+            $fileName = $oEmbed['title'] . '.' . $fileExtension;
+        } else {
+            $fileName = $mediaId . '.' . $fileExtension;
         }
-        return $file;
+        return $this->createNewFile($targetFolder, $fileName, $mediaId);
     }
 
     /**
diff --git a/typo3/sysext/core/Resources/Private/Language/locallang_core.xlf b/typo3/sysext/core/Resources/Private/Language/locallang_core.xlf
index 9ace3c98a9af..5ab2679d0d94 100644
--- a/typo3/sysext/core/Resources/Private/Language/locallang_core.xlf
+++ b/typo3/sysext/core/Resources/Private/Language/locallang_core.xlf
@@ -796,6 +796,9 @@ Do you want to continue WITHOUT saving?</source>
 			<trans-unit id="online_media.error.invalid_url" resname="online_media.error.invalid_url">
 				<source>Unknown/not allowed URL</source>
 			</trans-unit>
+			<trans-unit id="online_media.error.already_exists" resname="online_media.error.already_exists">
+				<source>Online media "%s" does already exist in this folder.</source>
+			</trans-unit>
 			<trans-unit id="online_media.update.success" resname="online_media.update.success">
 				<source>Successfully updated online media</source>
 			</trans-unit>
-- 
GitLab