Overhauls category implementation
authorMatthias Schmidt <gravatronics@live.com>
Wed, 1 May 2013 10:37:34 +0000 (12:37 +0200)
committerMatthias Schmidt <gravatronics@live.com>
Wed, 1 May 2013 10:37:34 +0000 (12:37 +0200)
Closes #1222

18 files changed:
com.woltlab.wcf/template/categoryOptionList.tpl
wcfsetup/install/files/acp/templates/categoryAdd.tpl
wcfsetup/install/files/acp/templates/categoryList.tpl
wcfsetup/install/files/acp/templates/categoryOptionList.tpl
wcfsetup/install/files/lib/acp/form/AbstractCategoryAddForm.class.php
wcfsetup/install/files/lib/acp/form/AbstractCategoryEditForm.class.php
wcfsetup/install/files/lib/acp/page/AbstractCategoryListPage.class.php
wcfsetup/install/files/lib/data/category/AbstractDecoratedCategory.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/category/Category.class.php
wcfsetup/install/files/lib/data/category/CategoryNode.class.php
wcfsetup/install/files/lib/data/category/CategoryNodeList.class.php [deleted file]
wcfsetup/install/files/lib/data/category/CategoryNodeTree.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/category/UncachedCategoryNodeTree.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/category/ViewableCategory.class.php [deleted file]
wcfsetup/install/files/lib/data/category/ViewableCategoryNode.class.php [deleted file]
wcfsetup/install/files/lib/data/category/ViewableCategoryNodeList.class.php [deleted file]
wcfsetup/install/files/lib/system/category/AbstractCategoryType.class.php
wcfsetup/install/files/lib/system/category/CategoryHandler.class.php

index 2e47acffa85686e7cfc45714f15ff206f4dde128..f362f14359a380eb062e8574fa0c5f3242beec0e 100644 (file)
@@ -1,5 +1,5 @@
-{foreach from=$categoryNodeList item=category}
-       {if !$maximumNestingLevel|isset || $maximumNestingLevel == -2 || $categoryNodeList->getDepth() <= $maximumNestingLevel}
+{foreach from=$categoryNodeList item='category'}
+       {if !$maximumNestingLevel|isset || $maximumNestingLevel == -1 || $categoryNodeList->getDepth() <= $maximumNestingLevel}
                <option value="{$category->categoryID}"{if $categoryID|isset && $categoryID == $category->categoryID} selected="selected"{/if}>{section name=i loop=$categoryNodeList->getDepth()}&nbsp;&nbsp;&nbsp;&nbsp;{/section}{$category->getTitle()}</option>
        {/if}
 {/foreach}
\ No newline at end of file
index 8796968bcc808fa3e416fd32fd1c6c70d17e5b65..383205d0b1e649ddecd00ac46fabc47555edaf84 100644 (file)
                <fieldset>
                        <legend>{lang}wcf.global.form.data{/lang}</legend>
                        
-                       {if $objectType->getProcessor()->getMaximumNestingLevel() && $categoryNodeList|count}
+                       {if $categoryNodeList->hasChildren() && $objectType->getProcessor()->getMaximumNestingLevel()}
                                <dl{if $errorField == 'parentCategoryID'} class="formError"{/if}>
                                        <dt><label for="parentCategoryID">{@$objectType->getProcessor()->getLanguageVariable('parentCategoryID')}</label></dt>
                                        <dd>
                                                <select id="parentCategoryID" name="parentCategoryID">
                                                        <option value="0"></option>
-                                                       {include file='categoryOptionList' categoryID=$parentCategoryID maximumNestingLevel=$objectType->getProcessor()->getMaximumNestingLevel() - 1}
+                                                       {include file='categoryOptionList' categoryID=$parentCategoryID maximumNestingLevel=$objectType->getProcessor()->getMaximumNestingLevel()}
                                                </select>
                                                {if $errorField == 'parentCategoryID'}
                                                        <small class="innerError">
index eb69daba67df55db26dcada898cf8cbb73b843e9..f84f3ef49059d07ddc92113a164db8f00cf1366f 100644 (file)
@@ -1,66 +1,65 @@
 {include file='header'}
 
