Newer
Older
<?php
# Lifter010: TODO
/**
* room_requests.php - administration of room requests
*
* 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 André Noack <noack@data-quest.de>
* @author Moritz Strohm <strohm@data-quest.de>
* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
* @category Stud.IP
* @package admin
*/

David Siegfried
committed
class Course_RoomRequestsController extends AuthenticatedController
{
/**
* Common tasks for all actions
*
* @param string $action Called action
* @param array $args Possible arguments
*/
public function before_filter(&$action, &$args)
{
$this->current_action = $action;
parent::before_filter($action, $args);
$this->current_user = User::findCurrent();
$this->user_is_global_resource_admin = ResourceManager::userHasGlobalPermission(
$this->current_user,
'admin'
);
$this->course_id = Request::option('cid', $args[0] ?? null);
$pagetitle = '';
//Navigation in der Veranstaltung:
if (Navigation::hasItem('/course/admin/room_requests')) {
Navigation::activateItem('/course/admin/room_requests');
}
if (!get_object_type($this->course_id, ['sem']) ||
SeminarCategories::GetBySeminarId($this->course_id)->studygroup_mode ||
!$GLOBALS['perm']->have_studip_perm("tutor", $this->course_id)
) {
throw new Trails_Exception(400);
}
PageLayout::setHelpKeyword('Basis.VeranstaltungenVerwaltenAendernVonZeitenUndTerminen');
$pagetitle .= Course::find($this->course_id)->getFullName() . ' - ';
$pagetitle .= _('Verwalten von Raumanfragen');
PageLayout::setTitle($pagetitle);
$this->available_room_categories = ResourceCategory::findByClass_name(Room::class);
$this->step = 0;
$this->max_preparation_time = Config::get()->RESOURCES_MAX_PREPARATION_TIME;
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
}
/**
* Display the list of room requests
*/
public function index_action()
{
if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
throw new AccessDeniedException(
_('Das Erstellen von Raumanfragen ist nicht erlaubt!')
);
}
$this->url_params = [];
if (Request::get('origin') !== null) {
$this->url_params['origin'] = Request::get('origin');
}
$this->room_requests = RoomRequest::findBySQL(
'course_id = :course_id
ORDER BY course_id, metadate_id, termin_id',
[
'course_id' => $this->course_id
]
);
$this->request_id = Request::option('request_id');
$actions = new ActionsWidget();
$actions->addLink(
_('Neue Raumanfrage erstellen'),
$this->url_for('course/room_requests/new'),
Icon::create('add', 'clickable')
);
Sidebar::get()->addWidget($actions);

David Siegfried
committed
if ($GLOBALS['perm']->have_studip_perm('admin', $this->course_id)) {
$widget = new CourseManagementSelectWidget();
Sidebar::Get()->addWidget($widget);
}
}
/**
* Show information about a request
*
* @param String $request_id Id of the request
*/
public function info_action($request_id)
{
$request = RoomRequest::find($request_id);
$this->request = $request;
$this->render_template('course/room_requests/_request.php', null);
}
/**
{
if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
throw new AccessDeniedException(
_('Das Erstellen von Raumanfragen ist nicht erlaubt!')
);
}
Helpbar::get()->addPlainText(
_('Information'),
_('Hier können Sie Angaben zu gewünschten Raumeigenschaften machen.')
);
if (Request::submitted('request_id')) {
$this->request_id = Request::get('request_id');
}
if (!$this->request_id) {
$this->request_id = md5(uniqid('RoomRequest'));
// e.g. cycle, course, date
$this->request_range = Request::get('range_str');
// multiple dates
$this->request_range_ids = Request::getArray('range_ids') ?: $_SESSION[$this->request_id]['range_ids'] ?? [];
// a single date or whole course
$this->request_range_id = Request::get('range_id', Context::getId());
$_SESSION[$this->request_id]['range'] = $this->request_range ?: $_SESSION[$this->request_id]['range'] ?? null;
$_SESSION[$this->request_id]['range_ids'] = $this->request_range_ids ?: [$this->request_range_id];
// look for existing request or create a new one
$this->request = new RoomRequest($this->request_id);
// time ranges (start date, end date)
$this->request->setRangeFields($_SESSION[$this->request_id]['range'], $_SESSION[$this->request_id]['range_ids']);
$this->request_time_intervals = $this->request->getTimeIntervals();
* Step 1: Either selecting a room category or searching for a room name initially
* @param String $request_id ID of the request
{
if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
throw new AccessDeniedException(
_('Das Erstellen von Raumanfragen ist nicht erlaubt!')
);
}
$this->request_id = $request_id;
if (Request::isPost()) {
CSRFProtection::verifyUnsafeRequest();
$this->category_id = Request::get('category_id');
$this->search_by_category = Request::submitted('search_by_category');
if (!isset($_SESSION[$request_id])) {
$_SESSION[$request_id] = [];
$_SESSION[$request_id]['room_category_id'] = $this->category_id;
$this->room_name = Request::get('room_name');
$this->search_by_roomname = Request::submitted('search_by_name');
$_SESSION[$request_id]['room_name'] = $this->room_name;
// user selects a room category OR enters a room name
if ($this->category_id !== null && $this->search_by_category) {
$_SESSION[$request_id]['search_by'] = 'category';
'course/room_requests/request_find_available_properties/' . $this->request_id . '/' . $this->step . '/category'
} elseif ($this->room_name && $this->search_by_roomname) {
$_SESSION[$request_id]['search_by'] = 'roomname';
$this->redirect(
'course/room_requests/request_find_matching_rooms/' . $this->request_id . '/' . $this->step . '/roomname'
);
} else {
$this->redirect(
'course/room_requests/new_request/' . $this->request_id
* Searching for (a) matching room(s) via room name, e.g. 'hör%'
* @param String $request_id ID of the request
* @param String $step
* @return void
public function request_find_matching_rooms_action($request_id, $step)
{
if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
throw new AccessDeniedException(
_('Das Erstellen von Raumanfragen ist nicht erlaubt!')
);
}
$this->request_id = $request_id;
$this->step = (int)$step;
$this->room_name = $_SESSION[$request_id]['room_name'];
$this->request->setRangeFields($_SESSION[$this->request_id]['range'], $_SESSION[$this->request_id]['range_ids'] ?? []);
$search_properties = $_SESSION[$request_id]['selected_properties'] ?? [];
if (!empty($_SESSION[$request_id]['room_category_id'])) {
$search_properties['room_category_id'] = $_SESSION[$request_id]['room_category_id'];
if (!empty($search_properties['seats'])) {
//The seats property value is a minimum.
$search_properties['seats'] = [
$search_properties['seats'],
null
];
// find rooms matching to selected properties
$this->available_rooms = RoomManager::findRooms(
$this->room_name,
null,
null,
$search_properties,
[],
'name ASC, mkdate ASC'
);
// small icons in front of room name to show whether they are bookable or not
$this->available_room_icons = $this->getRoomBookingIcons($this->available_rooms);
// selected room and its category
$this->selected_room = Resource::find($_SESSION[$request_id]['room_id'] ?: $this->request->resource_id);
$this->selected_room_category_id = $this->selected_room->category_id ?? $_SESSION[$request_id]['room_category_id'] ?? null;

Jan-Hendrik Willms
committed
$this->category = $this->selected_room_category_id ? ResourceCategory::find($this->selected_room_category_id) : null;
$_SESSION[$request_id]['room_category_id'] = $_SESSION[$request_id]['room_category_id'] ?? $this->selected_room->category_id ?? null;
// after selecting a room, go to next step or stay here if no room was selected at all
if (Request::submitted('select_room')) {
$this->selected_room_id = Request::get('selected_room_id');
$_SESSION[$request_id]['room_id'] = $this->selected_room_id;
$_SESSION[$request_id]['room_category_id'] = $room->category_id;
$_SESSION[$request_id]['select_room'] = true;
$this->redirect(
'course/room_requests/request_check_properties/' . $this->request_id
// we might also search for new rooms and stay within step 1
else if (Request::get('room_name') && Request::submitted('search_by_name')) {
$_SESSION[$request_id]['room_name'] = Request::get('room_name');
$this->redirect(
'course/room_requests/request_find_matching_rooms/' . $this->request_id . '/' . $this->step
);
return;
}
else if (Request::get('category_id') && Request::submitted('select_properties')) {
$_SESSION[$request_id]['search_by'] = 'category';
$_SESSION[$request_id]['room_category_id'] = Request::get('category_id');
$this->redirect(
'course/room_requests/request_find_available_properties/' . $this->request_id . '/' . $this->step
);
return;
} else if (Request::submitted('reset_category')) {
$this->init_session();
$this->redirect('course/room_requests/new_request');
// for step 2: after choosing a specific room OR searching via properties
if ($this->step === 2) {
$this->selected_properties = Request::getArray('selected_properties');
} else {
$this->selected_properties = $_SESSION[$request_id]['selected_properties'];
$_SESSION[$request_id]['selected_properties'] = $this->selected_properties;
if ($_SESSION[$request_id]['search_by'] === 'roomname') {
$this->selected_properties = $_SESSION[$request_id]['selected_properties'] ?? null;
$this->room = Room::find($_SESSION[$request_id]['room_id']);
if (!isset($_SESSION[$request_id]['selected_properties']['seats'])) {
$this->selected_properties['seats'] = $this->course->admission_turnout ?? Config::get()->RESOURCES_ROOM_REQUEST_DEFAULT_SEATS;
}
$_SESSION[$request_id]['selected_properties']['seats'] = $this->selected_properties['seats'];
$_SESSION[$request_id]['room_category_id'] = $this->selected_room_category_id;
} else {
// let's find all the properties belonging to the selected category
$this->room_category_id = $_SESSION[$request_id]['room_category_id'];
}
if ($this->category) {
$this->available_properties = $this->category->getRequestableProperties();
}
$this->preparation_time = $_SESSION[$request_id]['preparation_time'] ?? null;
$this->comment = $_SESSION[$request_id]['comment'] ?? null;
$this->request->category_id = $_SESSION[$request_id]['room_category_id'];
// finally we want to show a summary
if (Request::submitted('show_summary')) {
$this->selected_room_id = Request::get('selected_room_id');
$_SESSION[$request_id]['room_id'] = $this->selected_room_id;
$room = Room::find($this->selected_room_id);
if ($room) {
$_SESSION[$request_id]['room_category_id'] = $room->category_id;
}
$this->redirect('course/room_requests/request_show_summary/' . $this->request_id );
}
* Searching for (a) matching room(s) by initially selecting a room category, e.g. 'Hörsaal'
* @param String $request_id ID of the request
* @param String $step
* @return void
public function request_find_available_properties_action($request_id, $step)
{
if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
throw new AccessDeniedException(
_('Das Erstellen von Raumanfragen ist nicht erlaubt!')
);
}
$this->request_id = $request_id;
$this->request->setRangeFields(
$_SESSION[$this->request_id]['range'] ?? null,
$_SESSION[$this->request_id]['range_ids'] ?? null
);
// let's find all the properties belonging to the selected category
$this->room_category_id = $_SESSION[$request_id]['room_category_id'] ?: $this->request->category_id;
$this->room_name = $_SESSION[$request_id]['room_name'] ?? '';
$this->selected_room = Resource::find($_SESSION[$request_id]['room_id'] ?: $this->request->resource_id);
$this->category = $this->room_category_id ? ResourceCategory::find($this->room_category_id) : '';
$this->available_properties = $this->room_category_id ? $this->category->getRequestableProperties() : '';
$this->selected_properties = $_SESSION[$request_id]['selected_properties'] ?? [];
$this->course = Course::find($this->course_id);
$this->selected_properties['seats'] = $_SESSION[$request_id]['selected_properties']['seats']
?: Config::get()->RESOURCES_ROOM_REQUEST_DEFAULT_SEATS;
$this->preparation_time = $_SESSION[$request_id]['preparation_time'] ?? null;
$this->comment = $_SESSION[$request_id]['comment'] ?? null;
if (
isset($_SESSION[$request_id]['room_name'])
&& $_SESSION[$request_id]['room_name'] !== ''
) {
$search_properties['room_category_id'] = $this->room_category_id;
$search_properties['seats'] = [
$this->room_name,
null,
null,
$search_properties,
Moritz Strohm
committed
[],
'name ASC, mkdate ASC'
);
// small icons in front of room name to show whether they are bookable or not
$this->available_room_icons = $this->getRoomBookingIcons($this->available_rooms);
Moritz Strohm
committed
}
/**
* Check desired properties for a room category to go to step 2
* @param String $request_id ID of the request
* @return void
*
*/
public function request_check_properties_action($request_id)
{
if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
throw new AccessDeniedException(
_('Das Erstellen von Raumanfragen ist nicht erlaubt!')
);
}
$this->selected_properties = Request::getArray('selected_properties');
// select a room, search for a room name or search for rooms matching properties
if (Request::submitted('select_room')) {
$this->selected_room_id = Request::get('selected_room_id');
$_SESSION[$request_id]['room_id'] = $this->selected_room_id;
$_SESSION[$request_id]['room_category_id'] = $room->category_id;
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
$_SESSION[$request_id]['select_room'] = true;
$this->step = 2;
$this->request = new RoomRequest($this->request_id);
$this->redirect(
'course/room_requests/request_find_matching_rooms/' . $this->request_id . '/' . $this->step
);
} else if (Request::get('room_name') && Request::submitted('search_by_name')) {
$this->category_id = Request::get('category_id');
$_SESSION[$request_id]['selected_properties'] = $this->selected_properties;
$_SESSION[$request_id]['room_category_id'] = $this->category_id;
$_SESSION[$request_id]['comment'] = $this->comment;
$_SESSION[$request_id]['room_name'] = Request::get('room_name');
$this->request = new RoomRequest($this->request_id);
$this->redirect(
'course/room_requests/request_find_available_properties/' . $this->request_id . '/1/category'
);
} else if (Request::submitted('search_rooms')) {
$this->category_id = Request::get('category_id');
$_SESSION[$request_id]['room_category_id'] = $this->category_id;
$_SESSION[$request_id]['selected_properties'] = $this->selected_properties;
$_SESSION[$request_id]['room_name'] = '';
// no min number of seats
if (
(!$_SESSION[$request_id]['selected_properties']['seats'] || $_SESSION[$request_id]['selected_properties']['seats'] < 1)
&& $_SESSION[$request_id]['search_by'] === 'category'
) {
PageLayout::postError(
_('Die Mindestanzahl der Sitzplätze beträgt 1!')
);
'course/room_requests/request_find_available_properties/' . $request_id . '/1/category'
} else {
$this->step = 2;
$this->request = new RoomRequest($this->request_id);
$this->redirect(
'course/room_requests/request_find_matching_rooms/' . $this->request_id . '/' . $this->step
}
} else if (Request::submitted('reset_category')) {
//Delete all selected properties from the session since the category is reset
$this->redirect('course/room_requests/request_find_available_properties/' . $this->request_id . '/1');
} else if (Request::submitted('search_by_category')) {
if (Request::get('category_id') === '0') {
$_SESSION[$request_id]['room_category_id'] = '';
} else {
$_SESSION[$request_id]['room_category_id'] = Request::get('category_id');
}
$this->redirect(
'course/room_requests/request_find_available_properties/' . $this->request_id . '/1' . '/category'
);
} else if (Request::submitted('show_summary')) {
$this->request = new RoomRequest($this->request_id);
$this->selected_room_id = Request::get('selected_room_id');
$_SESSION[$request_id]['room_id'] = $this->selected_room_id;
$_SESSION[$request_id]['room_category_id'] = $room->category_id ?? $_SESSION[$request_id]['room_category_id'];
$_SESSION[$request_id]['selected_properties'] = $this->selected_properties;
$this->redirect('course/room_requests/request_show_summary/' . $this->request_id );
} else {
$room = Room::find($_SESSION[$request_id]['room_id']);
$this->step = 2;
$this->request = new RoomRequest($this->request_id);
$_SESSION[$request_id]['room_category_id'] = $room->category_id;
$this->redirect(
'course/room_requests/request_find_matching_rooms/' . $this->request_id . '/' . $this->step
);
* Show a summary of all request properties before storing; we have the possibility of going back and
* editing if necessary. This action is also used for editing a request via action menu
* @param String $request_id ID of the request
* @return void
*
public function request_show_summary_action($request_id)
{
if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
throw new AccessDeniedException(
_('Das Erstellen von Raumanfragen ist nicht erlaubt!')
);
}
$this->request_id = $request_id;
if (Request::submitted('clear_cache')) {
$this->request->setRangeFields(
$_SESSION[$this->request_id]['range'] ?? '',
$_SESSION[$this->request_id]['range_ids'] ?? []
);
$this->selected_room_category = ResourceCategory::find($_SESSION[$request_id]['room_category_id'] ?? $this->request->category_id);
$this->selected_room = Resource::find($_SESSION[$request_id]['room_id'] ?? $this->request->resource_id);
$this->room_id = $_SESSION[$request_id]['room_id'] ?? $this->request->resource_id;
$this->available_properties = $this->selected_room_category->getRequestableProperties();
$this->selected_properties = $_SESSION[$request_id]['selected_properties'] ?? [];
$this->request_properties = $this->request->properties;
// either properties from stored request or those from session
if ($this->request_properties && empty($_SESSION[$request_id]['selected_properties'])) {
foreach ($this->request_properties as $property) {
$this->selected_properties[$property->name] = $property->state;
$_SESSION[$request_id]['selected_properties'] = $this->selected_properties;
$this->preparation_time = intval($this->request->preparation_time / 60);
$this->reply_lecturers = $this->request->reply_recipients === ResourceRequest::REPLY_LECTURER;
$this->comment = $this->request->comment;
$_SESSION[$request_id]['search_by'] = $this->selected_room ? 'roomname' : 'category';
$_SESSION[$request_id]['room_category_id'] = $this->selected_room_category->id;

Jan-Hendrik Willms
committed
$_SESSION[$request_id]['room_id'] = $this->selected_room ? $this->selected_room->id : '';
}
public function store_request_action($request_id)
{
if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
throw new AccessDeniedException(
_('Das Erstellen von Raumanfragen ist nicht erlaubt!')
);
$this->request_id = $request_id;
$this->request = new RoomRequest($this->request_id);
$this->request->setRangeFields($_SESSION[$this->request_id]['range'], $_SESSION[$this->request_id]['range_ids']);
if (Request::isPost()) {
CSRFProtection::verifyUnsafeRequest();
$this->preparation_time = Request::int('preparation_time', 0);
$this->request->preparation_time = $this->preparation_time * 60;
$this->request->comment = Request::get('comment');
$this->request->reply_recipients = ResourceRequest::REPLY_LECTURER;
$this->request->reply_recipients = ResourceRequest::REPLY_REQUESTER;
}
$this->request->category_id = $_SESSION[$request_id]['room_category_id'] ?: $this->request->category_id;
$this->request->resource_id = $_SESSION[$request_id]['room_id'] ?: $this->request->resource_id;
$this->request->course_id = Context::getId();
$this->request->last_modified_by = $this->current_user->id;
//Store the properties:
foreach ($_SESSION[$request_id]['selected_properties'] as $name => $state) {
if (!empty($state)) {
$this->request->setProperty($name, $state);
}
// once stored, we can delete the session data for this request
$_SESSION[$this->request_id] = [];
PageLayout::postSuccess(_('Die Anfrage wurde gespeichert!'));
$this->relocate('course/timesrooms/');
* Store a request and its properties
* @param string $request ID of the request
* @param array $properties desired properties
* @return void
// once stored, we can delete the session data for this request
$request->store();
$_SESSION[$request->id] = [];
//Store the properties:
foreach ($properties as $name => $state) {
$request->setProperty($name, $state);
}
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
private function getRoomBookingIcons($available_rooms)
{
$this->available_room_icons = [];
$request_time_intervals = $this->request->getTimeIntervals();
foreach ($available_rooms as $room) {
$request_dates_booked = 0;
foreach ($request_time_intervals as $interval) {
$booked = ResourceBookingInterval::countBySql(
'resource_id = :room_id AND begin < :end AND end > :begin',
[
'room_id' => $room->id,
'begin' => $interval['begin'],
'end' => $interval['end']
]
) > 0;
if ($booked) {
$request_dates_booked++;
}
}
if ($request_dates_booked === 0) {
$this->available_room_icons[$room->id] =
Icon::create('check-circle', Icon::ROLE_STATUS_GREEN)->asImg(
[
'class' => 'text-bottom',
'title' => _('freier Raum')
]
);
$available_rooms[] = $room;
} elseif ($request_dates_booked < $request_time_intervals) {
$this->available_room_icons[$room->id] = Icon::create('exclaim-circle', Icon::ROLE_STATUS_YELLOW)->asImg([
'class' => 'text-bottom',
'title' => _('teilweise belegter Raum')
]);
$available_rooms[] = $room;
}
}
return $this->available_room_icons;
}
/**
* delete one room request
*/
public function delete_action($request_id)
{
$request = RoomRequest::find($request_id);
if (!$request) {
throw new Trails_Exception(403);
}
if (Request::isGet()) {
PageLayout::postQuestion(sprintf(
_('Möchten Sie die Raumanfrage "%s" löschen?'),
htmlReady($request->getTypeString())), $this->url_for('course/room_requests/delete/' . $request_id));
} else {
CSRFProtection::verifyUnsafeRequest();
if (Request::submitted('yes')) {
if ($request->delete()) {
PageLayout::postSuccess("Die Raumanfrage wurde gelöscht.");
}
}
}
private function init_session()
{
$_SESSION[$this->request_id] = array_merge(
$_SESSION[$this->request_id] ?? [],
[
'search_by' => '',
'room_category_id' => '',
'room_id' => '',
'room_name' => '',
'select_room' => false,
'selected_properties' => [],
]
);
}