aboutsummaryrefslogtreecommitdiff
path: root/lib/models/CourseDate.class.php
diff options
context:
space:
mode:
authorJan-Hendrik Willms <tleilax+github@gmail.com>2021-07-22 16:07:19 +0200
committerJan-Hendrik Willms <tleilax+github@gmail.com>2021-07-22 16:19:12 +0200
commita3da1483a9e689846179159355badfec8073dbec (patch)
tree770dcca6bdf5f6f2a11b0e7fcbbeda6919a3fc52 /lib/models/CourseDate.class.php
current code from svn, revision 62608
Diffstat (limited to 'lib/models/CourseDate.class.php')
-rw-r--r--lib/models/CourseDate.class.php465
1 files changed, 465 insertions, 0 deletions
diff --git a/lib/models/CourseDate.class.php b/lib/models/CourseDate.class.php
new file mode 100644
index 0000000..9930f23
--- /dev/null
+++ b/lib/models/CourseDate.class.php
@@ -0,0 +1,465 @@
+<?php
+/**
+ * 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 Rasmus Fuhse <fuhse@data-quest.de>
+ * @copyright 2014 Stud.IP Core-Group
+ * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
+ * @category Stud.IP
+ *
+ * @property string termin_id database column
+ * @property string id alias column for termin_id
+ * @property string range_id database column
+ * @property string autor_id database column
+ * @property string content database column
+ * @property string description database column
+ * @property string date database column
+ * @property string end_time database column
+ * @property string mkdate database column
+ * @property string chdate database column
+ * @property string date_typ database column
+ * @property string topic_id database column
+ * @property string raum database column
+ * @property string metadate_id database column
+ * @property User author belongs_to User
+ * @property Course course belongs_to Course
+ * @property SeminarCycleDate cycle belongs_to SeminarCycleDate
+ * @property RoomRequest room_requests has_many RoomRequest
+ * @property ResourceBooking room_booking has_one ResourceBooking
+ * @property SimpleORMapCollection topics has_and_belongs_to_many CourseTopic
+ * @property SimpleORMapCollection statusgruppen has_and_belongs_to_many Statusgruppen
+ * @property SimpleORMapCollection dozenten has_and_belongs_to_many User
+ */
+
+class CourseDate extends SimpleORMap implements PrivacyObject
+{
+ const FORMAT_DEFAULT = 'default';
+ const FORMAT_VERBOSE = 'verbose';
+
+ private static $numbered_dates = null;
+
+ /**
+ * Configures this model.
+ *
+ * @param Array $config Configuration array
+ */
+ protected static function configure($config = [])
+ {
+ $config['db_table'] = 'termine';
+ $config['has_and_belongs_to_many']['topics'] = [
+ 'class_name' => 'CourseTopic',
+ 'thru_table' => 'themen_termine',
+ 'order_by' => 'ORDER BY priority',
+ 'on_delete' => 'delete',
+ 'on_store' => 'store'
+ ];
+ $config['has_and_belongs_to_many']['statusgruppen'] = [
+ 'class_name' => 'Statusgruppen',
+ 'thru_table' => 'termin_related_groups',
+ 'order_by' => 'ORDER BY position',
+ 'on_delete' => 'delete',
+ 'on_store' => 'store'
+ ];
+ $config['has_and_belongs_to_many']['dozenten'] = [
+ 'class_name' => 'User',
+ 'thru_table' => 'termin_related_persons',
+ 'foreign_key' => 'termin_id',
+ 'thru_key' => 'range_id',
+ 'order_by' => 'ORDER BY Nachname, Vorname',
+ 'on_delete' => 'delete',
+ 'on_store' => 'store'
+ ];
+ $config['has_many']['folders'] = [
+ 'class_name' => 'Folder',
+ 'assoc_func' => 'findByTermin_id'
+ ];
+ $config['belongs_to']['author'] = [
+ 'class_name' => 'User',
+ 'foreign_key' => 'autor_id'
+ ];
+ $config['belongs_to']['course'] = [
+ 'class_name' => 'Course',
+ 'foreign_key' => 'range_id'
+ ];
+ $config['belongs_to']['cycle'] = [
+ 'class_name' => 'SeminarCycleDate',
+ 'foreign_key' => 'metadate_id'
+ ];
+ $config['has_one']['room_booking'] = [
+ 'class_name' => 'ResourceBooking',
+ 'foreign_key' => 'termin_id',
+ 'assoc_foreign_key' => 'range_id',
+ 'on_delete' => 'delete',
+ //'on_store' => 'store'
+ ];
+ $config['has_many']['room_requests'] = [
+ 'class_name' => 'RoomRequest',
+ 'assoc_foreign_key' => 'termin_id',
+ 'on_delete' => 'delete',
+ ];
+ $config['default_values']['date_typ'] = 1;
+ parent::configure($config);
+ }
+
+ /**
+ * return consecutive number for a date in its course, if semester is given
+ * only within that time range
+ *
+ * @param CourseDate $date
+ * @param null|Semester $semester
+ * @return int|null
+ */
+ public static function getConsecutiveNumber($date, $semester = null)
+ {
+ if (!isset(self::$numbered_dates[@$semester->id ?: 'all'])) {
+ $db = DBManager::get();
+ $numbered = array_flip($db->fetchFirst("SELECT termin_id FROM termine WHERE range_id = ?" .
+ ($semester ? " AND date BETWEEN ? AND ?" : "") .
+ " ORDER BY date",
+ $semester ? [$date->range_id, $semester->beginn, $semester->ende] : [$date->range_id]));
+ self::$numbered_dates[@$semester->id ?: 'all'] = $numbered;
+ }
+ return isset(self::$numbered_dates[@$semester->id ?: 'all'][$date->termin_id])
+ ? self::$numbered_dates[@$semester->id ?: 'all'][$date->termin_id] + 1
+ : null;
+ }
+
+ /**
+ * Returns course dates by issue id.
+ *
+ * @param String $issue_id Id of the issue
+ * @return array with the associated dates
+ */
+ public static function findByIssue_id($issue_id)
+ {
+ return self::findBySQL("INNER JOIN themen_termine USING (termin_id)
+ WHERE themen_termine.issue_id = ?
+ ORDER BY date ASC",
+ [$issue_id]
+ );
+ }
+
+ /**
+ * Returns course dates by course id
+ *
+ * @param String $seminar_id Id of the course
+ * @return array with the associated dates
+ */
+ public static function findBySeminar_id($seminar_id)
+ {
+ return self::findByRange_id($seminar_id);
+ }
+
+ /**
+ * Return course dates by range id (which is in many cases the course id)
+ *
+ * @param String $seminar_id Id of the course
+ * @param String $order_by Optional order definition
+ * @return array with the associated dates
+ */
+ public static function findByRange_id($seminar_id, $order_by = 'ORDER BY date')
+ {
+ return parent::findByRange_id($seminar_id, $order_by);
+ }
+
+ /**
+ * Returns course dates by issue id.
+ *
+ * @param String $issue_id Id of the issue
+ * @return array with the associated dates
+ */
+ public static function findByStatusgruppe_id($group_id)
+ {
+ return self::findBySQL("INNER JOIN `termin_related_groups` USING (`termin_id`)
+ WHERE `termin_related_groups`.`statusgruppe_id` = ?
+ ORDER BY `date` ASC",
+ [$group_id]
+ );
+ }
+
+ public function __construct($id = null)
+ {
+ parent::__construct($id);
+ $this->registerCallback('before_store after_create', 'cbStudipLog');
+ }
+
+ /**
+ * Adds a topic to this date.
+ *
+ * @param mixed $topic Topic definition (might be an id, an array or an
+ * object)
+ * @return number addition of all return values, false if none was called
+ */
+ public function addTopic($topic)
+ {
+ $topic = CourseTopic::toObject($topic);
+ if (!$this->topics->find($topic->id)) {
+ $this->topics[] = $topic;
+ return $this->storeRelations('topics');
+ }
+ }
+
+ /**
+ * Removes a topic from this date.
+ *
+ * @param mixed $topic Topic definition (might be an id, an array or an
+ * object)
+ * @return number addition of all return values, false if none was called
+ */
+ public function removeTopic($topic)
+ {
+ $this->topics->unsetByPk(is_string($topic) ? $topic : $topic->id);
+ return $this->storeRelations('topics');
+ }
+
+ /**
+ * Returns the name of the assigned room for this date.
+ *
+ * @return String containing the room name
+ */
+ public function getRoomName()
+ {
+ if (Config::get()->RESOURCES_ENABLE && $this->room_booking->resource_id) {
+ return $this->room_booking->resource->name;
+ }
+ return $this['raum'];
+ }
+
+ /**
+ * Returns the assigned room for this date as an object.
+ *
+ * @return Room Either the object or null if no room is assigned
+ */
+ public function getRoom()
+ {
+ if (Config::get()->RESOURCES_ENABLE && $this->room_booking->resource_id) {
+ return $this->room_booking->resource->getDerivedClassInstance();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the name of the type of this date.
+ *
+ * @param String containing the type name
+ */
+ public function getTypeName()
+ {
+ return $GLOBALS['TERMIN_TYP'][$this->date_typ]['name'];
+ }
+
+ /**
+ * Returns the full qualified name of this date.
+ *
+ * @param String $format Optional format type (only 'default', 'include-room' and
+ * 'verbose' are supported by now)
+ * @return String containing the full name of this date.
+ */
+ public function getFullname($format = 'default')
+ {
+ if (!$this->date || !in_array($format, ['default', 'verbose', 'include-room'])) {
+ return '';
+ }
+
+ $latter_template = $format === 'verbose' ? _('%R Uhr') : '%R';
+
+ if (($this->end_time - $this->date) / 60 / 60 > 23) {
+ $string = strftime('%a., %x (' . _('ganztägig') . ')' , $this->date);
+ } else {
+ $string = strftime('%a., %x, %R', $this->date) . ' - '
+ . strftime($latter_template, $this->end_time);
+ }
+
+ if($format === 'include-room') {
+ $room = $this->getRoom();
+ if($room) {
+ $string = sprintf('%s <a href="%s" target="_blank">%s</a>',
+ $string,
+ $room->getActionURL('booking_plan'),
+ htmlReady($room->name)
+ );
+ }
+ }
+ return $string;
+ }
+
+ /**
+ * Converts a CourseDate Entry to a CourseExDate Entry
+ * returns instance of the new CourseExDate or NULL
+ *
+ * @return Object CourseExDate
+ */
+ public function cancelDate()
+ {
+ //NOTE: If you modify this method make sure the changes
+ //are also inserted in SingleDateDB::storeSingleDate
+ //and CourseExDate::unCancelDate to keep the behavior consistent
+ //across Stud.IP!
+
+ //These statements are used below to update the relations
+ //of this date.
+ $db = DBManager::get();
+
+ $groups_stmt = $db->prepare(
+ "UPDATE termin_related_groups
+ SET termin_id = :ex_termin_id
+ WHERE termin_id = :termin_id;"
+ );
+
+ $persons_stmt = $db->prepare(
+ "UPDATE termin_related_persons
+ SET range_id = :ex_termin_id
+ WHERE range_id = :termin_id;"
+ );
+
+ $date = $this->toArray();
+
+ $ex_date = new CourseExDate();
+ $ex_date->setData($date);
+ if ($room = $this->getRoom()) {
+ $ex_date['resource_id'] = $room->getId();
+ }
+ $ex_date->setId($ex_date->getNewId());
+
+ if ($ex_date->store()) {
+ //Update some (but not all) relations to the date so that they
+ //use the ID of the new ex-date.
+
+ $groups_stmt->execute(
+ [
+ 'ex_termin_id' => $ex_date->id,
+ 'termin_id' => $this->id
+ ]
+ );
+
+ $persons_stmt->execute(
+ [
+ 'ex_termin_id' => $ex_date->id,
+ 'termin_id' => $this->id
+ ]
+ );
+
+ //After we updated the relations so that they refer to the
+ //new ex-date we can delete this date and return the ex-date:
+ $this->delete();
+ return $ex_date;
+ }
+ return null;
+ }
+
+ /**
+ * saves this object and expires the cache
+ *
+ * @see SimpleORMap::store()
+ */
+ public function store()
+ {
+ // load room-booking, if any
+ $this->room_booking;
+
+ $cache = StudipCacheFactory::getCache();
+ $cache->expire('course/undecorated_data/'. $this->range_id);
+ return parent::store();
+ }
+
+ /**
+ * deletes this object and expires the cache
+ *
+ * @see SimpleORMap::delete()
+ */
+ public function delete()
+ {
+ $cache = StudipCacheFactory::getCache();
+ $cache->expire('course/undecorated_data/'. $this->range_id);
+ return parent::delete();
+ }
+
+ /**
+ * @param $type string type of callback
+ */
+ protected function cbStudipLog($type)
+ {
+ if (!$this->metadate_id) {
+ if ($type == 'after_create') {
+ StudipLog::log('SEM_ADD_SINGLEDATE', $this->range_id, $this->getFullname());
+ }
+ if ($type == 'before_store' && !$this->isNew() && ($this->isFieldDirty('date') || $this->isFieldDirty('end_time'))) {
+ $old_entry = self::build($this->content_db);
+ StudipLog::log('SINGLEDATE_CHANGE_TIME', $this->range_id, $this->getFullname(), $old_entry->getFullname() . ' -> ' . $this->getFullname());
+ }
+ }
+ }
+
+ /**
+ * Returns a list of all possible warnings that should be considered when
+ * this date is deleted.
+ *
+ * @return array of warnings
+ */
+ public function getDeletionWarnings()
+ {
+ $warnings = [];
+ if (count($this->topics) > 0) {
+ if (Config::get()->RESOURCES_ENABLE_EXPERT_SCHEDULE_VIEW) {
+ $warnings[] = _('Diesem Termin ist im Ablaufplan ein Thema zugeordnet.') . "\n"
+ . _('Titel und Beschreibung des Themas bleiben erhalten und können in der Expertenansicht des Ablaufplans einem anderen Termin wieder zugeordnet werden.');
+ } else {
+ $warnings[] = _('Diesem Termin ist ein Thema zugeordnet.');
+ }
+ }
+
+ if (Config::get()->RESOURCES_ENABLE && $this->getRoom()) {
+ $warnings[] = _('Dieser Termin hat eine Raumbuchung, welche mit dem Termin gelöscht wird.');
+ }
+
+ return $warnings;
+ }
+
+ /**
+ * return all filerefs belonging to this date, permissions fpr given user are checked
+ *
+ * @param string|User $user_or_id
+ * @return mixed[] A mixed array with FolderType and FileRef objects.
+ */
+ public function getAccessibleFolderFiles($user_or_id)
+ {
+ $user_id = $user_or_id instanceof User ? $user_or_id->id : $user_or_id;
+ $all_files = [];
+ $all_folders = [];
+ $folders = $this->folders->getArrayCopy();
+ foreach ($this->topics as $topic) {
+ $folders = array_merge($folders, $topic->folders->getArrayCopy());
+ }
+ foreach ($folders as $folder) {
+ list($files, $typed_folders) = array_values(FileManager::getFolderFilesRecursive($folder->getTypedFolder(), $user_id));
+ foreach ($files as $file) {
+ $all_files[$file->id] = $file;
+ }
+ $all_folders = array_merge($all_folders, $typed_folders);
+ }
+ return ['files' => $all_files, 'folders' => $all_folders];
+ }
+
+ /**
+ * Export available data of a given user into a storage object
+ * (an instance of the StoredUserData class) for that user.
+ *
+ * @param StoredUserData $storage object to store data into
+ */
+ public static function exportUserData(StoredUserData $storage)
+ {
+ $sorm = self::findBySQL("autor_id = ?", [$storage->user_id]);
+ if ($sorm) {
+ $field_data = [];
+ foreach ($sorm as $row) {
+ $field_data[] = $row->toRawArray();
+ }
+ if ($field_data) {
+ $storage->addTabularData(_('Termine'), 'termine', $field_data);
+ }
+ }
+ }
+} \ No newline at end of file