Add media search on media list page in ACP
authorMatthias Schmidt <gravatronics@live.com>
Sat, 26 Dec 2015 08:22:51 +0000 (09:22 +0100)
committerMatthias Schmidt <gravatronics@live.com>
Sat, 26 Dec 2015 08:22:51 +0000 (09:22 +0100)
wcfsetup/install/files/acp/templates/mediaList.tpl
wcfsetup/install/files/js/WoltLab/WCF/Media/Manager/Search.js [new file with mode: 0644]
wcfsetup/install/files/js/WoltLab/WCF/Media/Search.js
wcfsetup/install/files/lib/acp/page/MediaListPage.class.php
wcfsetup/install/files/lib/data/media/MediaAction.class.php
wcfsetup/install/files/lib/data/media/MediaList.class.php
wcfsetup/install/files/lib/page/AbstractPage.class.php

index 75d296d3237aa20495005634115f3894520e8aea..31d90004d0f4d1b4bd193c241a8300ea95b51281 100644 (file)
@@ -1,39 +1,45 @@
 {include file='header' pageTitle='wcf.acp.media.list'}
 
 <script data-relocate="true">
-       require(['EventHandler', 'WoltLab/WCF/Controller/Clipboard'], function(EventHandler, Clipboard) {
-               Clipboard.setup({
-                       hasMarkedItems: {if $hasMarkedItems}true{else}false{/if},
-                       pageClassName: 'wcf\\acp\\page\\MediaListPage'
-               });
-               
-               EventHandler.add('com.woltlab.wcf.clipboard', 'com.woltlab.wcf.media', function(actionData) {
-                       // only consider events if the action has been executed
-                       if (actionData.responseData === null) {
-                               return;
-                       }
+       document.addEventListener('DOMContentLoaded', function() {
+               require(['EventHandler', 'Language', 'Ui/SimpleDropdown', 'WoltLab/WCF/Controller/Clipboard', 'WoltLab/WCF/Media/Search'], function (EventHandler, Language, UiSimpleDropdown, Clipboard, MediaSearch) {
+                       Language.add('wcf.media.search.filetype', '{lang}wcf.media.search.filetype{/lang}');
+                       
+                       Clipboard.setup({
+                               hasMarkedItems: {if $hasMarkedItems}true{else}false{/if},
+                               pageClassName: 'wcf\\acp\\page\\MediaListPage'
+                       });
                        
-                       if (actionData.data.actionName === 'com.woltlab.wcf.media.delete') {
-                               var mediaIds = actionData.responseData.objectIDs;
+                       EventHandler.add('com.woltlab.wcf.clipboard', 'com.woltlab.wcf.media', function (actionData) {
+                               // only consider events if the action has been executed
+                               if (actionData.responseData === null) {
+                                       return;
+                               }
                                
-                               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 (actionData.data.actionName === 'com.woltlab.wcf.media.delete') {
+                                       var mediaIds = actionData.responseData.objectIDs;
                                        
-                                       if (mediaIds.indexOf(mediaID) !== -1) {
-                                               elRemove(media);
-                                               i--;
+                                       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();
                                        }
                                }
-                               
-                               if (!mediaRows.length) {
-                                       window.location.reload();
-                               }
-                       }
+                       });
+                       
+                       new MediaSearch('{$fileType}');
+                       
+                       new WCF.Action.Delete('wcf\\data\\media\\MediaAction', '.jsMediaRow');
                });
-               
-               new WCF.Action.Delete('wcf\\data\\media\\MediaAction', '.jsMediaRow');
        });
 </script>
 
 
 {include file='formError'}
 
-{*
-TODO: add file search
 <form method="post" action="{link controller='MediaList'}{/link}">
-       <div class="container containerPadding marginTop">
-               <fieldset>
-                       <legend>{lang}wcf.global.filter{/lang}</legend>
-                       
-                       <dl>
-                               <dt><label for="username">{lang}wcf.user.username{/lang}</label></dt>
-                               <dd>
-                                       <input type="text" id="username" name="username" value="{$username}" class="long" />
-                               </dd>
-                       </dl>
-                       
-                       <dl>
-                               <dt><label for="filename">{lang}wcf.media.filename{/lang}</label></dt>
-                               <dd>
+       <section>
+               <h1 class="subHeadline">{lang}wcf.global.filter{/lang}</h1>
+               
+               <dl>
+                       <dt><label for="filename">{lang}wcf.media.filename{/lang}</label></dt>
+                       <dd>
+                               <div class="inputAddon dropdown" id="mediaSearch">
+                                       <span class="button dropdownToggle inputPrefix">
+                                               <span class="active">{lang}wcf.media.search.filetype{/lang}</span>
+                                       </span>
+                                       <ul class="dropdownMenu">
+                                               <li data-file-type="image"><span>{lang}wcf.media.search.filetype.image{/lang}</span></li>
+                                               <li data-file-type="text"><span>{lang}wcf.media.search.filetype.text{/lang}</span></li>
+                                               <li data-file-type="pdf"><span>{lang}wcf.media.search.filetype.pdf{/lang}</span></li>
+                                               <li data-file-type="other"><span>{lang}wcf.media.search.filetype.other{/lang}</span></li>
+                                               {event name='filetype'}
+                                               <li class="dropdownDivider"></li>
+                                               <li data-file-type="all"><span>{lang}wcf.media.search.filetype.all{/lang}</span></li>
+                                       </ul>
                                        <input type="text" id="filename" name="filename" value="{$filename}" class="long" />
-                               </dd>
-                       </dl>
-                       
-                       <dl>
-                               <dt><label for="fileType">{lang}wcf.media.fileType{/lang}</label></dt>
-                               <dd>
-                                       <select name="fileType" id="fileType">
-                                               <option value="">{lang}wcf.global.noSelection{/lang}</option>
-                                               {htmlOptions options=$availableFileTypes selected=$fileType}
-                                       </select>
-                               </dd>
-                       </dl>
-               </fieldset>
-       </div>
+                               </div>
+                       </dd>
+               </dl>
+               
+               <dl>
+                       <dt><label for="username">{lang}wcf.user.username{/lang}</label></dt>
+                       <dd>
+                               <input type="text" id="username" name="username" value="{$username}" class="long" />
+                       </dd>
+               </dl>
+               
+               {event name='filterFields'}
+       </section>
+       
+       {event name='sections'}
        
        <div class="formSubmit">
                <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
                {@SECURITY_TOKEN_INPUT_TAG}
        </div>
 </form>
-*}
 
 <div class="contentNavigation">
        {assign var='linkParameters' value=''}
-       {*
+       
        {if $username}{capture append=linkParameters}&username={@$username|rawurlencode}{/capture}{/if}
        {if $filename}{capture append=linkParameters}&filename={@$filename|rawurlencode}{/capture}{/if}
        {if $fileType}{capture append=linkParameters}&fileType={@$fileType|rawurlencode}{/capture}{/if}
-       *}
        
        {pages print=true assign=pagesLinks controller="MediaList" link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder$linkParameters"}
        
diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Media/Manager/Search.js b/wcfsetup/install/files/js/WoltLab/WCF/Media/Manager/Search.js
new file mode 100644 (file)
index 0000000..b64d292
--- /dev/null
@@ -0,0 +1,157 @@
+/**
+ * Provides the media search for the media manager.
+ *
+ * @author     Matthias Schmidt
+ * @copyright  2001-2015 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module     WoltLab/WCF/Media/Manager/Search
+ */
+define(['Ajax', 'Core', 'Dom/Traverse', 'Dom/Util', 'Language', 'WoltLab/WCF/Media/Search', 'Ui/SimpleDropdown'], function(Ajax, Core, DomTraverse, DomUtil, Language, MediaSearch, UiSimpleDropdown) {
+       "use strict";
+       
+       /**
+        * @constructor
+        */
+       function MediaManagerSearch(mediaManager) {
+               MediaSearch.call();
+               
+               this._mediaManager = mediaManager;
+               this._searchMode = false;
+               
+               this._input = elById(this._getIdPrefix() + 'SearchField');
+               this._input.addEventListener('keypress', this._keyPress.bind(this));
+               
+               this._cancelButton = elById(this._getIdPrefix() + 'SearchCancelButton');
+               this._cancelButton.addEventListener('click', this._cancelSearch.bind(this));
+       };
+       Core.inherit(MediaManagerSearch, MediaSearch, {
+               /**
+                * Returns the data for Ajax to setup the Ajax/Request object.
+                *
+                * @return      {object}        setup data for Ajax/Request object
+                */
+               _ajaxSetup: function() {
+                       return {
+                               data: {
+                                       actionName: 'getSearchResultList',
+                                       className: 'wcf\\data\\media\\MediaAction',
+                                       interfaceName: 'wcf\\data\\ISearchAction'
+                               }
+                       };
+               },
+               
+               /**
+                * Handles successful AJAX requests.
+                *
+                * @param       {object}        data    response data
+                */
+               _ajaxSuccess: function(data) {
+                       this._mediaManager.setMedia(data.returnValues.media || { }, data.returnValues.template || '');
+               },
+               
+               /**
+                * Cancels the search after clicking on the cancel search button.
+                */
+               _cancelSearch: function() {
+                       if (this._searchMode) {
+                               this._searchMode = false;
+                               
+                               this._mediaManager.resetMedia();
+                               this.resetSearch();
+                       }
+               },
+               
+               /**
+                * @see WoltLab/WCF/Media/Search#_getIdPrefix
+                */
+               _getIdPrefix: function() {
+                       return 'mediaManager';
+               },
+               
+               /**
+                * Handles the `[ENTER]` key to submit the form.
+                *
+                * @param       {Event}         event           event object
+                */
+               _keyPress: function(event) {
+                       // 13 = [ENTER]
+                       if (event.charCode === 13) {
+                               event.preventDefault();
+                               
+                               var innerInfo = DomTraverse.childByClass(this._input.parentNode.parentNode, 'innerInfo');
+                               
+                               // TODO: treshold option?
+                               if (this._input.value.length >= 3) {
+                                       if (innerInfo) {
+                                               elHide(innerInfo);
+                                       }
+                                       
+                                       this._search();
+                               }
+                               else {
+                                       if (innerInfo) {
+                                               elShow(innerInfo);
+                                       }
+                                       else {
+                                               innerInfo = elCreate('p');
+                                               innerInfo.className = 'innerInfo';
+                                               innerInfo.textContent = Language.get('wcf.media.search.info.searchStringTreshold');
+                                               
+                                               DomUtil.insertAfter(innerInfo, this._input.parentNode);
+                                       }
+                               }
+                       }
+               },
+               
+               /**
+                * Sends an AJAX request to fetch seach results.
+                */
+               _search: function() {
+                       this._searchMode = true;
+                       
+                       Ajax.api(this, {
+                               parameters: {
+                                       fileType: this._fileType,
+                                       fileTypeFilters: this._mediaManager.getOption('fileTypeFilters'),
+                                       mode: this._mediaManager.getMode(),
+                                       searchString: this._input.value
+                               }
+                       });
+               },
+               
+               /**
+                * @see WoltLab/WCF/Media/Search#_selectFileType
+                */
+               _selectFileType: function(event) {
+                       MediaManagerSearch._super.prototype._selectFileType.call(this, event);
+                       
+                       this._search();
+               },
+               
+               /**
+                * Hides the media search.
+                */
+               hideSearch: function() {
+                       elHide(elById(this._getIdPrefix() + 'Search'));
+               },
+               
+               /**
+                * Resets the media search.
+                */
+               resetSearch: function() {
+                       this._input.value = '';
+                       this._fileType = 'all';
+                       
+                       this._updateDropdownButtonLabel();
+               },
+               
+               /**
+                * Shows the media search.
+                */
+               showSearch: function() {
+                       elShow(elById(this._getIdPrefix() + 'Search'));
+               }
+       });
+       
+       return MediaManagerSearch;
+});
index e0e33a3f4d15af951a2f4c0f42cd711f943900aa..6dc909a9b8ceaefb287ef9b294d2d31a6255010c 100644 (file)
@@ -12,26 +12,41 @@ define(['Ajax', 'Dom/Traverse', 'Dom/Util', 'Language', 'Ui/SimpleDropdown'], fu
        /**
         * @constructor
         */
-       function MediaSearch(mediaManager) {
-               this._mediaManager = mediaManager;
-               this._searchMode = false;
+       function MediaSearch(initialFileType) {
                this._fileType = 'all';
                
-               this._input = elById('mediaManagerSearchField');
-               this._input.addEventListener('keypress', this._keyPress.bind(this));
-               
-               this._cancelButton = elById('mediaManagerSearchCancelButton');
-               this._cancelButton.addEventListener('click', this._cancelSearch.bind(this));
-               
-               var dropdown = UiSimpleDropdown.getDropdownMenu('mediaManagerSearch');
+               var dropdown = UiSimpleDropdown.getDropdownMenu(this._getIdPrefix() + 'Search');
                if (dropdown) {
                        this._fileTypes = DomTraverse.childrenBySel(dropdown, 'li:not(.dropdownDivider)');
+                       
                        var selectFileType = this._selectFileType.bind(this);
                        for (var i = 0, length = this._fileTypes.length; i < length; i++) {
+                               var listItem = this._fileTypes[i];
+                               
+                               if (initialFileType && elData(listItem, 'file-type') == initialFileType) {
+                                       this._fileType = initialFileType;
+                               }
+                               
                                this._fileTypes[i].addEventListener('click', selectFileType);
                        }
                        
-                       UiSimpleDropdown.registerCallback('mediaManagerSearch', this._updateFileTypeDropdown.bind(this));
+                       if (initialFileType && initialFileType.length) {
+                               this._updateDropdownButtonLabel();
+                       }
+                       
+                       UiSimpleDropdown.registerCallback(this._getIdPrefix() + 'Search', this._updateFileTypeDropdown.bind(this));
+                       
+                       var form = DomTraverse.parentByTag(elById(this._getIdPrefix() + 'Search'), 'FORM');
+                       if (form) {
+                               form.addEventListener('submit', function() {
+                                       var fileTypeInput = elCreate('input');
+                                       elAttr(fileTypeInput, 'type', 'hidden');
+                                       elAttr(fileTypeInput, 'name', 'fileType');
+                                       elAttr(fileTypeInput, 'value', this._fileType);
+                                       
+                                       form.appendChild(fileTypeInput);
+                               }.bind(this));
+                       }
                }
                else {
                        this._fileType = null;
@@ -39,90 +54,12 @@ define(['Ajax', 'Dom/Traverse', 'Dom/Util', 'Language', 'Ui/SimpleDropdown'], fu
        };
        MediaSearch.prototype = {
                /**
-                * Returns the data for Ajax to setup the Ajax/Request object.
+                * Returns the prefix to identify search-related elements.
                 * 
-                * @return      {object}        setup data for Ajax/Request object
-                */
-               _ajaxSetup: function() {
-                       return {
-                               data: {
-                                       actionName: 'getSearchResultList',
-                                       className: 'wcf\\data\\media\\MediaAction',
-                                       interfaceName: 'wcf\\data\\ISearchAction'
-                               }
-                       };
-               },
-               
-               /**
-                * Handles successful AJAX requests.
-                * 
-                * @param       {object}        data    response data
-                */
-               _ajaxSuccess: function(data) {
-                       this._mediaManager.setMedia(data.returnValues.media || { }, data.returnValues.template || '');
-               },
-               
-               /**
-                * Cancels the search after clicking on the cancel search button.
-                */
-               _cancelSearch: function() {
-                       if (this._searchMode) {
-                               this._searchMode = false;
-                               
-                               this._mediaManager.resetMedia();
-                               this.resetSearch();
-                       }
-               },
-               
-               /**
-                * Handles the `[ENTER]` key to submit the form.
-                * 
-                * @param       {Event}         event           event object
-                */
-               _keyPress: function(event) {
-                       // 13 = [ENTER]
-                       if (event.charCode === 13) {
-                               event.preventDefault();
-                               
-                               var innerInfo = DomTraverse.childByClass(this._input.parentNode.parentNode, 'innerInfo');
-                               
-                               // TODO: treshold option?
-                               if (this._input.value.length >= 3) {
-                                       if (innerInfo) {
-                                               elHide(innerInfo);
-                                       }
-                                       
-                                       this._search();
-                               }
-                               else {
-                                       if (innerInfo) {
-                                               elShow(innerInfo);
-                                       }
-                                       else {
-                                               innerInfo = elCreate('p');
-                                               innerInfo.className = 'innerInfo';
-                                               innerInfo.textContent = Language.get('wcf.media.search.info.searchStringTreshold');
-                                               
-                                               DomUtil.insertAfter(innerInfo, this._input.parentNode);
-                                       }
-                               }
-                       }
-               },
-               
-               /**
-                * Sends an AJAX request to fetch seach results.
+                * @return      {string}
                 */
-               _search: function() {
-                       this._searchMode = true;
-                       
-                       Ajax.api(this, {
-                               parameters: {
-                                       fileType: this._fileType,
-                                       fileTypeFilters: this._mediaManager.getOption('fileTypeFilters'),
-                                       mode: this._mediaManager.getMode(),
-                                       searchString: this._input.value
-                               }
-                       });
+               _getIdPrefix: function() {
+                       return 'media';
                },
                
                /**
@@ -133,20 +70,33 @@ define(['Ajax', 'Dom/Traverse', 'Dom/Util', 'Language', 'Ui/SimpleDropdown'], fu
                _selectFileType: function(event) {
                        this._fileType = elData(event.currentTarget, 'file-type');
                        
-                       this._updateDropdownButtonLabel();
-                       
-                       this._search();
+                       this._updateDropdownButtonLabel(event);
                },
                
                /**
                 * Updates the label of the dropdown button based on the currently selected file type.
                 */
-               _updateDropdownButtonLabel: function() {
-                       var dropdown = UiSimpleDropdown.getDropdown('mediaManagerSearch');
+               _updateDropdownButtonLabel: function(event) {
+                       var dropdown = UiSimpleDropdown.getDropdown(this._getIdPrefix() + 'Search');
                        var buttonLabel = DomTraverse.childBySel(DomTraverse.childByClass(dropdown, 'dropdownToggle'), 'SPAN');
                        
                        if (this._fileType !== 'all') {
-                               buttonLabel.textContent = DomTraverse.childBySel(event.currentTarget, 'SPAN').textContent;
+                               var listItem;
+                               if (event) {
+                                       listItem = event.currentTarget;
+                               }
+                               else {
+                                       for (var i = 0, length = this._fileTypes.length; i < length; i++) {
+                                               var _listItem = this._fileTypes[i];
+                                               
+                                               if (elData(_listItem, 'file-type') == this._fileType) {
+                                                       listItem = _listItem;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               
+                               buttonLabel.textContent = DomTraverse.childBySel(listItem, 'SPAN').textContent;
                        }
                        else {
                                buttonLabel.textContent = Language.get('wcf.media.search.filetype');
@@ -162,30 +112,6 @@ define(['Ajax', 'Dom/Traverse', 'Dom/Util', 'Language', 'Ui/SimpleDropdown'], fu
                                
                                listItem.classList[elData(listItem, 'file-type') === this._fileType ? 'add' : 'remove']('active');
                        }
-               },
-               
-               /**
-                * Hides the media search.
-                */
-               hideSearch: function() {
-                       elHide(elById('mediaManagerSearch'));
-               },
-               
-               /**
-                * Resets the media search.
-                */
-               resetSearch: function() {
-                       this._input.value = '';
-                       this._fileType = 'all';
-                       
-                       this._updateDropdownButtonLabel();
-               },
-               
-               /**
-                * Shows the media search.
-                */
-               showSearch: function() {
-                       elShow(elById('mediaManagerSearch'));
                }
        };
        
index 6bd76684332fbaaeae6528aa2749d5943a71ccc3..7080532b3edbb2d1e9637706f75574541c0fe156 100644 (file)
@@ -3,7 +3,9 @@ namespace wcf\acp\page;
 use wcf\data\media\ViewableMediaList;
 use wcf\page\SortablePage;
 use wcf\system\clipboard\ClipboardHandler;
+use wcf\system\request\LinkHandler;
 use wcf\system\WCF;
+use wcf\util\StringUtil;
 
 /**
  * Shows the list of media entries.
@@ -20,7 +22,7 @@ class MediaListPage extends SortablePage {
        /**
         * @inheritDoc
         */
-       public $activeMenuItem = 'wcf.acp.menu.link.media.list';
+       public $activeMenuItem = 'wcf.acp.menu.link.cms.media.list';
        
        /**
         * @inheritDoc
@@ -32,6 +34,23 @@ class MediaListPage extends SortablePage {
         */
        public $defaultSortOrder = 'DESC';
        
+       /**
+        * searched media filename
+        * @var string
+        */
+       public $filename = '';
+       
+       /**
+        * searched media file type
+        * @var string
+        */
+       public $fileType = 'all';
+       
+       /**
+        * @inheritDoc
+        */
+       public $forceCanonicalURL = true;
+       
        /**
         * @inheritDoc
         */
@@ -42,6 +61,12 @@ class MediaListPage extends SortablePage {
         */
        public $objectListClassName = ViewableMediaList::class;
        
+       /**
+        * name of the user who uploaded the searched media files
+        * @var string
+        */
+       public $username = '';
+       
        /**
         * @inheritDoc
         */
@@ -59,7 +84,51 @@ class MediaListPage extends SortablePage {
        public function assignVariables() {
                parent::assignVariables();
                
-               WCF::getTPL()->assign('hasMarkedItems', ClipboardHandler::getInstance()->hasMarkedItems(ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.media')));
+               WCF::getTPL()->assign([
+                       'filename' => $this->filename,
+                       'fileType' => $this->fileType,
+                       'hasMarkedItems' => ClipboardHandler::getInstance()->hasMarkedItems(ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.media')),
+                       'username' => $this->username
+               ]);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       protected function initObjectList() {
+               parent::initObjectList();
+               
+               if ($this->filename) {
+                       $this->objectList->addSearchConditions($this->filename);
+               }
+               if ($this->fileType) {
+                       $this->objectList->addDefaultFileTypeFilter($this->fileType);
+               }
+               if ($this->username) {
+                       $this->objectList->getConditionBuilder()->add('media.username LIKE ?', ['%'.addcslashes($this->username, '_%').'%']);
+               }
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (isset($_REQUEST['filename'])) $this->filename = StringUtil::trim($_REQUEST['filename']);
+               if (isset($_REQUEST['fileType'])) $this->fileType = StringUtil::trim($_REQUEST['fileType']);
+               if (isset($_REQUEST['username'])) $this->username = StringUtil::trim($_REQUEST['username']);
+               
+               if ($this->fileType == 'all') $this->fileType = '';
+               
+               $parameters = [];
+               if ($this->sortField) $parameters['sortField'] = $this->sortField;
+               if ($this->sortOrder) $parameters['sortOrder'] = $this->sortOrder;
+               if ($this->filename) $parameters['filename'] = $this->filename;
+               if ($this->fileType) $parameters['fileType'] = $this->fileType;
+               if ($this->username) $parameters['username'] = $this->username;
+               
+               $this->canonicalURL = LinkHandler::getInstance()->getLink('MediaList', $parameters);
        }
        
        /**
index 7fefe1c2bbaf333546f445a8c0b15027dddc09b6..e5662a5736ca2c6395e877ae4935b40f838a0467 100644 (file)
@@ -28,13 +28,7 @@ use wcf\util\FileUtil;
  */
 class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction, IUploadAction {
        /**
-        * condition builder for searched media file type
-        * @var PreparedStatementConditionBuilder
-        */
-       public $fileTypeConditionBuilder = null;
-       
-       /**
-        * @inheritdoc
+        * @inheritDoc
         */
        public function validateUpload() {
                WCF::getSession()->checkPermissions(['admin.content.cms.canManageMedia']);
@@ -47,7 +41,7 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
        }
        
        /**
-        * @inheritdoc
+        * @inheritDoc
         */
        public function upload() {
                // save files
@@ -258,7 +252,7 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
        }
        
        /**
-        * @inheritdoc
+        * @inheritDoc
         */
        public function validateUpdate() {
                WCF::getSession()->checkPermissions(['admin.content.cms.canManageMedia']);
@@ -275,7 +269,7 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
        }
        
        /**
-        * @inheritdoc
+        * @inheritDoc
         */
        public function update() {
                if (empty($this->objects)) {
@@ -345,7 +339,7 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
        }
        
        /**
-        * @inheritdoc
+        * @inheritDoc
         */
        public function validateGetSearchResultList() {
                if (!WCF::getSession()->getPermission('admin.content.cms.canManageMedia') && !WCF::getSession()->getPermission('admin.content.cms.canUseMedia')) {
@@ -359,27 +353,6 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
                        throw new UserInputException('searchString');
                }
                
-               $this->fileTypeConditionBuilder = new PreparedStatementConditionBuilder(false);
-               switch ($this->parameters['fileType']) {
-                       case 'other':
-                               $this->fileTypeConditionBuilder->add('media.fileType NOT LIKE ?', ['image/%']);
-                               $this->fileTypeConditionBuilder->add('media.fileType <> ?', ['application/pdf']);
-                               $this->fileTypeConditionBuilder->add('media.fileType NOT LIKE ?', ['text/%']);
-                       break;
-                       
-                       case 'image':
-                               $this->fileTypeConditionBuilder->add('media.fileType LIKE ?', ['image/%']);
-                       break;
-                       
-                       case 'pdf':
-                               $this->fileTypeConditionBuilder->add('media.fileType = ?', ['application/pdf']);
-                       break;
-                       
-                       case 'text':
-                               $this->fileTypeConditionBuilder->add('media.fileType LIKE ?', ['text/%']);
-                       break;
-               }
-               
                if (isset($this->parameters['fileTypeFilters']) && !is_array($this->parameters['fileTypeFilters'])) {
                        throw new UserInputException('fileTypeFilters');
                }
@@ -391,24 +364,15 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
        }
        
        /**
-        * @inheritdoc
+        * @inheritDoc
         */
        public function getSearchResultList() {
-               $searchString = '%'.addcslashes($this->parameters['searchString'], '_%').'%';
-               
                $mediaList = new MediaList();
-               $mediaList->sqlConditionJoins = 'LEFT JOIN wcf'.WCF_N.'_media_content media_content ON (media_content.mediaID = media.mediaID)';
-               
-               $searchConditionBuilder = new PreparedStatementConditionBuilder(false, 'OR');
-               $searchConditionBuilder->add('media_content.title LIKE ?', [$searchString]);
-               $searchConditionBuilder->add('media_content.caption LIKE ?', [$searchString]);
-               $searchConditionBuilder->add('media_content.altText LIKE ?', [$searchString]);
-               $searchConditionBuilder->add('media.filename LIKE ?', [$searchString]);
-               $mediaList->getConditionBuilder()->add($searchConditionBuilder->__toString(), $searchConditionBuilder->getParameters());
-               
-               if (!empty($this->fileTypeConditionBuilder->__toString())) {
-                       $mediaList->getConditionBuilder()->add($this->fileTypeConditionBuilder->__toString(), $this->fileTypeConditionBuilder->getParameters());
+               $mediaList->addSearchConditions($this->parameters['searchString']);
+               if (!empty($this->parameters['fileType'])) {
+                       $mediaList->addDefaultFileTypeFilter($this->parameters['fileType']);
                }
+               $mediaList->getConditionBuilder()->add($searchConditionBuilder->__toString(), $searchConditionBuilder->getParameters());
                if (!empty($this->parameters['fileTypeFilters'])) {
                        $mediaList->addFileTypeFilters($this->parameters['fileTypeFilters']);
                }
@@ -435,7 +399,7 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
        }
        
        /**
-        * @inheritdoc
+        * @inheritDoc
         */
        public function validateDelete() {
                WCF::getSession()->checkPermissions(['admin.content.cms.canManageMedia']);
@@ -450,7 +414,7 @@ class MediaAction extends AbstractDatabaseObjectAction implements ISearchAction,
        }
        
        /**
-        * @inheritdoc
+        * @inheritDoc
         */
        public function delete() {
                if (empty($this->objects)) {
index 4355635a9b7f1d832e618134ef1ec358fec8bf7b..001a061d4ad787c8e38e5707afe99f8713135eae 100644 (file)
@@ -44,4 +44,51 @@ class MediaList extends DatabaseObjectList {
                        $this->getConditionBuilder()->add($conditionBuilder->__toString(), $conditionBuilder->getParameters());
                }
        }
+       
+       /**
+        * Adds one of the default file filters.
+        * 
+        * Default filters are: 'image', 'pdf', 'text', 'other'.
+        * 
+        * @param       string          $filter
+        */
+       public function addDefaultFileTypeFilter($filter) {
+               switch ($filter) {
+                       case 'other':
+                               $this->getConditionBuilder()->add('media.fileType NOT LIKE ?', ['image/%']);
+                               $this->getConditionBuilder()->add('media.fileType <> ?', ['application/pdf']);
+                               $this->getConditionBuilder()->add('media.fileType NOT LIKE ?', ['text/%']);
+                       break;
+                       
+                       case 'image':
+                               $this->getConditionBuilder()->add('media.fileType LIKE ?', ['image/%']);
+                       break;
+                       
+                       case 'pdf':
+                               $this->getConditionBuilder()->add('media.fileType = ?', ['application/pdf']);
+                       break;
+                       
+                       case 'text':
+                               $this->getConditionBuilder()->add('media.fileType LIKE ?', ['text/%']);
+                       break;
+               }
+       }
+       
+       /**
+        * Adds conditions to search the media files by a certain search string.
+        * 
+        * @param       string          $searchString
+        */
+       public function addSearchConditions($searchString) {
+               $searchString = '%'.addcslashes($searchString, '_%').'%';
+               
+               $this->sqlConditionJoins .= ' LEFT JOIN wcf'.WCF_N.'_media_content media_content ON (media_content.mediaID = media.mediaID)';
+               
+               $conditionBuilder = new PreparedStatementConditionBuilder(false, 'OR');
+               $conditionBuilder->add('media_content.title LIKE ?', [$searchString]);
+               $conditionBuilder->add('media_content.caption LIKE ?', [$searchString]);
+               $conditionBuilder->add('media_content.altText LIKE ?', [$searchString]);
+               $conditionBuilder->add('media.filename LIKE ?', [$searchString]);
+               $this->getConditionBuilder()->add($conditionBuilder->__toString(), $conditionBuilder->getParameters());
+       }
 }
index c9f0334091802d9139333a1c0905726d74c18c9b..d6bf0f6ec781a9855fd20b8d60af49c975b40b63 100644 (file)
@@ -50,6 +50,12 @@ abstract class AbstractPage implements IPage, ITrackablePage {
         */
        public $enableTracking = false;
        
+       /**
+        * is true if canonical URL will be enforced even if POST data is represent
+        * @var boolean
+        */
+       public $forceCanonicalURL = false;
+       
        /**
         * indicates if you need to be logged in to access this page
         * @var boolean
@@ -181,7 +187,7 @@ abstract class AbstractPage implements IPage, ITrackablePage {
                }
                
                // check if current request URL matches the canonical URL
-               if ($this->canonicalURL && empty($_POST)) {
+               if ($this->canonicalURL && (empty($_POST) || $this->forceCanonicalURL)) {
                        $canoncialURL = parse_url(preg_replace('~[?&]s=[a-f0-9]{40}~', '', $this->canonicalURL));
                        
                        // use $_SERVER['REQUEST_URI'] because it represents the URL used to access the site and not the internally rewritten one
@@ -222,8 +228,9 @@ abstract class AbstractPage implements IPage, ITrackablePage {
                        }
                        
                        if ($redirect) {
-                               die("should redirect");
                                $redirectURL = $this->canonicalURL;
+                               // TODO
+                               /*
                                if (!empty($requestURL['query'])) {
                                        $queryString = $requestURL['query'];
                                        parse_str($requestURL['query'], $rQueryString);
@@ -252,6 +259,7 @@ abstract class AbstractPage implements IPage, ITrackablePage {
                                                $redirectURL .= (mb_strpos($redirectURL, '?') === false ? '?' : '&') . http_build_query($rQueryString, '', '&');
                                        }
                                }
+                               */
                                
                                // force a permanent redirect as recommended by Google
                                // https://support.google.com/webmasters/answer/6033086?hl=en#a_note_about_redirects