Custom sort order for articles per category
authorAlexander Ebert <ebert@woltlab.com>
Mon, 9 Jul 2018 15:37:53 +0000 (17:37 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 9 Jul 2018 15:37:53 +0000 (17:37 +0200)
See #2592

com.woltlab.wcf/templateListener.xml [new file with mode: 0644]
wcfsetup/install/files/acp/templates/__articleSortField.tpl [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/ArticleCategoryAddForm.class.php
wcfsetup/install/files/lib/acp/form/ArticleCategoryEditForm.class.php
wcfsetup/install/files/lib/data/article/category/ArticleCategory.class.php
wcfsetup/install/files/lib/page/CategoryArticleListPage.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

diff --git a/com.woltlab.wcf/templateListener.xml b/com.woltlab.wcf/templateListener.xml
new file mode 100644 (file)
index 0000000..4b08593
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/vortex/templateListener.xsd">
+       <import>
+               <templatelistener name="articleSortField">
+                       <environment>admin</environment>
+                       <templatename>categoryAdd</templatename>
+                       <eventname>dataFields</eventname>
+                       <templatecode><![CDATA[{include file='__articleSortField'}]]></templatecode>
+               </templatelistener>
+       </import>
+       <delete>
+               <templatelistener name="articleShowOrder">
+                       <environment>admin</environment>
+                       <templatename>categoryAdd</templatename>
+                       <eventname>dataFields</eventname>
+               </templatelistener>
+       </delete>
+</data>
diff --git a/wcfsetup/install/files/acp/templates/__articleSortField.tpl b/wcfsetup/install/files/acp/templates/__articleSortField.tpl
new file mode 100644 (file)
index 0000000..4affaf9
--- /dev/null
@@ -0,0 +1,14 @@
+<dl>
+       <dt><label for="sortField">{lang}wcf.acp.article.category.sortField{/lang}</label></dt>
+       <dd>
+               <select name="sortField" id="sortField">
+                       {foreach from=$availableSortFields item=availableSortField}
+                               <option value="{$availableSortField}"{if $availableSortField === $sortField} selected{/if}>{lang}wcf.acp.article.category.sortField.{$availableSortField}{/lang}</option>
+                       {/foreach}
+               </select>
+               <select name="sortOrder" id="sortOrder">
+                       <option value="ASC"{if $sortOrder === 'ASC'} selected{/if}>{lang}wcf.global.sortOrder.ascending{/lang}</option>
+                       <option value="DESC"{if $sortOrder === 'DESC'} selected{/if}>{lang}wcf.global.sortOrder.descending{/lang}</option>
+               </select>
+       </dd>
+</dl>
index 7adf1b78847cd21f65a387e9d032c096cc6765c8..25a26628c85aa144ef0c0a435f10e99febc3436c 100644 (file)
@@ -1,15 +1,18 @@
 <?php
 declare(strict_types=1);
 namespace wcf\acp\form;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
 
 /**
  * Shows the article category add form.
  *
- * @author     Marcel Werk
- * @copyright  2001-2018 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package    WoltLabSuite\Core\Acp\Form
- * @since      3.0
+ * @author      Marcel Werk
+ * @copyright   2001-2018 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package     WoltLabSuite\Core\Acp\Form
+ * @since       3.0
  */
 class ArticleCategoryAddForm extends AbstractCategoryAddForm {
        /**
@@ -26,4 +29,76 @@ class ArticleCategoryAddForm extends AbstractCategoryAddForm {
         * @inheritDoc
         */
        public $neededModules = ['MODULE_ARTICLE'];
+       
+       /**
+        * @var string[]
+        * @since 3.2
+        */
+       public $availableSortFields = [
+               'publicationDate',
+               'title'
+       ];
+       
+       /**
+        * @var string
+        * @since 3.2
+        */
+       public $sortField = 'publicationDate';
+       
+       /**
+        * @var string
+        * @since 3.2
+        */
+       public $sortOrder = 'DESC';
+       
+       /**
+        * @inheritDoc
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (isset($_POST['sortField'])) $this->sortField = StringUtil::trim($_POST['sortField']);
+               if (isset($_POST['sortOrder'])) $this->sortOrder = StringUtil::trim($_POST['sortOrder']);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function validate() {
+               parent::validate();
+               
+               if (!in_array($this->sortField, $this->availableSortFields)) {
+                       throw new UserInputException('sortField');
+               }
+               
+               if ($this->sortOrder !== 'ASC' && $this->sortOrder !== 'DESC') {
+                       throw new UserInputException('sortOrder');
+               }
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function save() {
+               $this->additionalData['sortField'] = $this->sortField;
+               $this->additionalData['sortOrder'] = $this->sortOrder;
+               
+               parent::save();
+               
+               $this->sortField = 'publicationDate';
+               $this->sortOrder = 'DESC';
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign([
+                       'availableSortFields' => $this->availableSortFields,
+                       'sortField' => $this->sortField,
+                       'sortOrder' => $this->sortOrder
+               ]);
+       }
 }
index 16587551193c68478aabb22f2c8472078178d6b9..b6b67ab25b02c221277627eb9aa48c816b25eaa5 100644 (file)
@@ -1,15 +1,18 @@
 <?php
 declare(strict_types=1);
 namespace wcf\acp\form;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
 
 /**
  * Shows the article category edit form.
  *
- * @author     Marcel Werk
- * @copyright  2001-2018 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package    WoltLabSuite\Core\Acp\Form
- * @since      3.0
+ * @author      Marcel Werk
+ * @copyright   2001-2018 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package     WoltLabSuite\Core\Acp\Form
+ * @since       3.0
  */
 class ArticleCategoryEditForm extends AbstractCategoryEditForm {
        /**
@@ -26,4 +29,87 @@ class ArticleCategoryEditForm extends AbstractCategoryEditForm {
         * @inheritDoc
         */
        public $neededModules = ['MODULE_ARTICLE'];
+       
+       /**
+        * @var string[]
+        * @since 3.2
+        */
+       public $availableSortFields = [
+               'publicationDate',
+               'title'
+       ];
+       
+       /**
+        * @var string
+        * @since 3.2
+        */
+       public $sortField = 'publicationDate';
+       
+       /**
+        * @var string
+        * @since 3.2
+        */
+       public $sortOrder = 'DESC';
+       
+       /**
+        * @inheritDoc
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (isset($_POST['sortField'])) $this->sortField = StringUtil::trim($_POST['sortField']);
+               if (isset($_POST['sortOrder'])) $this->sortOrder = StringUtil::trim($_POST['sortOrder']);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function validate() {
+               parent::validate();
+               
+               if (!in_array($this->sortField, $this->availableSortFields)) {
+                       throw new UserInputException('sortField');
+               }
+               
+               if ($this->sortOrder !== 'ASC' && $this->sortOrder !== 'DESC') {
+                       throw new UserInputException('sortOrder');
+               }
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function readData() {
+               parent::readData();
+               
+               if (empty($_POST)) {
+                       /** @noinspection PhpUndefinedFieldInspection */
+                       $this->sortField = ($this->category->sortField ?: 'publicationDate');
+                       /** @noinspection PhpUndefinedFieldInspection */
+                       $this->sortOrder = ($this->category->sortOrder ?: 'DESC');
+               }
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function save() {
+               $this->additionalData['sortField'] = $this->sortField;
+               $this->additionalData['sortOrder'] = $this->sortOrder;
+               
+               parent::save();
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign([
+                       'availableSortFields' => $this->availableSortFields,
+                       'sortField' => $this->sortField,
+                       'sortOrder' => $this->sortOrder
+               ]);
+       }
 }
index b79a1dfd08bd1e8685eb99f90c04f4187fd955c4..78b4d39ffb3c6884632d8579186b56f4551efb5c 100644 (file)
@@ -28,6 +28,8 @@ use wcf\system\WCF;
  * @method             ArticleCategory         getParentCategory()
  * @method             ArticleCategory[]       getParentCategories()
  * @method static      ArticleCategory|null    getCategory($categoryID)
+ * @property-read       string                  $sortField
+ * @property-read       string                  $sortOrder
  */
 class ArticleCategory extends AbstractDecoratedCategory implements IAccessibleObject, ITitledLinkObject {
        /**
index f28e5ea03a6c1e52e34d5bb6c8a676674ec5f1b7..92765f4de89ad910e93f9684908b1d0e5f18d368 100644 (file)
@@ -51,6 +51,17 @@ class CategoryArticleListPage extends ArticleListPage {
                $this->canonicalURL = LinkHandler::getInstance()->getLink('CategoryArticleList', [
                        'object' => $this->category
                ], ($this->pageNo > 1 ? 'pageNo=' . $this->pageNo : ''));
+               
+               if ($this->category->sortField) {
+                       if ($this->category->sortField === 'title') {
+                               $this->sortField = 'article_content.title';
+                               $this->sortOrder = $this->category->sortOrder;
+                       }
+                       else {
+                               $this->sortField = $this->category->sortField;
+                               $this->sortOrder = $this->category->sortOrder;
+                       }
+               }
        }
        
        /**
@@ -70,6 +81,12 @@ class CategoryArticleListPage extends ArticleListPage {
         */
        protected function initObjectList() {
                $this->objectList = new CategoryArticleList($this->categoryID, true);
+               if ($this->category->sortField === 'title') {
+                       $this->objectList->sqlJoins .= ' LEFT JOIN wcf' . WCF_N . '_article_content article_content ON (article_content.articleID = article.articleID AND (
+                               article_content.languageID IS NULL
+                               OR article_content.languageID = ' . WCF::getLanguage()->languageID . '
+                       ))';
+               }
                
                $this->applyFilters();
        }
index b696a01dd8aae6fc01b5dc09991fb6b60f288a49..2374b15c71cb72860fc50e6e37dc00fb1cfbbfe4 100644 (file)
@@ -76,6 +76,9 @@
                <item name="wcf.acp.article.button.toggleI18n"><![CDATA[Mehrsprachigkeit]]></item>
                <item name="wcf.acp.article.button.viewArticle"><![CDATA[Vorschau anzeigen]]></item>
                <item name="wcf.acp.article.category"><![CDATA[Kategorie]]></item>
+               <item name="wcf.acp.article.category.sortField"><![CDATA[Sortierung]]></item>
+               <item name="wcf.acp.article.category.sortField.publicationDate"><![CDATA[Veröffentlichungsdatum]]></item>
+               <item name="wcf.acp.article.category.sortField.title"><![CDATA[Titel]]></item>
                <item name="wcf.acp.article.content"><![CDATA[Inhalt]]></item>
                <item name="wcf.acp.article.delete.confirmMessage"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Willst du{else}Wollen Sie{/if} {if $isArticleEdit|empty}den Artikel <span class="confirmationObject">{$article->getTitle()}</span>{else}diesen Artikel{/if} wirklich löschen?]]></item>
                <item name="wcf.acp.article.enableComments"><![CDATA[Kommentare aktivieren]]></item>
index 26c00a9e3c4644698deb6871ec5f9f014f39f483..577a961cc3e51441550e457b7c81d186bf685523 100644 (file)
@@ -76,6 +76,9 @@
                <item name="wcf.acp.article.button.toggleI18n"><![CDATA[Internationalization]]></item>
                <item name="wcf.acp.article.button.viewArticle"><![CDATA[Show Preview]]></item>
                <item name="wcf.acp.article.category"><![CDATA[Category]]></item>
+               <item name="wcf.acp.article.category.sortField"><![CDATA[Show Order]]></item>
+               <item name="wcf.acp.article.category.sortField.publicationDate"><![CDATA[Publication Date]]></item>
+               <item name="wcf.acp.article.category.sortField.title"><![CDATA[Title]]></item>
                <item name="wcf.acp.article.content"><![CDATA[Content]]></item>
                <item name="wcf.acp.article.delete.confirmMessage"><![CDATA[Do you really want to delete {if $isArticleEdit|empty}the article <span class="confirmationObject">{$article->getTitle()}</span>{else}this article{/if}?]]></item>
                <item name="wcf.acp.article.enableComments"><![CDATA[Enable comments]]></item>