* @copyright 2022 Stud.IP Core-Group * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 * @category Stud.IP * @since 5.3 * * @property string $id alias column for item_id * @property string $item_id database column * @property string $parent_id database column * @property int $level database column * @property int $priority database column * @property string $name database column * @property string|null $studip_object database column * @property string|null $studip_object_id database column * @property SimpleORMapCollection $children has_many RangeTreeNode * @property Institute|null $institute belongs_to Institute * @property RangeTreeNode $parent belongs_to RangeTreeNode */ class RangeTreeNode extends SimpleORMap implements StudipTreeNode { use StudipTreeNodeCachableTrait; use StudipTreeNodeCourseTrait; protected static function configure($config = []) { $config['db_table'] = 'range_tree'; $config['belongs_to']['institute'] = [ 'class_name' => Institute::class, 'foreign_key' => 'studip_object_id', ]; $config['belongs_to']['parent'] = [ 'class_name' => RangeTreeNode::class, 'foreign_key' => 'parent_id', ]; $config['has_many']['children'] = [ 'class_name' => RangeTreeNode::class, 'assoc_foreign_key' => 'parent_id', 'order_by' => 'ORDER BY priority, name', 'on_delete' => 'delete', ]; $config = self::registerCachableCallbacks($config); parent::configure($config); } public static function getNode($id): ?StudipTreeNode { if ($id === 'root') { return static::build([ 'id' => 'root', 'name' => Config::get()->UNI_NAME_CLEAN, ]); } return static::find($id); } public static function getCourseNodes(string $course_id): array { $nodes = []; foreach (Course::find($course_id)->institutes as $institute) { $range = self::findOneByStudip_object_id($institute->id); if ($range) { $nodes[] = $range; } } return $nodes; } public function getName(): string { if ($this->id === 'root') { return Config::get()->UNI_NAME_CLEAN; } if ($this->institute) { return (string) $this->institute->name; } return $this->content['name']; } public function getDescription(): string { return ''; } public function getImage() { return $this->institute ? Avatar::getAvatar($this->studip_object_id) : Icon::create('institute'); } public function hasChildNodes(): bool { return count($this->children) > 0; } /** * @see StudipTreeNode::getChildNodes() */ public function getChildNodes(bool $onlyVisible = false): array { return self::findByParent_id($this->id, "ORDER BY `priority`"); } /** * @see StudipTreeNode::countCourses() */ public function countCourses($semester_id = '', $semclass = 0, $with_children = false): int { if (!$this->institute && !$with_children) { return 0; } [$condition, $parameters] = $this->getCoursesCondition( 'i', $semester_id, $semclass ); $query = "SELECT COUNT(DISTINCT i.`seminar_id`) FROM `seminar_inst` i {$condition}"; if ($with_children) { $query .= " AND i.`institut_id` IN ( SELECT DISTINCT `studip_object_id` FROM `range_tree` WHERE `item_id` IN (:ids) )"; $parameters['ids'] = array_merge([$this->id], $this->getDescendantIds()); } else { $query .= " AND i.`institut_id` = :id"; $parameters['id'] = $this->studip_object_id; } return DBManager::get()->fetchColumn($query, $parameters); } public function getCourses( $semester_id = 'all', $semclass = 0, $searchterm = '', $with_children = false, array $courses = [] ): array { [$condition, $parameters, $order_by] = $this->getCoursesCondition( 'i', $semester_id, $semclass, $searchterm, $courses ); $query = "SELECT DISTINCT s.* FROM `seminar_inst` AS i {$condition}"; if ($with_children) { $query .= " AND i.`institut_id` IN ( SELECT DISTINCT `studip_object_id` FROM `range_tree` WHERE `item_id` IN (:ids) )"; $parameters['ids'] = array_merge([$this->id], $this->getDescendantIds()); } else { $query .= " AND i.`institut_id` = :id"; $parameters['id'] = $this->studip_object_id; } $query .= " ORDER BY " . implode(', ', $order_by); return DBManager::get()->fetchAll($query, $parameters, 'Course::buildExisting'); } public function getAncestors(): array { $path = [ [ 'id' => $this->id, 'name' => $this->getName(), 'classname' => self::class ] ]; if ($this->parent_id) { $path = array_merge($this->getNode($this->parent_id)->getAncestors(), $path); } return $path; } }