Add media clipboard action to set category
authorMatthias Schmidt <gravatronics@live.com>
Sun, 5 Aug 2018 13:58:07 +0000 (15:58 +0200)
committerMatthias Schmidt <gravatronics@live.com>
Sun, 5 Aug 2018 13:58:07 +0000 (15:58 +0200)
Close #2658

14 files changed:
com.woltlab.wcf/clipboardAction.xml
com.woltlab.wcf/templates/__mediaSetCategoryDialog.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/mediaJavaScript.tpl
wcfsetup/install/files/acp/templates/__mediaSetCategoryDialog.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/mediaJavaScript.tpl
wcfsetup/install/files/acp/templates/mediaList.tpl
wcfsetup/install/files/js/WoltLabSuite/Core/Controller/Media/List.js
wcfsetup/install/files/js/WoltLabSuite/Core/Media/Clipboard.js [new file with mode: 0644]
wcfsetup/install/files/js/WoltLabSuite/Core/Media/Manager/Base.js
wcfsetup/install/files/js/WoltLabSuite/Core/Media/Manager/Editor.js
wcfsetup/install/files/lib/data/media/MediaAction.class.php
wcfsetup/install/files/lib/system/clipboard/action/MediaClipboardAction.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index a4b084e707687a05fa66d38dc4ba8b8ee3af7cb9..d62400fd38af76121f513fbc212f3efc5253c0e5 100644 (file)
                                <page>menuManagerDialog-select</page>
                        </pages>
                </action>
+               <action name="setCategory">
+                       <actionclassname>wcf\system\clipboard\action\MediaClipboardAction</actionclassname>
+                       <showorder>3</showorder>
+                       <pages>
+                               <page>wcf\acp\page\MediaListPage</page>
+                               <page>menuManagerDialog-editor</page>
+                               <page>menuManagerDialog-select</page>
+                       </pages>
+               </action>
                <!-- /com.woltlab.wcf.media -->
                
                <!-- com.woltlab.wcf.article -->
diff --git a/com.woltlab.wcf/templates/__mediaSetCategoryDialog.tpl b/com.woltlab.wcf/templates/__mediaSetCategoryDialog.tpl
new file mode 100644 (file)
index 0000000..9e0c334
--- /dev/null
@@ -0,0 +1,28 @@
+<div class="section">
+       <dl>
+               <dt><label for="postCopyNewThreadTopic">{lang}wcf.media.category.choose{/lang}</label></dt>
+               <select name="categoryID">
+                       <option value="0">{lang}wcf.global.noSelection{/lang}</option>
+                       
+                       {foreach from=$categoryList item=categoryItem}
+                               <option value="{$categoryItem->categoryID}">{$categoryItem->getTitle()}</option>
+                               
+                               {if $categoryItem->hasChildren()}
+                                       {foreach from=$categoryItem item=subCategoryItem}
+                                               <option value="{$subCategoryItem->categoryID}">&nbsp;&nbsp;&nbsp;&nbsp;{$subCategoryItem->getTitle()}</option>
+                                               
+                                               {if $subCategoryItem->hasChildren()}
+                                                       {foreach from=$subCategoryItem item=subSubCategoryItem}
+                                                               <option value="{$subSubCategoryItem->categoryID}">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{$subSubCategoryItem->getTitle()}</option>
+                                                       {/foreach}
+                                               {/if}
+                                       {/foreach}
+                               {/if}
+                       {/foreach}
+               </select>
+       </dl>
+</div>
+
+<div class="formSubmit">
+       <button data-type="submit" class="buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
+</div>
index 082d395fdaf21101d9fb6c02d097b4d8c308c4cf..b8c5d5fed709a7c058bcf4f20459512b3b25a3b2 100644 (file)
@@ -17,7 +17,8 @@
                        'wcf.media.search.noResults': '{lang}wcf.media.search.noResults{/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}'
+                       'wcf.media.upload.success': '{lang}wcf.media.upload.success{/lang}',
+                       'wcf.media.setCategory': '{lang}wcf.media.setCategory{/lang}'
                });
                
                Permission.add('admin.content.cms.canManageMedia', {if $__wcf->session->getPermission('admin.content.cms.canManageMedia')}true{else}false{/if});
