+<ul class="mediaEditorButtons buttonGroup">
+ <li><div class="mediaManagerMediaReplaceButton"></div></li>
+</ul>
+
{if $media->isImage && $media->hasThumbnail('small')}
<div class="mediaThumbnail">
{@$media->getThumbnailTag('small')}
require(['Language', 'Permission'], function(Language, Permission) {
Language.addObject({
'wcf.global.button.insert': '{lang}wcf.global.button.insert{/lang}',
- 'wcf.media.button.select': '{lang}wcf.media.button.select{/lang}',
+ 'wcf.media.button.replaceFile': '{lang}wcf.media.button.replaceFile{/lang}',
+ 'wcf.media.button.select': '{lang}wcf.media.button.select{/lang}',
'wcf.media.delete.confirmMessage': '{lang __encode=true __literal=true}wcf.media.delete.confirmMessage{/lang}',
+ 'wcf.media.imageDimensions.value': '{lang __literal=true}wcf.media.imageDimensions.value{/lang}',
'wcf.media.insert': '{lang}wcf.media.insert{/lang}',
'wcf.media.insert.imageSize': '{lang}wcf.media.insert.imageSize{/lang}',
'wcf.media.insert.imageSize.small': '{lang}wcf.media.insert.imageSize.small{/lang}',
'wcf.media.button.insert': '{lang}wcf.media.button.insert{/lang}',
'wcf.media.search.info.searchStringThreshold': '{lang __literal=true}wcf.media.search.info.searchStringThreshold{/lang}',
'wcf.media.search.noResults': '{lang}wcf.media.search.noResults{/lang}',
+ 'wcf.media.upload.error.differentFileExtension': '{lang}wcf.media.upload.error.differentFileExtension{/lang}',
+ 'wcf.media.upload.error.differentFileType': '{lang}wcf.media.upload.error.differentFileType{/lang}',
'wcf.media.upload.error.noImage': '{lang}wcf.media.upload.error.noImage{/lang}',
'wcf.media.upload.error.uploadFailed': '{lang}wcf.media.upload.error.uploadFailed{/lang}',
'wcf.media.upload.success': '{lang}wcf.media.upload.success{/lang}',
+<ul class="mediaEditorButtons buttonGroup">
+ <li><div class="mediaManagerMediaReplaceButton"></div></li>
+</ul>
+
{if $media->isImage && $media->hasThumbnail('small')}
<div class="mediaThumbnail">
{@$media->getThumbnailTag('small')}
require(['Language', 'Permission'], function(Language, Permission) {
Language.addObject({
'wcf.global.button.insert': '{lang}wcf.global.button.insert{/lang}',
+ 'wcf.media.button.replaceFile': '{lang}wcf.media.button.replaceFile{/lang}',
'wcf.media.button.select': '{lang}wcf.media.button.select{/lang}',
'wcf.media.delete.confirmMessage': '{lang __encode=true __literal=true}wcf.media.delete.confirmMessage{/lang}',
+ 'wcf.media.imageDimensions.value': '{lang __literal=true}wcf.media.imageDimensions.value{/lang}',
'wcf.media.insert': '{lang}wcf.media.insert{/lang}',
'wcf.media.insert.imageSize': '{lang}wcf.media.insert.imageSize{/lang}',
'wcf.media.insert.imageSize.small': '{lang}wcf.media.insert.imageSize.small{/lang}',
'wcf.media.button.insert': '{lang}wcf.media.button.insert{/lang}',
'wcf.media.search.info.searchStringThreshold': '{lang __literal=true}wcf.media.search.info.searchStringThreshold{/lang}',
'wcf.media.search.noResults': '{lang}wcf.media.search.noResults{/lang}',
+ 'wcf.media.upload.error.differentFileExtension': '{lang}wcf.media.upload.error.differentFileExtension{/lang}',
+ 'wcf.media.upload.error.differentFileType': '{lang}wcf.media.upload.error.differentFileType{/lang}',
'wcf.media.upload.error.noImage': '{lang}wcf.media.upload.error.noImage{/lang}',
'wcf.media.upload.error.uploadFailed': '{lang}wcf.media.upload.error.uploadFailed{/lang}',
'wcf.media.upload.success': '{lang}wcf.media.upload.success{/lang}',
*/
define(
[
- 'Ajax', 'Core', 'Dictionary', 'Dom/ChangeListener',
- 'Dom/Traverse', 'Language', 'Ui/Dialog', 'Ui/Notification',
- 'WoltLabSuite/Core/Language/Chooser', 'WoltLabSuite/Core/Language/Input', 'EventKey'
+ 'Ajax',
+ 'Core',
+ 'Dictionary',
+ 'Dom/ChangeListener',
+ 'Dom/Traverse',
+ 'Dom/Util',
+ 'Language',
+ 'Ui/Dialog',
+ 'Ui/Notification',
+ 'WoltLabSuite/Core/Language/Chooser',
+ 'WoltLabSuite/Core/Language/Input',
+ 'EventKey',
+ 'WoltLabSuite/Core/Media/Replace'
],
function(
- Ajax, Core, Dictionary, DomChangeListener,
- DomTraverse, Language, UiDialog, UiNotification,
- LanguageChooser, LanguageInput, EventKey
+ Ajax,
+ Core,
+ Dictionary,
+ DomChangeListener,
+ DomTraverse,
+ DomUtil,
+ Language,
+ UiDialog,
+ UiNotification,
+ LanguageChooser,
+ LanguageInput,
+ EventKey,
+ MediaReplace
)
{
"use strict";
}
},
+ /**
+ * Initializes the editor dialog.
+ *
+ * @param {HTMLElement} content
+ * @param {object} data
+ * @since 5.3
+ */
+ _initEditor: function(content, data) {
+ this._availableLanguageCount = ~~data.returnValues.availableLanguageCount;
+ this._categoryIds = data.returnValues.categoryIDs.map(function(number) {
+ return ~~number;
+ });
+
+ var didLoadMediaData = false;
+ if (data.returnValues.mediaData) {
+ this._media = data.returnValues.mediaData;
+
+ didLoadMediaData = true;
+ }
+
+ // make sure that the language chooser is initialized first
+ setTimeout(function() {
+ if (this._availableLanguageCount > 1) {
+ LanguageChooser.setLanguageId('mediaEditor_' + this._media.mediaID + '_languageID', this._media.languageID || LANGUAGE_ID);
+ }
+
+ if (this._categoryIds.length) {
+ elBySel('select[name=categoryID]', content).value = ~~this._media.categoryID;
+ }
+
+ var title = elBySel('input[name=title]', content);
+ var altText = elBySel('input[name=altText]', content);
+ var caption = elBySel('textarea[name=caption]', content);
+
+ if (this._availableLanguageCount > 1 && this._media.isMultilingual) {
+ if (elById('altText_' + this._media.mediaID)) LanguageInput.setValues('altText_' + this._media.mediaID, Dictionary.fromObject(this._media.altText || { }));
+ if (elById('caption_' + this._media.mediaID)) LanguageInput.setValues('caption_' + this._media.mediaID, Dictionary.fromObject(this._media.caption || { }));
+ LanguageInput.setValues('title_' + this._media.mediaID, Dictionary.fromObject(this._media.title || { }));
+ }
+ else {
+ title.value = this._media.title ? this._media.title[this._media.languageID || LANGUAGE_ID] : '';
+ if (altText) altText.value = this._media.altText ? this._media.altText[this._media.languageID || LANGUAGE_ID] : '';
+ if (caption) caption.value = this._media.caption ? this._media.caption[this._media.languageID || LANGUAGE_ID] : '';
+ }
+
+ if (this._availableLanguageCount > 1) {
+ var isMultilingual = elBySel('input[name=isMultilingual]', content);
+ isMultilingual.addEventListener('change', this._updateLanguageFields.bind(this));
+
+ this._updateLanguageFields(null, isMultilingual);
+ }
+
+ var keyPress = this._keyPress.bind(this);
+ if (altText) altText.addEventListener('keypress', keyPress);
+ title.addEventListener('keypress', keyPress);
+
+ elBySel('button[data-type=submit]', content).addEventListener(WCF_CLICK_EVENT, this._saveData.bind(this));
+
+ // remove focus from input elements and scroll dialog to top
+ document.activeElement.blur();
+ elById('mediaEditor_' + this._media.mediaID).parentNode.scrollTop = 0;
+
+ // Initialize button to replace media file.
+ var uploadButton = elByClass('mediaManagerMediaReplaceButton', content)[0];
+ var target = elByClass('mediaThumbnail', content)[0];
+ if (!target) {
+ target = elCreate('div');
+ content.appendChild(target);
+ }
+ new MediaReplace(
+ this._media.mediaID,
+ DomUtil.identify(uploadButton),
+ // Pass an anonymous element for non-images which is required internally
+ // but not needed in this case.
+ DomUtil.identify(target),
+ {
+ mediaEditor: this
+ }
+ );
+
+ DomChangeListener.trigger();
+ }.bind(this), 200);
+ },
+
/**
* Handles the `[ENTER]` key to submit the form.
*
title: Language.get('wcf.media.edit')
},
source: {
- after: (function(content, data) {
- this._availableLanguageCount = ~~data.returnValues.availableLanguageCount;
- this._categoryIds = data.returnValues.categoryIDs.map(function(number) {
- return ~~number;
- });
-
- var didLoadMediaData = false;
- if (data.returnValues.mediaData) {
- this._media = data.returnValues.mediaData;
-
- didLoadMediaData = true;
- }
-
- // make sure that the language chooser is initialized first
- setTimeout(function() {
- if (this._availableLanguageCount > 1) {
- LanguageChooser.setLanguageId('mediaEditor_' + this._media.mediaID + '_languageID', this._media.languageID || LANGUAGE_ID);
- }
-
- if (this._categoryIds.length) {
- elBySel('select[name=categoryID]', content).value = ~~this._media.categoryID;
- }
-
- var title = elBySel('input[name=title]', content);
- var altText = elBySel('input[name=altText]', content);
- var caption = elBySel('textarea[name=caption]', content);
-
- if (this._availableLanguageCount > 1 && this._media.isMultilingual) {
- if (elById('altText_' + this._media.mediaID)) LanguageInput.setValues('altText_' + this._media.mediaID, Dictionary.fromObject(this._media.altText || { }));
- if (elById('caption_' + this._media.mediaID)) LanguageInput.setValues('caption_' + this._media.mediaID, Dictionary.fromObject(this._media.caption || { }));
- LanguageInput.setValues('title_' + this._media.mediaID, Dictionary.fromObject(this._media.title || { }));
- }
- else {
- title.value = this._media.title ? this._media.title[this._media.languageID || LANGUAGE_ID] : '';
- if (altText) altText.value = this._media.altText ? this._media.altText[this._media.languageID || LANGUAGE_ID] : '';
- if (caption) caption.value = this._media.caption ? this._media.caption[this._media.languageID || LANGUAGE_ID] : '';
- }
-
- if (this._availableLanguageCount > 1) {
- var isMultilingual = elBySel('input[name=isMultilingual]', content);
- isMultilingual.addEventListener('change', this._updateLanguageFields.bind(this));
-
- this._updateLanguageFields(null, isMultilingual);
- }
-
- var keyPress = this._keyPress.bind(this);
- if (altText) altText.addEventListener('keypress', keyPress);
- title.addEventListener('keypress', keyPress);
-
- elBySel('button[data-type=submit]', content).addEventListener(WCF_CLICK_EVENT, this._saveData.bind(this));
-
- // remove focus from input elements and scroll dialog to top
- document.activeElement.blur();
- elById('mediaEditor_' + this._media.mediaID).parentNode.scrollTop = 0;
-
- DomChangeListener.trigger();
- }.bind(this), 200);
- }).bind(this),
+ after: this._initEditor.bind(this),
data: {
actionName: 'getEditorDialog',
className: 'wcf\\data\\media\\MediaAction',
}
UiDialog.open(this._dialogs.get('mediaEditor_' + media.mediaID));
+ },
+
+ /**
+ * Updates the data of the currently edited media file.
+ *
+ * @param {object} data
+ * @since 5.3
+ */
+ updateData: function(data) {
+ if (this._callbackObject._editorSuccess) {
+ this._callbackObject._editorSuccess(data);
+ }
}
};
var listItem = this._listItems.get(~~media.mediaID);
var p = elByClass('mediaTitle', listItem)[0];
if (media.isMultilingual) {
- p.textContent = media.title[LANGUAGE_ID] || media.filename;
+ if (media.title && media.title[LANGUAGE_ID]) {
+ p.textContent = media.title[LANGUAGE_ID];
+ }
+ else {
+ p.textContent = media.filename;
+ }
}
else {
- p.textContent = media.title[media.languageID] || media.filename;
+ if (media.title && media.title[media.languageID]) {
+ p.textContent = media.title[media.languageID];
+ }
+ else {
+ p.textContent = media.filename;
+ }
+ }
+
+ var thumbnail = elByClass('mediaThumbnail', listItem)[0];
+ thumbnail.innerHTML = media.elementTag;
+ // Bust browser cache by adding additional parameter.
+ var imgs = elByTag('img', thumbnail);
+ if (imgs.length) {
+ imgs[0].src += '&refresh=1';
}
},
--- /dev/null
+/**
+ * Uploads replacemnts for media files.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2020 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLabSuite/Core/Media/Upload
+ * @since 5.3
+ */
+define(
+ [
+ 'Core',
+ 'Dom/ChangeListener',
+ 'Dom/Util',
+ 'Language',
+ 'Ui/Notification',
+ './Upload'
+ ],
+ function(
+ Core,
+ DomChangeListener,
+ DomUtil,
+ Language,
+ UiNotification,
+ MediaUpload
+ )
+ {
+ "use strict";
+
+ if (!COMPILER_TARGET_DEFAULT) {
+ var Fake = function() {};
+ Fake.prototype = {
+ _createButton: function() {},
+ _success: function() {},
+ _upload: function() {},
+ _createFileElement: function() {},
+ _getParameters: function() {},
+ _uploadFiles: function() {},
+ _createFileElements: function() {},
+ _failure: function() {},
+ _insertButton: function() {},
+ _progress: function() {},
+ _removeButton: function() {}
+ };
+ return Fake;
+ }
+
+ /**
+ * @constructor
+ */
+ function MediaReplace(mediaID, buttonContainerId, targetId, options) {
+ this._mediaID = mediaID;
+
+ MediaUpload.call(this, buttonContainerId, targetId, Core.extend(options, {
+ action: 'replaceFile'
+ }));
+ }
+ Core.inherit(MediaReplace, MediaUpload, {
+ /**
+ * @see WoltLabSuite/Core/Upload#_createButton
+ */
+ _createButton: function() {
+ MediaUpload.prototype._createButton.call(this);
+
+ this._button.classList.add('small');
+
+ var span = elBySel('span', this._button);
+ span.textContent = Language.get('wcf.media.button.replaceFile');
+ },
+
+ /**
+ * @see WoltLabSuite/Core/Upload#_createFileElement
+ */
+ _createFileElement: function() {
+ return this._target;
+ },
+
+ /**
+ * @see WoltLabSuite/Core/Upload#_getFormData
+ */
+ _getFormData: function() {
+ return {
+ objectIDs: [this._mediaID]
+ };
+ },
+
+ /**
+ * @see WoltLabSuite/Core/Upload#_success
+ */
+ _success: function(uploadId, data) {
+ var files = this._fileElements[uploadId];
+
+ for (var i = 0, length = files.length; i < length; i++) {
+ var file = files[i];
+ var internalFileId = elData(file, 'internal-file-id');
+ var media = data.returnValues.media[internalFileId];
+
+ if (media) {
+ if (media.isImage) {
+ this._target.innerHTML = media.smallThumbnailTag;
+ }
+
+ elById('mediaFilename').textContent = media.filename;
+ elById('mediaFilesize').textContent = media.formattedFilesize;
+ if (media.isImage) {
+ elById('mediaImageDimensions').textContent = media.imageDimensions;
+ }
+ elById('mediaUploader').innerHTML = media.userLinkElement;
+
+ this._options.mediaEditor.updateData(media);
+
+ // Remove existing error messages.
+ elInnerError(this._buttonContainer, '');
+
+ UiNotification.show();
+ }
+ else {
+ var error = data.returnValues.errors[internalFileId];
+ if (!error) {
+ error = {
+ errorType: 'uploadFailed',
+ filename: elData(file, 'filename')
+ };
+ }
+
+ elInnerError(this._buttonContainer, Language.get('wcf.media.upload.error.' + error.errorType, {
+ filename: error.filename
+ }));
+ }
+
+ DomChangeListener.trigger();
+ }
+ },
+ });
+
+ return MediaReplace;
+ }
+);
* @property-read string $fileType type of the physical media file
* @property-read string $fileHash hash of the physical media file
* @property-read integer $uploadTime timestamp at which the media file has been uploaded
+ * @property-read int $fileUpdateTime timestamp at which the media file was updated the last or `0` if it has not been updated
* @property-read integer|null $userID id of the user who uploaded the media file or null if the user does not exist anymore
* @property-read string $username name of the user who uploaded the media file
* @property-read integer|null $languageID id of the language associated with the media file or null if the media file is multilingual or if the language has been deleted
use wcf\system\language\LanguageFactory;
use wcf\system\request\LinkHandler;
use wcf\system\upload\DefaultUploadFileSaveStrategy;
+use wcf\system\upload\MediaReplaceUploadFileValidationStrategy;
use wcf\system\upload\MediaUploadFileValidationStrategy;
use wcf\system\upload\UploadFile;
use wcf\system\WCF;
'captionEnableHtml' => $media->captionEnableHtml,
'categoryID' => $media->categoryID,
'elementTag' => $media instanceof ViewableMedia ? $media->getElementTag($this->parameters['elementTagSize'] ?? 144) : '',
+ 'elementTag48' => $media instanceof ViewableMedia ? $media->getElementTag(48) : '',
'fileHash' => $media->fileHash,
'filename' => $media->filename,
'filesize' => $media->filesize,
'fileType' => $media->fileType,
'height' => $media->height,
'languageID' => $media->languageID,
+ 'imageDimensions' => $media->isImage ? WCF::getLanguage()->getDynamicVariable('wcf.media.imageDimensions.value', [
+ 'media' => $media,
+ ]) : '',
'isImage' => $media->isImage,
'isMultilingual' => $media->isMultilingual,
'largeThumbnailHeight' => $media->largeThumbnailHeight,
'mediumThumbnailWidth' => $media->mediumThumbnailWidth,
'smallThumbnailHeight' => $media->smallThumbnailHeight,
'smallThumbnailLink' => $media->smallThumbnailType ? $media->getThumbnailLink('small') : '',
+ 'smallThumbnailTag' => $media->smallThumbnailType ? $media->getThumbnailTag('small') : '',
'smallThumbnailType' => $media->smallThumbnailType,
'smallThumbnailWidth' => $media->smallThumbnailWidth,
'tinyThumbnailHeight' => $media->tinyThumbnailHeight,
'id' => $media->userID,
'title' => $media->username
]) : '',
+ // TODO: find better solution
+ 'userLinkElement' => $media instanceof ViewableMedia ? WCF::getTPL()->fetchString(
+ WCF::getTPL()->getCompiler()->compileString('userLink','{user object=$userProfile}')['template'],
+ ['userProfile' => $media->getUserProfile()]
+ ) : '',
'username' => $media->username,
'width' => $media->width
];
$this->unmarkItems();
}
+
+ /**
+ * Validates the `replaceFile` action.
+ *
+ * @since 5.3
+ */
+ public function validateReplaceFile() {
+ WCF::getSession()->checkPermissions(['admin.content.cms.canManageMedia']);
+
+ $this->getSingleObject();
+
+ /** @noinspection PhpUndefinedMethodInspection */
+ $this->parameters['__files']->validateFiles(
+ new MediaReplaceUploadFileValidationStrategy($this->getSingleObject()->getDecoratedObject())
+ );
+ }
+
+ /**
+ * Replaces the actual file of a media file.
+ *
+ * @return array
+ * @since 5.3
+ */
+ public function replaceFile() {
+ $saveStrategy = new DefaultUploadFileSaveStrategy(self::class, [
+ 'action' => 'update',
+ 'generateThumbnails' => true,
+ 'object' => $this->getSingleObject()->getDecoratedObject(),
+ 'rotateImages' => true,
+ ], [
+ 'fileUpdateTime' => TIME_NOW,
+ 'userID' => $this->getSingleObject()->userID,
+ 'username' => $this->getSingleObject()->username,
+ ]);
+
+ /** @noinspection PhpUndefinedMethodInspection */
+ $this->parameters['__files']->saveFiles($saveStrategy);
+
+ /** @var Media[] $mediaFiles */
+ $mediaFiles = $saveStrategy->getObjects();
+
+ $result = [
+ 'errors' => [],
+ 'media' => []
+ ];
+
+ if (!empty($mediaFiles)) {
+ $mediaIDs = $mediaToFileID = [];
+ foreach ($mediaFiles as $internalFileID => $media) {
+ $mediaIDs[] = $media->mediaID;
+ $mediaToFileID[$media->mediaID] = $internalFileID;
+ }
+
+ // fetch media objects from database
+ $mediaList = new ViewableMediaList();
+ $mediaList->setObjectIDs($mediaIDs);
+ $mediaList->readObjects();
+
+ foreach ($mediaList as $media) {
+ $result['media'][$mediaToFileID[$media->mediaID]] = $this->getMediaData($media);
+ }
+ }
+
+ /** @var UploadFile[] $files */
+ /** @noinspection PhpUndefinedMethodInspection */
+ $files = $this->parameters['__files']->getFiles();
+ foreach ($files as $file) {
+ if ($file->getValidationErrorType()) {
+ $result['errors'][$file->getInternalFileID()] = [
+ 'filename' => $file->getFilename(),
+ 'filesize' => $file->getFilesize(),
+ 'errorType' => $file->getValidationErrorType()
+ ];
+ }
+ }
+
+ // Delete *old* files using the non-updated local media editor object.
+ if (empty($result['errors'])) {
+ $this->getSingleObject()->deleteFiles();
+ }
+
+ return $result;
+ }
}
'filesize' => $filesize,
'showInline' => in_array($mimeType, self::$inlineMimeTypes),
'enableRangeSupport' => $this->thumbnail ? true : false,
- 'lastModificationTime' => $this->media->uploadTime,
+ 'lastModificationTime' => $this->media->fileUpdateTime ?? $this->media->uploadTime,
'expirationDate' => TIME_NOW + 31536000,
- 'maxAge' => 31536000
+ 'maxAge' => 31536000,
]);
if ($this->eTag !== null) {
if (is_subclass_of($baseClass, IThumbnailFile::class)) {
$this->options['thumbnailSizes'] = call_user_func([$baseClass, 'getThumbnailSizes']);
}
+
+ $this->options['action'] = $this->options['action'] ?? 'create';
}
/**
'filesize' => $uploadFile->getFilesize(),
'fileType' => $uploadFile->getMimeType(),
'fileHash' => sha1_file($uploadFile->getLocation()),
- 'uploadTime' => TIME_NOW,
- 'userID' => WCF::getUser()->userID ?: null
+ 'userID' => WCF::getUser()->userID ?: null,
], $this->data);
+ if ($this->options['action'] === 'create') {
+ $data['uploadTime'] = TIME_NOW;
+ }
+
// get image data
if (($imageData = $uploadFile->getImageData()) !== null) {
$data['width'] = $imageData['width'];
}
/** @var IDatabaseObjectAction $action */
- $action = new $this->actionClassName([], 'create', [
- 'data' => $data
+ $objects = [];
+ if (isset($this->options['object'])) {
+ $objects = [$this->options['object']];
+ }
+ $action = new $this->actionClassName($objects, $this->options['action'], [
+ 'data' => $data,
]);
/** @var IThumbnailFile $object */
$object = $action->executeAction()['returnValues'];
+ if (isset($this->options['object'])) {
+ $className = get_class($this->options['object']);
+ $object = new $className($this->options['object']->getObjectID());
+ }
$dir = dirname($object->getLocation());
if (!@file_exists($dir)) {
--- /dev/null
+<?php
+namespace wcf\system\upload;
+use wcf\data\media\Media;
+
+/**
+ * Upload file validation strategy implementation for media file replacements.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2020 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Upload
+ * @since 5.3
+ */
+class MediaReplaceUploadFileValidationStrategy extends MediaUploadFileValidationStrategy {
+ /**
+ * media whose file will be replaced
+ * @var Media
+ */
+ protected $media;
+
+ /**
+ * Creates a new instance of MediaReplaceUploadFileValidationStrategy.
+ *
+ * @param Media $media
+ */
+ public function __construct(Media $media) {
+ $this->media = $media;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validate(UploadFile $uploadFile) {
+ if (!parent::validate($uploadFile)) {
+ return false;
+ }
+
+ if ($this->media->fileType !== $uploadFile->getMimeType()) {
+ $uploadFile->setValidationErrorType('differentFileType');
+ return false;
+ }
+
+ if (strtolower(pathinfo($this->media->filename, PATHINFO_EXTENSION)) !== strtolower($uploadFile->getFileExtension())) {
+ $uploadFile->setValidationErrorType('differentFileExtension');
+ return false;
+ }
+
+ return true;
+ }
+}
}
[id^=mediaEditor] {
+ .mediaEditorButtons {
+ margin-bottom: 20px;
+ }
+
.mediaThumbnail {
text-align: center;
margin-bottom: 20px;
<category name="wcf.media">
<item name="wcf.media.altText"><![CDATA[Alternativ-Text]]></item>
<item name="wcf.media.button.insert"><![CDATA[Einfügen]]></item>
+ <item name="wcf.media.button.replaceFile"><![CDATA[Datei ersetzen]]></item>
<item name="wcf.media.button.select"><![CDATA[Auswählen]]></item>
<item name="wcf.media.caption"><![CDATA[Bildunterschrift]]></item>
<item name="wcf.media.caption.enableHtml"><![CDATA[HTML in der Bildunterschrift verwenden]]></item>
<item name="wcf.media.media.pageTitle"><![CDATA[{if $__wcf->session->getPermission('admin.content.cms.canOnlyAccessOwnMedia')}Eigene {/if}Medien]]></item>
<item name="wcf.media.search.cancel"><![CDATA[Suche abbrechen]]></item>
<item name="wcf.media.search.placeholder"><![CDATA[Datei suchen]]></item>
+ <item name="wcf.media.upload.error.differentFileExtension"><![CDATA[Die neue Datei muss die gleiche Dateiendung haben wie die aktuelle Datei.]]></item>
+ <item name="wcf.media.upload.error.differentFileType"><![CDATA[Die neue Datei muss vom gleichen Dateityp sein wie die aktuelle Datei.]]></item>
<item name="wcf.media.upload.error.noImage"><![CDATA[Die hochgeladene Datei ist kein Bild.]]></item>
<item name="wcf.media.upload.error.uploadFailed"><![CDATA[Beim Hochladen der Datei ist ein unbekannter Fehler aufgetreten.]]></item>
<item name="wcf.media.upload.success"><![CDATA[Die Datei wurde erfolgreich hochgeladen.]]></item>
<category name="wcf.media">
<item name="wcf.media.altText"><![CDATA[Alternate Text]]></item>
<item name="wcf.media.button.insert"><![CDATA[Insert]]></item>
+ <item name="wcf.media.button.replaceFile"><![CDATA[Replace File]]></item>
<item name="wcf.media.button.select"><![CDATA[Select]]></item>
<item name="wcf.media.caption"><![CDATA[Caption]]></item>
<item name="wcf.media.caption.enableHtml"><![CDATA[Enable HTML code in caption]]></item>
<item name="wcf.media.media.pageTitle"><![CDATA[{if $__wcf->session->getPermission('admin.content.cms.canOnlyAccessOwnMedia')}Own {/if}Media]]></item>
<item name="wcf.media.search.cancel"><![CDATA[Cancel Search]]></item>
<item name="wcf.media.search.placeholder"><![CDATA[Search Files]]></item>
+ <item name="wcf.media.upload.error.differentFileExtension"><![CDATA[The new file must have the same file extension as the current file.]]></item>
+ <item name="wcf.media.upload.error.differentFileType"><![CDATA[The new file must be of the same file type as the current file.]]></item>
<item name="wcf.media.upload.error.noImage"><![CDATA[The uploaded file is no image.]]></item>
<item name="wcf.media.upload.error.uploadFailed"><![CDATA[An unknown error occurred during the upload.]]></item>
<item name="wcf.media.upload.success"><![CDATA[The file has been successfully uploaded.]]></item>
fileType VARCHAR(255) NOT NULL DEFAULT '',
fileHash VARCHAR(255) NOT NULL DEFAULT '',
uploadTime INT(10) NOT NULL DEFAULT 0,
+ fileUpdateTime INT(10) NOT NULL DEFAULT 0,
userID INT(10),
username VARCHAR(255) NOT NULL,
languageID INT(10),