Added menuItem pip
authorAlexander Ebert <ebert@woltlab.com>
Tue, 1 Dec 2015 12:54:32 +0000 (13:54 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Tue, 1 Dec 2015 12:54:32 +0000 (13:54 +0100)
wcfsetup/install/files/lib/data/menu/MenuEditor.class.php
wcfsetup/install/files/lib/data/menu/item/MenuItemEditor.class.php
wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/setup/db/install.sql

index 3ca4a5e4615f494c8fefeb1b2b812a384ea087fc..e285bce55a34043460728a08cbb20c8560656731 100644 (file)
@@ -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;
index 75106736c21cdbe549808c5a48b4f3607148b64f..e9d7b0c6b44790a0d4ccdfee177eab5b5f0daafa 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 namespace wcf\data\menu\item;
 use wcf\data\DatabaseObjectEditor;
+use wcf\system\language\LanguageFactory;
+use wcf\system\WCF;
 
 /**
  * Provides functions to edit menu items.
@@ -17,4 +19,57 @@ class MenuItemEditor extends DatabaseObjectEditor {
         * @inheritDoc
         */
        protected static $baseClass = MenuItem::class;
+       
+       /**
+        * @inheritDoc
+        */
+       public static function create(array $parameters = []) {
+               $title = '';
+               if (is_array($parameters['title'])) {
+                       $title = $parameters['title'];
+                       $parameters['title'] = '';
+               }
+               
+               $menuItem = parent::create($parameters);
+               
+               if (is_array($title)) {
+                       if (count($title) > 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 (file)
index 0000000..8304ef0
--- /dev/null
@@ -0,0 +1,204 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\data\menu\item\MenuItem;
+use wcf\data\menu\item\MenuItemEditor;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+
+/**
+ * Installs, updates and deletes menu items.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2015 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @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') . "'");
+                       }
+                       
+                       // <title> 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;
+       }
+}
index 5dfc2ee4f560c1aba2dcbf4d848305e9d2cd1309..a210f90003d9713d8e67af5cd94766e889b4c082 100644 (file)
@@ -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;