Newer
Older
<?php
/**
* @author David Siegfried <david.siegfried@uni-vechta.de>
* @license GPL2 or any later version
* @since 3.4
*/

David Siegfried
committed
class Course_TimesroomsController extends AuthenticatedController
{
/**
* Common actions before any other action
*
* @param String $action Action to be executed
* @param Array $args Arguments passed to the action
*
* @throws Trails\Exception when either no course was found or the user
* may not access this area
*/
public function before_filter(&$action, &$args)
{
parent::before_filter($action, $args);
// Try to find a valid course
if (!Course::findCurrent()) {
throw new Trails\Exception(404, _('Es wurde keine Veranstaltung ausgewählt!'));
}
if (!$GLOBALS['perm']->have_studip_perm('tutor', Course::findCurrent()->id)) {
throw new AccessDeniedException();
}
// Get seminar instance
$this->course = new Seminar(Course::findCurrent());
if (Navigation::hasItem('course/admin/dates')) {
Navigation::activateItem('course/admin/dates');
}
$this->locked = false;
if (LockRules::Check($this->course->id, 'room_time')) {
$this->locked = true;
$this->lock_rules = LockRules::getObjectRule($this->course->id);
PageLayout::postInfo(
_('Diese Seite ist für die Bearbeitung gesperrt. Sie können die Daten einsehen, jedoch nicht verändern.')
. ($this->lock_rules['description'] ? '<br>' . formatLinks($this->lock_rules['description']) : '')
);
}
$this->show = [
'regular' => true,
'irregular' => true,
'roomRequest' => !$this->locked && Config::get()->RESOURCES_ENABLE && Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS,
];
PageLayout::setHelpKeyword('Basis.Veranstaltungen');
$title = _('Verwaltung von Zeiten und Räumen');
$title = $this->course->getFullName() . ' - ' . $title;
PageLayout::setTitle($title);
URLHelper::bindLinkParam('semester_filter', $this->semester_filter);
if (empty($this->semester_filter)) {
if (!$this->course->hasDatesOutOfDuration() && count($this->course->semesters) == 1) {
$this->semester_filter = $this->course->start_semester->id;
} else {
$this->semester_filter = 'all';
}
}
if ($this->semester_filter == 'all') {
$this->course->applyTimeFilter(0, 0);
} else {
$semester = Semester::find($this->semester_filter);
$this->course->applyTimeFilter($semester['beginn'], $semester['ende']);
}
if ($this->course->isOpenEnded()) {
$selectable_semesters = Semester::getAll();
} else {
$selectable_semesters = $this->course->semesters->toArray();
}
if (count($selectable_semesters) > 1 || (count($selectable_semesters) == 1 && $this->course->hasDatesOutOfDuration())) {
$selectable_semesters[] = ['name' => _('Alle Semester'), 'semester_id' => 'all'];
}
$this->selectable_semesters = array_reverse($selectable_semesters);
if (!Request::isXhr()) {
$this->setSidebar();
} elseif (Request::isXhr() && $this->flash['update-times']) {
$semester_id = $GLOBALS['user']->cfg->MY_COURSES_SELECTED_CYCLE ?? '';
$this->response->add_header(
'X-Raumzeit-Update-Times',
json_encode([
'course_id' => $this->course->id,
'html' => $this->course->getDatesHTML([
'semester_id' => $semester_id,
'show_room' => true,
]) ?: _('nicht angegeben'),
])
);
}
}
Moritz Strohm
committed
protected function bookingTooShort(int $start_time, int $end_time)
{
return Config::get()->RESOURCES_MIN_BOOKING_TIME &&
(($end_time - $start_time) < Config::get()->RESOURCES_MIN_BOOKING_TIME * 60);
}
/**
* Displays the times and rooms of a course
*
* @param mixed $course_id Id of the course (optional, defaults to
* globally selected)
*/
public function index_action()
{
Helpbar::get()->addPlainText(_('Rot'), _('Kein Termin hat eine Raumbuchung.'));
Helpbar::get()->addPlainText(_('Gelb'), _('Mindestens ein Termin hat keine Raumbuchung.'));
Helpbar::get()->addPlainText(_('Grün'), _('Alle Termine haben eine Raumbuchung.'));
if (Request::isXhr()) {
$this->show = [
'regular' => true,
'irregular' => true,
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
];
}
$this->linkAttributes = ['fromDialog' => Request::isXhr() ? 1 : 0];
$this->semester = array_reverse(Semester::getAll());
$this->current_semester = Semester::findCurrent();
$this->cycle_dates = [];
$matched = [];
$this->cycle_room_names = [];
foreach ($this->course->cycles as $cycle) {
$cycle_has_multiple_rooms = false;
foreach ($cycle->getAllDates() as $val) {
foreach ($this->semester as $sem) {
if ($this->semester_filter !== 'all' && $this->semester_filter !== $sem->id) {
continue;
}
if ($sem->beginn <= $val->date && $sem->ende >= $val->date) {
if (!isset($this->cycle_dates[$cycle->metadate_id])) {
$this->cycle_dates[$cycle->metadate_id] = [
'cycle' => $cycle,
'dates' => [],
'room_request' => [],
];
}
if (!isset($this->cycle_dates[$cycle->metadate_id]['dates'][$sem->id])) {
$this->cycle_dates[$cycle->metadate_id]['dates'][$sem->id] = [];
}
$this->cycle_dates[$cycle->metadate_id]['dates'][$sem->id][] = $val;
if ($val->getRoom()) {
$this->cycle_dates[$cycle->metadate_id]['room_request'][] = $val->getRoom();
}
$matched[] = $val->termin_id;
//Check if a room is booked for the date:
if (($val->room_booking instanceof ResourceBooking)
&& !$cycle_has_multiple_rooms) {
$date_room = $val->room_booking->resource->name;
if (isset($this->cycle_room_names[$cycle->id])) {
if ($date_room && $date_room != $this->cycle_room_names[$cycle->id]) {
$cycle_has_multiple_rooms = true;
}
} elseif ($date_room) {
$this->cycle_room_names[$cycle->id] = $date_room;
}
}
}
}
}
if ($cycle_has_multiple_rooms) {
$this->cycle_room_names[$cycle->id] = _('mehrere gebuchte Räume');
}
}
$dates = $this->course->getDatesWithExdates();
$this->current_user = User::findCurrent();
$this->user_has_permissions = ResourceManager::userHasGlobalPermission($this->current_user, 'admin');
$check_room_requests = Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS;
$this->room_requests = RoomRequest::findBySQL(
'course_id = :course_id
ORDER BY course_id, metadate_id, termin_id',
[
'course_id' => $this->course->id
]
);
$this->global_requests = $this->course->room_requests->filter(function (RoomRequest $request) {
return $request->closed < 2 && !$request->termin_id;
});
$single_dates = [];
$this->single_date_room_request_c = 0;
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
foreach ($this->semester as $sem) {
if ($this->semester_filter !== 'all' && $this->semester_filter !== $sem->id) {
continue;
}
if ($sem->beginn > $val->date || $sem->ende < $val->date || $val->metadate_id != '') {
continue;
}
if (!isset($single_dates[$sem->id])) {
$single_dates[$sem->id] = new SimpleCollection();
}
$single_dates[$sem->id]->append($val);
$matched[] = $val->id;
if ($check_room_requests) {
$this->single_date_room_request_c += ResourceRequest::countBySql(
"resource_requests.closed < '2' AND termin_id = :termin_id",
[
'termin_id' => $val->id
]
);
}
}
}
if ($this->semester_filter === 'all') {
$out_of_bounds = $dates->findBy('id', $matched, '!=');
if (count($out_of_bounds)) {
$single_dates['none'] = $out_of_bounds;
}
}
$this->single_dates = $single_dates;
$this->checked_dates = [];
if (!empty($_SESSION['_checked_dates'])) {
$this->checked_dates = $_SESSION['_checked_dates'];
unset($_SESSION['_checked_dates']);
}
if (Request::isDialog()) {
$this->response->add_header('X-Dialog-Execute', '{"func": "STUDIP.AdminCourses.App.loadCourse", "payload": "'.$this->course->getId().'"}');
}
/**
* Edit the start-semester of a course
*
* @throws Trails\Exceptions\DoubleRenderError
*/
public function editSemester_action()
{
URLHelper::addLinkParam('origin', Request::option('origin', 'course_timesrooms'));
$this->semester = array_reverse(Semester::getAll());
$this->current_semester = Semester::findCurrent();
if (Request::submitted('save')) {
CSRFProtection::verifyUnsafeRequest();
$start_semester = Semester::find(Request::get('startSemester'));
if (Request::get('endSemester') != '-1' && Request::get('endSemester') != '0') {
$end_semester = Semester::find(Request::get('endSemester'));
} else {
$end_semester = Request::int('endSemester');
}
$course = Course::findCurrent();
if ($start_semester == $end_semester) {
$end_semester = 0;
}
if ($end_semester != 0 && $end_semester != -1 && $start_semester->beginn >= $end_semester->beginn) {
PageLayout::postError(_('Das Startsemester liegt nach dem Endsemester!'));
} else {
$old_start_weeks = !$course->isOpenEnded() ? $course->start_semester->getStartWeeks($course->end_semester) : [];
//set the new semester array:
if ($end_semester == -1) {
$course->semesters = [];
} elseif($end_semester == 0) {
$course->semesters = [$start_semester];
} else {
$selected_semesters = [];
foreach (Semester::getAll() as $sem) {
if ($sem['beginn'] >= $start_semester['beginn'] && $sem['ende'] <= $end_semester['ende']) {
$selected_semesters[] = $sem;
}
}
$course->semesters = $selected_semesters;
}
// set the semester-chooser to the first semester
$this->course->setFilter($course->getStartSemester());
$this->semester_filter = $start_semester->semester_id;
$course->store();
if (!$course->isOpenEnded()) {
$new_start_weeks = $course->start_semester->getStartWeeks($course->end_semester);
SeminarCycleDate::removeOutRangedSingleDates($this->course->getStartSemester(), $this->course->getEndSemesterVorlesEnde(), $course->id);
$cycles = SeminarCycleDate::findBySeminar_id($course->id);
foreach ($cycles as $cycle) {
$cycle->end_offset = $this->getNewEndOffset($cycle, $old_start_weeks, $new_start_weeks);
$cycle->generateNewDates();
$cycle->store();
}
}
$messages = $this->course->getStackedMessages();
foreach ($messages as $type => $msg) {
PageLayout::postMessage(MessageBox::$type($msg['title'], $msg['details']));
}
$this->relocate(str_replace('_', '/', Request::option('origin')));
}
if (Request::isDialog()) {
$this->response->add_header('X-Dialog-Execute', '{"func": "STUDIP.AdminCourses.App.loadCourse", "payload": "'.$this->course->getId().'"}');
}
}
/**
* Primary function to edit date-informations
*

David Siegfried
committed
* @param string $termin_id
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
*/
public function editDate_action($termin_id)
{
PageLayout::setTitle(_('Einzeltermin bearbeiten'));
$this->date = CourseDate::find($termin_id) ?: CourseExDate::find($termin_id);
$this->attributes = [];
$this->only_bookable_rooms = Request::submitted('only_bookable_rooms');
if (Config::get()->RESOURCES_ENABLE) {
$room_booking_id = '';
if ($this->date->room_booking instanceof ResourceBooking) {
$room_booking_id = $this->date->room_booking->id;
$room = $this->date->room_booking->resource;
if ($room instanceof Resource) {
$room = $room->getDerivedClassInstance();
if (!$room->userHasBookingRights(User::findCurrent())) {
PageLayout::postWarning(
_('Die Raumbuchung zu diesem Termin wird bei der Verlängerung des Zeitbereiches gelöscht, da sie keine Buchungsrechte am Raum haben!')
);
}
}
}
$this->setAvailableRooms([$this->date], [$room_booking_id], $this->only_bookable_rooms);
}
$this->teachers = $this->course->getMembersWithStatus('dozent');
$this->assigned_teachers = $this->date->dozenten;
$this->groups = $this->course->statusgruppen;
$this->assigned_groups = $this->date->statusgruppen;
$this->preparation_time = $this->date->room_booking instanceof ResourceBooking
? $this->date->room_booking->preparation_time / 60
: '0';
$this->max_preparation_time = Config::get()->RESOURCES_MAX_PREPARATION_TIME;
}
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
/**
* Clone an existing date
*
* @param $termin_id
*/
public function cloneDate_action($termin_id)
{
$date = CourseDate::find($termin_id);
if ($date) {
$termin = CourseDate::build($date);
$termin->setId($termin->getNewId());
$termin->dozenten = $date->dozenten;
$termin->statusgruppen = $date->statusgruppen;
$termin->store();
PageLayout::postSuccess(sprintf(
_('Der Termin "%s" wurde dupliziert.'),
htmlReady($termin->getFullName())
));
}
$this->redirect('course/timesrooms/index');
}
/**
* Save date-information
*
* @param $termin_id
*
* @throws Trails\Exceptions\DoubleRenderError
*/
public function saveDate_action($termin_id)
{
// TODO :: TERMIN -> SINGLEDATE
CSRFProtection::verifyUnsafeRequest();
$termin = CourseDate::find($termin_id);
$date = strtotime(sprintf('%s %s:00', Request::get('date'), Request::get('start_time')));
$end_time = strtotime(sprintf('%s %s:00', Request::get('date'), Request::get('end_time')));
$max_preparation_time = Config::get()->RESOURCES_MAX_PREPARATION_TIME;
if ($date === false || $end_time === false || $date > $end_time) {
$date = $termin->date;
$end_time = $termin->end_time;
PageLayout::postError(_('Die Zeitangaben sind nicht korrekt. Bitte überprüfen Sie diese!'));
}
Moritz Strohm
committed
if ($this->bookingTooShort($date, $end_time)) {
PageLayout::postError(
sprintf(
ngettext(
'Die minimale Dauer eines Termins von einer Minute wurde unterschritten.',
'Die minimale Dauer eines Termins von %u Minuten wurde unterschritten.',
Config::get()->RESOURCES_MIN_BOOKING_TIME
),
Config::get()->RESOURCES_MIN_BOOKING_TIME
)
);
$this->redirect('course/timesrooms/editDate/' . $termin_id, ['contentbox_open' => $termin->metadate_id]);
return;
}
$time_changed = ($date != $termin->date || $end_time != $termin->end_time);
//time changed for regular date. create normal singledate and cancel the regular date
if ($termin->metadate_id != '' && $time_changed) {
$termin_values = $termin->toArray();
$termin_info = $termin->getFullName();
PageLayout::postInfo(sprintf(
_('Der Termin %s wurde aus der Liste der regelmäßigen Termine'
. ' gelöscht und als unregelmäßiger Termin eingetragen, da Sie die Zeiten des Termins verändert haben,'
. ' so dass dieser Termin nun nicht mehr regelmäßig ist.'),
htmlReady($termin_info)
));
$termin = new CourseDate();
unset($termin_values['metadate_id']);
$termin->setData($termin_values);
$termin->setId($termin->getNewId());
}
$termin->date_typ = Request::get('course_type');
// Set assigned teachers
$assigned_teachers = Request::optionArray('assigned_teachers');
$dozenten = $this->course->getMembers();
if (count($assigned_teachers) === count($dozenten) || empty($assigned_teachers)) {
//The amount of lecturers of the course date is the same as the amount of lecturers of the course
//or no lecturers are assigned to the course date.
$termin->dozenten = [];
} else {
//The assigned lecturers (amount or persons) have been changed in the form.
//In those cases, the lecturers of the course date have to be set.
$termin->dozenten = User::findMany($assigned_teachers);

Thomas Hackl
committed
$assigned_groups = Request::optionArray('assigned-groups');
$termin->statusgruppen = Statusgruppen::findMany($assigned_groups);
$termin->store();
if ($time_changed) {
NotificationCenter::postNotification('CourseDidChangeSchedule', $this->course);
}
// Set Room
if ($termin->room_booking) {
$old_room_id = $termin->room_booking->resource_id;
} else {
$old_room_id = null;
}
$singledate = new SingleDate($termin);
if ($singledate->setTime($date, $end_time)) {
$singledate->store();
}
if ((Request::option('room') == 'room') || Request::option('room') == 'nochange') {
//Storing the SingleDate above has deleted the room booking
//(see SingleDateDB::storeSingleDate). Therefore, the booking
//has to be recereated, even if the room option
//is set to "nochange".
$room_id = null;
if (Request::option('room') == 'room') {
$room_id = Request::get('room_id');
if ($preparation_time > $max_preparation_time) {
PageLayout::postError(
sprintf(
_('Die eingegebene Rüstzeit überschreitet das erlaubte Maximum von %d Minuten!'),
$max_preparation_time
)
);
}
}
if ($room_id) {
if ($room_id != $singledate->resource_id) {
if ($singledate->bookRoom($room_id, $preparation_time ?: 0)) {
$messages = $singledate->getMessages();
$this->course->appendMessages($messages);
} else if (!$singledate->ex_termin) {
$this->course->createError(
sprintf(
_('Der angegebene Raum konnte für den Termin %s nicht gebucht werden!'),
'<strong>' . htmlReady($singledate->toString()) . '</strong>'
)
);
}
} elseif ($termin->room_booking->preparation_time != ($preparation_time * 60)) {
$singledate->bookRoom($room_id, $preparation_time ?: 0);
}
} else if ($old_room_id && !$singledate->resource_id) {
$this->course->createInfo(
sprintf(
_('Die Raumbuchung für den Termin %s wurde aufgehoben, da die neuen Zeiten außerhalb der alten liegen!'),
'<strong>'.htmlReady( $singledate->toString()) .'</strong>'
));
} else if (Request::get('room_id_parameter')) {
$this->course->createInfo(
_('Um eine Raumbuchung durchzuführen, müssen Sie einen Raum aus dem Suchergebnis auswählen!')
);
}
} elseif (Request::option('room') == 'freetext') {
$singledate->setFreeRoomText(Request::get('freeRoomText_sd'));
$singledate->killAssign();
$singledate->store();
$this->course->createMessage(sprintf(
_('Der Termin %s wurde geändert, etwaige Raumbuchungen wurden entfernt und stattdessen der angegebene Freitext eingetragen!'),
'<strong>' . htmlReady($singledate->toString()) . '</strong>'
));
} elseif (Request::option('room') == 'noroom') {
$singledate->setFreeRoomText('');
$singledate->killAssign();
$singledate->store();
$this->course->createMessage(sprintf(
_('Der Termin %s wurde geändert, etwaige freie Ortsangaben und Raumbuchungen wurden entfernt.'),
'<strong>' . htmlReady($singledate->toString()) . '</strong>'
));
if (!empty($singledate->messages['error'])) {
PageLayout::postError(
_('Die folgenden Fehler traten beim Bearbeiten des Termins auf:'),
htmlReady($singledate->messages['error'])
);
}
$this->displayMessages();
$this->redirect('course/timesrooms/index', ['contentbox_open' => $termin->metadate_id]);
}
/**
* Create Single Date
*/
public function createSingleDate_action()
{
PageLayout::setTitle(Course::findCurrent()->getFullName() . " - " . _('Einzeltermin anlegen'));
words('date start_time end_time room related_teachers related_statusgruppen freeRoomText dateType fromDialog course_type'),
$_SESSION['last_single_date'] ?? null
if (Config::get()->RESOURCES_ENABLE) {
$this->setAvailableRooms(null);
}
$this->teachers = $this->course->getMembers('dozent');
$this->groups = Statusgruppen::findBySeminar_id($this->course->id);
}
/**
* Save Single Date
*
* @throws Trails\Exceptions\DoubleRenderError
*/
public function saveSingleDate_action()
{
CSRFProtection::verifyUnsafeRequest();
$start_time = strtotime(sprintf('%s %s:00', Request::get('date'), Request::get('start_time')));
$end_time = strtotime(sprintf('%s %s:00', Request::get('date'), Request::get('end_time')));
if ($start_time === false || $end_time === false || $start_time > $end_time) {
$this->storeRequest();
PageLayout::postError(_('Die Zeitangaben sind nicht korrekt. Bitte überprüfen Sie diese!'));
$this->redirect('course/timesrooms/createSingleDate');
return;
}
Moritz Strohm
committed
if ($this->bookingTooShort($start_time, $end_time)) {
PageLayout::postError(
sprintf(
ngettext(
'Die minimale Dauer eines Termins von einer Minute wurde unterschritten.',
'Die minimale Dauer eines Termins von %u Minuten wurde unterschritten.',
Config::get()->RESOURCES_MIN_BOOKING_TIME
),
Config::get()->RESOURCES_MIN_BOOKING_TIME
)
);
$this->redirect('course/timesrooms/createSingleDate');
return;
}
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
$termin = new CourseDate();
$termin->termin_id = $termin->getNewId();
$termin->range_id = $this->course->id;
$termin->date = $start_time;
$termin->end_time = $end_time;
$termin->autor_id = $GLOBALS['user']->id;
$termin->date_typ = Request::get('dateType');
$current_count = CourseMember::countByCourseAndStatus($this->course->id, 'dozent');
$related_ids = Request::optionArray('related_teachers');
if ($related_ids && count($related_ids) !== $current_count) {
$termin->dozenten = User::findMany($related_ids);
}
$groups = Statusgruppen::findBySeminar_id($this->course->id);
$related_groups = Request::getArray('related_statusgruppen');
if ($related_groups && count($related_groups) !== count($groups)) {
$termin->statusgruppen = Statusgruppen::findMany($related_groups);
}
if (!Request::get('room_id')) {
$termin->raum = Request::get('freeRoomText');
$termin->store();
} else {
$termin->store();
$singledate = new SingleDate($termin);
$singledate->bookRoom(Request::option('room_id'));
$this->course->appendMessages($singledate->getMessages());
}
if (Request::get('room_id_parameter')) {
$this->course->createInfo(
_('Um eine Raumbuchung durchzuführen, müssen Sie einen Raum aus dem Suchergebnis auswählen!')
);
// store last created date in session
$_SESSION['last_single_date'] = Request::getInstance();
if ($start_time < $this->course->filterStart || $end_time > $this->course->filterEnd) {
$this->course->setFilter('all');
}
$this->course->createMessage(sprintf(_('Der Termin %s wurde hinzugefügt!'), htmlReady($termin->getFullName())));
$this->course->store();
$this->displayMessages();
$this->relocate('course/timesrooms/index');
}
/**
* Restores a previously removed date.
*
* @param String $termin_id Id of the previously removed date
*/
public function undeleteSingle_action($termin_id, $from_dates = false)
{
$ex_termin = CourseExDate::find($termin_id);
$termin = $ex_termin->unCancelDate();
if ($termin) {
$this->course->createMessage(sprintf(
_('Der Termin %s wurde wiederhergestellt!'),
htmlReady($termin->getFullName())
$this->displayMessages();
}
if ($from_dates) {
$this->redirect("course/dates#date_{$termin_id}");
} else {
$params = [];
if ($termin->metadate_id != '') {
$params['contentbox_open'] = $termin->metadate_id;
}
$this->redirect('course/timesrooms/index', $params);
}
}
/**
* Performs a stack action defined by url parameter method.
*
* @param String $cycle_id Id of the cycle the action should be performed
* upon
*/
public function stack_action($cycle_id = '')
{
$_SESSION['_checked_dates'] = Request::optionArray('single_dates');
if (empty($_SESSION['_checked_dates']) && isset($_SESSION['_checked_dates'])) {
PageLayout::postError(_('Sie haben keine Termine ausgewählt!'));
$this->redirect('course/timesrooms/index', ['contentbox_open' => $cycle_id]);
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
return;
}
$this->linkAttributes = ['fromDialog' => Request::int('fromDialog') ? 1 : 0];
switch (Request::get('method')) {
case 'edit':
PageLayout::setTitle(_('Termine bearbeiten'));
$this->editStack($cycle_id);
break;
case 'preparecancel':
PageLayout::setTitle(_('Termine ausfallen lassen'));
$this->prepareCancel($cycle_id);
break;
case 'undelete':
PageLayout::setTitle(_('Termine stattfinden lassen'));
$this->unDeleteStack($cycle_id);
break;
case 'request':
PageLayout::setTitle(
_('Anfrage auf ausgewählte Termine stellen')
);
$this->requestStack($cycle_id);
}
}
/**
* Edits a stack/cycle.
*
* @param String $cycle_id Id of the cycle to be edited.
*/
private function editStack($cycle_id)
{
$this->cycle_id = $cycle_id;
$this->teachers = $this->course->getMembers();
$this->gruppen = Statusgruppen::findBySeminar_id($this->course->id);
$checked_course_dates = CourseDate::findMany($_SESSION['_checked_dates']);
$this->only_bookable_rooms = Request::submitted('only_bookable_rooms');
$date_booking_ids = [];
if ($this->only_bookable_rooms) {
$date_ids = [];
foreach ($checked_course_dates as $date) {
$date_ids[] = $date->termin_id;
}
$db = DBManager::get();
$stmt = $db->prepare(
"SELECT DISTINCT `id` FROM `resource_bookings` WHERE `range_id` IN ( :date_ids )"
);
$stmt->execute(['date_ids' => $date_ids]);
$date_booking_ids = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);
}
$this->setAvailableRooms($checked_course_dates, $date_booking_ids, $this->only_bookable_rooms);
/*
* Extract a single date for start and end time
* (all cycle dates have the same start and end time,
* so it doesn't matter which date we get).
*/
$this->date = CourseDate::findOneByMetadate_id($cycle_id);
$this->checked_dates = $_SESSION['_checked_dates'];
$this->selected_lecturer_ids = $this->getSameFieldValue($checked_course_dates, function (CourseDate $date) {
return $date->dozenten->pluck('user_id');
});
$this->selected_room_id = $this->getSameFieldValue($checked_course_dates, function (CourseDate $date) {
return $date->room_booking->resource_id ?? '';
});
$this->selected_room_name = $this->getSameFieldValue($checked_course_dates, function (CourseDate $date) {
return $date->raum ?? '';
});
$preparation_time = $this->getSameFieldValue($checked_course_dates, function (CourseDate $date) {
return $date->room_booking->preparation_time ?? 0;
});
$this->preparation_time = floor($preparation_time / 60);
$this->max_preparation_time = Config::get()->RESOURCES_MAX_PREPARATION_TIME;
$this->render_template('course/timesrooms/editStack');
}
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
/**
* Checks a specific field value of the specified course dates for equality.
* A closure defines which field of the course dates to check.
*
* @param CourseDate[] $dates The dates from which to extract values.
* @param Closure $callback The closure that extracts values from a CourseDate object that is passed to it.
* @return mixed The identical value that has been retrieved from all course dates or a value that is equal to
* false in case the value differs. The returned result might be a string or an array or it may be empty.
*/
protected function getSameFieldValue(array $dates, Closure $callback)
{
$data = array_map($callback, $dates);
$initial = null;
foreach ($data as $item) {
if ($initial === null) {
$initial = $item;
continue;
}
// Compare array by checking their sizes and different items
if (
is_array($initial)
&& (
count($initial) !== count($item)
|| count(array_diff($initial, $item)) > 0
)
) {
return [];
}
// Otherwise compare items themselves
if (!is_array($initial) && $initial != $item) {
return '';
}
}
return $initial;
}
* Creates a new room request for the selected dates.
*/
protected function requestStack($cycle_id)
{
$appointment_ids = [];
foreach ($_SESSION['_checked_dates'] as $appointment_id) {
if (CourseDate::exists($appointment_id)) {
$appointment_ids[] = $appointment_id;
}
}
if (!$appointment_ids) {
PageLayout::postError(_('Es wurden keine gültigen Termin-IDs übergeben!'));
$this->relocate('course/timesrooms/index', ['contentbox_open' => $cycle_id]);
return;
}
[
'range' => 'date-multiple',
'range_ids' => $appointment_ids
]
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
);
}
/**
* Prepares a stack/cycle to be canceled.
*
* @param String $cycle_id Id of the cycle to be canceled.
*/
private function prepareCancel($cycle_id)
{
$this->cycle_id = $cycle_id;
$this->render_template('course/timesrooms/cancelStack');
}
/**
* Restores a previously deleted stack/cycle.
*
* @param String $cycle_id Id of the cycle to be restored.
*/
private function unDeleteStack($cycle_id = '')
{
foreach ($_SESSION['_checked_dates'] as $id) {
$ex_termin = CourseExDate::find($id);
if ($ex_termin === null) {
continue;
}
$ex_termin->content = '';
$termin = $ex_termin->unCancelDate();
if ($termin !== null) {
$this->course->createMessage(sprintf(
_('Der Termin %s wurde wiederhergestellt!'),
htmlReady($termin->getFullName())
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
}
}
$this->displayMessages();
$this->relocate('course/timesrooms/index', ['contentbox_open' => $cycle_id]);
}
/**
* Saves a stack/cycle.
*
* @param String $cycle_id Id of the cycle to be saved.
*/
public function saveStack_action($cycle_id = '')
{
CSRFProtection::verifyUnsafeRequest();
if (Request::submitted('only_bookable_rooms')) {
//Redirect to the editStack method and do not save anything.
$this->editStack($cycle_id);
return;
}
switch (Request::get('method')) {
case 'edit':
$this->saveEditedStack();
break;
case 'preparecancel':
$this->saveCanceledStack();
break;
case 'request':
$this->saveRequestStack();
}
$this->displayMessages();
$this->relocate('course/timesrooms/index', ['contentbox_open' => $cycle_id]);
}
/**
* Saves a canceled stack/cycle.
*
* @param String $cycle_id Id of the canceled cycle to be saved.
*/
private function saveCanceledStack()
{
$deleted_dates = [];
$cancel_comment = trim(Request::get('cancel_comment'));
$cancel_send_message = Request::int('cancel_send_message');
foreach ($_SESSION['_checked_dates'] as $id) {
$termin = CourseDate::find($id);
if ($termin) {
$deleted_dates[] = $this->deleteDate($termin, $cancel_comment);
}
}
if ($cancel_send_message && $cancel_comment != '' && count($deleted_dates) > 0) {
$snd_messages = raumzeit_send_cancel_message($cancel_comment, $deleted_dates);
if ($snd_messages > 0) {
$this->course->createMessage(_('Alle Teilnehmenden wurden benachrichtigt.'));
}
}
}
/**
* Saves an edited stack/cycle.
*
* @param String $cycle_id Id of the edited cycle to be saved.
*/
private function saveEditedStack()
{
$persons = Request::getArray('related_persons');
$action = Request::get('related_persons_action');
$groups = Request::getArray('related_groups');
$group_action = Request::get('related_groups_action');
$lecture_changed = false;
$groups_changed = false;
$singledates = [];
if (is_array($_SESSION['_checked_dates'])) {
foreach ($_SESSION['_checked_dates'] as $singledate_id) {
$singledate = CourseDate::find($singledate_id);
if (!isset($singledate)) {
$singledate = CourseExDate::find($singledate_id);
}
$singledates[] = $singledate;
}
}
// Update related persons
if (in_array($action, words('add delete'))) {
$course_lectures = $this->course->getMembers();
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
$persons = User::findMany($persons);
foreach ($singledates as $singledate) {
if ($action === 'add') {
if (count($course_lectures) === count($persons)) {
$singledate->dozenten = [];
} else {
foreach ($persons as $person) {
if (!count($singledate->dozenten->findBy('id', $person->id))) {
$singledate->dozenten[] = $person;
}
}
if (count($singledate->dozenten) === count($course_lectures)) {
$singledate->dozenten = [];
}
}
$lecture_changed = true;
}
if ($action === 'delete') {
foreach ($persons as $person) {
$singledate->dozenten->unsetBy('id', $person->id);
}
$lecture_changed = true;
}
$singledate->store();
}
}