Update media implementation
authorMatthias Schmidt <gravatronics@live.com>
Wed, 29 Jun 2016 16:55:14 +0000 (18:55 +0200)
committerMatthias Schmidt <gravatronics@live.com>
Wed, 29 Jun 2016 16:55:17 +0000 (18:55 +0200)
wcfsetup/install/files/js/3rdParty/redactor2/plugins/WoltLabMedia.js
wcfsetup/install/files/js/WoltLab/WCF/Media/Manager/Base.js
wcfsetup/install/files/js/WoltLab/WCF/Media/Manager/Editor.js
wcfsetup/install/files/lib/data/article/content/ViewableArticleContent.class.php
wcfsetup/install/files/lib/data/box/Box.class.php
wcfsetup/install/files/lib/data/media/Media.class.php
wcfsetup/install/files/lib/data/media/ViewableMedia.class.php
wcfsetup/install/files/lib/page/MediaPage.class.php
wcfsetup/install/files/lib/system/box/BoxHandler.class.php
wcfsetup/install/lang/en.xml

index be1e56f92daabf926677372e9352165196e34794..7a359f064c4291763cb47122153c324a2163a539 100644 (file)
@@ -7,8 +7,10 @@ $.Redactor.prototype.WoltLabMedia = function() {
                        $(button).addClass('jsMediaEditorButton');
                        
                        require(['WoltLab/WCF/Media/Manager/Editor'], function(MediaManagerEditor) {
-                               new MediaManagerEditor();
-                       });
+                               new MediaManagerEditor({
+                                       editor: this
+                               });
+                       }.bind(this));
                },
        };
 };
index c1c122ba224fb6f4f7ce0c40de33ae262713f7a6..77a3dc18732ca725b90ff6d4b41fd68e870f1764 100644 (file)
@@ -82,19 +82,13 @@ define(
                 */
                _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();
                        }
                },
                
index 16de1dac628b8d56c01427db2d44f938fee610fd..a35467d28d647f887284b847ac37debbd2a8a6de 100644 (file)
@@ -1,12 +1,12 @@
 /**
- * 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";
        
        /**
@@ -20,8 +20,8 @@ define(['Core', 'Dom/Traverse', 'Language', 'Ui/Dialog', 'WoltLab/WCF/Media/Mana
                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, {
                /**
@@ -44,6 +44,68 @@ define(['Core', 'Dom/Traverse', 'Language', 'Ui/Dialog', 'WoltLab/WCF/Media/Mana
                        }
                },
                
+               /**
+                * 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
                 */
@@ -53,92 +115,112 @@ define(['Core', 'Dom/Traverse', 'Language', 'Ui/Dialog', 'WoltLab/WCF/Media/Mana
                        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();
                        }
                },
                
@@ -156,7 +238,7 @@ define(['Core', 'Dom/Traverse', 'Language', 'Ui/Dialog', 'WoltLab/WCF/Media/Mana
                        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);
index 0bb734358b600e45e0dd1becf8396912dc147ce7..78da2ee575f7b02eb94823947c1decdfd76063df 100644 (file)
@@ -80,6 +80,8 @@ class ViewableArticleContent extends DatabaseObjectDecorator {
                if ($this->image === null) {
                        if ($this->imageID) {
                                $this->image = ViewableMedia::getMedia($this->imageID);
+                               
+                               $this->image->setLinkParameters(['articleID' => $this->articleID]);
                        }
                }
                
@@ -89,9 +91,10 @@ class ViewableArticleContent extends DatabaseObjectDecorator {
        /**
         * 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]);
        }
 }
index ba8d6d05f877ebf52c4b1f1ed250066c15b0cb75..ce4c1e508947ff900817295f2f135498f7cf5010 100644 (file)
@@ -341,6 +341,8 @@ class Box extends DatabaseObject {
                        $this->image = ViewableMedia::getMedia($boxContent[0]['imageID']);
                }
                
+               $this->image->setLinkParameters(['boxID' => $this->boxID]);
+               
                return $this->image;
        }
        
index 0e6e933b2f1b4b1e021ac4e72abcc2fd1bf451e0..dd10d0d1edb7766fd51d0308d5afc6a5322499b9 100644 (file)
@@ -3,7 +3,6 @@ namespace wcf\data\media;
 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;
@@ -16,7 +15,7 @@ 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
@@ -52,7 +51,13 @@ class Media extends DatabaseObject implements ILinkableObject, IRouteController,
         * 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
@@ -94,11 +99,20 @@ class Media extends DatabaseObject implements ILinkableObject, IRouteController,
        /**
         * @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;
        }
        
        /**
@@ -113,18 +127,18 @@ class Media extends DatabaseObject implements ILinkableObject, IRouteController,
         */
        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
-               ]);
+               ]));
        }
        
        /**
@@ -132,11 +146,11 @@ class Media extends DatabaseObject implements ILinkableObject, IRouteController,
         *
         * @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'}) {
@@ -151,11 +165,11 @@ class Media extends DatabaseObject implements ILinkableObject, IRouteController,
         *
         * @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'}) {
@@ -170,7 +184,7 @@ class Media extends DatabaseObject implements ILinkableObject, IRouteController,
         */
        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;
index af180a81322b30f8034f17c78592d650c491a50f..50bfb194adad86c7c47546f86d0a312691f4807c 100644 (file)
@@ -36,7 +36,7 @@ class ViewableMedia extends DatabaseObjectDecorator {
                        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>';
        }
        
        /**
index 824581344eeaffc534d1b35056af73eba69de12b..514573882cb1eb2d2e4612aabc5510f547fb304e 100644 (file)
@@ -1,8 +1,15 @@
 <?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;
 
@@ -16,23 +23,65 @@ 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
@@ -64,18 +113,45 @@ class MediaPage extends AbstractPage {
                '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
@@ -131,17 +207,21 @@ class MediaPage extends AbstractPage {
                        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']);
+               }
        }
        
        /**
index 71d03185f77b7519051c2c035201878633527155..d198196fff0d20c6d8c78fafd769b67e9c6732ad 100644 (file)
@@ -19,8 +19,8 @@ use wcf\system\WCF;
  */
 class BoxHandler extends SingletonFactory {
        /**
-        * boxes grouped by position
-        * @var Box[][]
+        * boxes with box id as key
+        * @var Box[]
         */
        protected $boxes = [];
        
@@ -30,6 +30,12 @@ class BoxHandler extends SingletonFactory {
         */
        protected $boxesByIdentifier = [];
        
+       /**
+        * boxes grouped by position
+        * @var Box[][]
+        */
+       protected $boxesByPosition = [];
+       
        /**
         * @inheritDoc
         */
@@ -46,12 +52,15 @@ class BoxHandler extends SingletonFactory {
                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;
-                       }       
+                       }
                }
        }
        
@@ -96,6 +105,20 @@ class BoxHandler extends SingletonFactory {
                ]))->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.
         * 
@@ -103,8 +126,8 @@ class BoxHandler extends SingletonFactory {
         * @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 [];
index 979d3f49ed3ffeefe1a87ceedb3ff681fc279ac8..9cbf443c7c88345800a1c0f848e6d15cea50758a 100644 (file)
@@ -2459,10 +2459,10 @@ Errors are:
                <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>