$(button).addClass('jsMediaEditorButton');
require(['WoltLab/WCF/Media/Manager/Editor'], function(MediaManagerEditor) {
- new MediaManagerEditor();
- });
+ new MediaManagerEditor({
+ editor: this
+ });
+ }.bind(this));
},
};
};
*/
_clipboardAction: function(actionData) {
// only consider events if the action has been executed
- if (actionData.responseData === null) {
- return;
- }
-
- switch (actionData.data.actionName) {
- case 'com.woltlab.wcf.media.delete':
- var mediaIds = actionData.responseData.objectIDs;
- for (var i = 0, length = mediaIds.length; i < length; i++) {
- this.removeMedia(~~mediaIds[i], true);
- }
-
- UiNotification.show();
- break;
+ if (actionData.data.actionName === 'com.woltlab.wcf.media.delete' && actionData.responseData === null) {
+ var mediaIds = actionData.responseData.objectIDs;
+ for (var i = 0, length = mediaIds.length; i < length; i++) {
+ this.removeMedia(~~mediaIds[i], true);
+ }
+
+ UiNotification.show();
}
},
/**
- * Provides the media manager dialog for selecting media for input elements.
+ * Provides the media manager dialog for selecting media for Redactor editors.
*
* @author Matthias Schmidt
* @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @module WoltLab/WCF/Media/Manager/Editor
*/
-define(['Core', 'Dom/Traverse', 'Language', 'Ui/Dialog', 'WoltLab/WCF/Media/Manager/Base'], function(Core, DomTraverse, Language, UiDialog, MediaManagerBase) {
+define(['Core', 'Dictionary', 'Dom/Traverse', 'Language', 'Ui/Dialog', 'WoltLab/WCF/Media/Manager/Base'], function(Core, Dictionary, DomTraverse, Language, UiDialog, MediaManagerBase) {
"use strict";
/**
for (var i = 0, length = this._buttons.length; i < length; i++) {
this._buttons[i].addEventListener(WCF_CLICK_EVENT, this._click.bind(this));
}
-
- this._activeButton = null;
+ this._mediaToInsert = new Dictionary();
+ this._mediaToInsertByClipboard = false;
};
Core.inherit(MediaManagerEditor, MediaManagerBase, {
/**
}
},
+ /**
+ * Builds the dialog to setup inserting media files.
+ */
+ _buildInsertDialog: function() {
+ var thumbnailOptions = '';
+
+ var sizes = ['small', 'medium', 'large'];
+ var size, option;
+ lengthLoop: for (var i = 0, length = sizes.length; i < length; i++) {
+ size = sizes[i];
+
+ // make sure that all thumbnails support the thumbnail size
+ for (var j = 0, mediaLength = this._mediaToInsert.length; j < mediaLength; j++) {
+ if (!this._mediaToInsert[i][size + 'ThumbnailType']) {
+ continue lengthLoop;
+ }
+ }
+
+ thumbnailOptions += '<option value="' + size + '">' + Language.get('wcf.media.insert.imageSize.' + size) + '</option>';
+ }
+ thumbnailOptions += '<option value="original">' + Language.get('wcf.media.insert.imageSize.original') + '</option>';
+
+ var dialog = '<div class="section">'
+ + (this._mediaToInsert.size > 1 ? '<dl>'
+ + '<dt>' + Language.get('wcf.media.insert.type') + '</dt>'
+ + '<dd>'
+ + '<select name="insertType">'
+ + '<option value="separate">' + Language.get('wcf.media.insert.type.separate') + '</option>'
+ + '<option value="gallery">' + Language.get('wcf.media.insert.type.gallery') + '</option>'
+ + '</select>'
+ + '</dd>'
+ + '</dl>' : '')
+ + '<dl>'
+ + '<dt>' + Language.get('wcf.media.insert.imageSize') + '</dt>'
+ + '<dd>'
+ + '<select name="thumbnailSize">'
+ + thumbnailOptions
+ + '</select>'
+ + '</dd>'
+ + '</dl>'
+ + '</div>'
+ + '<div class="formSubmit">'
+ + '<button class="buttonPrimary">' + Language.get('wcf.global.button.insert') + '</button>'
+ + '</div>';
+
+ UiDialog.open({
+ _dialogSetup: (function() {
+ return {
+ id: this._getInsertDialogId(),
+ options: {
+ onClose: this._editorClose.bind(this),
+ onSetup: function(content) {
+ elByClass('buttonPrimary', content)[0].addEventListener(WCF_CLICK_EVENT, this._insertMedia.bind(this));
+ }.bind(this),
+ title: Language.get('wcf.media.insert')
+ },
+ source: dialog
+ }
+ }).bind(this)
+ });
+ },
+
/**
* @see WoltLab/WCF/Media/Manager/Base#_click
*/
MediaManagerEditor._super.prototype._click.call(this, event);
},
- _insertMedia: function() {
- // TODO
+ /**
+ * @see WoltLab/WCF/Media/Manager/Base#_clipboardAction
+ */
+ _clipboardAction: function(actionData) {
+ MediaManagerEditor._super.prototype._clipboardAction.call(this, actionData);
+
+ if (actionData.data.actionName === 'com.woltlab.wcf.media.insert') {
+ this.insertMedia(actionData.data.parameters.objectIDs, true);
+ }
+ },
+
+ /**
+ * Returns the id of the insert dialog based on the media files to be inserted.
+ *
+ * @return {string} insert dialog id
+ */
+ _getInsertDialogId: function() {
+ var dialogId = 'mediaInsert';
+
+ this._mediaToInsert.forEach(function(media, mediaId) {
+ dialogId += '-' + mediaId;
+ });
+
+ return dialogId;
+ },
+
+ /**
+ * Inserts media files into redactor.
+ *
+ * @param {Event?} event
+ */
+ _insertMedia: function(event) {
+ var insertType = 'separate';
+ var thumbnailSize;
+
+ // update insert options with selected values if method is called by clicking on 'insert' button
+ // in dialog
+ if (event) {
+ UiDialog.close(this._getInsertDialogId());
+
+ var dialogContent = event.currentTarget.closest('.dialogContent');
+
+ if (this._mediaToInsert.size > 1) {
+ insertType = elBySel('select[name=insertType]', dialogContent).value;
+ }
+ thumbnailSize = elBySel('select[name=thumbnailSize]', dialogContent).value;
+ }
+
+ // TODO: media to be inserted is located in dictionary this._mediaToInsert
+ // TODO: insertType = 'separate' or 'gallery' (last case only possible if multiple media files are inserted and all of them are images)
+ // TODO: thumbnailSize = 'small', 'media', 'large' or 'original'
+ // TODO: redactor is accessible by this._options.editor
+ throw new Error("TODO: implement me")
+
+ if (this._mediaToInsertByClipboard) {
+ // TODO: unmark in clipboard
+ }
+
+ this._mediaToInsert = new Dictionary();
+ this._mediaToInsertByClipboard = false;
+
+ // todo: close manager dialog?
},
+ /**
+ * Handles clicking on the insert button.
+ *
+ * @param {Event} event insert button click event
+ */
_openInsertDialog: function(event) {
- var media = this._mediaData.get(~~elData(event.currentTarget, 'object-id'));
+ this.insertMedia([~~elData(event.currentTarget, 'object-id')]);
+ },
+
+ /**
+ * Prepares insertion of the media files with the given ids.
+ *
+ * @param {array<int>} mediaIds ids of the media files to be inserted
+ * @param {boolean?} insertedByClipboard is true if the media files are inserted by clipboard
+ */
+ insertMedia: function(mediaIds, insertedByClipboard) {
+ this._mediaToInsert = new Dictionary();
+ this._mediaToInsertByClipboard = insertedByClipboard || false;
+
+ // open the insert dialog if all media files are images
+ var imagesOnly = true, media;
+ for (var i = 0, length = mediaIds.length; i < length; i++) {
+ media = this._mediaData.get(mediaIds[i]);
+ this._mediaToInsert.set(media.mediaID, media);
+
+ if (!media.isImage) {
+ imagesOnly = false;
+ }
+ }
- // check if media file is image and has at least small thumbnail
- // to show insertion options
- if (media.isImage && media.smallThumbnailType) {
+ if (imagesOnly) {
UiDialog.close(this);
- var dialogId = 'mediaInsert' + media.mediaID;
+ var dialogId = this._getInsertDialogId();
if (UiDialog.getDialog(dialogId)) {
UiDialog.openStatic(dialogId);
}
else {
- var dialog = elCreate('div');
-
- var fieldset = elCreate('fieldset');
- dialog.appendChild(fieldset);
-
- var dl = elCreate('dl');
- fieldset.appendChild(dl);
-
- var dt = elCreate('dt');
- dt.textContent = Language.get('wcf.media.insert.imageSize');
- dl.appendChild(dt);
-
- var dd = elCreate('dd');
- dl.appendChild(dd);
-
- var select = elCreate('select');
- dd.appendChild(select);
-
- var sizes = ['small', 'medium', 'large'];
- var size, option;
- for (var i = 0, length = sizes.length; i < length; i++) {
- size = sizes[i];
-
- if (media[size + 'ThumbnailType']) {
- option = elCreate('option');
- elAttr(option, 'value', size);
- option.textContent = Language.get('wcf.media.insert.imageSize.' + size, {
- height: media[size + 'ThumbnailHeight'],
- width: media[size + 'ThumbnailWidth']
- });
- select.appendChild(option);
- }
- }
-
- option = elCreate('option');
- elAttr(option, 'value', 'original');
- option.textContent = Language.get('wcf.media.insert.imageSize.original', {
- height: media.height,
- width: media.width
- });
- select.appendChild(option);
-
- var formSubmit = elCreate('div');
- formSubmit.className = 'formSubmit';
- dialog.appendChild(formSubmit);
-
- var submitButton = elCreate('button');
- submitButton.className = 'buttonPrimary';
- submitButton.textContent = Language.get('wcf.global.button.insert');
- elData(submitButton, 'object-id', media.mediaID);
- submitButton.addEventListener(WCF_CLICK_EVENT, this._insertMedia.bind(this));
- formSubmit.appendChild(submitButton);
-
- UiDialog.open({
- _dialogSetup: (function() {
- return {
- id: dialogId,
- options: {
- onClose: this._editorClose.bind(this),
- title: Language.get('wcf.media.insert')
- },
- source: dialog.outerHTML
- }
- }).bind(this)
- });
+ this._buildInsertDialog();
}
}
else {
- // insert media
- // TODO
+ this._insertMedia();
}
},
MediaManagerEditor._super.prototype.setupMediaElement.call(this, media, mediaElement);
// add media insertion icon
- var smallButtons = elBySel('> nav.buttonGroupNavigation > ul.smallButtons', mediaElement);
+ var smallButtons = elBySel('nav.buttonGroupNavigation > ul.smallButtons', mediaElement);
var listItem = elCreate('li');
smallButtons.appendChild(listItem);
if ($this->image === null) {
if ($this->imageID) {
$this->image = ViewableMedia::getMedia($this->imageID);
+
+ $this->image->setLinkParameters(['articleID' => $this->articleID]);
}
}
/**
* Sets the article's image.
*
- * @param ViewableMedia $image
+ * @param ViewableMedia $image
*/
public function setImage(ViewableMedia $image) {
$this->image = $image;
+ $this->image->setLinkParameters(['articleID' => $this->articleID]);
}
}
$this->image = ViewableMedia::getMedia($boxContent[0]['imageID']);
}
+ $this->image->setLinkParameters(['boxID' => $this->boxID]);
+
return $this->image;
}
use wcf\data\DatabaseObject;
use wcf\data\ILinkableObject;
use wcf\data\IThumbnailFile;
-use wcf\system\exception\SystemException;
use wcf\system\request\IRouteController;
use wcf\system\request\LinkHandler;
use wcf\system\WCF;
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package WoltLabSuite\Core\Data\Media
* @since 3.0
- *
+ *
* @property-read integer $mediaID
* @property-read string $filename
* @property-read integer $filesize
* i18n media data grouped by language id for all language
* @var string[][]
*/
- protected $i18nData = null;
+ protected $i18nData;
+
+ /**
+ * parameters used to build the link to the media file
+ * @var array
+ */
+ protected $linkParameters = [];
/**
* @inheritDoc
/**
* @inheritDoc
*/
- public function getLink() {
- return LinkHandler::getInstance()->getLink('Media', [
+ public function getLink($articleID = null, $boxID = null, $messageObjectType = null, $messageID = null) {
+ return LinkHandler::getInstance()->getLink('Media', array_merge($this->linkParameters, [
'forceFrontend' => true,
'object' => $this
- ]);
+ ]));
+ }
+
+ /**
+ * Sets additional parameters used to build the link to the media file.
+ *
+ * @param array $parameters
+ */
+ public function setLinkParameters(array $parameters) {
+ $this->linkParameters = $parameters;
}
/**
*/
public function getThumbnailLink($size) {
if (!isset(self::$thumbnailSizes[$size])) {
- throw new SystemException("Unknown thumbnail size '".$size."'");
+ throw new \InvalidArgumentException("Unknown thumbnail size '".$size."'");
}
if (!$this->{$size.'ThumbnailType'}) {
return $this->getLink();
}
- return LinkHandler::getInstance()->getLink('Media', [
+ return LinkHandler::getInstance()->getLink('Media', array_merge($this->linkParameters, [
'forceFrontend' => true,
'object' => $this,
'thumbnail' => $size
- ]);
+ ]));
}
/**
*
* @param string $size
* @return integer
- * @throws SystemException
+ * @throws \InvalidArgumentException
*/
public function getThumbnailWidth($size) {
if (!isset(self::$thumbnailSizes[$size])) {
- throw new SystemException("Unknown thumbnail size '".$size."'");
+ throw new \InvalidArgumentException("Unknown thumbnail size '".$size."'");
}
if ($this->{$size.'ThumbnailType'}) {
*
* @param string $size
* @return integer
- * @throws SystemException
+ * @throws \InvalidArgumentException
*/
public function getThumbnailHeight($size) {
if (!isset(self::$thumbnailSizes[$size])) {
- throw new SystemException("Unknown thumbnail size '".$size."'");
+ throw new \InvalidArgumentException("Unknown thumbnail size '".$size."'");
}
if ($this->{$size.'ThumbnailType'}) {
*/
public function getThumbnailLocation($size) {
if (!isset(self::$thumbnailSizes[$size])) {
- throw new SystemException("Unknown thumbnail size '".$size."'");
+ throw new \InvalidArgumentException("Unknown thumbnail size '".$size."'");
}
return self::getStorage().substr($this->fileHash, 0, 2).'/'.$this->mediaID.'-'.$size.'-'.$this->fileHash;
return '<img src="'.$this->getLink().'" alt="'.StringUtil::encodeHTML($this->altText).'" '.($this->title ? 'title="'.StringUtil::encodeHTML($this->title).'" ' : '').'/>';
}
- return '<a href="'.$this->getLink().'>'.$this->getTitle().'</a>';
+ return '<a href="'.$this->getLink().'">'.StringUtil::encodeHTML($this->getTitle()).'</a>';
}
/**
<?php
namespace wcf\page;
+use wcf\data\article\Article;
+use wcf\data\box\Box;
use wcf\data\media\Media;
+use wcf\data\IMessage;
+use wcf\system\box\BoxHandler;
+use wcf\system\event\EventHandler;
use wcf\system\exception\IllegalLinkException;
-use wcf\system\request\LinkHandler;
+use wcf\system\exception\PermissionDeniedException;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
+use wcf\system\WCF;
use wcf\util\FileReader;
use wcf\util\StringUtil;
* @since 3.0
*/
class MediaPage extends AbstractPage {
+ /**
+ * article which uses the media file as the main article image
+ * @var Article|null
+ */
+ public $article;
+
+ /**
+ * id of the article which uses the media file as the main article image
+ * @var integer
+ */
+ public $articleID = 0;
+
+ /**
+ * box which uses the media file as box image
+ * @var Box
+ */
+ public $box;
+
+ /**
+ * id of the box which uses the media file as box image
+ * @var integer
+ */
+ public $boxID = 0;
+
/**
* etag for the media file
* @var string
*/
- public $eTag = null;
+ public $eTag;
/**
* file reader object
* @var FileReader
*/
- public $fileReader = null;
+ public $fileReader;
/**
* requested media file
* @var Media
*/
- public $media = null;
+ public $media;
+
+ /**
+ * message in which the media is embedded
+ * @var IMessage
+ */
+ public $message;
+
+ /**
+ * id of the message in which the media is embedded
+ * @var integer
+ */
+ public $messageID = 0;
+
+ /**
+ * name of the object type of the message in which the media is embedded
+ * @var string
+ */
+ public $messageObjectType = '';
/**
* id of the requested media file
'image/pjpeg'
];
- // TODO: remove the following line once method is implemented
- // @codingStandardsIgnoreStart
/**
* @inheritDoc
*/
public function checkPermissions() {
parent::checkPermissions();
- // TODO
+ if (!WCF::getSession()->getPermission('admin.content.cms.canManageMedia')) {
+ if ($this->articleID) {
+ $this->article = new Article($this->articleID);
+
+ if (!$this->article->articleID || !$this->article->canRead()) {
+ throw new PermissionDeniedException();
+ }
+ }
+ else if ($this->boxID) {
+ $this->box = BoxHandler::getInstance()->getBox($this->boxID);
+
+ if ($this->box === null || !$this->box->isAccessible()) {
+ throw new PermissionDeniedException();
+ }
+ }
+ else if ($this->messageID) {
+ MessageEmbeddedObjectManager::getInstance()->loadObjects($this->messageObjectType, [$this->messageID]);
+ $this->message = MessageEmbeddedObjectManager::getInstance()->getObject($this->messageObjectType, $this->messageID);
+ if ($this->message === null || !($this->message instanceof IMessage) || !$this->message->isVisible()) {
+ throw new PermissionDeniedException();
+ }
+ }
+ else {
+ $parameters = ['canAccess' => false];
+
+ EventHandler::getInstance()->fireAction($this, 'checkMediaAccess', $parameters);
+
+ if (empty($parameters['canAccess'])) {
+ throw new PermissionDeniedException();
+ }
+ }
+ }
}
- // TODO: remove the following line once method is implemented
- // @codingStandardsIgnoreEnd
/**
* @inheritDoc
throw new IllegalLinkException();
}
- $parameters = [
- 'object' => $this->media
- ];
- if ($this->thumbnail && $this->media->{$this->thumbnail.'ThumbnailType'}) {
- $parameters['thumbnail'] = $this->thumbnail;
- }
- else {
+ if ($this->thumbnail && !$this->media->{$this->thumbnail.'ThumbnailType'}) {
$this->thumbnail = '';
}
- $this->canonicalURL = LinkHandler::getInstance()->getLink('Media', $parameters);
+ // read context parameters
+ if (isset($_REQUEST['articleID'])) {
+ $this->articleID = intval($_REQUEST['articleID']);
+ }
+ else if (isset($_REQUEST['boxID'])) {
+ $this->boxID = intval($_REQUEST['boxID']);
+ }
+ else if (isset($_REQUEST['messageObjectType']) && isset($_REQUEST['messageID'])) {
+ $this->messageObjectType = StringUtil::trim($_REQUEST['messageObjectType']);
+ $this->messageID = intval($_REQUEST['messageID']);
+ }
}
/**
*/
class BoxHandler extends SingletonFactory {
/**
- * boxes grouped by position
- * @var Box[][]
+ * boxes with box id as key
+ * @var Box[]
*/
protected $boxes = [];
*/
protected $boxesByIdentifier = [];
+ /**
+ * boxes grouped by position
+ * @var Box[][]
+ */
+ protected $boxesByPosition = [];
+
/**
* @inheritDoc
*/
else $boxList->getConditionBuilder()->add('box.visibleEverywhere = ?', [1]);
$boxList->sqlOrderBy = 'showOrder';
$boxList->readObjects();
+
+ $this->boxes = $boxList->getObjects();
foreach ($boxList as $box) {
if ($box->isAccessible()) {
- if (!isset($this->boxes[$box->position])) $this->boxes[$box->position] = [];
- $this->boxes[$box->position][] = $box;
+ if (!isset($this->boxesByPosition[$box->position])) $this->boxesByPosition[$box->position] = [];
+ $this->boxesByPosition[$box->position][] = $box;
+
$this->boxesByIdentifier[$box->identifier] = $box;
- }
+ }
}
}
]))->executeAction();
}
+ /**
+ * Returns the box with the given id or null.
+ *
+ * @param integer $boxID
+ * @return Box|null
+ */
+ public function getBox($boxID) {
+ if (isset($this->boxes[$boxID])) {
+ return $this->boxes[$boxID];
+ }
+
+ return null;
+ }
+
/**
* Returns boxes for the given position.
*
* @return Box[]
*/
public function getBoxes($position) {
- if (isset($this->boxes[$position])) {
- return $this->boxes[$position];
+ if (isset($this->boxesByPosition[$position])) {
+ return $this->boxesByPosition[$position];
}
return [];
<item name="wcf.media.imageDimensions.value"><![CDATA[{#$width}×{#$height}]]></item>
<item name="wcf.media.insert"><![CDATA[Insert File]]></item>
<item name="wcf.media.insert.imageSize"><![CDATA[Image Size]]></item>
- <item name="wcf.media.insert.imageSize.large"><![CDATA[Large Thumbnail ({#$width}×{#$height})]]></item>
- <item name="wcf.media.insert.imageSize.medium"><![CDATA[Medium Thumbnail ({#$width}×{#$height})]]></item>
- <item name="wcf.media.insert.imageSize.original"><![CDATA[Original Image ({#$width}×{#$height})]]></item>
- <item name="wcf.media.insert.imageSize.small"><![CDATA[Small Thumbnail ({#$width}×{#$height})]]></item>
+ <item name="wcf.media.insert.imageSize.large"><![CDATA[Large Thumbnail]]></item>
+ <item name="wcf.media.insert.imageSize.medium"><![CDATA[Medium Thumbnail]]></item>
+ <item name="wcf.media.insert.imageSize.original"><![CDATA[Original Image]]></item>
+ <item name="wcf.media.insert.imageSize.small"><![CDATA[Small Thumbnail]]></item>
<item name="wcf.media.isMultilingual"><![CDATA[Enable Multilingualism]]></item>
<item name="wcf.media.languageID"><![CDATA[Language]]></item>
<item name="wcf.media.manager"><![CDATA[Manage Media]]></item>