3 namespace wcf\data\category
;
5 use wcf\system\category\CategoryHandler
;
6 use wcf\system\exception\SystemException
;
9 * Represents a tree of category nodes.
11 * @author Matthias Schmidt
12 * @copyright 2001-2019 WoltLab GmbH
13 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14 * @package WoltLabSuite\Core\Data\Category
16 class CategoryNodeTree
implements \IteratorAggregate
19 * list of ids of categories which will not be included in the node tree
22 protected $excludedCategoryIDs = [];
25 * if true, disabled categories are also included in the node tree
28 protected $includeDisabledCategories = false;
31 * maximum depth considered when building the node tree
34 protected $maxDepth = -1;
37 * name of the category node class
40 protected $nodeClassName = CategoryNode
::class;
43 * id of the parent category
46 protected $parentCategoryID = 0;
49 * parent category node
52 protected $parentNode;
55 * name of the category object type
58 protected $objectType = '';
61 * Creates a new instance of CategoryNodeTree.
63 * @param string $objectType
64 * @param int $parentCategoryID
65 * @param bool $includeDisabledCategories
66 * @param int[] $excludedCategoryIDs
67 * @throws SystemException
69 public function __construct(
71 $parentCategoryID = 0,
72 $includeDisabledCategories = false,
73 array $excludedCategoryIDs = []
75 $this->objectType
= $objectType;
76 $this->parentCategoryID
= $parentCategoryID;
77 $this->includeDisabledCategories
= $includeDisabledCategories;
78 $this->excludedCategoryIDs
= $excludedCategoryIDs;
80 // validate category object type
81 if (CategoryHandler
::getInstance()->getObjectTypeByName($this->objectType
) === null) {
82 throw new SystemException("Unknown category object type '" . $this->objectType
. "'");
87 * Sets the maximum depth considered when building the node tree, defaults
88 * to -1 which equals infinite.
90 * @param int $maxDepth
92 public function setMaxDepth($maxDepth)
94 $this->maxDepth
= $maxDepth;
98 * Builds the category node tree.
100 protected function buildTree()
102 $this->parentNode
= $this->getNode($this->parentCategoryID
);
103 $this->buildTreeLevel($this->parentNode
, $this->maxDepth
);
107 * Builds a certain level of the tree.
109 * @param CategoryNode $parentNode
112 protected function buildTreeLevel(CategoryNode
$parentNode, $depth = 0)
114 if ($this->maxDepth
!= -1 && $depth < 0) {
118 foreach ($this->getChildCategories($parentNode) as $childCategory) {
119 $childNode = $this->getNode($childCategory->categoryID
);
121 if ($this->isIncluded($childNode)) {
122 $parentNode->addChild($childNode);
125 $this->buildTreeLevel($childNode, $depth - 1);
131 * Returns the category with the given id.
133 * @param int $categoryID
136 protected function getCategory($categoryID)
138 return CategoryHandler
::getInstance()->getCategory($categoryID);
142 * Returns the child categories of the given category node.
144 * @param CategoryNode $parentNode
147 protected function getChildCategories(CategoryNode
$parentNode)
149 return CategoryHandler
::getInstance()->getChildCategories($parentNode->categoryID
, $parentNode->objectTypeID
);
155 public function getIterator()
157 if ($this->parentNode
=== null) {
161 return new \
RecursiveIteratorIterator($this->parentNode
, \RecursiveIteratorIterator
::SELF_FIRST
);
165 * Returns the category node for the category with the given id.
167 * @param int $categoryID
168 * @return CategoryNode
170 protected function getNode($categoryID)
173 $category = new Category(null, [
175 'objectTypeID' => CategoryHandler
::getInstance()->getObjectTypeByName($this->objectType
)->objectTypeID
,
178 $category = $this->getCategory($categoryID);
181 // decorate category if necessary
182 $decoratorClassName = \
call_user_func([$this->nodeClassName
, 'getBaseClass']);
183 if ($decoratorClassName != Category
::class) {
184 $category = new $decoratorClassName($category);
187 return new $this->nodeClassName($category);
191 * Returns true if the given category node fulfils all relevant conditions
192 * to be included in this tree.
194 * @param CategoryNode $categoryNode
197 protected function isIncluded(CategoryNode
$categoryNode)
199 return (!$categoryNode->isDisabled ||
$this->includeDisabledCategories
) && !\
in_array(
200 $categoryNode->categoryID
,
201 $this->excludedCategoryIDs