Implement custom show order for user profile menu
authorAlexander Ebert <ebert@woltlab.com>
Sat, 29 Apr 2017 17:48:33 +0000 (19:48 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sat, 29 Apr 2017 17:48:33 +0000 (19:48 +0200)
See #2259

com.woltlab.wcf/acpMenu.xml
com.woltlab.wcf/templates/user.tpl
wcfsetup/install/files/acp/templates/userProfileMenu.tpl [new file with mode: 0644]
wcfsetup/install/files/lib/acp/page/UserProfileMenuPage.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/profile/menu/item/UserProfileMenuItem.class.php
wcfsetup/install/files/lib/data/user/profile/menu/item/UserProfileMenuItemAction.class.php
wcfsetup/install/files/lib/page/UserPage.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 0e017691b699d9a18926e76159b76ebeeb139f92..a640cf8fc78e834e61ff50936a6af80d2cd8608d 100644 (file)
                                <parent>wcf.acp.menu.link.user.management</parent>
                                <permissions>admin.user.canMailUser</permissions>
                        </acpmenuitem>
+                       
+                       <acpmenuitem name="wcf.acp.menu.link.user.profileMenu">
+                               <controller>wcf\acp\page\UserProfileMenuPage</controller>
+                               <parent>wcf.acp.menu.link.user.management</parent>
+                               <permissions>admin.user.canManageUserOption</permissions>
+                       </acpmenuitem>
                        <!-- /management -->
                        
                        <!-- group -->
index 524dc0669bc6268b9896faff0b69b5700d5a645b..0aa901dc19bc9abf6946ce7f7d8084927e6bb0e6 100644 (file)
                        <ul>
                                {foreach from=$__wcf->getUserProfileMenu()->getMenuItems() item=menuItem}
                                        {if $menuItem->getContentManager()->isVisible($userID)}
-                                               <li><a href="{$__wcf->getAnchor($menuItem->getIdentifier())}">{lang}wcf.user.profile.menu.{@$menuItem->menuItem}{/lang}</a></li>
+                                               <li><a href="{$__wcf->getAnchor($menuItem->getIdentifier())}">{$menuItem}</a></li>
                                        {/if}
                                {/foreach}
                        </ul>
diff --git a/wcfsetup/install/files/acp/templates/userProfileMenu.tpl b/wcfsetup/install/files/acp/templates/userProfileMenu.tpl
new file mode 100644 (file)
index 0000000..1e3cef4
--- /dev/null
@@ -0,0 +1,47 @@
+{include file='header' pageTitle='wcf.acp.user.profileMenu.sort'}
+
+<script data-relocate="true">
+       require(['WoltLabSuite/Core/Ui/Sortable/List'], function (UiSortableList) {
+               new UiSortableList({
+                       containerId: 'userProfileMenuItemList',
+                       className: 'wcf\\data\\user\\profile\\menu\\item\\UserProfileMenuItemAction',
+                       isSimpleSorting: true
+               });
+       });
+</script>
+
+<header class="contentHeader">
+       <div class="contentHeaderTitle">
+               <h1 class="contentTitle">{lang}wcf.acp.user.profileMenu.sort{/lang}</h1>
+       </div>
+       
+       {hascontent}
+               <nav class="contentHeaderNavigation">
+                       <ul>
+                               {content}{event name='contentHeaderNavigation'}{/content}
+                       </ul>
+               </nav>
+       {/hascontent}
+</header>
+
+<div id="userProfileMenuItemList" class="section">
+       <ol class="sortableList" data-object-id="0">
+               {foreach from=$userProfileMenuItemList item=menuItem}
+                       <li class="sortableNode" data-object-id="{@$menuItem->menuItemID}">
+                               <span class="sortableNodeLabel">
+                                       <span>{$menuItem}</span>
+                                       
+                                       <span class="statusDisplay sortableButtonContainer">
+                                               <span class="icon icon16 fa-arrows sortableNodeHandle"></span>
+                                       </span>
+                               </span>
+                       </li>
+               {/foreach}
+       </ol>
+</div>
+
+<div class="formSubmit">
+       <button class="button buttonPrimary" data-type="submit">{lang}wcf.global.button.saveSorting{/lang}</button>
+</div>
+
+{include file='footer'}
diff --git a/wcfsetup/install/files/lib/acp/page/UserProfileMenuPage.class.php b/wcfsetup/install/files/lib/acp/page/UserProfileMenuPage.class.php
new file mode 100644 (file)
index 0000000..3da1062
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+namespace wcf\acp\page;
+use wcf\data\user\profile\menu\item\UserProfileMenuItemList;
+use wcf\page\AbstractPage;
+use wcf\system\WCF;
+
+/**
+ * Provides sorting capabilities for the user profile menu.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2017 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    WoltLabSuite\Core\Acp\Page
+ */
+class UserProfileMenuPage extends AbstractPage {
+       /**
+        * @inheritDoc
+        */
+       public $activeMenuItem = 'wcf.acp.menu.link.user.profileMenu';
+       
+       /**
+        * @inheritDoc
+        */
+       public $neededPermissions = ['admin.user.canManageUserOption'];
+       
+       /**
+        * user profile menu item list object
+        * @var UserProfileMenuItemList
+        */
+       public $userProfileMenuItemList;
+       
+       /**
+        * @inheritDoc
+        */
+       public function readData() {
+               parent::readData();
+               
+               $this->userProfileMenuItemList = new UserProfileMenuItemList();
+               $this->userProfileMenuItemList->sqlOrderBy = "showOrder";
+               $this->userProfileMenuItemList->readObjects();
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign([
+                       'userProfileMenuItemList' => $this->userProfileMenuItemList
+               ]);
+       }
+}
index 5c04054e35d41b5b2ea9641887761a19e7757551..04759e293afdff55fcec3e415f050c6848ddb545 100644 (file)
@@ -8,6 +8,7 @@ use wcf\data\TDatabaseObjectOptions;
 use wcf\data\TDatabaseObjectPermissions;
 use wcf\system\exception\SystemException;
 use wcf\system\SingletonFactory;
+use wcf\system\WCF;
 
 /**
  * Represents an user profile menu item.
@@ -74,4 +75,11 @@ class UserProfileMenuItem extends DatabaseObject {
                
                return $this->contentManager;
        }
+       
+       /**
+        * @return string
+        */
+       public function __toString() {
+               return WCF::getLanguage()->get('wcf.user.profile.menu.' . $this->menuItem);
+       }
 }
