From aa779877b40cb244ee98515772671a64e4f5ce25 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Wed, 30 Dec 2015 14:07:23 +0100 Subject: [PATCH] Added menu box implementation --- com.woltlab.wcf/menu.xml | 11 +++ com.woltlab.wcf/menuItem.xml | 7 +- com.woltlab.wcf/templates/__menu.tpl | 12 +++ .../install/files/acp/templates/menuAdd.tpl | 60 +++++++++++++++ .../files/lib/acp/form/BoxAddForm.class.php | 2 +- .../files/lib/acp/form/BoxEditForm.class.php | 4 + .../files/lib/acp/form/MenuAddForm.class.php | 74 ++++++++++++++++++- .../files/lib/acp/form/MenuEditForm.class.php | 29 ++++++++ .../files/lib/acp/page/BoxListPage.class.php | 10 +++ .../install/files/lib/data/box/Box.class.php | 43 ++++++++--- .../files/lib/data/box/BoxAction.class.php | 2 - .../files/lib/data/menu/Menu.class.php | 68 +++++++++++++++++ .../files/lib/data/menu/MenuAction.class.php | 26 +++++++ .../lib/data/menu/item/MenuItem.class.php | 36 +++++++++ .../files/lib/data/page/Page.class.php | 14 +++- .../MenuPackageInstallationPlugin.class.php | 7 +- .../plugin/PageBlockTemplatePlugin.class.php | 8 +- 17 files changed, 388 insertions(+), 25 deletions(-) create mode 100644 com.woltlab.wcf/templates/__menu.tpl diff --git a/com.woltlab.wcf/menu.xml b/com.woltlab.wcf/menu.xml index 80da9c4f5e..03955034c4 100644 --- a/com.woltlab.wcf/menu.xml +++ b/com.woltlab.wcf/menu.xml @@ -11,5 +11,16 @@ 1 + + + Footer-Menü + Footer Menu + + + footer + 0 + 1 + + diff --git a/com.woltlab.wcf/menuItem.xml b/com.woltlab.wcf/menuItem.xml index cb2f054c1f..c9087974bb 100644 --- a/com.woltlab.wcf/menuItem.xml +++ b/com.woltlab.wcf/menuItem.xml @@ -39,6 +39,11 @@ com.woltlab.wcf.UserSearch - + + com.woltlab.wcf.FooterMenu + <![CDATA[Datenschutzerklärung]]> + <![CDATA[Privacy Policy]]> + com.woltlab.wcf.PrivacyPolicy + diff --git a/com.woltlab.wcf/templates/__menu.tpl b/com.woltlab.wcf/templates/__menu.tpl new file mode 100644 index 0000000000..91a4298d11 --- /dev/null +++ b/com.woltlab.wcf/templates/__menu.tpl @@ -0,0 +1,12 @@ +
    + {foreach from=$menuItemNodeList item=menuItemNode} +
  1. + {lang}{$menuItemNode->getMenuItem()->title}{/lang} + + {if $menuItemNode->hasChildren()}
      {else}{/if} + + {if !$menuItemNode->hasChildren() && $menuItemNode->isLastSibling()} + {@"
  2. "|str_repeat:$menuItemNode->getOpenParentNodes()} + {/if} + {/foreach} +
diff --git a/wcfsetup/install/files/acp/templates/menuAdd.tpl b/wcfsetup/install/files/acp/templates/menuAdd.tpl index 82677d9ce2..8459533de3 100644 --- a/wcfsetup/install/files/acp/templates/menuAdd.tpl +++ b/wcfsetup/install/files/acp/templates/menuAdd.tpl @@ -42,6 +42,66 @@ + {if $action == 'add' || $menu->identifier != 'com.woltlab.wcf.MainMenu'} + +
+
+ + + {if $errorField == 'position'} + + {if $errorType == 'empty'} + {lang}wcf.global.form.error.empty{/lang} + {else} + {lang}wcf.acp.box.position.error.{@$errorType}{/lang} + {/if} + + {/if} +
+ + +
+
+
+ +
+
+ + +
+
+ + {if $errorField == 'cssClassName'} + + {if $errorType == 'empty'} + {lang}wcf.global.form.error.empty{/lang} + {else} + {lang}wcf.acp.box.cssClassName.error.{@$errorType}{/lang} + {/if} + + {/if} +
+ + +
+
+
+ +
+
+ +
+
+
+ +
+
+ {/if} + {event name='dataFields'} diff --git a/wcfsetup/install/files/lib/acp/form/BoxAddForm.class.php b/wcfsetup/install/files/lib/acp/form/BoxAddForm.class.php index 160628691e..807948f0d9 100644 --- a/wcfsetup/install/files/lib/acp/form/BoxAddForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/BoxAddForm.class.php @@ -257,7 +257,7 @@ class BoxAddForm extends AbstractForm { // set generic box identifier $boxEditor = new BoxEditor($returnValues['returnValues']); $boxEditor->update([ - 'identifier' => 'com.woltlab.wcf.generic'.$boxEditor->boxID + 'identifier' => 'com.woltlab.wcf.genericBox'.$boxEditor->boxID ]); // call saved event diff --git a/wcfsetup/install/files/lib/acp/form/BoxEditForm.class.php b/wcfsetup/install/files/lib/acp/form/BoxEditForm.class.php index 827fbff123..dd4a8e9be9 100644 --- a/wcfsetup/install/files/lib/acp/form/BoxEditForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/BoxEditForm.class.php @@ -47,6 +47,10 @@ class BoxEditForm extends BoxAddForm { if (!$this->box->boxID) { throw new IllegalLinkException(); } + if ($this->box->boxType == 'menu') { + // it's not allowed to edit menu boxes directly + throw new IllegalLinkException(); + } if ($this->box->isMultilingual) $this->isMultilingual = 1; } diff --git a/wcfsetup/install/files/lib/acp/form/MenuAddForm.class.php b/wcfsetup/install/files/lib/acp/form/MenuAddForm.class.php index c63717d474..6744d3ce5c 100644 --- a/wcfsetup/install/files/lib/acp/form/MenuAddForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/MenuAddForm.class.php @@ -1,11 +1,13 @@ readValues(); if (I18nHandler::getInstance()->isPlainValue('title')) $this->title = I18nHandler::getInstance()->getValue('title'); + + $this->visibleEverywhere = $this->showOrder = 0; + if (isset($_POST['position'])) $this->position = $_POST['position']; + if (isset($_POST['showOrder'])) $this->showOrder = intval($_POST['showOrder']); + if (isset($_POST['visibleEverywhere'])) $this->visibleEverywhere = intval($_POST['visibleEverywhere']); + if (isset($_POST['cssClassName'])) $this->cssClassName = StringUtil::trim($_POST['cssClassName']); + if (isset($_POST['showHeader'])) $this->showHeader = intval($_POST['showHeader']); } /** @@ -70,6 +109,20 @@ class MenuAddForm extends AbstractForm { throw new UserInputException('title', 'multilingual'); } } + + // validate box position + $this->validatePosition(); + } + + /** + * Validates box position. + * + * @throws UserInputException + */ + protected function validatePosition() { + if (!in_array($this->position, Box::$availablePositions)) { + throw new UserInputException('position'); + } } /** @@ -83,12 +136,21 @@ class MenuAddForm extends AbstractForm { 'title' => $this->title, 'packageID' => 1, 'identifier' => '' - )))); + )), 'boxData' => array( + 'name' => $this->title, + 'boxType' => 'menu', + 'position' => $this->position, + 'visibleEverywhere' => ($this->visibleEverywhere) ? 1 : 0, + 'showHeader' => ($this->showHeader) ? 1 : 0, + 'showOrder' => $this->showOrder, + 'cssClassName' => $this->cssClassName, + 'packageID' => 1 + ))); $returnValues = $this->objectAction->executeAction(); // set generic identifier $menuEditor = new MenuEditor($returnValues['returnValues']); $menuEditor->update(array( - 'identifier' => 'com.woltlab.wcf.generic'.$menuEditor->menuID + 'identifier' => 'com.woltlab.wcf.genericMenu'.$menuEditor->menuID )); // save i18n if (!I18nHandler::getInstance()->isPlainValue('title')) { @@ -122,7 +184,13 @@ class MenuAddForm extends AbstractForm { WCF::getTPL()->assign(array( 'action' => 'add', - 'title' => 'title' + 'title' => 'title', + 'position' => $this->position, + 'cssClassName' => $this->cssClassName, + 'showOrder' => $this->showOrder, + 'visibleEverywhere' => $this->visibleEverywhere, + 'showHeader' => $this->showHeader, + 'availablePositions' => Box::$availableMenuPositions )); } } diff --git a/wcfsetup/install/files/lib/acp/form/MenuEditForm.class.php b/wcfsetup/install/files/lib/acp/form/MenuEditForm.class.php index cbaf394dc5..954b5bcbc0 100644 --- a/wcfsetup/install/files/lib/acp/form/MenuEditForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/MenuEditForm.class.php @@ -1,5 +1,6 @@ menu->identifier != 'com.woltlab.wcf.MainMenu') { + parent::validatePosition(); + } + } + /** * @inheritDoc */ @@ -69,6 +79,19 @@ class MenuEditForm extends MenuAddForm { 'title' => $this->title )))); $this->objectAction->executeAction(); + + // update box + if ($this->menu->identifier != 'com.woltlab.wcf.MainMenu') { + $boxAction = new BoxAction(array($this->menu->getBox()->boxID), 'update', array('data' => array_merge($this->additionalFields, array( + 'position' => $this->position, + 'visibleEverywhere' => ($this->visibleEverywhere) ? 1 : 0, + 'showHeader' => ($this->showHeader) ? 1 : 0, + 'showOrder' => $this->showOrder, + 'cssClassName' => $this->cssClassName + )))); + $boxAction->executeAction(); + } + $this->saved(); // show success @@ -87,6 +110,12 @@ class MenuEditForm extends MenuAddForm { I18nHandler::getInstance()->setOptions('title', 1, $this->menu->title, 'wcf.menu.menu\d+'); $this->title = $this->menu->title; + $this->position = $this->menu->getBox()->position; + $this->cssClassName = $this->menu->getBox()->cssClassName; + $this->cssClassName = $this->menu->getBox()->cssClassName; + $this->showOrder = $this->menu->getBox()->showOrder; + $this->visibleEverywhere = $this->menu->getBox()->visibleEverywhere; + $this->showHeader = $this->menu->getBox()->showHeader; } } diff --git a/wcfsetup/install/files/lib/acp/page/BoxListPage.class.php b/wcfsetup/install/files/lib/acp/page/BoxListPage.class.php index 195bf83125..e8fb0c7170 100644 --- a/wcfsetup/install/files/lib/acp/page/BoxListPage.class.php +++ b/wcfsetup/install/files/lib/acp/page/BoxListPage.class.php @@ -38,4 +38,14 @@ class BoxListPage extends SortablePage { * @see \wcf\page\SortablePage::$validSortFields */ public $validSortFields = array('boxID', 'name', 'boxType', 'position', 'showOrder'); + + /** + * @inheritdoc + */ + protected function initObjectList() { + parent::initObjectList(); + + // hide menu boxes + $this->objectList->getConditionBuilder()->add('box.boxType <> ?', array('menu')); + } } diff --git a/wcfsetup/install/files/lib/data/box/Box.class.php b/wcfsetup/install/files/lib/data/box/Box.class.php index e61422c729..7d7cb4c6aa 100644 --- a/wcfsetup/install/files/lib/data/box/Box.class.php +++ b/wcfsetup/install/files/lib/data/box/Box.class.php @@ -53,6 +53,12 @@ class Box extends DatabaseObject { */ public static $availablePositions = ['hero', 'headerBoxes', 'top', 'sidebarLeft', 'contentTop', 'sidebarRight', 'contentBottom', 'bottom', 'footerBoxes', 'footer']; + /** + * available menu positions + * @var string[] + */ + public static $availableMenuPositions = ['top', 'sidebarLeft', 'sidebarRight', 'bottom', 'footer']; + /** * menu object * @var Menu @@ -177,22 +183,19 @@ class Box extends DatabaseObject { return $this->getController()->hasContent(); } else if ($this->boxType == 'menu') { - // TODO: - return false; return $this->getMenu()->hasContent(); } + + $boxContent = $this->getBoxContent(); + $content = ''; + if ($this->isMultilingual) { + if (isset($boxContent[WCF::getLanguage()->languageID])) $content = $boxContent[WCF::getLanguage()->languageID]['content']; + } else { - $boxContent = $this->getBoxContent(); - $content = ''; - if ($this->isMultilingual) { - if (isset($boxContent[WCF::getLanguage()->languageID])) $content = $boxContent[WCF::getLanguage()->languageID]['content']; - } - else { - if (isset($boxContent[0])) $content = $boxContent[0]['content']; - } - - return !empty($content); + if (isset($boxContent[0])) $content = $boxContent[0]['content']; } + + return !empty($content); } public function getController() { @@ -283,4 +286,20 @@ class Box extends DatabaseObject { return $statement->fetchObject(Box::class); } + + /** + * Returns the box with the menu id. + * + * @param int $menuID + * @return Box + */ + public static function getBoxByMenuID($menuID) { + $sql = "SELECT * + FROM wcf".WCF_N."_box + WHERE menuID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute([$menuID]); + + return $statement->fetchObject(Box::class); + } } diff --git a/wcfsetup/install/files/lib/data/box/BoxAction.class.php b/wcfsetup/install/files/lib/data/box/BoxAction.class.php index a23b4de7f9..dc8911b629 100644 --- a/wcfsetup/install/files/lib/data/box/BoxAction.class.php +++ b/wcfsetup/install/files/lib/data/box/BoxAction.class.php @@ -99,8 +99,6 @@ class BoxAction extends AbstractDatabaseObjectAction { } } } - - return $box; } /** diff --git a/wcfsetup/install/files/lib/data/menu/Menu.class.php b/wcfsetup/install/files/lib/data/menu/Menu.class.php index 088d39ccd7..631255f3fc 100644 --- a/wcfsetup/install/files/lib/data/menu/Menu.class.php +++ b/wcfsetup/install/files/lib/data/menu/Menu.class.php @@ -1,5 +1,6 @@ menuItemNodeList === null) { + $this->menuItemNodeList = MenuCache::getInstance()->getMenuItemsByMenuID($this->menuID)->getNodeList(); + } + + return $this->menuItemNodeList; + } + + /** + * Returns false if this menu has no content (has menu items). + * + * @return boolean + */ + public function hasContent() { + return true; // @todo + //return count(MenuCache::getInstance()->getMenuItemsByMenuID($this->menuID)->getNodeList()); + } + + /** + * Returns the title for the rendered version of this menu. + * + * @return string + */ + public function getTitle() { + return WCF::getLanguage()->get($this->title); + } + + /** + * Returns the content for the rendered version of this menu. + * + * @return string + */ + public function getContent() { + WCF::getTPL()->assign(['menuItemNodeList' => $this->getMenuItemNodeList()]); + return WCF::getTPL()->fetch('__menu'); + } + + /** + * Returns the box of this menu. + * + * @return Box + */ + public function getBox() { + if ($this->box === null) { + $this->box = Box::getBoxByMenuID($this->menuID); + } + + return $this->box; + } } diff --git a/wcfsetup/install/files/lib/data/menu/MenuAction.class.php b/wcfsetup/install/files/lib/data/menu/MenuAction.class.php index 644100d287..3aa0af9b44 100644 --- a/wcfsetup/install/files/lib/data/menu/MenuAction.class.php +++ b/wcfsetup/install/files/lib/data/menu/MenuAction.class.php @@ -1,6 +1,8 @@ parameters['boxData']; + $boxData['menuID'] = $menu->menuID; + $boxData['identifier'] = ''; + $boxAction = new BoxAction([], 'create', ['data' => $boxData]); + $returnValues = $boxAction->executeAction(); + + // set generic box identifier + $boxEditor = new BoxEditor($returnValues['returnValues']); + $boxEditor->update([ + 'identifier' => 'com.woltlab.wcf.genericMenuBox'.$boxEditor->boxID + ]); + + // return new menu + return $menu; + } + /** * @inheritDoc */ diff --git a/wcfsetup/install/files/lib/data/menu/item/MenuItem.class.php b/wcfsetup/install/files/lib/data/menu/item/MenuItem.class.php index 7aac56977e..3f936b1043 100644 --- a/wcfsetup/install/files/lib/data/menu/item/MenuItem.class.php +++ b/wcfsetup/install/files/lib/data/menu/item/MenuItem.class.php @@ -1,6 +1,7 @@ pageID) { + return $this->getPage()->getURL(); + } + else { + return $this->externalURL; + } + } + + /** + * Returns the page that is linked by this menu item. + * + * @return Page + */ + public function getPage() { + if ($this->page === null) { + if ($this->pageID) { + $this->page = new Page($this->pageID); + } + } + + return $this->page; + } } diff --git a/wcfsetup/install/files/lib/data/page/Page.class.php b/wcfsetup/install/files/lib/data/page/Page.class.php index 9d567c7d52..322f97b7fd 100644 --- a/wcfsetup/install/files/lib/data/page/Page.class.php +++ b/wcfsetup/install/files/lib/data/page/Page.class.php @@ -2,6 +2,7 @@ namespace wcf\data\page; use wcf\data\DatabaseObject; use wcf\system\database\util\PreparedStatementConditionBuilder; +use wcf\system\request\LinkHandler; use wcf\system\WCF; /** @@ -108,7 +109,18 @@ class Page extends DatabaseObject { * @return string */ public function getURL() { - // @todo + if ($this->controller) { + // todo + $controllerParts = explode('\\', $this->controller); + $controllerName = $controllerParts[count($controllerParts) - 1]; + $controllerName = preg_replace('/(page|action|form)$/i', '', $controllerName); + return LinkHandler::getInstance()->getLink($controllerName, [ + 'application' => $controllerParts[0] + ]); + } + else { + return LinkHandler::getInstance()->getCmsLink($this->pageID); + } } /** diff --git a/wcfsetup/install/files/lib/system/package/plugin/MenuPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/MenuPackageInstallationPlugin.class.php index 76ae7eedb0..e5124a79a6 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/MenuPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/MenuPackageInstallationPlugin.class.php @@ -106,13 +106,11 @@ class MenuPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin if (!empty($data['elements']['box'])) { $position = $data['elements']['box']['position']; - $visibleEverywhere = false; if ($identifier === 'com.woltlab.wcf.MainMenu') { $position = 'mainMenu'; - $visibleEverywhere = true; } - else if (!in_array($position, ['bottom', 'contentBottom', 'contentTop', 'footer', 'footerBoxes', 'headerBoxes', 'hero', 'sidebarLeft', 'sidebarRight', 'top'])) { + else if (!in_array($position, Box::$availableMenuPositions)) { throw new SystemException("Unknown box position '{$position}' for menu box '{$identifier}'"); } @@ -121,7 +119,8 @@ class MenuPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin 'name' => $this->getI18nValues($data['elements']['title'], true), 'boxType' => 'menu', 'position' => $position, - 'visibleEverywhere' => ($visibleEverywhere) ? 1 : 0, + 'showHeader' => (!empty($data['elements']['box']['showheader']) ? 1 : 0), + 'visibleEverywhere' => (!empty($data['elements']['box']['visibleeveryhwere']) ? 1 : 0), 'cssClassName' => (!empty($data['elements']['box']['cssclassname'])), 'originIsSystem' => 1, 'packageID' => $this->installation->getPackageID() diff --git a/wcfsetup/install/files/lib/system/template/plugin/PageBlockTemplatePlugin.class.php b/wcfsetup/install/files/lib/system/template/plugin/PageBlockTemplatePlugin.class.php index 1446d01907..04155980a7 100644 --- a/wcfsetup/install/files/lib/system/template/plugin/PageBlockTemplatePlugin.class.php +++ b/wcfsetup/install/files/lib/system/template/plugin/PageBlockTemplatePlugin.class.php @@ -5,6 +5,7 @@ use wcf\system\exception\SystemException; use wcf\system\language\LanguageFactory; use wcf\system\request\LinkHandler; use wcf\system\template\TemplateEngine; +use wcf\util\StringUtil; /** * Template block plugin which generates a link to a CMS page. @@ -68,7 +69,12 @@ class PageBlockTemplatePlugin implements IBlockTemplatePlugin { if ($language !== null) $languageID = $language->languageID; } - return LinkHandler::getInstance()->getCmsLink($pageID, $languageID); + $link = LinkHandler::getInstance()->getCmsLink($pageID, $languageID); + if (!empty($tagArgs['encode'])) { + return StringUtil::encodeHTML($link); + } + + return $link; } /** -- 2.20.1