diff --git a/lib/classes/StudipTreeNodeCachableTrait.php b/lib/classes/StudipTreeNodeCachableTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..31823acee79b07ab7c52e17d7b25ee1e97290cc6 --- /dev/null +++ b/lib/classes/StudipTreeNodeCachableTrait.php @@ -0,0 +1,59 @@ +<?php +trait StudipTreeNodeCachableTrait +{ + protected static $descendants_cache_array = null; + + protected static function getDescendantsCacheArray(): StudipCachedArray + { + if (self::$descendants_cache_array === null) { + self::$descendants_cache_array = new StudipCachedArray( + static::class . '/descendants', + 30 * 60 + ); + } + return self::$descendants_cache_array; + } + + protected static function registerCachableCallbacks(array $config): array + { + if (!isset($config['registered_callbacks'])) { + $config['registered_callbacks'] = []; + } + + if (!isset($config['registered_callbacks']['before_store'])) { + $config['registered_callbacks']['before_store'] = []; + } + $config['registered_callbacks']['before_store'][] = function ($node): void { + self::getDescendantsCacheArray()->expire(); + }; + + if (!isset($config['registered_callbacks']['after_delete'])) { + $config['registered_callbacks']['after_delete'] = []; + } + $config['registered_callbacks']['after_delete'][] = function ($node): void { + self::getDescendantsCacheArray()->expire(); + }; + + return $config; + } + + protected function getDescendantIds(): array + { + $cache = self::getDescendantsCacheArray(); + + if (isset($cache[$this->id])) { + return $cache[$this->id]; + } + + $ids = []; + + foreach ($this->getChildNodes() as $child) { + $ids = array_merge($ids, [$child->id], $child->getDescendantIds()); + } + + $cache[$this->id] = $ids; + + return $ids; + } + +} diff --git a/lib/models/RangeTreeNode.php b/lib/models/RangeTreeNode.php index 4d52fedaf718b57f137e28e2bc625b48959a09f8..c142579e05d0d16aac5db8bdf8ed522dd8803e75 100644 --- a/lib/models/RangeTreeNode.php +++ b/lib/models/RangeTreeNode.php @@ -27,6 +27,8 @@ */ class RangeTreeNode extends SimpleORMap implements StudipTreeNode { + use StudipTreeNodeCachableTrait; + protected static function configure($config = []) { $config['db_table'] = 'range_tree'; @@ -41,12 +43,13 @@ class RangeTreeNode extends SimpleORMap implements StudipTreeNode ]; $config['has_many']['children'] = [ 'class_name' => RangeTreeNode::class, - 'foreign_key' => 'item_id', 'assoc_foreign_key' => 'parent_id', 'order_by' => 'ORDER BY priority, name', - 'on_delete' => 'delete' + 'on_delete' => 'delete', ]; + $config = self::registerCachableCallbacks($config); + parent::configure($config); } @@ -240,17 +243,6 @@ class RangeTreeNode extends SimpleORMap implements StudipTreeNode return DBManager::get()->fetchAll($query, $parameters, 'Course::buildExisting'); } - public function getDescendantIds() - { - $ids = []; - - foreach ($this->children as $child) { - $ids = array_merge($ids, [$child->id], $child->getDescendantIds()); - } - - return $ids; - } - public function getAncestors(): array { $path = [ diff --git a/lib/models/StudipStudyArea.class.php b/lib/models/StudipStudyArea.class.php index 1ea7722fc47cc0feb89c3f60a3f2f35f9954f502..518e6c1dcfa41e9b21b08666a87a971a4dc51ba9 100644 --- a/lib/models/StudipStudyArea.class.php +++ b/lib/models/StudipStudyArea.class.php @@ -30,6 +30,8 @@ class StudipStudyArea extends SimpleORMap implements StudipTreeNode { + use StudipTreeNodeCachableTrait; + /** * This constant represents the key of the root area. */ @@ -53,6 +55,9 @@ class StudipStudyArea extends SimpleORMap implements StudipTreeNode 'class_name' => StudipStudyArea::class, 'foreign_key' => 'parent_id', ]; + + $config = self::registerCachableCallbacks($config); + parent::configure($config); } @@ -64,7 +69,7 @@ class StudipStudyArea extends SimpleORMap implements StudipTreeNode /** * Returns the children of the study area with the specified ID. */ - static function findByParent($parent_id) + public static function findByParent($parent_id) { return self::findByparent_id($parent_id, "ORDER BY priority,name"); } @@ -601,17 +606,6 @@ class StudipStudyArea extends SimpleORMap implements StudipTreeNode return $path; } - private function getDescendantIds() - { - $ids = []; - - foreach ($this->_children as $child) { - $ids = array_merge($ids, [$child->id], $child->getDescendantIds()); - } - - return $ids; - } - /** * Constructs an index from the level hierarchy, This index is a number, * containing the "depth" level and the priority on this level. For example,