-{if $categoryNodeList|count}
+{if $categoryNodeList->hasChildren()}
        <script type="text/javascript">
                //<![CDATA[
                $(function() {
-                       {if $collapsibleObjectTypeID && $categoryNodeList|count > 1}
+                       {if $collapsibleObjectTypeID}
                                new WCF.ACP.Category.Collapsible('wcf\\data\\category\\CategoryAction', {@$collapsibleObjectTypeID});
                        {/if}
-                       
+                               
                        {if $objectType->getProcessor()->canDeleteCategory()}
                                new WCF.ACP.Category.Delete('wcf\\data\\category\\CategoryAction', $('.jsCategory'));
                        {/if}
                        {if $objectType->getProcessor()->canEditCategory()}
                                new WCF.Action.Toggle('wcf\\data\\category\\CategoryAction', '.jsCategory', '> .sortableNodeLabel > .buttons > .jsToggleButton');
                                
-                               {if $categoryNodeList|count > 1}
-                                       var sortableNodes = $('.sortableNode');
-                                       sortableNodes.each(function(index, node) {
-                                               $(node).wcfIdentify();
-                                       });
-                                       
-                                       new WCF.Sortable.List('categoryList', 'wcf\\data\\category\\CategoryAction', 0{if $objectType->getProcessor()->getMaximumNestingLevel() != -1}, {
-                                               /**
-                                                * Updates the sortable nodes after a sorting is started with
-                                                * regard to their possibility to have child the currently sorted
-                                                * category as a child category.
-                                                */
-                                               start: function(event, ui) {
-                                                       var sortedListItem = $(ui.item);
-                                                       var itemNestingLevel = sortedListItem.find('.sortableList:has(.sortableNode)').length;
+                               var sortableNodes = $('.sortableNode');
+                               sortableNodes.each(function(index, node) {
+                                       $(node).wcfIdentify();
+                               });
+                               
+                               new WCF.Sortable.List('categoryList', 'wcf\\data\\category\\CategoryAction', 0{if $objectType->getProcessor()->getMaximumNestingLevel() != -1}, {
+                                       /**
+                                        * Updates the sortable nodes after a sorting is started with
+                                        * regard to their possibility to have child the currently sorted
+                                        * category as a child category.
+                                        */
+                                       start: function(event, ui) {
+                                               var sortedListItem = $(ui.item);
+                                               var itemNestingLevel = sortedListItem.find('.sortableList:has(.sortableNode)').length;
+                                               
+                                               sortableNodes.each(function(index, node) {
+                                                       node = $(node);
                                                        
-                                                       sortableNodes.each(function(index, node) {
-                                                               node = $(node);
-                                                               
-                                                               if (node.attr('id') != sortedListItem.attr('id')) {
-                                                                       if (node.parents('.sortableList').length + itemNestingLevel >= {@$objectType->getProcessor()->getMaximumNestingLevel() + 1}) {
-                                                                               node.addClass('sortableNoNesting');
-                                                                       }
-                                                                       else if (node.hasClass('sortableNoNesting')) {
-                                                                               node.removeClass('sortableNoNesting');
-                                                                       }
-                                                               }
-                                                       });
-                                               },
-                                               /**
-                                                * Updates the sortable nodes after a sorting is completed with
-                                                * regard to their possibility to have child categories.
-                                                */
-                                               stop: function(event, ui) {
-                                                       sortableNodes.each(function(index, node) {
-                                                               node = $(node);
-                                                               
-                                                               if (node.parents('.sortableList').length == {@$objectType->getProcessor()->getMaximumNestingLevel() + 1}) {
+                                                       if (node.attr('id') != sortedListItem.attr('id')) {
+                                                               if (node.parents('.sortableList').length + itemNestingLevel >= {@$objectType->getProcessor()->getMaximumNestingLevel() + 1}) {
                                                                        node.addClass('sortableNoNesting');
                                                                }
                                                                else if (node.hasClass('sortableNoNesting')) {
                                                                        node.removeClass('sortableNoNesting');
                                                                }
-                                                       });
-                                               }
-                                       }{/if});
-                               {/if}
+                                                       }
+                                               });
+                                       },
+                                       
+                                       /**
+                                        * Updates the sortable nodes after a sorting is completed with
+                                        * regard to their possibility to have child categories.
+                                        */
+                                       stop: function(event, ui) {
+                                               sortableNodes.each(function(index, node) {
+                                                       node = $(node);
+                                                       
+                                                       if (node.parents('.sortableList').length == {@$objectType->getProcessor()->getMaximumNestingLevel() + 1}) {
+                                                               node.addClass('sortableNoNesting');
+                                                       }
+                                                       else if (node.hasClass('sortableNoNesting')) {
+                                                               node.removeClass('sortableNoNesting');
+                                                       }
+                                               });
+                                       }
+                               }{/if});
                        {/if}
                });
                //]]>
                                                <li><a href="{link controller=$addController application=$objectType->getProcessor()->getApplication()}{/link}" class="button"><span class="icon icon16 icon-plus"></span> <span>{@$objectType->getProcessor()->getLanguageVariable('add')}</span></a></li>
                                        {/if}
                                        
-                                       {event name='contentNavigationButtonsTop'}
+                                       {event name='contentNavigationButtons'}
                                {/content}
                        </ul>
                </nav>
        {/hascontent}
 </div>
 
-{if $categoryNodeList|count}
-       <section id="categoryList" class="container containerPadding marginTop{if $objectType->getProcessor()->canEditCategory() && $categoryNodeList|count > 1} sortableListContainer{/if}">
+{hascontent}
+       <section id="categoryList" class="container containerPadding marginTop{if $objectType->getProcessor()->canEditCategory()} sortableListContainer{/if}">
                <ol class="categoryList sortableList" data-object-id="0">
-                       {assign var=oldDepth value=0}
-                       {foreach from=$categoryNodeList item=category}
-                               {section name=i loop=$oldDepth-$categoryNodeList->getDepth()}</ol></li>{/section}
-                               
-                               <li class="{if $objectType->getProcessor()->canEditCategory() && $categoryNodeList|count > 1}sortableNode {if $categoryNodeList->getDepth() == $objectType->getProcessor()->getMaximumNestingLevel()}sortableNoNesting {/if}{/if}jsCategory" data-object-id="{@$category->categoryID}"{if $collapsedCategoryIDs|is_array} data-is-open="{if $collapsedCategoryIDs[$category->categoryID]|isset}0{else}1{/if}"{/if}>
-                                       <span class="sortableNodeLabel">
-                                               <span class="title">
-                                                       {if $objectType->getProcessor()->canEditCategory()}
-                                                               <a href="{link controller=$editController application=$objectType->getProcessor()->getApplication() id=$category->categoryID title=$category->getTitle()}{/link}">{$category->getTitle()}</a>
-                                                       {else}
-                                                               {$category->getTitle()}
-                                                       {/if}
-                                               </span>
-                                               
-                                               <span class="statusDisplay buttons">
-                                                       {if $objectType->getProcessor()->canEditCategory()}
-                                                               <a href="{link controller=$editController application=$objectType->getProcessor()->getApplication() id=$category->categoryID title=$category->getTitle()}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip"><span class="icon icon16 icon-pencil"></span></a>
-                                                       {/if}
-                                                       
-                                                       {if $objectType->getProcessor()->canDeleteCategory()}
-                                                               <span class="icon icon16 icon-remove jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{@$category->categoryID}" data-confirm-message="{@$objectType->getProcessor()->getLanguageVariable('delete.sure')}"></span>
-                                                       {/if}
-                                                       
-                                                       {if $objectType->getProcessor()->canEditCategory()}
-                                                               <span class="icon icon16 icon-{if !$category->isDisabled}circle-blank{else}off{/if} jsToggleButton jsTooltip pointer" title="{lang}wcf.global.button.{if !$category->isDisabled}disable{else}enable{/if}{/lang}" data-object-id="{@$category->categoryID}"></span>
-                                                       {/if}
+                       {content}
+                               {assign var=oldDepth value=0}
+                               {foreach from=$categoryNodeList item='category'}
+                                       {section name=i loop=$oldDepth-$categoryNodeList->getDepth()}</ol></li>{/section}
+                                       
+                                       <li class="{if $objectType->getProcessor()->canEditCategory()}sortableNode {if $categoryNodeList->getDepth() == $objectType->getProcessor()->getMaximumNestingLevel()}sortableNoNesting {/if}{/if}jsCategory" data-object-id="{@$category->categoryID}"{if $collapsedCategoryIDs|is_array} data-is-open="{if $collapsedCategoryIDs[$category->categoryID]|isset}0{else}1{/if}"{/if}>
+                                               <span class="sortableNodeLabel">
+                                                       <span class="title">
+                                                               {if $objectType->getProcessor()->canEditCategory()}
+                                                                       <a href="{link controller=$editController application=$objectType->getProcessor()->getApplication() id=$category->categoryID title=$category->getTitle()}{/link}">{$category->getTitle()}</a>
+                                                               {else}
+                                                                       {$category->getTitle()}
+                                                               {/if}
+                                                       </span>
                                                        
-                                                       {event name='itemButtons'}
+                                                       <span class="statusDisplay buttons">
+                                                               {if $objectType->getProcessor()->canEditCategory()}
+                                                                       <a href="{link controller=$editController application=$objectType->getProcessor()->getApplication() id=$category->categoryID title=$category->getTitle()}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip"><span class="icon icon16 icon-pencil"></span></a>
+                                                               {/if}
+                                                               
+                                                               {if $objectType->getProcessor()->canDeleteCategory()}
+                                                                       <span class="icon icon16 icon-remove jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{@$category->categoryID}" data-confirm-message="{@$objectType->getProcessor()->getLanguageVariable('delete.sure')}"></span>
+                                                               {/if}
+                                                               
+                                                               {if $objectType->getProcessor()->canEditCategory()}
+                                                                       <span class="icon icon16 icon-{if !$category->isDisabled}circle-blank{else}off{/if} jsToggleButton jsTooltip pointer" title="{lang}wcf.global.button.{if !$category->isDisabled}disable{else}enable{/if}{/lang}" data-object-id="{@$category->categoryID}"></span>
+                                                               {/if}
+                                                               
+                                                               {event name='itemButtons'}
+                                                       </span>
                                                </span>
-                                       </span>
-                                       
-                                       <ol class="categoryList sortableList" data-object-id="{@$category->categoryID}">
-                               {if !$categoryNodeList->current()->hasChildren()}
-                                       </ol></li>
-                               {/if}
-                               {assign var=oldDepth value=$categoryNodeList->getDepth()}
-                       {/foreach}
-                       {section name=i loop=$oldDepth}</ol></li>{/section}
+                                               
+                                               <ol class="categoryList sortableList" data-object-id="{@$category->categoryID}">
+                                       {if !$categoryNodeList->current()->hasChildren()}
+                                               </ol></li>
+                                       {/if}
+                                       {assign var=oldDepth value=$categoryNodeList->getDepth()}
+                               {/foreach}
+                               {section name=i loop=$oldDepth}</ol></li>{/section}
+                       {/content}
                </ol>
-               
-               {if $objectType->getProcessor()->canEditCategory() && $categoryNodeList|count > 1}
-                       <div class="formSubmit">
-                               <button class="button buttonPrimary" data-type="submit">{lang}wcf.global.button.saveSorting{/lang}</button>
-                       </div>
-               {/if}
        </section>
        
-       <div class="contentNavigation">
-               {hascontent}
-                       <nav>
-                               <ul>
-                                       {content}
-                                               {if $objectType->getProcessor()->canAddCategory()}
-                                                       <li><a href="{link controller=$addController application=$objectType->getProcessor()->getApplication()}{/link}" class="button"><span class="icon icon16 icon-plus"></span> <span>{@$objectType->getProcessor()->getLanguageVariable('add')}</span></a></li>
-                                               {/if}
-                                               
-                                               {event name='contentNavigationButtonsBottom'}
-                                       {/content}
-                               </ul>
-                       </nav>
-               {/hascontent}
+       <div class="formSubmit">
+               <button class="button" data-type="submit">{lang}wcf.global.button.saveSorting{/lang}</button>
        </div>
-{else}
+{hascontentelse}
        <p class="info">{@$objectType->getProcessor()->getLanguageVariable('noneAvailable')}</p>
-{/if}
+{/hascontent}
 
 {include file='footer'}
\ No newline at end of file
index 2e47acffa85686e7cfc45714f15ff206f4dde128..f362f14359a380eb062e8574fa0c5f3242beec0e 100644 (file)
@@ -1,5 +1,5 @@
-{foreach from=$categoryNodeList item=category}
-       {if !$maximumNestingLevel|isset || $maximumNestingLevel == -2 || $categoryNodeList->getDepth() <= $maximumNestingLevel}
+{foreach from=$categoryNodeList item='category'}
+       {if !$maximumNestingLevel|isset || $maximumNestingLevel == -1 || $categoryNodeList->getDepth() <= $maximumNestingLevel}
                <option value="{$category->categoryID}"{if $categoryID|isset && $categoryID == $category->categoryID} selected="selected"{/if}>{section name=i loop=$categoryNodeList->getDepth()}&nbsp;&nbsp;&nbsp;&nbsp;{/section}{$category->getTitle()}</option>
        {/if}
 {/foreach}
\ No newline at end of file
index df99bc6aabc813b51cb37d6ee543376fb09e5be9..d461b662b21b6d0068a14db5f1d056d09c12d6f8 100644 (file)
@@ -2,7 +2,7 @@
 namespace wcf\acp\form;
 use wcf\data\category\CategoryAction;
 use wcf\data\category\CategoryEditor;
-use wcf\data\category\CategoryNodeList;
+use wcf\data\category\UncachedCategoryNodeTree;
 use wcf\form\AbstractForm;
 use wcf\system\acl\ACLHandler;
 use wcf\system\category\CategoryHandler;
@@ -45,10 +45,10 @@ abstract class AbstractCategoryAddForm extends AbstractForm {
        public $additionalData = array();
        
        /**
-        * list with the category nodes
-        * @var wcf\data\category\CategoryNodeList
+        * tree with the category nodes
+        * @var wcf\data\category\CategoryNodeTree
         */
-       public $categoryNodeList = null;
+       public $categoryNodeTree = null;
        
        /**
         * indicates if the category is disabled
@@ -146,7 +146,7 @@ abstract class AbstractCategoryAddForm extends AbstractForm {
                        'action' => 'add',
                        'addController' => $this->addController,
                        'additionalData' => $this->additionalData,
-                       'categoryNodeList' => $this->categoryNodeList,
+                       'categoryNodeList' => $this->categoryNodeTree->getIterator(),
                        'editController' => $this->editController,
                        'isDisabled' => $this->isDisabled,
                        'listController' => $this->listController,
@@ -173,13 +173,13 @@ abstract class AbstractCategoryAddForm extends AbstractForm {
         * Reads the categories.
         */
        protected function readCategories() {
-               $this->categoryNodeList = new CategoryNodeList($this->objectType->objectType, 0, true);
+               $this->categoryNodeTree = new UncachedCategoryNodeTree($this->objectType->objectType, 0, true);
        }
        
        /**
         * @see wcf\page\IPage::readData()
         */
-       public function readData() {            
+       public function readData() {
                $this->objectType = CategoryHandler::getInstance()->getObjectTypeByName($this->objectTypeName);
                if ($this->objectType === null) {
                        throw new SystemException("Unknown category object type with name '".$this->objectTypeName."'");
@@ -204,9 +204,9 @@ abstract class AbstractCategoryAddForm extends AbstractForm {
                }
                I18nHandler::getInstance()->register('title');
                
-               $this->readCategories();
-               
                parent::readData();
+               
+               $this->readCategories();
        }
        
        /**
@@ -330,19 +330,14 @@ abstract class AbstractCategoryAddForm extends AbstractForm {
                                return;
                        }
                        
-                       if (CategoryHandler::getInstance()->getCategory($this->parentCategoryID) === null) {
-                               throw new UserInputException('parentCategoryID', 'invalid');
+                       $category = CategoryHandler::getInstance()->getCategory($this->parentCategoryID);
+                       if ($category === null) {
+                               throw new UserInputException('parentCategoryID', 'notValid');
                        }
                        
                        if ($this->objectType->getProcessor()->getMaximumNestingLevel() != -1) {
-                               foreach ($this->categoryNodeList as $category) {
-                                       if ($category->categoryID == $this->parentCategoryID) {
-                                               if ($this->categoryNodeList->getDepth() > $this->objectType->getProcessor()->getMaximumNestingLevel() - 1) {
-                                                       throw new UserInputException('parentCategoryID', 'invalid');
-                                               }
-                                               
-                                               break;
-                                       }
+                               if (count($category->getParentCategories()) > $this->objectType->getProcessor()->getMaximumNestingLevel()) {
+                                       throw new UserInputException('parentCategoryID', 'notValid');
                                }
                        }
                }
index d3065c4d28584ce8a91eea1c2511343728870a67..6301a653755ba13c9226e9cd608e932b5bc0ab15 100644 (file)
@@ -2,7 +2,7 @@
 namespace wcf\acp\form;
 use wcf\data\category\Category;
 use wcf\data\category\CategoryAction;
-use wcf\data\category\CategoryNodeList;
+use wcf\data\category\CategoryNodeTree;
 use wcf\form\AbstractForm;
 use wcf\system\acl\ACLHandler;
 use wcf\system\category\CategoryHandler;
@@ -63,7 +63,7 @@ class AbstractCategoryEditForm extends AbstractCategoryAddForm {
         * @see wcf\acp\form\AbstractCategoryAddForm::readCategories()
         */
        protected function readCategories() {
-               $this->categoryNodeList = new CategoryNodeList($this->objectType->objectType, 0, true, array($this->category->categoryID));
+               $this->categoryNodeTree = new CategoryNodeTree($this->objectType->objectType, 0, true, array($this->category->categoryID));
        }
        
        /**
@@ -164,7 +164,7 @@ class AbstractCategoryEditForm extends AbstractCategoryAddForm {
                parent::validateParentCategory();
                
                // check if new parent category is no child category of the category
-               $childCategories = CategoryHandler::getInstance()->getChildCategories($this->category);
+               $childCategories = CategoryHandler::getInstance()->getChildCategories($this->categoryID, $this->objectType->objectTypeID);
                if (isset($childCategories[$this->parentCategoryID])) {
                        throw new UserInputException('parentCategoryID', 'invalid');
                }
index d816884dd6e514a5a8a01544c58d7f1282262471..58173c1a5d96be93bd168b5b3cd70b3e3058e311 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 namespace wcf\acp\page;
-use wcf\data\category\CategoryNodeList;
+use wcf\data\category\CategoryNodeTree;
 use wcf\page\AbstractPage;
 use wcf\system\category\CategoryHandler;
 use wcf\system\exception\PermissionDeniedException;
@@ -28,10 +28,10 @@ abstract class AbstractCategoryListPage extends AbstractPage {
        public $addController = '';
        
        /**
-        * category node list
-        * @var wcf\data\category\CategoryNodeList
+        * category node tree
+        * @var wcf\data\category\CategoryNodeTree
         */
-       public $categoryNodeList = null;
+       public $categoryNodeTree = null;
        
        /**
         * ids of collapsed categories
@@ -100,7 +100,7 @@ abstract class AbstractCategoryListPage extends AbstractPage {
                
                WCF::getTPL()->assign(array(
                        'addController' => $this->addController,
-                       'categoryNodeList' => $this->categoryNodeList,
+                       'categoryNodeList' => $this->categoryNodeTree->getIterator(),
                        'collapsedCategoryIDs' => $this->collapsedCategoryIDs,
                        'collapsibleObjectTypeID' => $this->collapsibleObjectTypeID,
                        'editController' => $this->editController,
@@ -125,7 +125,7 @@ abstract class AbstractCategoryListPage extends AbstractPage {
         * Reads the categories.
         */
        protected function readCategories() {
-               $this->categoryNodeList = new CategoryNodeList($this->objectType->objectType, 0, true);
+               $this->categoryNodeTree = new CategoryNodeTree($this->objectType->objectType, 0, true);
        }
        
        /**
diff --git a/wcfsetup/install/files/lib/data/category/AbstractDecoratedCategory.class.php b/wcfsetup/install/files/lib/data/category/AbstractDecoratedCategory.class.php
new file mode 100644 (file)
index 0000000..5618735
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+namespace wcf\data\category;
+use wcf\data\DatabaseObjectDecorator;
+use wcf\system\category\CategoryHandler;
+
+/**
+ * Abstract implementation of a decorated category.
+ * 
+ * @author     Matthias Schmidt
+ * @copyright  2001-2013 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.category
+ * @category   Community Framework
+ */
+abstract class AbstractDecoratedCategory extends DatabaseObjectDecorator {
+       /**
+        * list of all child categories of this category
+        * @var array<wcf\data\category\Category>
+        */
+       protected $childCategories = null;
+       
+       /**
+        * list of all parent category generations of this category
+        * @var array<wcf\data\category\AbstractDecoratedCategory>
+        */
+       protected $parentCategories = null;
+       
+       /**
+        * parent category of this category
+        * @var wcf\data\category\AbstractDecoratedCategory
+        */
+       protected $parentCategory = null;
+       
+       /**
+        * @see wcf\data\DatabaseObjectDecorator::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\category\Category';
+       
+       /**
+        * @see wcf\data\category\Category::getChildCategories()
+        */
+       public function getChildCategories() {
+               if ($this->childCategories === null) {
+                       $this->childCategories = array();
+                       foreach ($this->getDecoratedObject()->getChildCategories() as $category) {
+                               $this->childCategories[$category->categoryID] = new static($category);
+                       }
+               }
+               
+               return $this->childCategories;
+       }
+       
+       /**
+        * @see wcf\data\category\Category::getParentCategories()
+        */
+       public function getParentCategories() {
+               if ($this->parentCategories === null) {
+                       $this->parentCategories = array();
+                       foreach ($this->getDecoratedObject()->getParentCategories() as $category) {
+                               $this->parentCategories[$category->categoryID] = new static($category);
+                       }
+               }
+               
+               return $this->parentCategories;
+       }
+       
+       /**
+        * @see wcf\data\category\Category::getParentCategory()
+        */
+       public function getParentCategory() {
+               if ($this->parentCategoryID && $this->parentCategory === null) {
+                       $this->parentCategory = new static($this->getDecoratedObject()->getParentCategory());
+               }
+               
+               return $this->parentCategory;
+       }
+       
+       /**
+        * Returns the decorated category with the given id or null if no such
+        * category exists.
+        * 
+        * @param       integer         $categoryID
+        * @return      wcf\data\category\AbstractDecoratedCategory
+        */
+       public static function getCategory($categoryID) {
+               $category = CategoryHandler::getInstance()->getCategory($categoryID);
+               if ($category) {
+                       return new static($category);
+               }
+               
+               return null;
+       }
+}
index cf1539fcda1a59488ae87f81279c1051742f5816..2f84c8f05681fedc9dd7b7b71eabf28577a2cf23 100644 (file)
@@ -1,7 +1,10 @@
 <?php
 namespace wcf\data\category;
+use wcf\data\IPermissionObject;
 use wcf\data\ProcessibleDatabaseObject;
 use wcf\system\category\CategoryHandler;
+use wcf\system\category\CategoryPermissionHandler;
+use wcf\system\exception\PermissionDeniedException;
 use wcf\system\request\IRouteController;
 use wcf\system\WCF;
 
@@ -15,7 +18,13 @@ use wcf\system\WCF;
  * @subpackage data.category
  * @category   Community Framework
  */
-class Category extends ProcessibleDatabaseObject implements IRouteController {
+class Category extends ProcessibleDatabaseObject implements IPermissionObject, IRouteController {
+       /**
+        * list of all child categories of this category
+        * @var array<wcf\data\category\Category>
+        */
+       protected $childCategories = null;
+       
        /**
         * list of all parent category generations of this category
         * @var array<wcf\data\category\Category>
@@ -28,6 +37,12 @@ class Category extends ProcessibleDatabaseObject implements IRouteController {
         */
        protected $parentCategory = null;
        
+       /**
+        * acl permissions for the active user of this category
+        * @var array<boolean>
+        */
+       protected $permissions = null;
+       
        /**
         * @see wcf\data\DatabaseObject::$databaseTableIndexName
         */
@@ -64,6 +79,17 @@ class Category extends ProcessibleDatabaseObject implements IRouteController {
                return $value;
        }
        
+       /**
+        * @see wcf\data\IPermissionObject::checkPermissions()
+        */
+       public function checkPermissions(array $permissions) {
+               foreach ($permissions as $permission) {
+                       if (!$this->getPermission($permission)) {
+                               throw new PermissionDeniedException();
+                       }
+               }
+       }
+       
        /**
         * Returns the category object type of the category.
         * 
@@ -73,6 +99,19 @@ class Category extends ProcessibleDatabaseObject implements IRouteController {
                return CategoryHandler::getInstance()->getObjectType($this->objectTypeID);
        }
        
+       /**
+        * Returns the child categories of this category.
+        * 
+        * @return      array<wcf\data\category\Category>
+        */
+       public function getChildCategories() {
+               if ($this->childCategories === null) {
+                       $this->childCategories = CategoryHandler::getInstance()->getChildCategories($this->categoryID);
+               }
+               
+               return $this->childCategories;
+       }
+       
        /**
         * Returns the parent category of this category.
         * 
@@ -105,6 +144,21 @@ class Category extends ProcessibleDatabaseObject implements IRouteController {
                return $this->parentCategories;
        }
        
+       /**
+        * @see wcf\data\IPermissionObject::getPermission()
+        */
+       public function getPermission($permission) {
+               if ($this->permissions === null) {
+                       $this->permissions = CategoryPermissionHandler::getInstance()->getPermissions($this);
+               }
+               
+               if (isset($this->permissions[$permission])) {
+                       return $this->permissions[$permission];
+               }
+               
+               return false;
+       }
+       
        /**
         * @see wcf\data\ITitledObject::getTitle()
         */
index 4a154a3feb5503ba5c0a95e7047572fda912fbeb..cb8331ec0135ff55bf4036278a7bdaa7d1fb5a41 100644 (file)
@@ -1,8 +1,6 @@
 <?php
 namespace wcf\data\category;
-use wcf\data\DatabaseObject;
 use wcf\data\DatabaseObjectDecorator;
-use wcf\system\category\CategoryHandler;
 
 /**
  * Represents a category node.
@@ -19,19 +17,13 @@ class CategoryNode extends DatabaseObjectDecorator implements \RecursiveIterator
         * child category nodes
         * @var array<wcf\data\category\CategoryNode>
         */
-       protected $childCategories = array();
+       protected $children = array();
        
        /**
-        * indicates if disabled categories are included
+        * current iterator key
         * @var integer
         */
-       protected $includeDisabledCategories = false;
-       
-       /**
-        * list of object type category ids of excluded categories
-        * @var array<integer>
-        */
-       protected $excludedCategoryIDs = false;
+       protected $index = 0;
        
        /**
         * @see wcf\data\DatabaseObjectDecorator::$baseClass
@@ -39,59 +31,40 @@ class CategoryNode extends DatabaseObjectDecorator implements \RecursiveIterator
        protected static $baseClass = 'wcf\data\category\Category';
        
        /**
-        * @see wcf\data\DatabaseObjectDecorator::__construct()
+        * Adds the given category node as child node.
+        * 
+        * @param       wcf\data\category\CategoryNode          $categoryNode
         */
-       public function __construct(DatabaseObject $object, $includeDisabledCategories = false, array $excludedCategoryIDs = array()) {
-               parent::__construct($object);
-               
-               $this->includeDisabledCategories = $includeDisabledCategories;
-               $this->excludedCategoryIDs = $excludedCategoryIDs;
-               
-               $className = get_called_class();
-               foreach (CategoryHandler::getInstance()->getChildCategories($this->getDecoratedObject()) as $category) {
-                       if ($this->fulfillsConditions($category)) {
-                               $this->childCategories[] = new $className($category, $includeDisabledCategories, $excludedCategoryIDs);
-                       }
-               }
+       public function addChild(CategoryNode $categoryNode) {
+               $this->children[] = $categoryNode;
        }
        
        /**
         * @see \Countable::count()
         */
        public function count() {
-               return count($this->childCategories);
+               return count($this->children);
        }
        
        /**
         * @see \Iterator::current()
         */
        public function current() {
-               return $this->childCategories[$this->index];
-       }
-       
-       /**
-        * Returns true if the given category fulfills all needed conditions to
-        * be included in the list.
-        * 
-        * @param       wcf\data\DatabaseObject $category
-        * @return      boolean
-        */
-       protected function fulfillsConditions(DatabaseObject $category) {
-               return !in_array($category->categoryID, $this->excludedCategoryIDs) && ($this->includeDisabledCategories || !$category->isDisabled);
+               return $this->children[$this->index];
        }
        
        /**
         * @see \RecursiveIterator::getChildren()
         */
        public function getChildren() {
-               return $this->childCategories[$this->index];
+               return $this->children[$this->index];
        }
        
        /**
         * @see \RecursiveIterator::getChildren()
         */
        public function hasChildren() {
-               return !empty($this->childCategories);
+               return !empty($this->children);
        }
        
        /**
@@ -119,6 +92,6 @@ class CategoryNode extends DatabaseObjectDecorator implements \RecursiveIterator
         * @see \Iterator::valid()
         */
        public function valid() {
-               return isset($this->childCategories[$this->index]);
+               return isset($this->children[$this->index]);
        }
 }
diff --git a/wcfsetup/install/files/lib/data/category/CategoryNodeList.class.php b/wcfsetup/install/files/lib/data/category/CategoryNodeList.class.php
deleted file mode 100644 (file)
index 0f2fbf3..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-namespace wcf\data\category;
-use wcf\system\category\CategoryHandler;
-use wcf\system\exception\SystemException;
-
-/**
- * Represents a category node list.
- * 
- * @author     Matthias Schmidt
- * @copyright  2001-2012 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package    com.woltlab.wcf
- * @subpackage data.category
- * @category   Community Framework
- */
-class CategoryNodeList extends \RecursiveIteratorIterator implements \Countable {
-       /**
-        * number of (real) category nodes in this list
-        * @var integer
-        */
-       protected $count = null;
-       
-       /**
-        * name of the category node class
-        * @var string
-        */
-       protected $nodeClassName = '';
-       
-       /**
-        * id of the parent category
-        * @var integer
-        */
-       protected $parentCategoryID = 0;
-       
-       /**
-        * Creates a new CategoryNodeList instance.
-        * 
-        * @param       string          $objectType
-        * @param       integer         $parentCategoryID
-        * @param       boolean         $includeDisabledCategories
-        * @param       array<integer>  $excludedCategoryIDs
-        */
-       public function __construct($objectType, $parentCategoryID = 0, $includeDisabledCategories = false, array $excludedCategoryIDs = array()) {
-               if (empty($this->nodeClassName)) {
-                       $this->nodeClassName = str_replace('List', '', get_class($this));
-                       if (!class_exists($this->nodeClassName)) {
-                               throw new SystemException("Unknown category node class '".$this->nodeClassName."'.");
-                       }
-               }
-               
-               $this->parentCategoryID = $parentCategoryID;
-               
-               // get parent category
-               if (!$this->parentCategoryID) {
-                       // empty node
-                       $parentCategory = new Category(null, array(
-                               'categoryID' => 0,
-                               'objectTypeID' => CategoryHandler::getInstance()->getObjectTypeByName($objectType)->objectTypeID
-                       ));
-               }
-               else {
-                       $parentCategory = CategoryHandler::getInstance()->getCategory($this->parentCategoryID);
-                       if ($parentCategory === null) {
-                               throw new SystemException("There is no category with id '".$this->parentCategoryID."'");
-                       }
-               }
-               
-               parent::__construct(new $this->nodeClassName($parentCategory, $includeDisabledCategories, $excludedCategoryIDs), \RecursiveIteratorIterator::SELF_FIRST);
-       }
-       
-       /**
-        * @see \Countable::count()
-        */
-       public function count() {
-               if ($this->count === null) {
-                       $this->count = 0;
-                       foreach ($this as $categoryNode) {
-                               $this->count++;
-                       }
-               }
-               
-               return $this->count;
-       }
-}
diff --git a/wcfsetup/install/files/lib/data/category/CategoryNodeTree.class.php b/wcfsetup/install/files/lib/data/category/CategoryNodeTree.class.php
new file mode 100644 (file)
index 0000000..50312f1
--- /dev/null
@@ -0,0 +1,148 @@
+<?php
+namespace wcf\data\category;
+use wcf\system\category\CategoryHandler;
+use wcf\system\exception\SystemException;
+
+/**
+ * Represents a tree of category nodes.
+ * 
+ * @author     Matthias Schmidt
+ * @copyright  2001-2013 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.category
+ * @category   Community Framework
+ */
+class CategoryNodeTree implements \IteratorAggregate {
+       /**
+        * name of the category node class
+        * @var string
+        */
+       protected $nodeClassName = 'wcf\data\category\CategoryNode';
+       
+       /**
+        * id of the parent category
+        * @var integer
+        */
+       protected $parentCategoryID = 0;
+       
+       /**
+        * parent category node
+        * @var wcf\data\category\CategoryNode
+        */
+       protected $parentNode = null;
+       
+       /**
+        * Creates a new instance of CategoryNodeTree.
+        * 
+        * @param       string                  $objectType
+        * @param       integer                 $parentCategoryID
+        * @param       boolean                 $includeDisabledCategories
+        * @param       array<integer>          $excludedCategoryIDs
+        */
+       public function __construct($objectType, $parentCategoryID = 0, $includeDisabledCategories = false, array $excludedCategoryIDs = array()) {
+               $this->objectType = $objectType;
+               $this->parentCategoryID = $parentCategoryID;
+               $this->includeDisabledCategories = $includeDisabledCategories;
+               $this->excludedCategoryIDs = $excludedCategoryIDs;
+               
+               // validate category object type
+               if (CategoryHandler::getInstance()->getObjectTypeByName($this->objectType) === null) {
+                       throw new SystemException("Unknown category object type '".$this->objectType."'");
+               }
+       }
+       
+       /**
+        * Builds the category node tree.
+        */
+       protected function buildTree() {
+               $this->parentNode = $this->getNode($this->parentCategoryID);
+               $this->buildTreeLevel($this->parentNode);
+       }
+       
+       /**
+        * Builds a certain level of the tree.
+        * 
+        * @param       wcf\data\category\CategoryNode  $parentNode
+        */
+       protected function buildTreeLevel(CategoryNode $parentNode) {
+               foreach ($this->getChildCategories($parentNode) as $childCategory) {
+                       $childNode = $this->getNode($childCategory->categoryID);
+                       
+                       if ($this->isIncluded($childNode)) {
+                               $parentNode->addChild($childNode);
+                               
+                               // build next level
+                               $this->buildTreeLevel($childNode);
+                       }
+               }
+       }
+       
+       /**
+        * Returns the category with the given id.
+        * 
+        * @param       integer         $categoryID
+        * @return      wcf\data\category\Category
+        */
+       protected function getCategory($categoryID) {
+               return CategoryHandler::getInstance()->getCategory($categoryID);
+       }
+       
+       /**
+        * Returns the child categories of the given category node.
+        * 
+        * @param       wcf\data\category\CategoryNode          $parentNode
+        * @return      array<wcf\data\category\Category>
+        */
+       protected function getChildCategories(CategoryNode $parentNode) {
+               return CategoryHandler::getInstance()->getChildCategories($parentNode->categoryID, $parentNode->objectTypeID);
+       }
+       
+       /**
+        * @see \IteratorAggregate::getIterator()
+        */
+       public function getIterator() {
+               if ($this->parentNode === null) {
+                       $this->buildTree();
+               }
+               
+               return new \RecursiveIteratorIterator($this->parentNode, \RecursiveIteratorIterator::SELF_FIRST);
+       }
+       
+       /**
+        * Returns the category node for the category with the given id.
+        * 
+        * @param       integer         $categoryID
+        * @return      wcf\data\category\CategoryNode
+        */
+       protected function getNode($categoryID) {
+               if (!$categoryID) {
+                       $category = new Category(null, array(
+                               'categoryID' => 0,
+                               'objectTypeID' => CategoryHandler::getInstance()->getObjectTypeByName($this->objectType)->objectTypeID
+                       ));
+               }
+               else {
+                       $category = $this->getCategory($categoryID);
+               }
+               
+               // decorate category if necessary
+               $decoratorClassName = call_user_func(array($this->nodeClassName, 'getBaseClass'));
+               if ($decoratorClassName != 'wcf\data\category\Category') {
+                       $category = new $decoratorClassName($category);
+               }
+               
+               return new $this->nodeClassName($category);
+       }
+       
+       /**
+        * Returns true if the given category node fulfils all relevant conditions
+        * to be included in this tree.
+        * 
+        * @param       wcf\data\category\CategoryNode          $categoryNode
+        * @return      boolean
+        */
+       protected function isIncluded(CategoryNode $categoryNode) {
+               return (!$categoryNode->isDisabled || $this->includeDisabledCategories) && !in_array($categoryNode->categoryID, $this->excludedCategoryIDs);
+       }
+}
diff --git a/wcfsetup/install/files/lib/data/category/UncachedCategoryNodeTree.class.php b/wcfsetup/install/files/lib/data/category/UncachedCategoryNodeTree.class.php
new file mode 100644 (file)
index 0000000..a7b8a69
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+namespace wcf\data\category;
+use wcf\system\category\CategoryHandler;
+
+/**
+ * Represents an uncached tree of category nodes.
+ * 
+ * @author     Matthias Schmidt
+ * @copyright  2001-2013 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.category
+ * @category   Community Framework
+ */
+class UncachedCategoryNodeTree extends CategoryNodeTree {
+       /**
+        * locally cached categories
+        * @var array<wcf\data\category\Category>
+        */
+       protected $categoryCache = array();
+       
+       /**
+        * locally cached category ids grouped by the id of their parent category
+        * @var array
+        */
+       protected $categoryStructureCache = array();
+       
+       /**
+        * @see wcf\data\category\CategoryNodeTree::buildTree()
+        */
+       protected function buildTree() {
+               $categoryList = new CategoryList();
+               $categoryList->getConditionBuilder()->add('category.objectTypeID = ?', array(CategoryHandler::getInstance()->getObjectTypeByName($this->objectType)->objectTypeID));
+               $categoryList->readObjects();
+               foreach ($categoryList as $category) {
+                       if (!isset($this->categoryStructureCache[$category->parentCategoryID])) {
+                               $this->categoryStructureCache[$category->parentCategoryID] = array();
+                       }
+                       
+                       $this->categoryStructureCache[$category->parentCategoryID][] = $category->categoryID;
+                       $this->categoryCache[$category->categoryID] = $category;
+               }
+               
+               parent::buildTree();
+       }
+       
+       /**
+        * @see wcf\data\category\CategoryNodeTree::getCategory()
+        */
+       protected function getCategory($categoryID) {
+               return $this->categoryCache[$categoryID];
+       }
+       
+       /**
+        * @see wcf\data\category\CategoryNodeTree::getChildCategories()
+        */
+       protected function getChildCategories(CategoryNode $parentNode) {
+               $categories = array();
+               if (isset($this->categoryStructureCache[$parentNode->categoryID])) {
+                       foreach ($this->categoryStructureCache[$parentNode->categoryID] as $categoryID) {
+                               $categories[$categoryID] = $this->getCategory($categoryID);
+                       }
+               }
+               
+               return $categories;
+       }
+}
diff --git a/wcfsetup/install/files/lib/data/category/ViewableCategory.class.php b/wcfsetup/install/files/lib/data/category/ViewableCategory.class.php
deleted file mode 100644 (file)
index 27a1fea..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-<?php
-namespace wcf\data\category;
-use wcf\data\DatabaseObjectDecorator;
-use wcf\data\IPermissionObject;
-use wcf\system\category\CategoryPermissionHandler;
-use wcf\system\exception\PermissionDeniedException;
-
-/**
- * Represents a viewable category.
- * 
- * @author     Matthias Schmidt
- * @copyright  2001-2012 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package    com.woltlab.wcf
- * @subpackage data.category
- * @category   Community Framework
- */
-class ViewableCategory extends DatabaseObjectDecorator implements IPermissionObject {
-       /**
-        * list of all parent category generations of this category
-        * @var array<wcf\data\category\ViewableCategory>
-        */
-       protected $parentCategories = null;
-       
-       /**
-        * parent category of this category
-        * @var wcf\data\category\ViewableCategory
-        */
-       protected $parentCategory = null;
-       
-       /**
-        * @see wcf\data\DatabaseObjectDecorator::$baseClass
-        */
-       protected static $baseClass = 'wcf\data\category\Category';
-       
-       /**
-        * acl permissions for the active user of this category
-        * @var array<boolean>
-        */
-       protected $permissions = null;
-       
-       /**
-        * @see wcf\data\IPermissionObject::checkPermissions()
-        */
-       public function checkPermissions(array $permissions) {
-               foreach ($permissions as $permission) {
-                       if (!$this->getPermission($permission)) {
-                               throw new PermissionDeniedException();
-                       }
-               }
-       }
-       
-       /**
-        * @see wcf\data\category\Category::getParentCategories()
-        */
-       public function getParentCategories() {
-               if ($this->parentCategories === null) {
-                       $this->parentCategories = array();
-                       $className = get_class($this);
-                       
-                       foreach ($this->getDecoratedObject()->getParentCategories() as $category) {
-                               $this->parentCategories[$category->categoryID] = new $className($category);
-                       }
-               }
-               
-               return $this->parentCategories;
-       }
-       
-       /**
-        * @see wcf\data\category\Category::getParentCategory()
-        */
-       public function getParentCategory() {
-               if ($this->parentCategoryID && $this->parentCategory === null) {
-                       $className = get_class($this);
-                       
-                       $this->parentCategory = new $className($this->getDecoratedObject()->getParentCategory());
-               }
-               
-               return $this->parentCategory;
-       }
-       
-       /**
-        * @see wcf\data\IPermissionObject::getPermission()
-        */
-       public function getPermission($permission) {
-               if ($this->permissions === null) {
-                       $this->permissions = CategoryPermissionHandler::getInstance()->getPermissions($this->getDecoratedObject());
-               }
-               
-               if (isset($this->permissions[$permission])) {
-                       return $this->permissions[$permission];
-               }
-               
-               return false;
-       }
-}
diff --git a/wcfsetup/install/files/lib/data/category/ViewableCategoryNode.class.php b/wcfsetup/install/files/lib/data/category/ViewableCategoryNode.class.php
deleted file mode 100644 (file)
index 0727611..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-namespace wcf\data\category;
-use wcf\data\DatabaseObject;
-
-/**
- * Represents a viewable category node.
- * 
- * @author     Matthias Schmidt
- * @copyright  2001-2012 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package    com.woltlab.wcf
- * @subpackage data.category
- * @category   Community Framework
- */
-class ViewableCategoryNode extends CategoryNode {
-       /**
-        * @see wcf\data\DatabaseObjectDecorator::$baseClass
-        */
-       protected static $baseClass = 'wcf\data\category\ViewableCategory';
-       
-       /**
-        * @see wcf\data\DatabaseObjectDecorator::__construct()
-        */
-       public function __construct(DatabaseObject $object, $includeDisabledCategories = false, array $excludedCategoryIDs = array()) {
-               if (!($object instanceof static::$baseClass)) {
-                       $object = new static::$baseClass($object);
-               }
-               
-               parent::__construct($object, $includeDisabledCategories, $excludedCategoryIDs);
-       }
-}
diff --git a/wcfsetup/install/files/lib/data/category/ViewableCategoryNodeList.class.php b/wcfsetup/install/files/lib/data/category/ViewableCategoryNodeList.class.php
deleted file mode 100644 (file)
index deee714..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-namespace wcf\data\category;
-
-/**
- * Represents a list of viewable category nodes.
- * 
- * @author     Matthias Schmidt
- * @copyright  2001-2013 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package    com.woltlab.wcf
- * @subpackage data.category
- * @category   Community Framework
- */
-class ViewableCategoryNodeList extends CategoryNodeList { }
index 4889d09a96a510599b805b3186c34ef001549b49..bcae5d6db17ec7f1ff5818322ac7755469e6008f 100644 (file)
@@ -63,7 +63,7 @@ abstract class AbstractCategoryType extends SingletonFactory implements ICategor
         * @see wcf\system\category\ICategoryType::afterDeletion()
         */
        public function afterDeletion(CategoryEditor $categoryEditor) {
-               $categoryIDs = array_keys(CategoryHandler::getInstance()->getChildCategories($categoryEditor->getDecoratedObject()));
+               $categoryIDs = array_keys(CategoryHandler::getInstance()->getChildCategories($categoryEditor->categoryID));
                
                if (!empty($categoryIDs)) {
                        // move child categories to parent category
index 6e76794a59cf5a00c653a76ff5a0b8bb4f068607..64d718e9babdab317308c3898e4fa070ca48cdff 100644 (file)
@@ -1,9 +1,6 @@
 <?php
 namespace wcf\system\category;
-use wcf\data\category\Category;
 use wcf\data\object\type\ObjectTypeCache;
-use wcf\data\DatabaseObject;
-use wcf\data\DatabaseObjectDecorator;
 use wcf\system\cache\builder\CategoryCacheBuilder;
 use wcf\system\exception\SystemException;
 use wcf\system\SingletonFactory;
@@ -81,20 +78,23 @@ class CategoryHandler extends SingletonFactory {
        }
        
        /**
-        * Returns the child categories of the given category.
+        * Returns the child categories of the category with the given id.
         * 
-        * @param       wcf\data\DatabaseObject         $category
+        * The second parameter is only needed if $categoryID is 0.
+        * 
+        * @param       integer         $categoryID
+        * @param       integer         $objectTypeID
         * @return      array<wcf\data\category\Category>
         */
-       public function getChildCategories(DatabaseObject $category) {
-               if (!($category instanceof Category) && (!($category instanceof DatabaseObjectDecorator) || !($category->getDecoratedObject() instanceof Category))) {
-                       throw new SystemException("Invalid object given (class: ".get_class($category).")");
+       public function getChildCategories($categoryID, $objectTypeID = null) {
+               if (!$categoryID && $objectTypeID === null) {
+                       throw new SystemException("Missing object type id");
                }
                
                $categories = array();
-               foreach ($this->categories as $__category) {
-                       if ($__category->parentCategoryID == $category->categoryID && ($category->categoryID || $category->objectTypeID == $__category->objectTypeID)) {
-                               $categories[$__category->categoryID] = $__category;
+               foreach ($this->categories as $category) {
+                       if ($category->parentCategoryID == $categoryID && ($categoryID || $category->objectTypeID == $objectTypeID)) {
+                               $categories[$category->categoryID] = $category;
                        }
                }