diff --git a/wcfsetup/install/files/acp/templates/__mediaSetCategoryDialog.tpl b/wcfsetup/install/files/acp/templates/__mediaSetCategoryDialog.tpl
new file mode 100644 (file)
index 0000000..9e0c334
--- /dev/null
@@ -0,0 +1,28 @@
+<div class="section">
+       <dl>
+               <dt><label for="postCopyNewThreadTopic">{lang}wcf.media.category.choose{/lang}</label></dt>
+               <select name="categoryID">
+                       <option value="0">{lang}wcf.global.noSelection{/lang}</option>
+                       
+                       {foreach from=$categoryList item=categoryItem}
+                               <option value="{$categoryItem->categoryID}">{$categoryItem->getTitle()}</option>
+                               
+                               {if $categoryItem->hasChildren()}
+                                       {foreach from=$categoryItem item=subCategoryItem}
+                                               <option value="{$subCategoryItem->categoryID}">&nbsp;&nbsp;&nbsp;&nbsp;{$subCategoryItem->getTitle()}</option>
+                                               
+                                               {if $subCategoryItem->hasChildren()}
+                                                       {foreach from=$subCategoryItem item=subSubCategoryItem}
+                                                               <option value="{$subSubCategoryItem->categoryID}">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{$subSubCategoryItem->getTitle()}</option>
+                                                       {/foreach}
+                                               {/if}
+                                       {/foreach}
+                               {/if}
+                       {/foreach}
+               </select>
+       </dl>
+</div>
+
+<div class="formSubmit">
+       <button data-type="submit" class="buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
+</div>
index 77911300c2cf546313140e55b3d8ed4d6c86af2b..bfa7c9750b9afc31aa4cc8e01340a4273076c564 100644 (file)
@@ -17,7 +17,8 @@
                        'wcf.media.search.noResults': '{lang}wcf.media.search.noResults{/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}'
+                       'wcf.media.upload.success': '{lang}wcf.media.upload.success{/lang}',
+                       'wcf.media.setCategory': '{lang}wcf.media.setCategory{/lang}'
                });
                
                Permission.add('admin.content.cms.canManageMedia', {if $__wcf->session->getPermission('admin.content.cms.canManageMedia')}true{else}false{/if});
