<visibleeveryhwere>1</visibleeveryhwere>
</box>
</menu>
+
+ <menu identifier="com.woltlab.wcf.FooterMenu">
+ <title language="de">Footer-Menü</title>
+ <title language="en">Footer Menu</title>
+
+ <box>
+ <position>footer</position>
+ <showheader>0</showheader>
+ <visibleeveryhwere>1</visibleeveryhwere>
+ </box>
+ </menu>
</import>
</data>
<page>com.woltlab.wcf.UserSearch</page>
</item>
- <!-- TODO: privacy policy / footer menu? -->
+ <item identifier="com.woltlab.wcf.PrivacyPolicy">
+ <menu>com.woltlab.wcf.FooterMenu</menu>
+ <title language="de"><![CDATA[Datenschutzerklärung]]></title>
+ <title language="en"><![CDATA[Privacy Policy]]></title>
+ <page>com.woltlab.wcf.PrivacyPolicy</page>
+ </item>
</import>
</data>
--- /dev/null
+<ol>
+ {foreach from=$menuItemNodeList item=menuItemNode}
+ <li>
+ <a href="{$menuItemNode->getMenuItem()->getURL()}">{lang}{$menuItemNode->getMenuItem()->title}{/lang}</a>
+
+ {if $menuItemNode->hasChildren()}<ol>{else}</li>{/if}
+
+ {if !$menuItemNode->hasChildren() && $menuItemNode->isLastSibling()}
+ {@"</ol></li>"|str_repeat:$menuItemNode->getOpenParentNodes()}
+ {/if}
+ {/foreach}
+</ol>
</dd>
</dl>
+ {if $action == 'add' || $menu->identifier != 'com.woltlab.wcf.MainMenu'}
+ <dl{if $errorField == 'position'} class="formError"{/if}>
+ <dt><label for="position">{lang}wcf.acp.box.position{/lang}</label></dt>
+ <dd>
+ <select name="position" id="position">
+ {foreach from=$availablePositions item=availablePosition}
+ <option value="{@$availablePosition}"{if $availablePosition == $position} selected="selected"{/if}>{lang}wcf.acp.box.position.{@$availablePosition}{/lang}</option>
+ {/foreach}
+ </select>
+
+ {if $errorField == 'position'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {else}
+ {lang}wcf.acp.box.position.error.{@$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ </dd>
+ </dl>
+
+ <dl>
+ <dt><label for="showOrder">{lang}wcf.acp.box.showOrder{/lang}</label></dt>
+ <dd>
+ <input type="number" id="showOrder" name="showOrder" value="{@$showOrder}" class="tiny" min="0" />
+ </dd>
+ </dl>
+
+ <dl{if $errorField == 'cssClassName'} class="formError"{/if}>
+ <dt><label for="cssClassName">{lang}wcf.acp.box.cssClassName{/lang}</label></dt>
+ <dd>
+ <input type="text" id="cssClassName" name="cssClassName" value="{$cssClassName}" class="long" />
+ {if $errorField == 'cssClassName'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {else}
+ {lang}wcf.acp.box.cssClassName.error.{@$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ </dd>
+ </dl>
+
+ <dl>
+ <dt></dt>
+ <dd>
+ <label><input type="checkbox" id="showHeader" name="showHeader" value="1" {if $showHeader}checked="checked" {/if}/> {lang}wcf.acp.box.showHeader{/lang}</label>
+ </dd>
+ </dl>
+
+ <dl>
+ <dt></dt>
+ <dd>
+ <label><input type="checkbox" id="visibleEverywhere" name="visibleEverywhere" value="1" {if $visibleEverywhere}checked="checked" {/if}/> {lang}wcf.acp.box.visibleEverywhere{/lang}</label>
+ </dd>
+ </dl>
+ {/if}
+
{event name='dataFields'}
</section>
// 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
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;
}
<?php
namespace wcf\acp\form;
+use wcf\data\box\Box;
use wcf\data\menu\MenuAction;
use wcf\data\menu\MenuEditor;
use wcf\form\AbstractForm;
use wcf\system\exception\UserInputException;
use wcf\system\language\I18nHandler;
use wcf\system\WCF;
+use wcf\util\StringUtil;
/**
* Shows the menu add form.
*/
public $title = '';
+ /**
+ * box position
+ * @var string
+ */
+ public $position = '';
+
+ /**
+ * show order
+ * @var integer
+ */
+ public $showOrder = 0;
+
+ /**
+ * true if created box is visible everywhere
+ * @var boolean
+ */
+ public $visibleEverywhere = 1;
+
+ /**
+ * css class name of created box
+ * @var string
+ */
+ public $cssClassName = '';
+
+ /**
+ * true if box header is visible
+ * @var boolean
+ */
+ public $showHeader = 1;
+
/**
* @inheritDoc
*/
I18nHandler::getInstance()->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']);
}
/**
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');
+ }
}
/**
'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')) {
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
));
}
}
<?php
namespace wcf\acp\form;
+use wcf\data\box\BoxAction;
use wcf\data\menu\Menu;
use wcf\data\menu\MenuAction;
use wcf\form\AbstractForm;
}
}
+ /**
+ * @inheritDoc
+ */
+ protected function validatePosition() {
+ if ($this->menu->identifier != 'com.woltlab.wcf.MainMenu') {
+ parent::validatePosition();
+ }
+ }
+
/**
* @inheritDoc
*/
'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
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;
}
}
* @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'));
+ }
}
*/
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
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() {
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);
+ }
}
}
}
}
-
- return $box;
}
/**
<?php
namespace wcf\data\menu;
+use wcf\data\box\Box;
use wcf\data\DatabaseObject;
use wcf\system\WCF;
*/
protected static $databaseTableIndexName = 'menuID';
+ /**
+ * menu item node list
+ * @var \RecursiveIteratorIterator
+ */
+ protected $menuItemNodeList = null;
+
+ /**
+ * box object
+ * @var Box
+ */
+ protected $box = null;
+
/**
* Returns true if the active user can delete this menu.
*
return false;
}
+
+ /**
+ * Returns the items of this menu.
+ *
+ * @return \RecursiveIteratorIterator
+ */
+ public function getMenuItemNodeList() {
+ if ($this->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;
+ }
}
<?php
namespace wcf\data\menu;
use wcf\data\AbstractDatabaseObjectAction;
+use wcf\data\box\BoxAction;
+use wcf\data\box\BoxEditor;
use wcf\system\exception\PermissionDeniedException;
/**
*/
protected $requireACP = ['create', 'delete', 'update'];
+ /**
+ * @inheritdoc
+ */
+ public function create() {
+ // create menu
+ $menu = parent::create();
+
+ // create box
+ $boxData = $this->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
*/
<?php
namespace wcf\data\menu\item;
use wcf\data\DatabaseObject;
+use wcf\data\page\Page;
use wcf\system\WCF;
/**
*/
protected static $databaseTableIndexName = 'itemID';
+ /**
+ * page object
+ * @var Page
+ */
+ protected $page = null;
+
/**
* Returns true if the active user can delete this menu item.
*
return false;
}
+
+ /**
+ * Returns the URL of this menu item.
+ *
+ * @return string
+ */
+ public function getURL() {
+ if ($this->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;
+ }
}
namespace wcf\data\page;
use wcf\data\DatabaseObject;
use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\request\LinkHandler;
use wcf\system\WCF;
/**
* @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);
+ }
}
/**
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}'");
}
'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()
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.
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;
}
/**