From: Matthias Schmidt Date: Sun, 30 Dec 2012 17:47:52 +0000 (+0100) Subject: Fixes and improves ACPMenuCacheBuilder X-Git-Tag: 2.0.0_Beta_1~647^2~1 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=4b9e3e0dc9b4598e3bcc89a007605a81b1021074;p=GitHub%2FWoltLab%2FWCF.git Fixes and improves ACPMenuCacheBuilder Previously, the menu items for the option categories were broken. Additionally, I rewrote the code using database object lists which saves two queries, only including a sub-query. --- diff --git a/wcfsetup/install/files/lib/system/cache/builder/ACPMenuCacheBuilder.class.php b/wcfsetup/install/files/lib/system/cache/builder/ACPMenuCacheBuilder.class.php index 993e130935..02a494eb3f 100644 --- a/wcfsetup/install/files/lib/system/cache/builder/ACPMenuCacheBuilder.class.php +++ b/wcfsetup/install/files/lib/system/cache/builder/ACPMenuCacheBuilder.class.php @@ -1,8 +1,11 @@ */ - protected $optionCategoryStructure = array(); + protected $categoriesWithOptions = array(); + + /** + * list of option categories grouped by the name of their parent category + * @var array + */ + protected $categoryStructure = array(); /** * @see wcf\system\cache\ICacheBuilder::getData() @@ -27,113 +36,100 @@ class ACPMenuCacheBuilder implements ICacheBuilder { public function getData(array $cacheResource) { $data = array(); - // get all menu items and filter menu items with low priority - $sql = "SELECT menuItem, menuItemID - FROM wcf".WCF_N."_acp_menu_item menu_item"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute(); - $itemIDs = array(); - while ($row = $statement->fetchArray()) { - $itemIDs[$row['menuItem']] = $row['menuItemID']; + // get "real" menu items + $menuItemList = new ACPMenuItemList(); + $menuItemList->sqlLimit = 0; + $menuItemList->readObjects(); + foreach ($menuItemList as $menuItem) { + $data[$menuItem->parentMenuItem][] = $menuItem; } - if (!empty($itemIDs)) { - $conditions = new PreparedStatementConditionBuilder(); - $conditions->add("menuItemID IN (?)", array($itemIDs)); - - // get needed menu items and build item tree - $sql = "SELECT * - FROM wcf".WCF_N."_acp_menu_item menu_item - LEFT JOIN wcf".WCF_N."_package package - ON (package.packageID = menu_item.packageID) - ".$conditions." - ORDER BY showOrder ASC"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute($conditions->getParameters()); - while ($row = $statement->fetchArray()) { - if (!isset($data[$row['parentMenuItem']])) { - $data[$row['parentMenuItem']] = array(); - } - - $data[$row['parentMenuItem']][] = new ACPMenuItem(null, $row); - } - } - - // get top option categories - $optionCategories = $this->getTopOptionCategories(); - if (!empty($optionCategories)) { - if (!isset($data['wcf.acp.menu.link.option.category'])) { - $data['wcf.acp.menu.link.option.category'] = array(); - } - - // get option category data - $conditions = new PreparedStatementConditionBuilder(); - $conditions->add("categoryID IN (?)", array($optionCategories)); - - $sql = "SELECT * - FROM wcf".WCF_N."_option_category - ".$conditions." - ORDER BY showOrder ASC"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute($conditions->getParameters()); - while ($row = $statement->fetchArray()) { - $data['wcf.acp.menu.link.option.category'][] = new ACPMenuItem(null, array( - 'menuItem' => 'wcf.acp.option.category.'.$row['categoryName'], - 'parentMenuItem' => 'wcf.acp.menu.link.option.category', - 'menuItemLink' => 'index.php/Option/'.$row['categoryID'].'/', - 'packageDir' => '', - 'permissions' => $row['permissions'], - 'options' => $row['options'] - )); - } + // get menu items for top option categories + $data['wcf.acp.menu.link.option.category'] = array(); + foreach ($this->getTopOptionCategories() as $optionCategory) { + $data['wcf.acp.menu.link.option.category'][] = new ACPMenuItem(null, array( + 'menuItem' => 'wcf.acp.option.category.'.$optionCategory->categoryName, + 'parentMenuItem' => 'wcf.acp.menu.link.option.category', + 'menuItemLink' => LinkHandler::getInstance()->getLink('Option', array( + 'application' => 'wcf', + 'id' => $optionCategory->categoryID + )), + 'permissions' => $optionCategory->permissions, + 'options' => $optionCategory->options + )); } return $data; } + /** + * Returns the list with top option categories which contain options. + * + * @return array + */ protected function getTopOptionCategories() { - // get all option categories - $sql = "SELECT categoryName, categoryID - FROM wcf".WCF_N."_option_category"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute(); - $optionCategories = array(); - while ($row = $statement->fetchArray()) { - $optionCategories[$row['categoryName']] = $row['categoryID']; + $optionCategoryList = new OptionCategoryList(); + $optionCategoryList->sqlLimit = 0; + $optionCategoryList->readObjects(); + $optionCategories = $optionCategoryList->getObjects(); + + // build category structure + $this->categoryStructure = array(); + foreach ($optionCategories as $optionCategory) { + if (!isset($this->categoryStructure[$optionCategory->parentCategoryName])) { + $this->categoryStructure[$optionCategory->parentCategoryName] = array(); + } + + $this->categoryStructure[$optionCategory->parentCategoryName][] = $optionCategory; } - $conditions = new PreparedStatementConditionBuilder(); - $conditions->add("categoryID IN (?)", array($optionCategories)); - $sql = "SELECT categoryID, parentCategoryName, categoryName, - ( - SELECT COUNT(*) FROM wcf".WCF_N."_option WHERE categoryName = category.categoryName - ) AS count - FROM wcf".WCF_N."_option_category category - ".$conditions; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute($conditions->getParameters()); - while ($row = $statement->fetchArray()) { - if (!isset($this->optionCategoryStructure[$row['parentCategoryName']])) $this->optionCategoryStructure[$row['parentCategoryName']] = array(); - $this->optionCategoryStructure[$row['parentCategoryName']][] = $row; + $optionList = new OptionList(); + $optionList->sqlLimit = 0; + $optionList->readObjects(); + + // collect names of categories which contain options + foreach ($optionList as $option) { + if (!isset($this->categoriesWithOptions[$option->categoryName])) { + $this->categoriesWithOptions[$option->categoryName] = $option->categoryName; + } } - $topOptionCategories = array(); - foreach ($this->optionCategoryStructure[''] as $optionCategory) { - $count = $optionCategory['count'] + $this->countOptions($optionCategory['categoryName']); - if ($count > 0) $topOptionCategories[] = $optionCategory['categoryID']; + // collect top categories which contain options + $topCategories = array(); + foreach ($this->categoryStructure[""] as $topCategory) { + if ($this->containsOptions($topCategory)) { + $topCategories[$topCategory->categoryID] = $topCategory; + } } - return $topOptionCategories; + return $topCategories; } - protected function countOptions($parentCategoryName) { - if (!isset($this->optionCategoryStructure[$parentCategoryName])) return 0; + /** + * Returns true if the given category or one of its child categories contains + * options. + * + * @return boolean + */ + protected function containsOptions(OptionCategory $topCategory) { + // check if category directly contains options + if (isset($this->categoriesWithOptions[$topCategory->categoryName])) { + return true; + } - $count = 0; - foreach ($this->optionCategoryStructure[$parentCategoryName] as $optionCategory) { - $count += $optionCategory['count'] + $this->countOptions($optionCategory['categoryName']); + if (!isset($this->categoryStructure[$topCategory->categoryName])) { + // if category directly contains no options and has no child + // categories, it contains no options at all + return false; + } + + // check child categories + foreach ($this->categoryStructure[$topCategory->categoryName] as $category) { + if ($this->containsOptions($category)) { + return true; + } } - return $count; + return false; } }