aboutsummaryrefslogtreecommitdiff
path: root/app/controllers/resources/resource.php
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers/resources/resource.php')
-rw-r--r--app/controllers/resources/resource.php1488
1 files changed, 1488 insertions, 0 deletions
diff --git a/app/controllers/resources/resource.php b/app/controllers/resources/resource.php
new file mode 100644
index 0000000..19d951b
--- /dev/null
+++ b/app/controllers/resources/resource.php
@@ -0,0 +1,1488 @@
+<?php
+
+/**
+ * resource.php - contains Resources_ResourceController
+ *
+ * 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 Moritz Strohm <strohm@data-quest.de>
+ * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
+ * @copyright 2017-2019
+ * @category Stud.IP
+ * @since 4.5
+ */
+
+
+/**
+ * Resources_ResourceController contains general resource actions.
+ */
+class Resources_ResourceController extends AuthenticatedController
+{
+ public function before_filter(&$action, &$args)
+ {
+ parent::before_filter($action, $args);
+
+ $this->edit_global_permissions = false;
+
+ $this->resource_id_parameter = $args[0];
+
+ $this->resources = [];
+ $this->resource_ids = [];
+ $this->clipboard_id = null;
+
+ $this->no_reload = false;
+ if (Request::submitted('no_reload')) {
+ $this->no_reload = true;
+ }
+
+ if ($action == 'add') {
+ //Noting to be done below this point.
+ return;
+ }
+
+ if (strpos($args[0], 'clipboard_') !== false) {
+ //A clipboard has been selected:
+ //Get all resources from it:
+ $this->clipboard_id = substr($args[0], 10);
+
+ $clipboard = Clipboard::find($this->clipboard_id);
+ if ($clipboard) {
+ $this->resource_ids = $clipboard->getAllRangeIds(
+ ['Resource', 'Room', 'Building', 'Location']
+ );
+
+ $resources = Resource::findMany($this->resource_ids);
+ if ($resources) {
+ foreach ($resources as $resource) {
+ $this->resources[] = $resource->getDerivedClassInstance();
+ }
+ }
+ }
+
+ if (!$this->resources) {
+ PageLayout::postError(
+ _('Es konnten keine Ressourcen gefunden werden!')
+ );
+ return;
+ }
+ } else {
+ //$args[0] contains the ID of a resource.
+ $resource = Resource::find($args[0]);
+
+ if ($resource) {
+ //We need the specialisations here to display the name correctly:
+ try {
+ $this->resources = [$resource->getDerivedClassInstance()];
+ } catch (Exception $e) {
+ //Use the base class as fallback.
+ $this->resources = [$resource];
+ }
+ $this->resource_ids = [$resource->id];
+ } elseif ($args[0] == 'global') {
+ $this->edit_global_permissions = true;
+ $this->resource_ids = [$args[0]];
+ }
+ if (!$this->resources && ($args[0] != 'global')) {
+ PageLayout::postError(
+ _('Die Ressource wurde nicht gefunden!')
+ );
+ return;
+ }
+ }
+ if (!Request::isDialog()) {
+ if (Navigation::hasItem('/resources/structure')) {
+ Navigation::activateItem('/resources/structure');
+ }
+ }
+ }
+
+
+ protected function getUserAndCheckPermissions($permission_level = 'admin')
+ {
+ $this->current_user = User::findCurrent();
+
+ $insufficient_permissions = true;
+ if ($this->edit_global_permissions) {
+ if (ResourceManager::userHasGlobalPermission($this->current_user, $permission_level)) {
+ $insufficient_permissions = false;
+ }
+ } else {
+ $for_loop_break = false;
+ foreach ($this->resources as $resource) {
+ if (!$resource->userHasPermission($this->current_user, $permission_level)) {
+ //The permissions are insufficient for at least one
+ //resource. No need to continue the permission check.
+ $for_loop_break = true;
+ break;
+ }
+ }
+ if (!$for_loop_break) {
+ //The for loop checked all resources and the user has
+ //sufficient permissiosn for all resources:
+ $insufficient_permissions = false;
+ }
+ }
+
+ if ($insufficient_permissions) {
+ //The permissions are insufficient for at least one resource.
+ if (count($this->resources) == 1) {
+ throw new AccessDeniedException(
+ sprintf(
+ _('%s: Unzureichende Berechtigungen für die gewählte Aktion!'),
+ $this->resources[0]->getFullName()
+ )
+ );
+ } else {
+ throw new AccessDeniedException(
+ sprintf(
+ _('Unzureichende Berechtigungen für die gewählte Aktion!')
+ )
+ );
+ }
+ }
+ }
+
+ protected function getPermissionUserSearch()
+ {
+ return QuickSearch::get(
+ 'searched_user_id', new StandardSearch('user_id'));
+ }
+
+
+ protected function getCourseSearch()
+ {
+ $all_semesters = Semester::getAll();
+ $all_semester_ids = [];
+ foreach ($all_semesters as $semester) {
+ $all_semester_ids[] = $semester->id;
+ }
+
+ return QuickSearch::get(
+ 'course_id',
+ new StandardSearch(
+ 'Seminar_id'
+ )
+ );
+ }
+
+
+ public function index_action($resource_id = null)
+ {
+ if (count($this->resources) > 1) {
+ PageLayout::postError(
+ _('Diese Aktion kann nur für einzelne Ressourcen oder Räume verwendet werden!')
+ );
+ return;
+ }
+ $this->resource = $this->resources[0];
+
+ PageLayout::setTitle(
+ $this->resource->getFullName()
+ );
+
+ if ($GLOBALS['user']->id != 'nobody') {
+ $current_user = User::findCurrent();
+
+ if (!Request::isDialog()) {
+ $sidebar = Sidebar::get();
+
+ if (!($this->resource instanceof ResourceLabel)) {
+ $actions = new ActionsWidget();
+ $actions->addLink(
+ _('Belegungsplan'),
+ URLHelper::getURL(
+ 'dispatch.php/resources/resource/booking_plan/' . $this->resource->id
+ ),
+ Icon::create('timetable')
+ );
+ $sidebar->addWidget($actions);
+
+ }
+
+ $tree_widget = new ResourceTreeWidget(
+ Location::findAll(),
+ null,
+ null
+ );
+ $tree_widget->setCurrentResource($this->resource);
+ $sidebar->addWidget($tree_widget);
+ }
+ }
+ }
+
+ protected function addEditDeleteHandler($mode = 'add')
+ {
+ $this->resource = $this->resources[0];
+ $user = User::findCurrent();
+
+ $this->show_form = false;
+ $this->mode = $mode;
+
+ if (($mode == 'edit') || ($mode == 'delete')) {
+ if (!$this->resource) {
+ PageLayout::postError(
+ _('Die angegebene Ressource wurde nicht gefunden!')
+ );
+ return;
+ }
+
+ if ((($mode == 'edit') && !$this->resource->userHasPermission($user, 'autor'))
+ || (($mode == 'delete') && !$this->resource->userHasPermission($user, 'admin'))) {
+ throw new AccessDeniedException();
+ }
+ }
+
+ if (($mode == 'add') && !ResourceManager::userHasGlobalPermission($user, 'admin')) {
+ throw new AccessDeniedException();
+ }
+
+ //Get a quick search for the parent resource selection:
+ $resource_search = new ResourceSearch();
+
+ $this->parent_search = new QuickSearch(
+ 'parent_id',
+ $resource_search
+ );
+ if (($mode == 'edit') && $this->resource->parent) {
+ $this->parent_search->defaultValue(
+ $this->resource->parent_id,
+ $this->resource->parent->name
+ );
+ }
+
+ //Get all properties of the resource:
+ $this->property_data = [];
+ $this->grouped_defined_properties = [];
+ if ($mode == 'edit') {
+ $this->grouped_defined_properties =
+ $this->resource->category->getGroupedPropertyDefinitions();
+ foreach ($this->grouped_defined_properties as $group => $properties) {
+ foreach ($properties as $property) {
+ $this->property_data[$property->id] =
+ $this->resource->getProperty($property->name);
+ }
+ }
+ } elseif ($mode == 'add') {
+ $this->grouped_defined_properties =
+ $this->category->getGroupedPropertyDefinitions();
+ foreach ($this->grouped_defined_properties as $group => $properties) {
+ foreach ($properties as $property) {
+ //Set the property state to an empty string
+ //for all properties as a default value:
+ $this->property_data[$property->id] = '';
+ }
+ }
+ }
+
+ $this->show_form = true;
+ if (Request::submitted('confirmed')) {
+ CSRFProtection::verifyUnsafeRequest();
+ if (($mode == 'add') || ($mode == 'edit')) {
+ //Process submitted form:
+ $this->parent_id = $this->resource->parent_id;
+ if ($mode == 'add') {
+ $this->category_id = Request::get('category_id');
+ $this->parent_id = Request::get('parent_id', '');
+ }
+ $this->name = Request::get('name');
+ $this->description = Request::get('description');
+ $this->property_data = Request::getArray('properties');
+ $this->sort_position = Request::get('sort_position');
+
+ if ($mode == 'add') {
+ $category_class_name = ResourceCategory::getClassNameById(
+ $this->category_id
+ );
+ if ((!$category_class_name)
+ || !is_a($category_class_name, 'Resource', true)) {
+ PageLayout::postError(
+ _('Die gewählte Kategorie ist für Ressourcen nicht geeignet!')
+ );
+ return;
+ }
+ }
+
+ if (!$this->name) {
+ PageLayout::postError(
+ _('Der Name des Ressource ist leer!')
+ );
+ return;
+ }
+
+ if ($mode == 'add') {
+ $this->resource = new Resource();
+ }
+
+ //store the resource object:
+ $this->resource->parent_id = $this->parent_id;
+ if ($mode == 'add') {
+ $this->resource->category_id = $this->category_id;
+ }
+ $this->resource->name = $this->name;
+ $this->resource->description = $this->description;
+
+ if ($GLOBALS['perm']->have_perm('root')) {
+ $this->resource->sort_position = $this->sort_position;
+ }
+ if ($this->resource->isDirty()) {
+ $successfully_stored = $this->resource->store();
+ } else {
+ $successfully_stored = true;
+ }
+
+ //Now we can store the resource's properties, if the permissions
+ //are high enough:
+ $unchanged_properties = $this->resource->setPropertiesById(
+ $this->property_data,
+ $user
+ );
+ array_walk($unchanged_properties, function(&$item){$item = htmlReady($item);});
+
+ if ($successfully_stored && !$unchanged_properties) {
+ $this->show_form = false;
+ PageLayout::postSuccess(
+ _('Die Ressource wurde gespeichert!')
+ );
+ } elseif ($successfully_stored) {
+ $this->show_form = false;
+ if (count($unchanged_properties) == 1) {
+ PageLayout::postWarning(
+ sprintf(
+ _('Die Ressource wurde gespeichert, aber die Eigenschaft %s konnte wegen fehlender Berechtigungen nicht gespeichert werden!'),
+ htmlReady($unchanged_properties[0])
+ )
+ );
+ } else {
+ PageLayout::postWarning(
+ _('Die Ressource wurde gespeichert, aber die folgenden Eigenschaften konnten wegen fehlender Berechtigungen nicht gespeichert werden:'),
+ $unchanged_properties
+ );
+ }
+ } else {
+ PageLayout::postError(
+ _('Fehler beim Speichern der Ressource!')
+ );
+ }
+ } elseif ($mode == 'delete') {
+ if ($this->resource->delete()) {
+ $this->show_form = false;
+ PageLayout::postSuccess(
+ _('Die Ressource wurde gelöscht!')
+ );
+ } else {
+ PageLayout::postError(
+ _('Fehler beim Löschen der Ressource!')
+ );
+ }
+ }
+ } else {
+ //For add mode $this->category_id is set directly in add_action!
+ if (($mode == 'edit') || ($mode == 'delete')) {
+ //Show form with current data:
+ $this->parent_id = $this->resource->parent_id;
+ $this->category_id = $this->resource->category_id;
+ $this->name = $this->resource->name;
+ $this->description = $this->resource->description;
+ $this->sort_position = $this->resource->sort_position;
+ }
+ }
+ }
+
+
+ public function add_action()
+ {
+ $this->category_selected = false;
+
+ $category_id = Request::get('category_id');
+ $this->category = ResourceCategory::find($category_id);
+ if ($this->category instanceof ResourceCategory) {
+ $this->category_selected = true;
+ $this->addEditDeleteHandler('add');
+ } else {
+ PageLayout::postError(
+ _('Die gewählte Ressourcenkategorie wurde nicht gefunden!')
+ );
+ }
+
+ PageLayout::setTitle(
+ sprintf(
+ _('Kategorie %s: Ressource hinzufügen'),
+ $this->category->name
+ )
+ );
+ }
+
+
+ public function edit_action($resource_id = null)
+ {
+ $this->addEditDeleteHandler('edit');
+
+ PageLayout::setTitle(
+ sprintf(
+ _('%s: bearbeiten'),
+ $this->resource->getFullname()
+ )
+ );
+ }
+
+
+ public function delete_action($resource_id = null)
+ {
+ $this->addEditDeleteHandler('delete');
+
+ PageLayout::setTitle(
+ sprintf(
+ _('%s: löschen'),
+ $this->resource->getFullname()
+ )
+ );
+ }
+
+
+ public function booking_plan_action($resource_id = null)
+ {
+ if (count($this->resources) > 1) {
+ PageLayout::postError(
+ _('Diese Aktion kann nur für einzelne Ressourcen oder Räume verwendet werden!')
+ );
+ return;
+ }
+ $this->resource = $this->resources[0];
+
+ $current_user = User::findCurrent();
+
+ //The booking plan is visible when the user-ID is not 'nobody'
+ //and the user has at least 'user' permissions on the resource.
+ //The booking plan is also visible when the resource is a room
+ //and its booking plan is publicly available.
+ $booking_plan_is_visible = false;
+ if ($GLOBALS['user']->id != 'nobody') {
+ $booking_plan_is_visible = $this->resource->userHasPermission(
+ $current_user,
+ 'user'
+ );
+ }
+ if ($booking_plan_is_visible === false) {
+ $booking_plan_is_visible = (
+ ($this->resource instanceof Room)
+ and $this->resource->booking_plan_is_public
+ );
+ }
+ if (!$booking_plan_is_visible) {
+ throw new AccessDeniedException(
+ _('Der Belegungsplan ist für Sie nicht zugänglich!')
+ );
+ }
+
+ PageLayout::setTitle(
+ sprintf(
+ _('Belegungsplan: %s'),
+ $this->resource->getFullName()
+ )
+ );
+
+ $week_timestamp = Request::get('timestamp');
+ $this->date = new DateTime();
+ if ($week_timestamp) {
+ $this->date->setTimestamp($week_timestamp);
+ }
+
+ //Build sidebar:
+ $sidebar = Sidebar::get();
+
+ $views = new ViewsWidget();
+ if ($GLOBALS['user']->id && ($GLOBALS['user']->id != 'nobody')) {
+ if ($this->resource->userHasPermission($current_user, 'user')) {
+ $views->addLink(
+ _('Standard Zeitfenster'),
+ URLHelper::getURL(
+ 'dispatch.php/resources/resource/booking_plan/' . $this->resource->id,
+ [
+ 'defaultDate' => Request::get('defaultDate', date('Y-m-d'))
+ ]
+ ),
+ null,
+ ['class' => 'booking-plan-std_view']
+ )->setActive(!Request::get('allday'));
+
+ $views->addLink(
+ _('Ganztägiges Zeitfenster'),
+ URLHelper::getURL(
+ 'dispatch.php/resources/resource/booking_plan/' . $this->resource->id,
+ [
+ 'allday' => true,
+ 'defaultDate' => Request::get('defaultDate', date('Y-m-d'))
+ ]
+ ),
+ null,
+ ['class' => 'booking-plan-allday_view']
+ )->setActive(Request::get('allday'));
+ }
+ }
+ $sidebar->addWidget($views);
+
+ $actions = new ActionsWidget();
+ if ($GLOBALS['user']->id and ($GLOBALS['user']->id != 'nobody')) {
+ if ($this->resource->userHasPermission($current_user, 'user')) {
+ $actions->addLink(
+ _('Druckansicht'),
+ 'javascript:void(window.print());',
+ Icon::create('print')
+ );
+ $actions->addLink(
+ _('Individuelle Druckansicht'),
+ URLHelper::getURL(
+ 'dispatch.php/resources/print/individual_booking_plan/' . $this->resource->id,
+ [
+ 'timestamp' => $week_timestamp
+ ]
+ ),
+ Icon::create('print'),
+ [
+ 'target' => '_blank'
+ ]
+ );
+ $actions->addLink(
+ _('Als Tabelle exportieren'),
+ URLHelper::getURL(
+ 'dispatch.php/resources/export/booking_plan/' . $this->resource->id,
+ [
+ 'timestamp' => $week_timestamp,
+ 'export_type' => 'csv'
+ ]
+ ),
+ Icon::create('file-excel'),
+ [
+ 'target' => '_blank'
+ ]
+ );
+ }
+ }
+ if (($this->resource instanceof Room) and $this->resource->booking_plan_is_public) {
+ $actions->addLink(
+ _('QR-Code anzeigen'),
+ $this->resource->getActionURL('booking_plan'),
+ Icon::create('download'),
+ [
+ 'data-qr-code' => '',
+ 'data-qr-code-print' => '1'
+ ]
+ );
+ }
+
+ $sidebar->addWidget($actions);
+
+ $booking_colour = ColourValue::find('Resources.BookingPlan.Booking.Bg');
+ $lock_colour = ColourValue::find('Resources.BookingPlan.Lock.Bg');
+ $preparation_colour = ColourValue::find('Resources.BookingPlan.PreparationTime.Bg');
+ $reservation_colour = ColourValue::find('Resources.BookingPlan.Reservation.Bg');
+ $this->table_keys = [
+ [
+ 'colour' => $booking_colour->__toString(),
+ 'text' => _('Buchungen')
+ ],
+ [
+ 'colour' => $lock_colour->__toString(),
+ 'text' => _('Sperrbuchungen')
+ ],
+ [
+ 'colour' => $preparation_colour->__toString(),
+ 'text' => _('Rüstzeiten')
+ ],
+ [
+ 'colour' => $reservation_colour->__toString(),
+ 'text' => _('Reservierungen')
+ ]
+ ];
+ }
+
+
+ public function permissions_action($resource_id = null)
+ {
+ PageLayout::setTitle(
+ _('Berechtigungen verwalten')
+ );
+
+ if (is_array($this->resources) && count($this->resources) > 1) {
+ PageLayout::postError(
+ _('Diese Aktion kann nur für einzelne Ressourcen verwendet werden!')
+ );
+ return;
+ }
+ $this->resource = $this->resources[0];
+
+ $this->getUserAndCheckPermissions('admin');
+
+ if ($this->resource_id == 'global') {
+ PageLayout::setTitle(
+ _('Globale Berechtigungen verwalten')
+ );
+ } else {
+ $this->resource_id = $this->resource->id;
+ PageLayout::setTitle(
+ sprintf(
+ _('%s: Berechtigungen verwalten'),
+ (
+ $this->resource instanceof Resource
+ ? $this->resource->getFullName()
+ : _('unbekannt')
+ )
+ )
+ );
+ }
+
+ //The user_id parameter is only needed in
+ //the single user permission mode.
+ $this->single_user_mode = false;
+ $this->user = User::find(Request::get('user_id'));
+ if ($this->user) {
+ $this->single_user_mode = true;
+ }
+
+ if (!$this->single_user_mode) {
+ //Setup the user search:
+ $this->user_search = $this->getPermissionUserSearch();
+ $this->user_search->fireJSFunctionOnSelect(
+ "function (user_id) {
+ var table = jQuery('#PermissionList')[0];
+ STUDIP.Resources.addUserToPermissionList(user_id, table);
+ }"
+ );
+
+ if (!$this->edit_global_permissions &&
+ (ResourceManager::userHasGlobalPermission($this->current_user, 'admin') ||
+ $GLOBALS['perm']->have_perm('root'))) {
+ //Setup the course search:
+ $this->course_search = $this->getCourseSearch();
+ $this->course_search->fireJSFunctionOnSelect(
+ "function (course_id) {
+ var table = jQuery('#PermissionList')[0];
+ STUDIP.Resources.addCourseUsersToPermissionList(course_id, table);
+ }"
+ );
+ }
+ }
+ $this->table_id = 'PermissionList';
+
+ if (Request::submitted('bulk_delete')) {
+ CSRFProtection::verifyUnsafeRequest();
+
+ $resource_permissions = Request::getArray('selected_permissions');
+ $deleted_c = ResourcePermission::deleteBySql(
+ 'resource_id = :resource_id AND user_id IN ( :user_ids )',
+ [
+ 'resource_id' => $this->resource_id,
+ 'user_ids' => $resource_permissions
+ ]
+ );
+
+ PageLayout::postSuccess(
+ sprintf(
+ ngettext(
+ '%d Berechtigung wurde gelöscht!',
+ '%d Berechtigungen wurden gelöscht!',
+ $deleted_c
+ ),
+ $deleted_c
+ )
+ );
+ } else if (Request::submitted('save')) {
+ CSRFProtection::verifyUnsafeRequest();
+
+ //Get the list of permissions for the user-IDs in the list:
+ $user_permissions = Request::getArray('permissions');
+
+ $processed_permissions = 0;
+ $deleted_permissions = 0;
+ $errors = [];
+ $user_ids = [];
+ //We must check for each permission if the user exists and if
+ //a permission object already exists. If a permission object
+ //exists we must update it.
+ foreach (array_keys($user_permissions['user_id']) as $key) {
+ $user_id = $user_permissions['user_id'][$key];
+ $permission_level = $user_permissions['level'][$key];
+
+ $user = User::find($user_id);
+ if (!$user) {
+ //We don't have to do anything if the user doesn't exist.
+ continue;
+ }
+ if (!in_array($permission_level, ['user', 'autor', 'tutor', 'admin'])) {
+ //If the permission level is invalid we don't have to do
+ //anything either.
+ continue;
+ }
+
+ $user_ids[] = $user_id;
+
+ $permission_object = ResourcePermission::findOneBySql(
+ 'resource_id = :resource_id
+ AND
+ user_id = :user_id',
+ [
+ 'resource_id' => $this->resource_id,
+ 'user_id' => $user_id
+ ]
+ );
+
+ if (!$permission_object) {
+ //Create a new permission object:
+ $permission_object = new ResourcePermission();
+ $permission_object->resource_id = $this->resource_id;
+ $permission_object->user_id = $user_id;
+ }
+
+ $permission_object->perms = $permission_level;
+
+ if ($permission_object->isDirty()) {
+ $processed_permissions++;
+ if (!$permission_object->store()) {
+ if ($this->edit_global_permissions) {
+ $errors[] = sprintf(
+ _(
+ 'Die globalen Berechtigungen von %s konnten nicht gespeichert werden!'
+ ),
+ htmlReady($user->getFullName())
+ );
+ } else {
+ $errors[] = sprintf(
+ _(
+ 'Die Berechtigungen von %1$s an der Ressource %2$s konnten nicht gespeichert werden!'
+ ),
+ htmlReady($user->getFullName()),
+ htmlReady($this->resource->name)
+ );
+ }
+ }
+ }
+ }
+
+ if ($this->single_user_mode) {
+ if (!in_array($this->user->id, $user_ids) || empty($user_ids)) {
+ //The user is not in the array of processed user permissions
+ //or no user permissions have been processed which means that
+ //no user permissions were submitted at all.Both cases mean
+ //that the user's permissions have been revoked.
+ ResourcePermission::deleteBySql(
+ 'resource_id = :resource_id AND user_id = :user_id',
+ [
+ 'resource_id' => $this->resource_id,
+ 'user_id' => $this->user->id
+ ]
+ );
+ }
+ } else {
+ //We must remove all permissions where the resource_id is given
+ //and where the user_id is not in the $user_ids array which has been
+ //filled above.
+ if ($user_ids) {
+ $deleted_permissions = ResourcePermission::deleteBySql(
+ 'resource_id = :resource_id
+ AND
+ user_id NOT IN ( :user_ids )',
+ [
+ 'resource_id' => $this->resource_id,
+ 'user_ids' => $user_ids
+ ]
+ );
+ } else {
+ //In case no user_ids are collected above all permissions
+ //for the resource have to be deleted:
+ $deleted_permissions = ResourcePermission::deleteBySQL(
+ 'resource_id = :resource_id',
+ [
+ 'resource_id' => $this->resource_id,
+ ]
+ );
+ }
+ }
+
+ if (count($errors)) {
+ PageLayout::postError(
+ _('Die folgenden Fehler traten auf beim Speichern der Berechtigungen:'),
+ $errors
+ );
+ } elseif (($processed_permissions > 0) || ($deleted_permissions > 0)) {
+ PageLayout::postSuccess(
+ _('Die Berechtigungen wurden gespeichert!')
+ );
+ }
+ }
+
+ if ($this->single_user_mode) {
+ //Load permissions of the specified user:
+ $this->permissions = ResourcePermission::findBySql(
+ "resource_id = :resource_id
+ AND user_id = :user_id",
+ [
+ 'resource_id' => $this->resource_id,
+ 'user_id' => $this->user->id
+ ]
+ );
+ } else {
+ //Load existing permissions:
+ //Sort the permissions by the user's name:
+ $this->permissions = ResourcePermission::findBySql(
+ "INNER JOIN auth_user_md5 USING (user_id)
+ WHERE
+ resource_id = :resource_id
+ ORDER BY
+ nachname ASC, vorname ASC",
+ [
+ 'resource_id' => $this->resource_id
+ ]
+ );
+ }
+ }
+
+
+ public function temporary_permissions_action($resource_id = null)
+ {
+ PageLayout::setTitle(
+ _('Temporäre Berechtigungen verwalten')
+ );
+
+ if (count($this->resources) > 1) {
+ PageLayout::postError(
+ _('Diese Aktion kann nur für einzelne Ressourcen verwendet werden!')
+ );
+ return;
+ }
+ $this->resource = $this->resources[0];
+ $this->resource_id = $this->resource->id;
+
+ $this->getUserAndCheckPermissions('admin');
+
+ PageLayout::setTitle(
+ sprintf(
+ _('%s: Temporäre Berechtigungen verwalten'),
+ $this->resource->getFullName()
+ )
+ );
+
+ //The user_id parameter is only needed in
+ //the single user permission mode.
+ $this->single_user_mode = false;
+ $this->user = User::find(Request::get('user_id'));
+ if ($this->user) {
+ $this->single_user_mode = true;
+ }
+
+ if (!$this->single_user_mode) {
+ //Setup the user search:
+ $this->user_search = $this->getPermissionUserSearch();
+ $this->user_search->fireJSFunctionOnSelect(
+ "function (user_id) {
+ var table = jQuery('#TemporaryPermissionList')[0];
+ STUDIP.Resources.addUserToPermissionList(user_id, table);
+ }"
+ );
+
+ if (ResourceManager::userHasGlobalPermission($this->current_user, 'admin') ||
+ $GLOBALS['perm']->have_perm('root')) {
+ //Setup the course search:
+ $this->course_search = $this->getCourseSearch();
+ $this->course_search->fireJSFunctionOnSelect(
+ "function (course_id) {
+ var table = jQuery('#TemporaryPermissionList')[0];
+ STUDIP.Resources.addCourseUsersToPermissionList(course_id, table);
+ }"
+ );
+ }
+ }
+
+ $this->bulk_begin = new DateTime();
+ $this->bulk_begin->setTime(
+ intval($this->bulk_begin->format('H')),
+ 0,
+ 0
+ );
+ $this->bulk_end = new DateTime();
+ $this->bulk_end = $this->bulk_end->add(
+ new DateInterval('P1M')
+ );
+ $this->bulk_end->setTime(
+ intval($this->bulk_end->format('H')),
+ 0,
+ 0
+ );
+
+ if (Request::submitted('bulk_save')) {
+ CSRFProtection::verifyUnsafeRequest();
+
+ $permission_ids = Request::getArray('selected_permission_ids');
+ $this->bulk_begin = Request::getDateTime(
+ 'bulk_begin_date',
+ 'd.m.Y',
+ 'bulk_begin_time',
+ 'H:i'
+ );
+ $this->bulk_end = Request::getDateTime(
+ 'bulk_end_date',
+ 'd.m.Y',
+ 'bulk_end_time',
+ 'H:i'
+ );
+
+ $valid = true;
+
+ if ($this->bulk_begin === false) {
+ PageLayout::postError(
+ _('Der Startzeitpunkt ist in einem ungültigen Format!')
+ );
+ $valid = false;
+ }
+
+ if ($this->bulk_end === false) {
+ PageLayout::postError(
+ _('Der Endzeitpunkt ist in einem ungültigen Format!')
+ );
+ $valid = false;
+ }
+
+ if ($this->bulk_begin >= $this->bulk_end) {
+ PageLayout::postError(
+ _('Der Startzeitpunkt darf nicht hinter dem Endzeitpunkt liegen!')
+ );
+ $valid = false;
+ }
+
+ if ($valid) {
+ $permissions = ResourceTemporaryPermission::findBySql(
+ 'id IN ( :permission_ids ) AND resource_id = :resource_id',
+ [
+ 'permission_ids' => $permission_ids,
+ 'resource_id' => $this->resource_id
+ ]
+ );
+
+ $errors = 0;
+ $processed_permissions = 0;
+ $amount = count($permissions);
+ foreach ($permissions as $permission) {
+ $permission->begin = $this->bulk_begin->getTimestamp();
+ $permission->end = $this->bulk_end->getTimestamp();
+ if ($permission->isDirty()) {
+ $processed_permissions++;
+ $result = $permission->store();
+ }
+ if (!$result) {
+ $errors++;
+ }
+ }
+
+ if (($errors == $amount) && ($amount > 0)) {
+ PageLayout::postError(
+ _('Fehler beim Speichern der Berechtigungen!')
+ );
+ } elseif ($errors) {
+ PageLayout::postWarning(
+ _('Es konnten nicht alle Berechtigungen gespeichert werden!')
+ );
+ } elseif ($processed_permissions > 0) {
+ PageLayout::postSuccess(
+ _('Die Änderung der Zeitbereiche der Berechtigungen wurden gespeichert!')
+ );
+ }
+ }
+ } else if (Request::submitted('bulk_delete')) {
+ CSRFProtection::verifyUnsafeRequest();
+
+ $permission_ids = Request::getArray('selected_permission_ids');
+ $deleted_c = ResourceTemporaryPermission::deleteBySql(
+ 'resource_id = :resource_id AND id IN ( :ids )',
+ [
+ 'resource_id' => $this->resource_id,
+ 'ids' => $permission_ids
+ ]
+ );
+
+ PageLayout::postSuccess(
+ sprintf(
+ ngettext(
+ '%d Berechtigung wurde gelöscht!',
+ '%d Berechtigungen wurden gelöscht!',
+ $deleted_c
+ ),
+ $deleted_c
+ )
+ );
+ } else if (Request::submitted('save')) {
+ CSRFProtection::verifyUnsafeRequest();
+
+ //Get the list of temporary permissions for the user-IDs in the list:
+ $user_permissions = Request::getArray('permissions');
+ //var_dump($user_permissions);die();
+
+ $processed_permissions = 0;
+ $errors = [];
+ $user_ids = [];
+ //We must check for each permission if the user exists and if
+ //a permission object already exists. If a permission object
+ //exists we must update it.
+ foreach (array_keys($user_permissions['user_id']) as $key) {
+ $permission_id = $user_permissions['permission_id'][$key];
+ $user_id = $user_permissions['user_id'][$key];
+ $permission_level = $user_permissions['level'][$key];
+ $permission_begin_date = $user_permissions['begin_date'][$key];
+ $permission_begin_time = $user_permissions['begin_time'][$key];
+ $permission_end_date = $user_permissions['end_date'][$key];
+ $permission_end_time = $user_permissions['end_time'][$key];
+
+ $user = User::find($user_id);
+ if (!$user) {
+ //We don't have to do anything if the user doesn't exist.
+ continue;
+ }
+ if ($user_permissions['user_id'][$key] == 'USERID') {
+ //It is just the entry from the JavaScript template.
+ continue;
+ }
+ if (!in_array($permission_level, ['user', 'autor', 'tutor', 'admin'])) {
+ //If the permission level is invalid we don't have to do
+ //anything either.
+ continue;
+ }
+
+ $user_ids[] = $user_id;
+
+ //Generate DateTime objects from the date and time strings:
+ $begin = new DateTime();
+ $time_zone = $begin->getTimezone();
+ $begin = DateTime::createFromFormat(
+ 'd.m.Y H:i',
+ $permission_begin_date . ' ' . $permission_begin_time,
+ $time_zone
+ );
+ if ($begin === false) {
+ $begin = DateTime::createFromFormat(
+ 'Y-m-d H:i',
+ $permission_begin_date . ' ' . $permission_begin_time,
+ $time_zone
+ );
+ }
+ $end = DateTime::createFromFormat(
+ 'd.m.Y H:i',
+ $permission_end_date . ' ' . $permission_end_time,
+ $time_zone
+ );
+ if ($end === false) {
+ $end = DateTime::createFromFormat(
+ 'Y-m-d H:i',
+ $permission_end_date . ' ' . $permission_end_time,
+ $time_zone
+ );
+ }
+
+ $permission_object = null;
+ if ($permission_id) {
+ //It is an existing permission.
+ //Existing permission objects can only be determined
+ //by their permission-ID or if the resource-ID,
+ //user-ID and the begin and end timestamps match.
+ //In all other cases we must create a new permission object.
+ $permission_object = ResourceTemporaryPermission::findOneBySql(
+ 'id = :permission_id
+ OR
+ (
+ resource_id = :resource_id
+ AND
+ user_id = :user_id
+ AND
+ begin = :begin
+ AND
+ end = :end
+ )',
+ [
+ 'permission_id' => $permission_id,
+ 'resource_id' => $this->resource_id,
+ 'user_id' => $user_id,
+ 'begin' => $begin->getTimestamp(),
+ 'end' => $end->getTimestamp()
+ ]
+ );
+ }
+
+ if (!$permission_object) {
+ //Create a new permission object:
+ $permission_object = new ResourceTemporaryPermission();
+ $permission_object->resource_id = $this->resource_id;
+ $permission_object->user_id = $user_id;
+ }
+
+ $permission_object->perms = $permission_level;
+ $permission_object->begin = $begin->getTimestamp();
+ $permission_object->end = $end->getTimestamp();
+
+ if ($permission_object->isDirty()) {
+ $processed_permissions++;
+ if (!$permission_object->store()) {
+ if ($this->edit_global_permissions) {
+ $errors[] = sprintf(
+ _(
+ 'Die globalen Berechtigungen von %s konnten nicht gespeichert werden!'
+ ),
+ htmlReady($user->getFullName())
+ );
+ } else {
+ $errors[] = sprintf(
+ _(
+ 'Die Berechtigungen von %1$s an der Ressource %2$s konnten nicht gespeichert werden!'
+ ),
+ htmlReady($user->getFullName()),
+ htmlReady($this->resource->name)
+ );
+ }
+ }
+ }
+ }
+
+ //Now we must remove all permissions where the resource_id is given
+ //and where the user_id is not in the $user_ids array which has been
+ //filled above.
+ if ($user_ids) {
+ $deleted_permissions = ResourceTemporaryPermission::deleteBySql(
+ 'resource_id = :resource_id
+ AND
+ user_id NOT IN ( :user_ids )',
+ [
+ 'resource_id' => $this->resource_id,
+ 'user_ids' => $user_ids
+ ]
+ );
+ } else {
+ //In case no user_ids are collected above all permissions
+ //for the resource have to be deleted:
+ $deleted_permissions = ResourceTemporaryPermission::deleteBySQL(
+ 'resource_id = :resource_id',
+ [
+ 'resource_id' => $this->resource_id,
+ ]
+ );
+ }
+
+ if (count($errors)) {
+ PageLayout::postError(
+ _('Die folgenden Fehler traten auf beim Speichern der Berechtigungen:'),
+ $errors
+ );
+ } elseif (($processed_permissions > 0) || ($deleted_permissions > 0)) {
+ PageLayout::postSuccess(
+ _('Die Berechtigungen wurden gespeichert!')
+ );
+ }
+ }
+
+ if ($this->single_user_mode) {
+ //Load permissions of the specified user:
+ $this->temp_permissions = ResourceTemporaryPermission::findBySql(
+ "resource_id = :resource_id
+ AND user_id = :user_id",
+ [
+ 'resource_id' => $this->resource_id,
+ 'user_id' => $this->user->id
+ ]
+ );
+ } else {
+ //Load existing permissions:
+ //Sort the permissions by the user's name:
+ $this->temp_permissions = ResourceTemporaryPermission::findBySql(
+ "INNER JOIN auth_user_md5 USING (user_id)
+ WHERE
+ resource_id = :resource_id
+ ORDER BY
+ nachname ASC, vorname ASC",
+ [
+ 'resource_id' => $this->resource_id
+ ]
+ );
+ }
+ }
+
+
+ public function special_assign_action($resource_id = null)
+ {
+ if (count($this->resources) > 1) {
+ PageLayout::postError(
+ _('Diese Aktion kann nur für einzelne Ressourcen verwendet werden!')
+ );
+ return;
+ }
+ $this->resource = $this->resources[0];
+
+ $this->getUserAndCheckPermissions('admin');
+
+ $this->show_form = false;
+
+ $this->booking_type = Request::int('type');
+ if (!in_array($this->booking_type, [1, 2])) {
+ PageLayout::postError(
+ _('Es wurde kein passender Buchungstyp angegeben!')
+ );
+ return;
+ }
+
+ if ($this->booking_type == 1) {
+ PageLayout::setTitle(
+ sprintf(
+ _('%s: Reservierung erstellen'),
+ $this->resource->getFullName()
+ )
+ );
+ } elseif ($this->booking_type == 2) {
+ PageLayout::setTitle(
+ sprintf(
+ _('%s: Sperrbuchung erstellen'),
+ $this->resource->getFullName()
+ )
+ );
+ }
+
+ //Set default form data:
+ $this->begin = new DateTime();
+ $this->begin->setTime(date('H') + 1, 0, 0);
+ $this->end = clone $this->begin;
+ $this->end->add(new DateInterval('P1D'));
+ $this->show_form = true;
+
+ if (Request::submitted('save')) {
+ $begin_date = Request::get('begin_date');
+ $begin_time = Request::get('begin_time');
+ $end_date = Request::get('end_date');
+ $end_time = Request::get('end_time');
+
+ //$begin and $end are in the format Y-m-d H:i
+ $begin_date = explode('-', $begin_date);
+ $begin_time = explode(':', $begin_time);
+ $this->begin = new DateTime();
+ $this->begin->setDate(
+ intval($begin_date[0]),
+ intval($begin_date[1]),
+ intval($begin_date[2])
+ );
+ $this->begin->setTime(
+ intval($begin_time[0]),
+ intval($begin_time[1]),
+ 0
+ );
+
+ $end_date = explode('-', $end_date);
+ $end_time = explode(':', $end_time);
+ $this->end = new DateTime();
+ $this->end->setDate(
+ intval($end_date[0]),
+ intval($end_date[1]),
+ intval($end_date[2])
+ );
+ $this->end->setTime(
+ intval($end_time[0]),
+ intval($end_time[1]),
+ 0
+ );
+
+ try {
+ $this->resource->createSimpleBooking(
+ $this->current_user,
+ $this->begin,
+ $this->end,
+ $this->booking_type
+ );
+ } catch (ResourceUnlockableException $e) {
+ PageLayout::postError(
+ $e->getMessage()
+ );
+ $this->show_form = true;
+ return;
+ } catch (ResourceUnavailableException $e) {
+ PageLayout::postError(
+ $e->getMessage()
+ );
+ $this->show_form = true;
+ return;
+ }
+ $this->show_form = false;
+ PageLayout::postSuccess(
+ sprintf(
+ _('%1$s: Die Sperrbuchung für den Zeitraum von %2$s bis %3$s wurde gespeichert!'),
+ htmlReady($this->resource->getFullName()),
+ $this->begin->format('d.m.Y H:i'),
+ $this->end->format('d.m.Y H:i')
+ )
+ );
+ }
+ }
+
+
+ public function delete_bookings_action($resource_id = null)
+ {
+ //Set the next week as default time range:
+ $this->begin = new DateTime();
+ $this->begin->setTimestamp(strtotime('next week'));
+ $this->end = clone $this->begin;
+ $this->end = $this->end->add(new DateInterval('P7DT23H59M59S'));
+
+ $this->show_form = true;
+
+ if (Request::submitted('delete')) {
+ CSRFProtection::verifyUnsafeRequest();
+
+ $this->begin = Request::getDateTime(
+ 'begin_date',
+ 'd.m.Y',
+ 'begin_time',
+ 'H:i'
+ );
+ $this->end = Request::getDateTime(
+ 'end_date',
+ 'd.m.Y',
+ 'end_time',
+ 'H:i'
+ );
+
+ if ($this->begin >= $this->end) {
+ PageLayout::postError(
+ _('Der Startzeitpunkt darf nicht hinter dem Endzeitpunkt liegen!')
+ );
+ return;
+ }
+
+ //Collect all resource-IDs:
+ $resource_ids = [];
+ foreach ($this->resources as $resource) {
+ $resource_ids[] = $resource->id;
+ }
+
+ //Delete all bookings in that time range
+ //which are not assigned to a course:
+ $deleted = ResourceBookingInterval::deleteBySql(
+ 'INNER JOIN resource_bookings
+ ON resource_bookings.id = resource_booking_intervals.booking_id
+ INNER JOIN auth_user_md5
+ ON resource_bookings.range_id = auth_user_md5.user_id
+ WHERE
+ resource_booking_intervals.resource_id IN ( :resource_ids )
+ AND
+ resource_booking_intervals.begin >= :begin
+ AND
+ resource_booking_intervals.end <= :end',
+ [
+ 'resource_ids' => $resource_ids,
+ 'begin' => $this->begin->getTimestamp(),
+ 'end' => $this->end->getTimestamp()
+ ]
+ );
+
+ if ($deleted !== false) {
+ $this->show_form = false;
+ PageLayout::postSuccess(
+ sprintf(
+ ngettext(
+ 'Eine Buchung wurde im Zeitbereich von %1$s, %2$s Uhr bis zum %3$s, %4$s Uhr gelöscht!',
+ '%5$d Buchungen wurde im Zeitbereich von %1$s, %2$s Uhr bis zum %3$s, %4$s Uhr gelöscht!',
+ $deleted
+ ),
+ $this->begin->format('d.m.Y'),
+ $this->begin->format('H:i'),
+ $this->end->format('d.m.Y'),
+ $this->end->format('H:i'),
+ $deleted
+ )
+ );
+ } else {
+ PageLayout::postError(
+ sprintf(
+ _('Die Buchungen im Zeitbereich von %1$s, %2$s Uhr bis %3$s, %4$s Uhr konnten nicht gelöscht werden!'),
+ $this->begin->format('d.m.Y'),
+ $this->begin->format('H:i'),
+ $this->end->format('d.m.Y'),
+ $this->end->format('H:i')
+ )
+ );
+ }
+ }
+ }
+
+
+ public function files_action($resource_id = null, $folder_id = null)
+ {
+ if (count($this->resources) > 1) {
+ PageLayout::postError(
+ _('Diese Aktion kann nur für einzelne Ressourcen verwendet werden!')
+ );
+ return;
+ }
+ $this->resource = $this->resources[0];
+
+ $this->getUserAndCheckPermissions('user');
+
+ //Set the page title:
+
+ PageLayout::setTitle(
+ $this->resource->getFullName() . ': ' . _('Dateien')
+ );
+
+ //Get the resource's folder:
+
+ if ($folder_id) {
+ $folder = Folder::find($folder_id);
+ if ($folder) {
+ $this->folder = $folder->getTypedFolder();
+ }
+ } else {
+ $this->folder = $this->resource->getFolder();
+ }
+
+ if (!$this->folder) {
+ PageLayout::postError(
+ sprintf(
+ _('Der Dateiordner zur Ressource %1$s konnte nicht gefunden werden!'),
+ htmlReady($this->resource->name)
+ )
+ );
+ return;
+ }
+
+ if (!$this->folder->isReadable($this->current_user->id)) {
+ throw new AccessDeniedException(
+ _('Sie sind nicht berechtigt, den Inhalt dieses Ordners zu sehen!')
+ );
+ }
+
+ //Build the sidebar:
+
+ $sidebar = Sidebar::get();
+ $actions = new ActionsWidget();
+ $sidebar->addWidget($actions);
+
+ if ($this->folder->isWritable($this->current_user->id)) {
+ $actions->addLink(
+ _('Dokument hinzufügen'),
+ '#',
+ Icon::create('file+add'),
+ [
+ 'onclick' => 'STUDIP.Files.openAddFilesWindow(); return false;'
+ ]
+ );
+ //Add the file upload widget:
+ $upload_area = new LinksWidget();
+ $upload_area->setTitle(_('Dateien hinzufügen'));
+ $upload_area->addElement(
+ new WidgetElement(
+ $this->render_template_as_string('files/upload-drag-and-drop')
+ )
+ );
+ $sidebar->addWidget($upload_area);
+ }
+
+ //Get all files of the folder:
+
+ $this->folder_files = $this->folder->getFiles();
+
+ //Set the last visit date to the current timestamp:
+ $this->last_visitdate = time();
+ }
+}