2 namespace wcf\system\package\plugin
;
3 use wcf\data\menu\item\MenuItem
;
4 use wcf\data\menu\item\MenuItemEditor
;
5 use wcf\system\exception\SystemException
;
9 * Installs, updates and deletes menu items.
11 * @author Alexander Ebert
12 * @copyright 2001-2016 WoltLab GmbH
13 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14 * @package WoltLabSuite\Core\Acp\Package\Plugin
17 class MenuItemPackageInstallationPlugin
extends AbstractXMLPackageInstallationPlugin
{
21 public $className = MenuItemEditor
::class;
26 public $tagName = 'item';
31 protected function handleDelete(array $items) {
32 $sql = "DELETE FROM wcf".WCF_N
."_menu_item
35 $statement = WCF
::getDB()->prepareStatement($sql);
37 WCF
::getDB()->beginTransaction();
38 foreach ($items as $item) {
40 $item['attributes']['identifier'],
41 $this->installation
->getPackageID()
44 WCF
::getDB()->commitTransaction();
49 * @throws SystemException
51 protected function getElement(\DOMXPath
$xpath, array &$elements, \DOMElement
$element) {
52 $nodeValue = $element->nodeValue
;
54 if ($element->tagName
=== 'title') {
55 if (empty($element->getAttribute('language'))) {
56 throw new SystemException("Missing required attribute 'language' for menu item '" . $element->parentNode
->getAttribute('identifier') . "'");
59 // <title> can occur multiple times using the `language` attribute
60 if (!isset($elements['title'])) $elements['title'] = [];
62 $elements['title'][$element->getAttribute('language')] = $element->nodeValue
;
65 $elements[$element->tagName
] = $nodeValue;
71 * @throws SystemException
73 protected function prepareImport(array $data) {
75 if (!empty($data['elements']['menu'])) {
77 FROM wcf".WCF_N
."_menu
78 WHERE identifier = ?";
79 $statement = WCF
::getDB()->prepareStatement($sql, 1);
80 $statement->execute([$data['elements']['menu']]);
81 $row = $statement->fetchSingleRow();
83 throw new SystemException("Unable to find menu '" . $data['elements']['menu'] . "' for menu item '" . $data['attributes']['identifier'] . "'");
86 $menuID = $row['menuID'];
90 if (!empty($data['elements']['parent'])) {
91 if ($menuID !== null) {
92 throw new SystemException("The menu item '" . $data['attributes']['identifier'] . "' can either have an associated menu or a parent menu item, but not both.");
96 FROM wcf".WCF_N
."_menu_item
97 WHERE identifier = ?";
98 $statement = WCF
::getDB()->prepareStatement($sql, 1);
99 $statement->execute([$data['elements']['parent']]);
101 /** @var MenuItem|null $parent */
102 $parent = $statement->fetchObject(MenuItem
::class);
103 if ($parent === null) {
104 throw new SystemException("Unable to find parent menu item '" . $data['elements']['parent'] . "' for menu item '" . $data['attributes']['identifier'] . "'");
107 $parentItemID = $parent->itemID
;
108 $menuID = $parent->menuID
;
111 if ($menuID === null && $parentItemID === null) {
112 throw new SystemException("The menu item '" . $data['attributes']['identifier'] . "' must either have an associated menu or a parent menu item.");
116 if (!empty($data['elements']['page'])) {
117 $sql = "SELECT pageID
118 FROM wcf".WCF_N
."_page
119 WHERE identifier = ?";
120 $statement = WCF
::getDB()->prepareStatement($sql, 1);
121 $statement->execute([$data['elements']['page']]);
122 $row = $statement->fetchSingleRow();
123 if ($row === false) {
124 throw new SystemException("Unable to find page '" . $data['elements']['page'] . "' for menu item '" . $data['attributes']['identifier'] . "'");
127 $pageID = $row['pageID'];
130 $externalURL = (!empty($data['elements']['externalURL'])) ?
$data['elements']['externalURL'] : '';
132 if ($pageID === null && empty($externalURL)) {
133 throw new SystemException("The menu item '" . $data['attributes']['identifier'] . "' must either have an associated page or an external url set.");
135 else if ($pageID !== null && !empty($externalURL)) {
136 throw new SystemException("The menu item '" . $data['attributes']['identifier'] . "' can either have an associated page or an external url, but not both.");
140 'externalURL' => $externalURL,
141 'identifier' => $data['attributes']['identifier'],
143 'originIsSystem' => 1,
145 'parentItemID' => $parentItemID,
146 'showOrder' => $this->getItemOrder($menuID, $parentItemID),
147 'title' => $this->getI18nValues($data['elements']['title'])
154 protected function findExistingItem(array $data) {
156 FROM wcf".WCF_N
."_menu_item
161 $this->installation
->getPackageID()
166 'parameters' => $parameters
173 protected function import(array $row, array $data) {
174 // updating menu items is not supported because all fields that could be modified
175 // would potentially overwrite changes made by the user
177 return new MenuItem(null, $row);
180 return parent
::import($row, $data);
184 * Returns the show order for a new item that will append it to the current
185 * menu or parent item.
187 * @param integer $menuID
188 * @param integer $parentItemID
190 * @throws \wcf\system\database\DatabaseException
192 protected function getItemOrder($menuID, $parentItemID = null) {
193 $sql = "SELECT MAX(showOrder) AS showOrder
194 FROM wcf".WCF_N
."_menu_item
195 WHERE " . ($parentItemID === null ?
'menuID' : 'parentItemID') . " = ?";
196 $statement = WCF
::getDB()->prepareStatement($sql, 1);
197 $statement->execute([
198 $parentItemID === null ?
$menuID : $parentItemID
201 $row = $statement->fetchSingleRow();
203 return (!$row['showOrder']) ?
1 : $row['showOrder'] +
1;