From effc938990ce906c83788ddad1b95e565f825e0d Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Tue, 1 Dec 2015 13:54:32 +0100 Subject: [PATCH] Added menuItem pip --- .../files/lib/data/menu/MenuEditor.class.php | 2 +- .../data/menu/item/MenuItemEditor.class.php | 55 +++++ ...enuItemPackageInstallationPlugin.class.php | 204 ++++++++++++++++++ wcfsetup/setup/db/install.sql | 6 +- 4 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php diff --git a/wcfsetup/install/files/lib/data/menu/MenuEditor.class.php b/wcfsetup/install/files/lib/data/menu/MenuEditor.class.php index 3ca4a5e461..e285bce55a 100644 --- a/wcfsetup/install/files/lib/data/menu/MenuEditor.class.php +++ b/wcfsetup/install/files/lib/data/menu/MenuEditor.class.php @@ -65,9 +65,9 @@ class MenuEditor extends DatabaseObjectEditor { $title = reset($title); } - //$menuEditor = new MenuItemEditor($menu); $menuEditor = new self($menu); $menuEditor->update(['title' => $title]); + $menu = new static::$baseClass($menu->menuID); } return $menu; diff --git a/wcfsetup/install/files/lib/data/menu/item/MenuItemEditor.class.php b/wcfsetup/install/files/lib/data/menu/item/MenuItemEditor.class.php index 75106736c2..e9d7b0c6b4 100644 --- a/wcfsetup/install/files/lib/data/menu/item/MenuItemEditor.class.php +++ b/wcfsetup/install/files/lib/data/menu/item/MenuItemEditor.class.php @@ -1,6 +1,8 @@ 1) { + $sql = "SELECT languageCategoryID + FROM wcf".WCF_N."_language_category + WHERE languageCategory = ?"; + $statement = WCF::getDB()->prepareStatement($sql, 1); + $statement->execute(['wcf.menu']); + $languageCategoryID = $statement->fetchSingleColumn(); + + $sql = "INSERT INTO wcf".WCF_N."_language_item + (languageID, languageItem, languageItemValue, languageItemOriginIsSystem, languageCategoryID, packageID) + VALUES (?, ?, ?, ?, ?, ?)"; + $statement = WCF::getDB()->prepareStatement($sql); + + WCF::getDB()->beginTransaction(); + foreach ($title as $languageCode => $value) { + $statement->execute([ + LanguageFactory::getInstance()->getLanguageByCode($languageCode)->languageID, + 'wcf.menu.menuItem' . $menuItem->itemID, + $value, + 1, + $languageCategoryID, + $menuItem->packageID + ]); + } + WCF::getDB()->commitTransaction(); + + $title = 'wcf.menu.menuItem' . $menuItem->itemID; + } + else { + $title = reset($title); + } + + $menuEditor = new self($menuItem); + $menuEditor->update(['title' => $title]); + $menuItem = new static::$baseClass($menuItem->itemID); + } + + return $menuItem; + } } diff --git a/wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php new file mode 100644 index 0000000000..8304ef03ad --- /dev/null +++ b/wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php @@ -0,0 +1,204 @@ + + * @package com.woltlab.wcf + * @subpackage acp.package.plugin + * @category Community Framework + */ +class MenuItemPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin { + /** + * @inheritDoc + */ + public $className = MenuItemEditor::class; + + /** + * @inheritDoc + */ + public $tagName = 'item'; + + /** + * @inheritDoc + */ + protected function handleDelete(array $items) { + $sql = "DELETE FROM wcf".WCF_N."_menu_item + WHERE identifier = ? + AND packageID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + + WCF::getDB()->beginTransaction(); + foreach ($items as $item) { + $statement->execute([ + $item['attributes']['identifier'], + $this->installation->getPackageID() + ]); + } + WCF::getDB()->commitTransaction(); + } + + /** + * @inheritDoc + * @throws SystemException + */ + protected function getElement(\DOMXPath $xpath, array &$elements, \DOMElement $element) { + $nodeValue = $element->nodeValue; + + if ($element->tagName === 'title') { + if (empty($element->getAttribute('language'))) { + throw new SystemException("Missing required attribute 'language' for menu item '" . $element->parentNode->getAttribute('identifier') . "'"); + } + + // can occur multiple times using the `language` attribute + if (!isset($elements['title'])) $elements['title'] = []; + + $elements['title'][$element->getAttribute('language')] = $element->nodeValue; + } + else { + $elements[$element->tagName] = $nodeValue; + } + } + + /** + * @inheritDoc + * @throws SystemException + */ + protected function prepareImport(array $data) { + $menuID = null; + if (!empty($data['elements']['menu'])) { + $sql = "SELECT menuID + FROM wcf".WCF_N."_menu + WHERE identifier = ?"; + $statement = WCF::getDB()->prepareStatement($sql, 1); + $statement->execute([$data['elements']['menu']]); + $row = $statement->fetchSingleRow(); + if ($row === false) { + throw new SystemException("Unable to find menu '" . $data['elements']['menu'] . "' for menu item '" . $data['attributes']['identifier'] . "'"); + } + + $menuID = $row['menuID']; + } + + $parentItemID = null; + if (!empty($data['elements']['parent'])) { + if ($menuID !== null) { + throw new SystemException("The menu item '" . $data['attributes']['identifier'] . "' can either have an associated menu or a parent menu item, but not both."); + } + + $sql = "SELECT * + FROM wcf".WCF_N."_menu_item + WHERE identifier = ?"; + $statement = WCF::getDB()->prepareStatement($sql, 1); + $statement->execute([$data['elements']['parent']]); + $parent = $statement->fetchObject(MenuItem::class); + if ($parent === null) { + throw new SystemException("Unable to find parent menu item '" . $data['elements']['parent'] . "' for menu item '" . $data['attributes']['identifier'] . "'"); + } + + $parentItemID = $parent->itemID; + $menuID = $parent->menuID; + } + + if ($menuID === null && $parentItemID === null) { + throw new SystemException("The menu item '" . $data['attributes']['identifier'] . "' must either have an associated menu or a parent menu item."); + } + + $pageID = null; + if (!empty($data['elements']['page'])) { + $sql = "SELECT pageID + FROM wcf".WCF_N."_page + WHERE identifier = ?"; + $statement = WCF::getDB()->prepareStatement($sql, 1); + $statement->execute([$data['elements']['page']]); + $row = $statement->fetchSingleRow(); + if ($row === false) { + throw new SystemException("Unable to find page '" . $data['elements']['page'] . "' for menu item '" . $data['attributes']['identifier'] . "'"); + } + + $pageID = $row['pageID']; + } + + $externalURL = (!empty($data['elements']['externalurl'])) ? $data['elements']['externalurl'] : ''; + + if ($pageID === null && empty($externalURL)) { + throw new SystemException("The menu item '" . $data['attributes']['identifier'] . "' must either have an associated page or an external url set."); + } + elseif ($pageID !== null && !empty($externalURL)) { + throw new SystemException("The menu item '" . $data['attributes']['identifier'] . "' can either have an associated page or an external url, but not both."); + } + + return [ + 'externalURL' => $externalURL, + 'identifier' => $data['attributes']['identifier'], + 'menuID' => $menuID, + 'originIsSystem' => 1, + 'pageID' => $pageID, + 'parentItemID' => $parentItemID, + 'showOrder' => $this->getItemOrder($menuID, $parentItemID), + 'title' => $this->getI18nValues($data['elements']['title']) + ]; + } + + /** + * @inheritDoc + */ + protected function findExistingItem(array $data) { + $sql = "SELECT * + FROM wcf".WCF_N."_menu_item + WHERE identifier = ? + AND packageID = ?"; + $parameters = array( + $data['identifier'], + $this->installation->getPackageID() + ); + + return array( + 'sql' => $sql, + 'parameters' => $parameters + ); + } + + /** + * @inheritDoc + */ + protected function import(array $row, array $data) { + // updating menu items is not supported because all fields that could be modified + // would potentially overwrite changes made by the user + if (!empty($row)) { + return new MenuItem(null, $row); + } + + return parent::import($row, $data); + } + + /** + * Returns the show order for a new item that will append it to the current + * menu or parent item. + * + * @param int $menuID + * @param int $parentItemID + * @return int + * @throws \wcf\system\database\DatabaseException + */ + protected function getItemOrder($menuID, $parentItemID = null) { + $sql = "SELECT MAX(showOrder) AS showOrder + FROM wcf".WCF_N."_menu_item + WHERE " . ($parentItemID === null ? 'menuID' : 'parentItemID') . " = ?"; + $statement = WCF::getDB()->prepareStatement($sql, 1); + $statement->execute([ + ($parentItemID === null ? $menuID : $parentItemID) + ]); + + $row = $statement->fetchSingleRow(); + + return (!$row['showOrder']) ? 1 : $row['showOrder'] + 1; + } +} diff --git a/wcfsetup/setup/db/install.sql b/wcfsetup/setup/db/install.sql index 5dfc2ee4f5..a210f90003 100644 --- a/wcfsetup/setup/db/install.sql +++ b/wcfsetup/setup/db/install.sql @@ -526,7 +526,8 @@ CREATE TABLE wcf1_menu_item ( externalURL VARCHAR(255) NOT NULL DEFAULT '', showOrder INT(10) NOT NULL DEFAULT 0, isDisabled TINYINT(1) NOT NULL DEFAULT 0, - originIsSystem TINYINT(1) NOT NULL DEFAULT 0 + originIsSystem TINYINT(1) NOT NULL DEFAULT 0, + packageID INT(10) NOT NULL ); DROP TABLE IF EXISTS wcf1_message_embedded_object; @@ -1603,7 +1604,8 @@ ALTER TABLE wcf1_menu ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packa ALTER TABLE wcf1_menu_item ADD FOREIGN KEY (menuID) REFERENCES wcf1_menu (menuID) ON DELETE CASCADE; ALTER TABLE wcf1_menu_item ADD FOREIGN KEY (parentItemID) REFERENCES wcf1_menu_item (itemID) ON DELETE SET NULL; -ALTER TABLE wcf1_menu_item ADD FOREIGN KEY (pageID) REFERENCES wcf1_page (pageID) ON DELETE CASCADE; +ALTER TABLE wcf1_menu_item ADD FOREIGN KEY (pageID) REFERENCES wcf1_page (pageID) ON DELETE CASCADE; +ALTER TABLE wcf1_menu_item ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE; ALTER TABLE wcf1_modification_log ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE; ALTER TABLE wcf1_modification_log ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE SET NULL; -- 2.20.1