Skip to content
Snippets Groups Projects
RangeTreeNode.php 8.39 KiB
Newer Older
<?php

/**
 * RangeTreeNode.php
 * model class for table range_tree
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * @author      Thomas Hackl <hackl@data-quest.de>
 * @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 database column
 * @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 studip_object database column
 * @property string studip_object_id database column
 */
class RangeTreeNode extends SimpleORMap implements StudipTreeNode
{
    use StudipTreeNodeCachableTrait;

    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`, `name`");
    }

    /**
     * @see StudipTreeNode::countCourses()
     */
    public function countCourses($semester_id = '', $semclass = 0, $with_children = false): int
    {
        if ($semester_id) {
            $query = "SELECT COUNT(DISTINCT i.`seminar_id`)
                      FROM `seminar_inst` i
                      JOIN `seminare` s ON (s.`Seminar_id` = i.`seminar_id`)
                      LEFT JOIN `semester_courses` sc ON (i.`seminar_id` = sc.`course_id`)
                      WHERE i.`institut_id` IN (
                          SELECT DISTINCT `studip_object_id`
                          FROM `range_tree`
                          WHERE `item_id` IN (:ids)
                      ) AND (
                          sc.`semester_id` = :semester
                          OR sc.`semester_id` IS NULL
                      )";
            $parameters = [
                'ids' => $with_children ? $this->getDescendantIds() : [$this->id],
                'semester' => $semester_id
            ];
        } else {
            $query = "SELECT COUNT(DISTINCT `seminar_id`)
                      FROM `seminar_inst` i
                      JOIN `seminare` s ON (s.`Seminar_id` = i.`seminar_id`)
                      WHERE `institut_id` IN (
                          SELECT DISTINCT `studip_object_id`
                          FROM `range_tree`
                          WHERE `item_id` IN (:ids)
                      )";
            $parameters = ['ids' => $with_children ? $this->getDescendantIds() : [$this->id]];
        }

        if (!$GLOBALS['perm']->have_perm(Config::get()->SEM_VISIBILITY_PERM)) {
            $query .= " AND s.`visible` = 1";
        }

        if ($semclass !== 0) {
            $query .= "  AND s.`status` IN (:types)";
            $parameters['types'] = array_map(
                function ($type) {
                    return $type['id'];
                },
                array_filter(
                    SemType::getTypes(),
                    function ($t) use ($semclass) { return $t['class'] === $semclass; }
                )
            );
        }

        return !$this->institute && !$with_children ? 0 : DBManager::get()->fetchColumn($query, $parameters);
    }

    public function getCourses(
        $semester_id = 'all',
        $semclass = 0,
        $searchterm = '',
        $with_children = false,
        array $courses = []
    ): array
    {
        if ($semester_id !== 'all') {
            $query = "SELECT DISTINCT s.*
                      FROM `seminare` s
                      JOIN `seminar_inst` i ON (i.`seminar_id` = s.`Seminar_id`)
                      LEFT JOIN `semester_courses` sem ON (sem.`course_id` = s.`Seminar_id`)
                      WHERE i.`institut_id` IN (
                          SELECT DISTINCT `studip_object_id`
                          FROM `range_tree`
                          WHERE `item_id` IN (:ids)
                      ) AND (
                          sem.`semester_id` = :semester
                          OR sem.`semester_id` IS NULL
                      )";

            $parameters = [
                'ids' => $with_children ? $this->getDescendantIds() : [$this->id],
                'semester' => $semester_id
            ];
        } else {
            $query = "SELECT DISTINCT s.*
                      FROM `seminare` s
                      JOIN `seminar_inst` i ON (i.`seminar_id` = s.`Seminar_id`)
                      WHERE i.`institut_id` IN (
                          SELECT DISTINCT `studip_object_id`
                          FROM `range_tree`
                          WHERE `item_id` IN (:ids)
                      )";
            $parameters = ['ids' => $with_children ? $this->getDescendantIds() : [$this->id]];
        }

        if (!$GLOBALS['perm']->have_perm(Config::get()->SEM_VISIBILITY_PERM)) {
            $query .= " AND s.`visible` = 1";
        }

        if ($searchterm) {
            $query .= " AND s.`Name` LIKE :searchterm";
            $parameters['searchterm'] = '%' . trim($searchterm) . '%';
        }

        if ($courses) {
            $query .= " AND s.`Seminar_id` IN (:courses)";
            $parameters['courses'] = $courses;
        }

        if ($semclass !== 0) {
            $query .= "  AND s.`status` IN (:types)";
            $parameters['types'] = array_map(
                function ($type) {
                    return $type['id'];
                },
                array_filter(
                    SemType::getTypes(),
                    function ($t) use ($semclass) { return $t['class'] === $semclass; }
                )
            );
        }

        if (Config::get()->IMPORTANT_SEMNUMBER) {
            $query .= " ORDER BY s.`start_time`, s.`VeranstaltungsNummer`, s.`Name`";
        } else {
            $query .= " ORDER BY s.`start_time`, s.`Name`";
        }

        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;
    }

}