index eae832d3aad70239726b29efa09105561eac65b6..0be90d401037153c28d690d0cd8fbecd7393947d 100644 (file)
@@ -1,9 +1,13 @@
 <?php
 namespace wcf\data\user\profile\menu\item;
 use wcf\data\AbstractDatabaseObjectAction;
+use wcf\data\ISortableAction;
+use wcf\system\cache\builder\UserProfileMenuCacheBuilder;
 use wcf\system\exception\PermissionDeniedException;
 use wcf\system\exception\UserInputException;
 use wcf\system\menu\user\profile\UserProfileMenu;
+use wcf\system\WCF;
+use wcf\util\ArrayUtil;
 
 /**
  * Executes user profile menu item-related actions.
@@ -17,7 +21,7 @@ use wcf\system\menu\user\profile\UserProfileMenu;
  * @method     UserProfileMenuItemEditor[]     getObjects()
  * @method     UserProfileMenuItemEditor       getSingleObject()
  */
-class UserProfileMenuItemAction extends AbstractDatabaseObjectAction {
+class UserProfileMenuItemAction extends AbstractDatabaseObjectAction implements ISortableAction {
        /**
         * @inheritDoc
         */
@@ -27,7 +31,12 @@ class UserProfileMenuItemAction extends AbstractDatabaseObjectAction {
         * menu item
         * @var UserProfileMenuItem
         */
-       protected $menuItem = null;
+       protected $menuItem;
+       
+       /**
+        * @inheritDoc
+        */
+       protected $requireACP = ['updatePosition'];
        
        /**
         * Validates menu item.
@@ -57,4 +66,59 @@ class UserProfileMenuItemAction extends AbstractDatabaseObjectAction {
                        'template' => $contentManager->getContent($this->parameters['data']['userID'])
                ];
        }
+       
+       /**
+        * @inheritDoc
+        */
+       public function validateUpdatePosition() {
+               WCF::getSession()->checkPermissions(['admin.user.canManageUserOption']);
+               
+               if (!isset($this->parameters['data']['structure'][0])) {
+                       throw new UserInputException('structure');
+               }
+               
+               $sql = "SELECT  menuItemID
+                       FROM    wcf".WCF_N."_user_profile_menu_item";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute();
+               $menuItemIDs = [];
+               while ($menuItemID = $statement->fetchColumn()) {
+                       $menuItemIDs[$menuItemID] = $menuItemID;
+               }
+               
+               $this->parameters['data']['structure'][0] = ArrayUtil::toIntegerArray($this->parameters['data']['structure'][0]);
+               foreach ($this->parameters['data']['structure'][0] as $menuItemID) {
+                       if (!isset($menuItemIDs[$menuItemID])) {
+                               throw new UserInputException('structure');
+                       }
+                       
+                       unset($menuItemIDs[$menuItemID]);
+               }
+               
+               if (!empty($menuItemIDs)) {
+                       throw new UserInputException('structure');
+               }
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function updatePosition() {
+               $sql = "UPDATE  wcf".WCF_N."_user_profile_menu_item
+                       SET     showOrder = ?
+                       WHERE   menuItemID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               
+               WCF::getDB()->beginTransaction();
+               for ($i = 0, $length = count($this->parameters['data']['structure'][0]); $i < $length; $i++) {
+                       $statement->execute([
+                               $i,
+                               $this->parameters['data']['structure'][0][$i]
+                       ]);
+               }
+               WCF::getDB()->commitTransaction();
+               
+               // reset cache
+               UserProfileMenuCacheBuilder::getInstance()->reset();
+       }
 }
index eaae0ebfd9967581a4a18a8040a3cb4604c9a741..cf250b503be21d21794981e59b7f5d99bbc2eec5 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 namespace wcf\page;
+use wcf\data\object\type\ObjectType;
 use wcf\data\object\type\ObjectTypeCache;
 use wcf\data\user\follow\UserFollowerList;
 use wcf\data\user\follow\UserFollowingList;
@@ -35,7 +36,7 @@ class UserPage extends AbstractPage {
        
        /**
         * overview editable content object type
-        * @var \wcf\data\object\type\ObjectType
+        * @var ObjectType
         */
        public $objectType;
        
index bb48edce837da54d6fdd010aafdbcb6406485561..45b7f217653c560f4b974bcb365eee81e429cee4 100644 (file)
                <item name="wcf.acp.menu.link.user.option.category.list"><![CDATA[Profilfeld-Kategorien]]></item>
                <item name="wcf.acp.menu.link.user.option.category.add"><![CDATA[Profilfeld-Kategorie hinzufügen]]></item>
                <item name="wcf.acp.menu.link.userOptionDefaults"><![CDATA[Benutzerprofil-Einstellungen]]></item>
+               <item name="wcf.acp.menu.link.user.profileMenu"><![CDATA[Benutzerprofil-Menü]]></item>
                <item name="wcf.acp.menu.link.template"><![CDATA[Templates]]></item>
                <item name="wcf.acp.menu.link.template.list"><![CDATA[Templates]]></item>
                <item name="wcf.acp.menu.link.template.add"><![CDATA[Template hinzufügen]]></item>
@@ -2005,6 +2006,7 @@ Benutzerkontos nun in vollem Umfang nutzen.]]></item>
                <item name="wcf.acp.user.bulkProcessing.sendMail"><![CDATA[E-Mail an Benutzer senden]]></item>
                <item name="wcf.acp.user.bulkProcessing.success"><![CDATA[Die gewählte Aktion wurde auf {#$affectedObjectCount} Benutzer ausgeführt.]]></item>
                <item name="wcf.acp.user.bulkProcessing.warning"><![CDATA[Die Massenbearbeitung von Benutzern führt die unten ausgewählte Aktion <b>ohne zusätzliche Sicherheitsabfrage</b> bei allen Benutzern aus, die unter die eingestellten Bedingungen fallen.]]></item>
+               <item name="wcf.acp.user.profileMenu.sort"><![CDATA[Benutzerprofil-Menü Sortierung]]></item>
        </category>
        
        <category name="wcf.acp.worker">
index 9b4bf83d9867db578762b284fdca1819bb053d02..deee925028bdc6450b198ca48f1df8d10508a330 100644 (file)
@@ -737,6 +737,7 @@ Examples for medium ID detection:
                <item name="wcf.acp.menu.link.user.option.category.list"><![CDATA[Field Categories]]></item>
                <item name="wcf.acp.menu.link.user.option.category.add"><![CDATA[Add Field Category]]></item>
                <item name="wcf.acp.menu.link.userOptionDefaults"><![CDATA[User Field Settings]]></item>
+               <item name="wcf.acp.menu.link.user.profileMenu"><![CDATA[User Profile Menu]]></item>
                <item name="wcf.acp.menu.link.template"><![CDATA[Templates]]></item>
                <item name="wcf.acp.menu.link.template.list"><![CDATA[Templates]]></item>
                <item name="wcf.acp.menu.link.template.add"><![CDATA[Add Template]]></item>
@@ -1952,6 +1953,7 @@ full extend.]]></item>
                <item name="wcf.acp.user.bulkProcessing.sendMail"><![CDATA[Send Email to Users]]></item>
                <item name="wcf.acp.user.bulkProcessing.success"><![CDATA[The selection action has been executed and affected {#$affectedObjectCount} user{if $affectedObjectCount != 1}s{/if}.]]></item>
                <item name="wcf.acp.user.bulkProcessing.warning"><![CDATA[Heads up! The bulk processing executes all actions below on all users matching the selected conditions without any further confirmation prompt!]]></item>
+               <item name="wcf.acp.user.profileMenu.sort"><![CDATA[User Profile Menu Show Order]]></item>
        </category>
        
        <category name="wcf.acp.worker">