index 62aea3cbdf8ca05a7a0c8bed2240a5c54481e418..2569f6beb6599b227fd997af3621de4038df650e 100644 (file)
@@ -4,7 +4,11 @@
        {include file='mediaJavaScript'}
        
        require(['Language', 'WoltLabSuite/Core/Controller/Media/List'], function (Language, ControllerMediaList) {
-               Language.add('wcf.media.delete.confirmMessage', '{lang __literal=true}wcf.media.delete.confirmMessage{/lang}')
+               Language.addObject({
+                       'wcf.media.delete.confirmMessage': '{lang __literal=true}wcf.media.delete.confirmMessage{/lang}',
+                       'wcf.media.setCategory': '{lang}wcf.media.setCategory{/lang}'
+               });
+               
                ControllerMediaList.init({
                        {if $categoryID}
                                categoryId: {@$categoryID},
index 2da40a9aa4f32e66908821cb1278c9f78309a631..d5cc2cb1a7a4c5ce7bbd12772edd557f3d3b28ca 100644 (file)
@@ -10,6 +10,7 @@ define([
                'Dom/ChangeListener',
                'EventHandler',
                'WoltLabSuite/Core/Controller/Clipboard',
+               'WoltLabSuite/Core/Media/Clipboard',
                'WoltLabSuite/Core/Media/Editor',
                'WoltLabSuite/Core/Media/List/Upload'
        ],
@@ -17,6 +18,7 @@ define([
                DomChangeListener,
                EventHandler,
                Clipboard,
+               MediaClipboard,
                MediaEditor,
                MediaListUpload
        ) {
@@ -26,7 +28,9 @@ define([
                var Fake = function() {};
                Fake.prototype = {
                        init: function() {},
-                       _clipboardAction: function() {},
+                       _addButtonEventListeners: function() {},
+                       _deleteCallback: function() {},
+                       _deleteMedia: function(mediaIds) {},
                        _edit: function() {}
                };
                return Fake;
@@ -34,6 +38,7 @@ define([
        
        var _mediaEditor;
        var _tableBody = elById('mediaListTableBody');
+       var _clipboardObjectIds = [];
        
        /**
         * @exports     WoltLabSuite/Core/Controller/Media/List
@@ -46,12 +51,12 @@ define([
                                multiple: true
                        });
                        
-                       Clipboard.setup({
-                               hasMarkedItems: options.hasMarkedItems || false,
-                               pageClassName: 'wcf\\acp\\page\\MediaListPage'
-                       });
+                       MediaClipboard.init(
+                               'wcf\\acp\\page\\MediaListPage',
+                               options.hasMarkedItems || false,
+                               this
+                       );
                        
-                       EventHandler.add('com.woltlab.wcf.clipboard', 'com.woltlab.wcf.media', this._clipboardAction.bind(this));
                        EventHandler.add('com.woltlab.wcf.media.upload', 'removedErroneousUploadRow', this._deleteCallback.bind(this));
                        
                        var deleteAction = new WCF.Action.Delete('wcf\\data\\media\\MediaAction', '.jsMediaRow');
@@ -107,43 +112,34 @@ define([
                },
                
                /**
-                * Handles successful clipboard actions.
+                * Is called when a media edit icon is clicked.
                 * 
-                * @param       {object}        actionData
+                * @param       {Event}         event
                 */
-               _clipboardAction: function(actionData) {
-                       // only consider events if the action has been executed
-                       if (actionData.responseData === null) {
-                               return;
-                       }
-                       
-                       if (actionData.data.actionName === 'com.woltlab.wcf.media.delete') {
-                               var mediaIds = actionData.responseData.objectIDs;
-                               
-                               var mediaRows = elByClass('jsMediaRow');
-                               for (var i = 0; i < mediaRows.length; i++) {
-                                       var media = mediaRows[i];
-                                       var mediaID = ~~elData(elByClass('jsClipboardItem', media)[0], 'object-id');
-                                       
-                                       if (mediaIds.indexOf(mediaID) !== -1) {
-                                               elRemove(media);
-                                               i--;
-                                       }
-                               }
-                               
-                               if (!mediaRows.length) {
-                                       window.location.reload();
-                               }
-                       }
+               _edit: function(event) {
+                       _mediaEditor.edit(elData(event.currentTarget, 'object-id'));
                },
                
                /**
-                * Is called when a media edit icon is clicked.
+                * Is called after the media files with the given ids have been deleted via clipboard.
                 * 
-                * @param       {Event}         event
+                * @param       {int[]}         mediaIds        ids of deleted media files
                 */
-               _edit: function(event) {
-                       _mediaEditor.edit(elData(event.currentTarget, 'object-id'));
+               clipboardDeleteMedia: function(mediaIds) {
+                       var mediaRows = elByClass('jsMediaRow');
+                       for (var i = 0; i < mediaRows.length; i++) {
+                               var media = mediaRows[i];
+                               var mediaID = ~~elData(elByClass('jsClipboardItem', media)[0], 'object-id');
+                               
+                               if (mediaIds.indexOf(mediaID) !== -1) {
+                                       elRemove(media);
+                                       i--;
+                               }
+                       }
+                       
+                       if (!mediaRows.length) {
+                               window.location.reload();
+                       }
                }
        }
 });
\ No newline at end of file
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Media/Clipboard.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Media/Clipboard.js
new file mode 100644 (file)
index 0000000..7bb6045
--- /dev/null
@@ -0,0 +1,173 @@
+/**
+ * Initializes modules required for media clipboard.
+ * 
+ * @author     Matthias Schmidt
+ * @copyright  2001-2018 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module     WoltLabSuite/Core/Media/Clipboard
+ */
+define([
+               'Ajax',
+               'Dom/ChangeListener',
+               'EventHandler',
+               'Language',
+               'Ui/Dialog',
+               'Ui/Notification',
+               'WoltLabSuite/Core/Controller/Clipboard',
+               'WoltLabSuite/Core/Media/Editor',
+               'WoltLabSuite/Core/Media/List/Upload'
+       ],
+       function(
+               Ajax,
+               DomChangeListener,
+               EventHandler,
+               Language,
+               UiDialog,
+               UiNotification,
+               Clipboard,
+               MediaEditor,
+               MediaListUpload
+       ) {
+       "use strict";
+       
+       if (!COMPILER_TARGET_DEFAULT) {
+               var Fake = function() {};
+               Fake.prototype = {
+                       init: function() {},
+                       _ajaxSetup: function() {},
+                       _ajaxSuccess: function() {},
+                       _clipboardAction: function() {},
+                       _dialogSetup: function() {},
+                       _edit: function() {},
+                       _setCategory: function() {}
+               };
+               return Fake;
+       }
+       
+       var _clipboardObjectIds = [];
+       var _mediaManager;
+       
+       /**
+        * @exports     WoltLabSuite/Core/Media/Clipboard
+        */
+       return {
+               init: function(pageClassName, hasMarkedItems, mediaManager) {
+                       Clipboard.setup({
+                               hasMarkedItems: hasMarkedItems,
+                               pageClassName: pageClassName
+                       });
+                       
+                       _mediaManager = mediaManager;
+                       
+                       EventHandler.add('com.woltlab.wcf.clipboard', 'com.woltlab.wcf.media', this._clipboardAction.bind(this));
+               },
+               
+               /**
+                * Returns the data used to setup the AJAX request object.
+                *
+                * @return      {object}        setup data
+                */
+               _ajaxSetup: function() {
+                       return {
+                               data: {
+                                       className: 'wcf\\data\\media\\MediaAction'
+                               }
+                       }
+               },
+               
+               /**
+                * Handles successful AJAX request.
+                *
+                * @param       {object}        data    response data
+                */
+               _ajaxSuccess: function(data) {
+                       switch (data.actionName) {
+                               case 'getSetCategoryDialog':
+                                       UiDialog.open(this, data.returnValues.template);
+                                       
+                                       break;
+                                       
+                               case 'setCategory':
+                                       UiDialog.close(this);
+                                       
+                                       UiNotification.show();
+                                       
+                                       Clipboard.reload();
+                                       
+                                       break;
+                       }
+               },
+               
+               /**
+                * Returns the data used to setup the dialog.
+                * 
+                * @return      {object}        setup data
+                */
+               _dialogSetup: function() {
+                       return {
+                               id: 'mediaSetCategoryDialog',
+                               options: {
+                                       onSetup: function(content) {
+                                               elBySel('button', content).addEventListener(WCF_CLICK_EVENT, function(event) {
+                                                       event.preventDefault();
+                                                       
+                                                       this._setCategory(~~elBySel('select[name="categoryID"]', content).value);
+                                                       
+                                                       event.currentTarget.disabled = true;
+                                               }.bind(this));
+                                       }.bind(this),
+                                       title: Language.get('wcf.media.setCategory')
+                               },
+                               source: null
+                       }
+               },
+               
+               /**
+                * Handles successful clipboard actions.
+                * 
+                * @param       {object}        actionData
+                */
+               _clipboardAction: function(actionData) {
+                       var mediaIds = actionData.data.parameters.objectIDs;
+                       
+                       switch (actionData.data.actionName) {
+                               case 'com.woltlab.wcf.media.delete':
+                                       // only consider events if the action has been executed
+                                       if (actionData.responseData !== null) {
+                                               _mediaManager.clipboardDeleteMedia(mediaIds);
+                                       }
+                                       
+                                       break;
+                                       
+                               case 'com.woltlab.wcf.media.insert':
+                                       _mediaManager.clipboardInsertMedia(mediaIds);
+                                       
+                                       break;
+                                       
+                               case 'com.woltlab.wcf.media.setCategory':
+                                       _clipboardObjectIds = mediaIds;
+                                       
+                                       Ajax.api(this, {
+                                               actionName: 'getSetCategoryDialog'
+                                       });
+                                       
+                                       break;
+                       }
+               },
+               
+               /**
+                * Sets the category of the marked media files.
+                * 
+                * @param       {int}           categoryID      selected category id
+                */
+               _setCategory: function(categoryID) {
+                       Ajax.api(this, {
+                               actionName: 'setCategory',
+                               objectIDs: _clipboardObjectIds,
+                               parameters: {
+                                       categoryID: categoryID
+                               }
+                       });
+               }
+       }
+});
\ No newline at end of file
index 76672ed8a8590ef3f2ff3fdc028f004d5e356a12..f7f05fa88d48cfcd3a97a8ee617379b7feda67f3 100644 (file)
@@ -12,14 +12,16 @@ define(
                'Dom/Util',                 'EventHandler',             'Language',                        'List',
                'Permission',               'Ui/Dialog',                'Ui/Notification',                 'WoltLabSuite/Core/Controller/Clipboard',
                'WoltLabSuite/Core/Media/Editor', 'WoltLabSuite/Core/Media/Upload', 'WoltLabSuite/Core/Media/Manager/Search', 'StringUtil',
-               'WoltLabSuite/Core/Ui/Pagination'
+               'WoltLabSuite/Core/Ui/Pagination',
+               'WoltLabSuite/Core/Media/Clipboard'
        ],
        function(
                Core,                        Dictionary,                 DomChangeListener,                 DomTraverse,
                DomUtil,                     EventHandler,               Language,                          List,
                Permission,                  UiDialog,                   UiNotification,                    Clipboard,
                MediaEditor,                 MediaUpload,                MediaManagerSearch,                StringUtil,
-               UiPagination
+               UiPagination,
+               MediaClipboard
        )
 {
        "use strict";
@@ -29,7 +31,6 @@ define(
                Fake.prototype = {
                        _addButtonEventListeners: function() {},
                        _click: function() {},
-                       _clipboardAction: function() {},
                        _dialogClose: function() {},
                        _dialogInit: function() {},
                        _dialogSetup: function() {},
@@ -40,6 +41,7 @@ define(
                        _removeClipboardCheckboxes: function() {},
                        _setMedia: function() {},
                        addMedia: function() {},
+                       clipboardDeleteMedia: function() {},
                        getDialog: function() {},
                        getMode: function() {},
                        getOption: function() {},
@@ -118,23 +120,6 @@ define(
                        UiDialog.open(this);
                },
                
-               /**
-                * Reacts to executed clipboard actions.
-                * 
-                * @param       {object<string, *>}     actionData      data of the executed clipboard action
-                */
-               _clipboardAction: function(actionData) {
-                       // only consider events if the action has been executed
-                       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();
-                       }
-               },
-               
                /**
                 * Is called if the media manager dialog is closed.
                 */
@@ -227,12 +212,11 @@ define(
                                }
                                
                                if (Permission.get('admin.content.cms.canManageMedia') || this._forceClipboard) {
-                                       EventHandler.add('com.woltlab.wcf.clipboard', 'com.woltlab.wcf.media', this._clipboardAction.bind(this));
-                                       
-                                       Clipboard.setup({
-                                               hasMarkedItems: this._hadInitiallyMarkedItems ? true : false,
-                                               pageClassName: 'menuManagerDialog-' + this.getMode()
-                                       });
+                                       MediaClipboard.init(
+                                               'menuManagerDialog-' + this.getMode(),
+                                               this._hadInitiallyMarkedItems ? true : false,
+                                               this
+                                       );
                                }
                                else {
                                        this._removeClipboardCheckboxes();
@@ -414,6 +398,19 @@ define(
                        }
                },
                
+               /**
+                * Is called after the media files with the given ids have been deleted via clipboard.
+                * 
+                * @param       {int[]}         mediaIds        ids of deleted media files
+                */
+               clipboardDeleteMedia: function(mediaIds) {
+                       for (var i = 0, length = mediaIds.length; i < length; i++) {
+                               this.removeMedia(~~mediaIds[i], true);
+                       }
+                       
+                       UiNotification.show();
+               },
+               
                /**
                 * Returns the id of the currently selected category or `0` if no category is selected.
                 * 
index 20220bd121c03ab490c63666aa4bb869a0d51bc3..9f0268de65ab4836ee241427187208267315f50e 100644 (file)
@@ -16,7 +16,6 @@ define(['Core', 'Dictionary', 'Dom/Traverse', 'EventHandler', 'Language', 'Permi
                                _addButtonEventListeners: function() {},
                                _buildInsertDialog: function() {},
                                _click: function() {},
-                               _clipboardAction: function() {},
                                _getInsertDialogId: function() {},
                                _getThumbnailSizes: function() {},
                                _insertMedia: function() {},
@@ -36,6 +35,7 @@ define(['Core', 'Dictionary', 'Dom/Traverse', 'EventHandler', 'Language', 'Permi
                                _removeClipboardCheckboxes: function() {},
                                _setMedia: function() {},
                                addMedia: function() {},
+                               clipboardInsertMedia: function() {},
                                getDialog: function() {},
                                getOption: function() {},
                                removeMedia: function() {},
@@ -179,17 +179,6 @@ define(['Core', 'Dictionary', 'Dom/Traverse', 'EventHandler', 'Language', 'Permi
                        MediaManagerEditor._super.prototype._click.call(this, event);
                },
                
-               /**
-                * @see WoltLabSuite/Core/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);
-                       }
-               },
-               
                /**
                 * @see WoltLabSuite/Core/Media/Manager/Base#_dialogShow
                 */
@@ -401,6 +390,15 @@ define(['Core', 'Dictionary', 'Dom/Traverse', 'EventHandler', 'Language', 'Permi
                        this.insertMedia([~~elData(event.currentTarget, 'object-id')]);
                },
                
+               /**
+                * Is called to insert the media files with the given ids into an editor.
+                * 
+                * @param       {int[]}         mediaIds
+                */
+               clipboardInsertMedia: function(mediaIds) {
+                       this.insertMedia(mediaIds, true);
+               },
+               
                /**
                 * Prepares insertion of the media files with the given ids.
                 * 
index 9976e129165fcf08cb3c7ec243f037a8be546296..be6f37ad44cc95309127b10163dbc1f175146a93 100644 (file)
@@ -8,6 +8,7 @@ use wcf\system\acl\simple\SimpleAclHandler;
 use wcf\system\category\CategoryHandler;
 use wcf\system\clipboard\ClipboardHandler;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\IllegalLinkException;
 use wcf\system\exception\PermissionDeniedException;
 use wcf\system\exception\UserInputException;
 use wcf\system\language\I18nHandler;
@@ -567,4 +568,74 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
                        ClipboardHandler::getInstance()->unmark($mediaIDs, ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.media'));
                }
        }
+       
+       /**
+        * Validates the `getSetCategoryDialog` action.
+        * 
+        * @throws      PermissionDeniedException       if user is not allowed to set category of media files
+        * @throws      IllegalLinkException            if no media file categories exist
+        */
+       public function validateGetSetCategoryDialog() {
+               if (!WCF::getSession()->getPermission('admin.content.cms.canManageMedia')) {
+                       throw new PermissionDeniedException();
+               }
+               
+               if (empty(CategoryHandler::getInstance()->getCategories('com.woltlab.wcf.media.category'))) {
+                       throw new IllegalLinkException();
+               }
+       }
+       
+       /**
+        * Returns the dialog to set the category of multiple media files.
+        * 
+        * @return      string[]
+        */
+       public function getSetCategoryDialog() {
+               $categoryList = (new CategoryNodeTree('com.woltlab.wcf.media.category'))->getIterator();
+               $categoryList->setMaxDepth(0);
+               
+               return [
+                       'template' => WCF::getTPL()->fetch('__mediaSetCategoryDialog', 'wcf', [
+                               'categoryList' => $categoryList
+                       ])
+               ];
+       }
+       
+       /**
+        * Validates the `setCategory` action.
+        * 
+        * @throws      UserInputException      if no object ids are given
+        */
+       public function validateSetCategory() {
+               $this->validateGetSetCategoryDialog();
+               
+               if (empty($this->objects)) {
+                       $this->readObjects();
+                       
+                       if (empty($this->objects)) {
+                               throw new UserInputException('objectIDs');
+                       }
+               }
+               
+               $this->readInteger('categoryID', true);
+       }
+       
+       /**
+        * Sets the category of multiple media files.
+        */
+       public function setCategory() {
+               $conditionBuilder = new PreparedStatementConditionBuilder();
+               $conditionBuilder->add('mediaID IN (?)', [$this->objectIDs]);
+               
+               $sql = "UPDATE  wcf" . WCF_N . "_media
+                       SET     categoryID = ?
+                       " . $conditionBuilder;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array_merge(
+                       [$this->parameters['categoryID'] ?: null],
+                       $conditionBuilder->getParameters()
+               ));
+               
+               $this->unmarkItems();
+       }
 }
index 66312c8c8a0497174afd9100298561000782fc4f..b3d079c53be674a79a85eae9f20aabc0ebba3817 100644 (file)
@@ -2,6 +2,7 @@
 namespace wcf\system\clipboard\action;
 use wcf\data\clipboard\action\ClipboardAction;
 use wcf\data\media\MediaAction;
+use wcf\system\category\CategoryHandler;
 use wcf\system\WCF;
 
 /**
@@ -24,7 +25,8 @@ class MediaClipboardAction extends AbstractClipboardAction {
         */
        protected $supportedActions = [
                'delete',
-               'insert'
+               'insert',
+               'setCategory'
        ];
        
        /**
@@ -84,4 +86,22 @@ class MediaClipboardAction extends AbstractClipboardAction {
        public function validateInsert() {
                return array_keys($this->objects);
        }
+       
+       /**
+        * Returns the ids of the media files whose category can be set.
+        * 
+        * @return      integer[]
+        */
+       public function validateSetCategory() {
+               if (!WCF::getSession()->getPermission('admin.content.cms.canManageMedia')) {
+                       return [];
+               }
+               
+               // category can only be set if any category exists
+               if (empty(CategoryHandler::getInstance()->getCategories('com.woltlab.wcf.media.category'))) {
+                       return [];
+               }
+               
+               return array_keys($this->objects);
+       }
 }
index c6b4f07ea658cd63babe10c78462dee97e006b52..e8587e4ee02c37bdba54962ba6ef8b305b9332ee 100644 (file)
@@ -2508,7 +2508,8 @@ Fehler sind beispielsweise:
                <item name="wcf.clipboard.item.com.woltlab.wcf.media.delete"><![CDATA[Löschen ({#$count})]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.media.delete.confirmMessage"><![CDATA[{if $count == 1}Eine Datei{else}{#$count} Dateien{/if} löschen?]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.media.insert"><![CDATA[Einfügen ({#$count})]]></item>
-               
+               <item name="wcf.clipboard.item.com.woltlab.wcf.media.setCategory"><![CDATA[Kategorie bearbeiten ({#$count})]]></item>
+
                <item name="wcf.clipboard.item.com.woltlab.wcf.tag.delete"><![CDATA[Löschen ({#$count})]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.tag.delete.confirmMessage"><![CDATA[{if $count == 1}Einen Tag{else}{#$count} Tag{/if} löschen?]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.tag.setAsSynonyms"><![CDATA[Als Synonyme verwenden ({#$count})]]></item>
@@ -3154,6 +3155,7 @@ E-Mail-Adresse: {@$emailAddress} {* this line ends with a space *}
                <item name="wcf.media.uploadTime"><![CDATA[Datum hochgeladen]]></item>
                <item name="wcf.media.search.noResults"><![CDATA[Es wurden keine Ergebnisse gefunden.]]></item>
                <item name="wcf.media.search.info.searchStringThreshold"><![CDATA[Der Suchbegriff muss mindestens {#$minSearchLength} Zeichen lang sein.]]></item>
+               <item name="wcf.media.setCategory"><![CDATA[Kategorie bearbeiten]]></item>
        </category>
        
        <category name="wcf.message">
index 06ecb2e3ca9680892718c7fc668efa98198cf5cd..ee58a1ba983a5c5178581d8d6d6d5a591bb0b334 100644 (file)
@@ -2442,6 +2442,7 @@ Errors are:
                <item name="wcf.clipboard.item.com.woltlab.wcf.media.delete"><![CDATA[Delete ({#$count})]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.media.delete.confirmMessage"><![CDATA[Do you really want to delete {#$count} file{if $count != 1}s{/if}?]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.media.insert"><![CDATA[Insert ({#$count})]]></item>
+               <item name="wcf.clipboard.item.com.woltlab.wcf.media.setCategory"><![CDATA[Edit Category ({#$count})]]></item>
                
                <item name="wcf.clipboard.item.com.woltlab.wcf.tag.delete"><![CDATA[Delete ({#$count})]]></item>
                <item name="wcf.clipboard.item.com.woltlab.wcf.tag.delete.confirmMessage"><![CDATA[Do you really want to delete {#$count} tag{if $count != 1}s{/if}?]]></item>
@@ -3099,6 +3100,7 @@ Email: {@$emailAddress} {* this line ends with a space *}
                <item name="wcf.media.uploadTime"><![CDATA[Upload Date]]></item>
                <item name="wcf.media.search.noResults"><![CDATA[The search returned no results.]]></item>
                <item name="wcf.media.search.info.searchStringThreshold"><![CDATA[The search term must contain at least {#$minSearchLength} character{if $minSearchLength > 1}s{/if}.]]></item>
+               <item name="wcf.media.setCategory"><![CDATA[Edit Category]]></item>
        </category>
        
        <category name="wcf.message">