aboutsummaryrefslogtreecommitdiff
path: root/app/routes
diff options
context:
space:
mode:
authorPhilipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de>2024-09-24 10:53:31 +0200
committerPhilipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de>2024-09-24 10:53:31 +0200
commit4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch)
tree5c07151ae61276d334e88f6309c30d439a85c12e /app/routes
parentda0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff)
parent97a188592c679890a25c37ab78463add76a52ff7 (diff)
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'app/routes')
-rw-r--r--app/routes/Activity.php168
-rw-r--r--app/routes/Blubber.php321
-rw-r--r--app/routes/Clipboard.php193
-rw-r--r--app/routes/Contacts.php302
-rw-r--r--app/routes/Course.php242
-rw-r--r--app/routes/Discovery.php27
-rw-r--r--app/routes/Events.php186
-rw-r--r--app/routes/Feedback.php271
-rw-r--r--app/routes/FileSystem.php684
-rw-r--r--app/routes/Forum.php419
-rw-r--r--app/routes/Messages.php301
-rw-r--r--app/routes/News.php375
-rw-r--r--app/routes/ResourceBooking.php192
-rw-r--r--app/routes/ResourceCategories.php349
-rw-r--r--app/routes/ResourcePermissions.php585
-rw-r--r--app/routes/ResourceProperties.php224
-rw-r--r--app/routes/ResourceRequest.php138
-rw-r--r--app/routes/Resources.php950
-rw-r--r--app/routes/RoomClipboard.php322
-rw-r--r--app/routes/Schedule.php71
-rw-r--r--app/routes/Semester.php115
-rw-r--r--app/routes/Studip.php65
-rw-r--r--app/routes/User.php300
-rw-r--r--app/routes/UserConfig.php99
-rw-r--r--app/routes/Wiki.php148
25 files changed, 0 insertions, 7047 deletions
diff --git a/app/routes/Activity.php b/app/routes/Activity.php
deleted file mode 100644
index fadca0f..0000000
--- a/app/routes/Activity.php
+++ /dev/null
@@ -1,168 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @author Till Glöggler <tgloeggl@uos.de>
- * @author André Klaßen <klassen@elan-ev.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition user_id ^[a-f0-9]{1,32}$
- */
-class Activity extends \RESTAPI\RouteMap
-{
- /**
- * List activities for an user
- *
- * @get /user/:user_id/activitystream
- *
- * @param string $user_id the user to get the activities for
- *
- * @return array the activities as array('collection' => array(...), 'pagination' => array())
- */
- public function getActivities($user_id)
- {
- // only root can retrieve arbitrary streams
- if (!$GLOBALS['perm']->have_perm('root') && $GLOBALS['user']->id != $user_id) {
- $this->error(401);
- }
-
- // failsafe einbauen - falls es keine älteren Aktivitäten mehr im System gibt, Abbruch!
-
- $oldest_activity = \Studip\Activity\Activity::getOldestActivity();
- $max_age = $oldest_activity ? $oldest_activity->mkdate : time();
-
-
- $contexts = [];
-
- $user = \User::find($user_id);
-
- // create system context
- $system_context = new \Studip\Activity\SystemContext($user);
- $contexts[] = $system_context;
-
- $contexts[] = new \Studip\Activity\UserContext($user, $user);
- $user->contacts->each(function($another_user) use (&$contexts, $user) {
- $contexts[] = new \Studip\Activity\UserContext($another_user, $user);
- });
-
- if (!in_array($user->perms, ['admin','root'])) {
- // create courses and institutes context
- foreach (\Course::findMany($user->course_memberships->pluck('seminar_id')) as $course) {
- $contexts[] = new \Studip\Activity\CourseContext($course, $user);
- }
- foreach (\Institute::findMany($user->institute_memberships->pluck('institut_id')) as $institute) {
- $contexts[] = new \Studip\Activity\InstituteContext($institute, $user);
- }
- }
-
-
- // add filters
- $filter = new \Studip\Activity\Filter();
-
- $start = \Request::int('start', strtotime('-1 days'));
- $end = \Request::int('end', time());
-
-
- $scrollfrom = \Request::int('scrollfrom', false);
- $filtertype = \Request::get('filtertype', '');
-
- $objectType = \Request::get('object_type');
- $filter->setObjectType($objectType);
-
- $objectId = \Request::get('object_id');
- $filter->setObjectId($objectId);
-
- $context = \Request::get('context_type');
- $filter->setContext($context);
-
- $contextId = \Request::get('context_id');
- $filter->setContextId($contextId);
-
- if (!empty($filtertype)) {
- $filter->setType(json_decode($filtertype));
- }
-
- if ($scrollfrom) {
- // shorten "watch-window" by one second to prevent duplication of activities
- $scrollfrom -= 1;
-
- if ($scrollfrom > $max_age){
- $end = $scrollfrom;
- $start = strtotime('-1 day', $end);
- $data = [];
-
- $backtrack = 1;
-
- while (empty($data)) {
- $filter->setStartDate($start);
- $filter->setEndDate($end);
-
- $data = $this->getStreamData($contexts, $filter);
-
- if ($start < $max_age) {
- break;
- }
-
- // move "watch-window" back one day at a time
- $end = $start - 1;
- $start = strtotime('-'. $backtrack . ' days', $start);
-
- // enforce maximum "watch-window", currently 2 weeks
- $backtrack = min (14, $backtrack + 1);
- }
- } else {
- $data = false;
- }
- } else {
-
- $filter->setStartDate($start);
- $filter->setEndDate($end);
- $data = $this->getStreamData($contexts, $filter);
-
- }
-
- // set etag for preventing resending the same stuff over and over again
- $this->etag(md5(serialize($data)));
-
- return $data;
- }
-
- /**
- * private helper function to get stream data for given contexts and filter
- *
- * @param $contexts
- * @param $filter
- * @return array
- */
-
- private function getStreamData($contexts, $filter)
- {
- $stream = new \Studip\Activity\Stream($contexts, $filter);
- $data = $stream->toArray();
-
- foreach ($data as $key => $act) {
- $actor = [
- 'type' => $data[$key]['actor_type'],
- 'id' => $data[$key]['actor_id']
- ];
-
- if ($data[$key]['actor_type'] == 'user') {
- $a_user = \User::findFull($data[$key]['actor_id']);
- $actor['details'] = User::getMiniUser($this, $a_user ?: new \User());
- } elseif ($data[$key]['actor_type'] === 'anonymous') {
- $actor['details'] = [
- 'name' => _('Anonym'),
- ];
- }
-
- unset($data[$key]['actor_type']);
- unset($data[$key]['actor_id']);
-
- $data[$key]['actor'] = $actor;
- }
-
- return $data;
-
- }
-}
diff --git a/app/routes/Blubber.php b/app/routes/Blubber.php
deleted file mode 100644
index 1445088..0000000
--- a/app/routes/Blubber.php
+++ /dev/null
@@ -1,321 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition course_id ^[a-f0-9]{1,32}$
- * @condition stream_id ^(global|[a-f0-9]{1,32})$
- * @condition user_id ^[a-f0-9]{1,32}$
- * @condition blubber_id ^[a-f0-9]{1,32}$
- */
-class Blubber extends \RESTAPI\RouteMap
-{
-
- /**
- * Get content and some comments for a blubber-thread or for the "global" thread all "public" threads.
- *
- * @get /blubber/threads/:thread_id
- * @param string $thread_id id of the blubber thread or "global" if you want public threads (not comments). Remind the global thread is a virtual thread with a special behaviour.
- * @return array the blubber as array
- */
- public function getThreadData($thread_id)
- {
- if (!$GLOBALS['perm']->have_perm('autor')) {
- $this->error(401);
- }
- $GLOBALS['user']->cfg->store('BLUBBER_DEFAULT_THREAD', $thread_id);
-
- $thread = new \BlubberThread($thread_id);
- $thread = \BlubberThread::upgradeThread($thread);
- if (!$thread->isReadable()) {
- $this->error(401);
- }
-
- $json = $thread->getJSONData(50, null, \Request::get("search"));
- $thread->markAsRead();
-
- $this->etag(md5(serialize($json)));
-
- return $json;
- }
-
- /**
- * Get threads
- *
- * @get /blubber/threads
- * @return array the stream as array
- */
- public function getMyThreads()
- {
- $threads_data = [
- 'threads' => [],
- 'more_down' => 0,
- ];
- $limit = \Request::int('limit', 50);
-
- $threads = \BlubberThread::findMyGlobalThreads(
- $limit + 1,
- null,
- \Request::int('timestamp'),
- null,
- \Request::get("search") ?: null
- );
- if (count($threads) > $limit) {
- array_pop($threads);
- $threads_data['more_down'] = 1;
- }
- foreach ($threads as $thread) {
- $threads_data['threads'][] = [
- 'thread_id' => $thread->getId(),
- 'avatar' => $thread->getAvatar(),
- 'name' => $thread->getName(),
- 'timestamp' => (int) $thread->getLatestActivity(),
- ];
- }
- return $threads_data;
- }
-
- /**
- * Write a comment to a thread
- *
- * @post /blubber/threads/:thread_id/comments
- * @param string $thread_id id of the blubber thread
- * @return array the comment as array
- */
- public function postComment($thread_id)
- {
- if (!$GLOBALS['perm']->have_perm('autor')) {
- $this->error(401);
- }
-
- if (!trim($this->data['content'])) {
- $this->error(406);
- }
-
- $thread = \BlubberThread::find($thread_id);
- if (!$thread->isCommentable()) {
- $this->error(401);
- }
-
- $comment = new \BlubberComment();
- $comment['thread_id'] = $thread_id;
- $comment['content'] = $this->data['content'];
- $comment['user_id'] = $GLOBALS['user']->id;
- $comment['external_contact'] = 0;
- $comment->store();
-
- $thread->setLastVisit();
-
- return $comment->getJSONData();
- }
-
- /**
- * Write a comment to a thread
- *
- * @put /blubber/threads/:thread_id/comments/:comment_id
- *
- * @param string $thread_id id of the blubber thread
- * @param string $comment id of the comment
- *
- * @return array the comment as array
- */
- public function editComment($thread_id, $comment_id)
- {
- $comment = \BlubberComment::find($comment_id);
- if (!$comment->isWritable()) {
- $this->error(401);
- }
- $old_content = $comment['content'];
- $comment['content'] = $this->data['content'];
-
- if ($comment['user_id'] !== $GLOBALS['user']->id) {
- $messaging = new \messaging();
- $message = sprintf(
- _("%s hat als Moderator gerade Ihren Beitrag in Blubber editiert.\n\nDie alte Version des Beitrags lautete:\n\n%s\n\nDie neue lautet:\n\n%s\n"),
- get_fullname(), $old_content, $comment['content']
- );
-
- $message .= "\n\n";
-
- $message .= '[' . _('Link zu diesem Beitrag') . ']';
- $message .= \URLHelper::getURL(
- "{$GLOBALS['ABSOLUTE_URI_STUDIP']}dispatch.php/blubber/index/{$comment->thread_id}",
- [],
- true
- );
-
- $messaging->insert_message(
- $message,
- get_username($comment['user_id']),
- $GLOBALS['user']->id,
- null, null, null, null,
- _("Änderungen an Ihrem Blubber.")
- );
- }
-
- if (!trim($this->data['content'])) {
- $data = $comment->getJSONData();
- $comment->delete();
- } else {
- $comment->store();
- $data = $comment->getJSONData();
- }
- return $data;
- }
-
- /**
- * Write a comment to a thread
- *
- * @get /blubber/threads/:thread_id/comments
- *
- * @param string $thread_id id of the blubber thread
- *
- * @return array the comments as array
- */
- public function getComments($thread_id)
- {
- if (!$GLOBALS['perm']->have_perm('autor')) {
- $this->error(401);
- }
-
- $thread = new \BlubberThread($thread_id);
- if (!$thread->isReadable()) {
- $this->error(401);
- }
-
- $modifier = \Request::get('modifier');
- if ($modifier === 'olderthan') {
- $limit = \Request::int('limit', 50);
-
- $query = "SELECT blubber_comments.*
- FROM blubber_comments
- WHERE blubber_comments.thread_id = :thread_id
- AND blubber_comments.mkdate <= :timestamp
- ORDER BY mkdate DESC
- LIMIT :limit";
- $result = \DBManager::get()->fetchAll($query, [
- 'thread_id' => $thread_id,
- 'timestamp' => \Request::int('timestamp', time()),
- 'limit' => $limit + 1,
- ]);
-
- $output = ['comments' => []];
-
- if (count($result) > $limit) {
- array_pop($result);
- $output['more_up'] = 1;
- } else {
- $output['more_up'] = 0;
- }
- foreach ($result as $data) {
- $comment = \BlubberComment::buildExisting($data);
- $output['comments'][] = $comment->getJSONData();
- }
- return $output;
- }
-
- if ($modifier === 'newerthan') {
- $limit = \Request::int('limit', 50);
-
- $query = "SELECT blubber_comments.*
- FROM blubber_comments
- WHERE blubber_comments.thread_id = :thread_id
- AND blubber_comments.mkdate >= :timestamp
- ORDER BY mkdate
- LIMIT :limit";
- $comments = \DBManager::get()->fetchAll($query, [
- 'thread_id' => $thread_id,
- 'timestamp' => \Request::int('timestamp', time()),
- 'limit' => $limit + 1,
- ], function ($comment) {
- return \BlubberComment::buildExisting($comment)->getJSONData();
- });
-
- $output = ['comments' => $comments];
-
- if (count($comments) > $limit) {
- array_pop($output['comments']);
- $output['more_down'] = 1;
- } else {
- $output['more_down'] = 0;
- }
-
- return $output;
- }
-
- $query = "SELECT blubber_comments.*
- FROM blubber_comments
- WHERE blubber_comments.thread_id = :thread_id ";
- $parameters = ['thread_id' => $thread_id];
-
- if (\Request::get('search')) {
- $query .= " AND blubber_comments.content LIKE :search ";
- $parameters['search'] = '%'.\Request::get('search').'%';
- }
- $query .= " ORDER BY mkdate ASC ";
-
- $output['comments'] = \DBManager::get()->fetchAll($query, $parameters, function ($comment) {
- return \BlubberComment::buildExisting($comment)->getJSONData();
- });
- $output['more_up'] = 0;
- $output['more_down'] = 0;
-
- return $output;
- }
-
- /**
- * Does the current user follow the thread?
- *
- * @get /blubber/threads/:thread_id/follow
- */
- public function threadIsFollowed($thread_id)
- {
- return $this->requireThread($thread_id)->isFollowedByUser();
- }
-
- /**
- * User follows a thread.
- *
- * @post /blubber/threads/:thread_id/follow
- *
- * @param string $thread_id id of the blubber thread
- */
- public function followThread($thread_id)
- {
- $this->requireThread($thread_id)->addFollowingByUser();
- }
-
- /**
- * User unfollows a thread.
- *
- * @delete /blubber/threads/:thread_id/follow
- *
- * @param string $thread_id id of the blubber thread
- */
- public function unfollowThread($thread_id)
- {
- $this->requireThread($thread_id)->removeFollowingByUser();
- }
-
- /**
- * Returns a blubber thread and checks permissions.
- *
- * @param string $thread_id Id of the blubber thread
- * @return \BlubberThread
- */
- private function requireThread($thread_id)
- {
- if (!$GLOBALS['perm']->have_perm('autor')) {
- $this->error(401);
- }
-
- $thread = new \BlubberThread($thread_id);
- if (!$thread->isReadable()) {
- $this->error(401);
- }
-
- return \BlubberThread::upgradeThread($thread);
- }
-}
diff --git a/app/routes/Clipboard.php b/app/routes/Clipboard.php
deleted file mode 100644
index dfe22e0..0000000
--- a/app/routes/Clipboard.php
+++ /dev/null
@@ -1,193 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-
-/**
- * This file contains the REST class for the clipboard system.
- *
- * @author Moritz Strohm <strohm@data-quest.de>
- * @copyright 2017-2019
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @since 4.5
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- */
-class Clipboard extends \RESTAPI\RouteMap
-{
- /**
- * Adds a new clipboard.
- *
- * @post /clipboard/add
- */
- public function addClipboard()
- {
- $name = \Request::get('name');
-
- if (!$name) {
- $this->halt(400, _('Es wurde kein Name angegeben!'));
- }
-
- $clipboard = new \Clipboard();
- $clipboard->user_id = $GLOBALS['user']->id;
- $clipboard->name = $name;
- if (!$clipboard->store()) {
- $this->halt(500, _('Fehler beim Speichern des Merkzettels!'));
- }
-
- $result = $clipboard->toRawArray();
- //A special treatment for the widget_id parameter:
- //It is passed through:
- $widget_id = \Request::get('widget_id');
- if ($widget_id) {
- $result['widget_id'] = $widget_id;
- }
-
- return $result;
- }
-
-
- /**
- * Edits a clipboard.
- *
- * @put /clipboard/:clipboard_id
- */
- public function editCliboard($clipboard_id = null)
- {
- $clipboard = \Clipboard::find($clipboard_id);
- if (!$clipboard) {
- $this->notFound(_('Ungültige Merkzettel-ID!'));
- }
-
- if ($clipboard->user_id != $GLOBALS['user']->id) {
- //Thou shalt not delete clipboards
- //which don't belong to you!
- throw new \AccessDeniedException();
- }
-
- $name = $this->data['name'];
- if (!$name) {
- $this->halt(400, _('Es wurde kein Name angegeben!'));
- }
-
- $clipboard->name = $name;
-
- if ($clipboard->isDirty()) {
- $success = $clipboard->store();
- } else {
- $success = true;
- }
-
- if (!$success) {
- $this->halt(500, _('Fehler beim Bearbeiten des Merkzettels!'));
- }
-
- $result = $clipboard->toRawArray();
-
- //A special treatment for the widget_id parameter:
- //It is passed through:
- $widget_id = \Request::get('widget_id');
- if ($widget_id) {
- $result['widget_id'] = $widget_id;
- }
-
- return $result;
- }
-
-
- /**
- * Deletes a clipboard.
- *
- * @delete /clipboard/:clipboard_id
- */
- public function deleteClipboard($clipboard_id = null)
- {
- $clipboard = \Clipboard::find($clipboard_id);
- if (!$clipboard) {
- $this->notFound(_('Ungültige Merkzettel-ID!'));
- }
-
- if ($clipboard->user_id !== $GLOBALS['user']->id) {
- //Thou shalt not delete items of clipboards
- //which don't belong to you!
- throw new \AccessDeniedException();
- }
-
- if (!$clipboard->delete()) {
- $this->halt(500, _('Fehler beim Löschen des Merkzettels!'));
- }
-
- return "";
- }
-
-
- /**
- * Adds an item to a clipboard.
- *
- * @post /clipboard/:clipboard_id/item
- */
- public function addClipboardItem($clipboard_id = null)
- {
- $clipboard = \Clipboard::find($clipboard_id);
- if (!$clipboard) {
- $this->notFound(_('Ungültige Merkzettel-ID!'));
- }
-
- if ($clipboard->user_id != $GLOBALS['user']->id) {
- //Thou shalt not add items to clipboards
- //which don't belong to you!
- throw new \AccessDeniedException();
- }
-
- $range_id = \Request::get('range_id');
- $range_type = \Request::get('range_type');
- $widget_id = \Request::get('widget_id');
-
- if (!is_a($range_type, $clipboard->allowed_item_class, true)) {
- $this->halt(
- 400,
- sprintf(
- _('Die Klasse %s ist in dieser Merkzettel-Klasse nicht erlaubt!'),
- $range_type
- )
- );
- }
-
- try {
- $item = $clipboard->addItem($range_id, $range_type);
-
- $result = $item->toRawArray();
- $result['name'] = $item->__toString();
- if ($widget_id) {
- $result['widget_id'] = $widget_id;
- }
- return $result;
- } catch (\Exception $e) {
- $this->halt(500, $e->getMessage());
- }
- }
-
-
- /**
- * Removes an item (selected by its range-ID) from a clipboard.
- *
- * @delete /clipboard/:clipboard_id/item/:range_id
- */
- public function removeClipboardItem($clipboard_id = null, $range_id = null)
- {
- $clipboard = \Clipboard::find($clipboard_id);
- if (!$clipboard) {
- $this->notFound(_('Ungültige Merkzettel-ID!'));
- }
-
- if ($clipboard->user_id != $GLOBALS['user']->id) {
- //Thou shalt not delete items of clipboards
- //which don't belong to you!
- throw new \AccessDeniedException();
- }
-
- if ($clipboard->removeItem($range_id)) {
- return ['range_id' => $range_id];
- } else {
- $this->halt(500, _('Fehler beim Löschen des Eintrags!'));
- }
- }
-}
diff --git a/app/routes/Contacts.php b/app/routes/Contacts.php
deleted file mode 100644
index d7fd010..0000000
--- a/app/routes/Contacts.php
+++ /dev/null
@@ -1,302 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition user_id ^[a-f0-9]{1,32}$
- * @condition friend_id ^[a-f0-9]{1,32}$
- * @condition group_id ^[a-f0-9]{1,32}$
- */
-class Contacts extends \RESTAPI\RouteMap
-{
-
- public static function before()
- {
- require_once 'User.php';
- require_once 'lib/statusgruppe.inc.php';
- }
-
- /**
- * Lists all contacts of a user
- *
- * @get /user/:user_id/contacts
- */
- public function getUserContacts($user_id)
- {
- if ($GLOBALS['user']->id !== $user_id) {
- $this->error(401);
- }
-
- // quite degenerated as long as we can only see our own contacts
- $user = $this->requireUser($user_id);
-
- $total = count($user->contacts);
- $contacts = $user->contacts->limit($this->offset, $this->limit);
-
- $contacts_json = $this->contactsToJSON($contacts);
- $this->etag(md5(serialize($contacts_json)));
-
- return $this->paginated($contacts_json,
- $total, compact('user_id'));
- }
-
- /**
- * Adds/Updates a contact to user's list of contacts
- *
- * @put /user/:user_id/contacts/:friend_id
- */
- public function addUserContact($user_id, $buddy_user_id)
- {
- if ($GLOBALS['user']->id !== $user_id) {
- $this->error(401);
- }
-
- $user = $this->requireUser($user_id);
- $friend = $this->requireUser($buddy_user_id);
-
- // prevent duplicates
- if ($user->isFriendOf($friend)) {
- $this->error(409, sprintf('User "%s" is already a contact', htmlReady($friend->id)));
- }
-
- $user->contacts[] = $friend;
- $user->store();
-
- $this->status(201);
- }
-
- /**
- * Deletes a contact
- *
- * @delete /user/:user_id/contacts/:friend_id
- */
- public function removeUserContact($user_id, $buddy_user_id)
- {
- if ($GLOBALS['user']->id !== $user_id) {
- $this->error(401);
- }
-
- $user = $this->requireUser($user_id);
- $friend = $this->requireUser($buddy_user_id);
-
- if (!$user->isFriendOf($friend)) {
- $this->notFound("Contact not found");
- }
-
- $user->contacts->unsetByPK($friend->id);
- $user->store();
-
- $this->status(204);
- }
-
-
- /**
- * List all contact groups of a user
- *
- * @get /user/:user_id/contact_groups
- */
- public function getUserContactGroups($user_id)
- {
- if ($GLOBALS['user']->id !== $user_id) {
- $this->error(401);
- }
-
- $contact_groups = \SimpleCollection::createFromArray(
- \Statusgruppen::findByRange_id($GLOBALS['user']->id))
- ->orderBy('name ASC');
-
- $total = count($contact_groups);
- $contact_groups = $contact_groups->limit($this->offset, $this->limit);
-
- $contact_groups_json = $this->contactGroupsToJSON($contact_groups);
- $this->etag(md5(serialize($contact_groups_json)));
-
- return $this->paginated($contact_groups_json,
- $total, compact('user_id'));
- }
-
- /**
- * Create a new contact group for a user.
- *
- * @post /user/:user_id/contact_groups
- */
- public function createContactGroup($user_id)
- {
- if ($GLOBALS['user']->id !== $user_id) {
- $this->error(401);
- }
-
- if (!isset($this->data['name']) || !mb_strlen($name = trim($this->data['name']))) {
- $this->error(400, 'Contact group name required.');
- }
-
- $group = new \Statusgruppen();
- $group->range_id = $GLOBALS['user']->id;
- $group->name = $name;
- $group->size = 0;
- $group->selfassign = 0;
- $group->calendar_group = 0;
- $group->store();
- $this->redirect('contact_group/' . $group->id, 201, 'ok');
- }
-
- /**
- * Show a single contact group
- *
- * @get /contact_group/:group_id
- */
- public function showContactGroup($group_id)
- {
- $group = $this->requireContactGroup($group_id);
- $contact_group_json = $this->contactGroupToJSON($group);
- $this->etag(md5(serialize($contact_group_json)));
- return $contact_group_json;
- }
-
- /**
- * Remove a contact group
- *
- * @delete /contact_group/:group_id
- */
- public function destroyContactGroup($group_id)
- {
- $group = $this->requireContactGroup($group_id);
-
- $group->remove();
-
- $this->status(204);
- }
-
- /**
- * List all members of a contact group
- *
- * @get /contact_group/:group_id/members
- */
- public function indexOfContactGroupMembers($group_id)
- {
- $group = $this->requireContactGroup($group_id);
- $contacts = $group->members->limit($this->offset, $this->limit);
-
- $json = [];
- foreach ($contacts as $contact) {
- $url = $this->urlf('/contact_group/%s/members/%s', [$group_id, $contact->user_id]);
- $json[$url] = User::getMiniUser($this, $contact->user);
- }
-
- $this->etag(md5(serialize($json)));
-
- return $this->paginated($json, count($group->members), compact('group_id'));
- }
-
- /**
- * Add a user to a contact group
- *
- * @put /contact_group/:group_id/members/:user_id
- */
- public function addToContactGroup($group_id, $user_id)
- {
- $group = $this->requireContactGroup($group_id);
- $user = $this->requireUser($user_id);
-
- // prevent duplicates
- $exists = $group->members->findBy('user_id', $user_id)->first();
- if ($exists) {
- $this->halt(204);
- }
-
- $new_contact = [
- 'owner_id' => $GLOBALS['user']->id,
- 'user_id' => $user->id];
-
- $new_contact['group_assignments'][] = ['statusgruppe_id' => $group->id,
- 'user_id' => $user->id];
-
- $success = (bool)\Contact::import($new_contact)->store();
-
-
- if (!$success) {
- $this->error(500);
- }
-
- $this->status(201);
- }
-
- /**
- * Remove a user from a contact group
- *
- * @delete /contact_group/:group_id/members/:user_id
- */
- public function removeFromContactGroup($group_id, $user_id)
- {
- $group = $this->requireContactGroup($group_id);
- $membership = $group->members->findBy('user_id', $user_id)->first();
- if (!$membership) {
- $this->notFound();
- }
-
- $membership->delete();
-
- $this->status(204);
- }
-
-
- /**************************************************/
- /* PRIVATE HELPER METHODS */
- /**************************************************/
-
- private function requireUser($user_id)
- {
- $user = \User::find($user_id);
- // TODO: checks visibility using the global perm object!
- if (!$user || !get_visibility_by_id($user_id)) {
- $this->notFound(sprintf("Could not find user with id: %s", htmlReady($user_id)));
- }
-
- return $user;
- }
-
- private function requireContactGroup($group_id)
- {
- $group = \Statusgruppen::find($group_id);
- if (!$group) {
- $this->notFound();
- }
-
- if ($group->range_id !== $GLOBALS['user']->id) {
- $this->error(401);
- }
- return $group;
- }
-
- private function contactsToJSON($contacts) {
- $result = [];
- foreach ($contacts as $contact) {
- $result[] = User::getMiniUser($this, $contact);
- }
- return $result;
- }
-
- private function contactGroupsToJSON($contact_groups)
- {
- $result = [];
- foreach ($contact_groups as $cg) {
- $url = $this->urlf('/contact_group/%s', [htmlReady($cg->id)]);
- $result[$url] = $this->contactGroupToJSON($cg);
- }
- return $result;
- }
-
- private function contactGroupToJSON($group)
- {
- $json = [
- 'id' => $group->id,
- 'name' => (string) $group->name,
- 'contacts' => $this->urlf('/contact_group/%s/members', [htmlReady($group->id)]),
- 'contacts_count' => sizeof($group->members)
- ];
- return $json;
- }
-}
diff --git a/app/routes/Course.php b/app/routes/Course.php
deleted file mode 100644
index d1fad96..0000000
--- a/app/routes/Course.php
+++ /dev/null
@@ -1,242 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition course_id ^[a-f0-9]{1,32}$
- * @condition user_id ^[a-f0-9]{1,32}$
- */
-class Course extends \RESTAPI\RouteMap
-{
-
- public function before()
- {
- require_once 'User.php';
- }
-
- /**
- * Lists all courses of a user including the semesters in which
- * that course is active.
- * Optionally filtered by a URL parameter 'semester'.
- *
- * @get /user/:user_id/courses
- */
- public function getUserCourses($user_id)
- {
- if (($GLOBALS['user']->id !== $user_id) && !$GLOBALS['perm']->have_perm("root")) {
- $this->error(401);
- }
-
- // setting up semester to filter by
- $semester = null;
- $semester_id = \Request::get('semester');
- if ($semester_id) {
- $semester = \Semester::find($semester_id);
- if (!$semester) {
- $this->error(400, "Semester not found.");
- }
- }
-
- $memberships = $this->findMembershipsByUserId($user_id, $semester);
-
- $total = count($memberships);
- $memberships = $memberships->limit($this->offset, $this->limit);
- $memberships_json = $this->membershipsToJSON($memberships);
- $this->etag(md5(serialize($memberships_json)));
- return $this->paginated(
- $memberships_json,
- $total,
- compact('user_id'),
- ['semester' => $semester_id]
- );
- }
-
- /**
- * Show a single course
- *
- * @get /course/:course_id
- */
- public function getCourse($course_id)
- {
- if (!$course = \Course::find($course_id)) {
- $this->notFound("Course not found");
- }
-
- $course = $this->requireCourse($course_id);
- $this->lastmodified($course->chdate);
- $course_json = $this->courseToJSON($course);
- $this->etag(md5(serialize($course_json)));
- return $course_json;
- }
-
- /**
- * List all members of a course.
- * Optionally filtered by a URL parameter 'status'.
- *
- * @get /course/:course_id/members
- */
- public function getMembers($course_id)
- {
- $status_filter = \Request::get('status');
- if ($status_filter && !in_array($status_filter, words("user autor tutor dozent"))) {
- $this->error(400, "Status may be one of: user, autor, tutor, dozent");
- }
-
- $course = $this->requireCourse($course_id);
- $members = $course->members;
- if ($status_filter) {
- $members = $members->findBy('status', $status_filter);
- }
-
- $total = count($members);
- $members = $members->limit($this->offset, $this->limit);
- $members_json = $this->membersToJSON($course, $members);
- $this->etag(md5(serialize($members_json)));
- return $this->paginated(
- $members_json,
- $total,
- compact('course_id'),
- ['status' => $status_filter]
- );
- }
-
- /**
- * Get the root file folder of a course.
- *
- * @get /course/:course_id/top_folder
- */
- public function getTopFolder($course_id)
- {
- $top_folder = \Folder::findTopFolder(
- $this->requireCourse($course_id)->id,
- 'course'
- );
-
- if (!$top_folder) {
- $this->notFound("No folder found for course with id {$course_id}!");
- }
-
- return (new FileSystem())->getFolder($top_folder->id);
- }
-
- /**************************************************/
- /* PRIVATE HELPER METHODS */
- /**************************************************/
-
- private function findMembershipsByUserId($user_id, $semester)
- {
- $memberships = \SimpleORMapCollection::createFromArray(
- \CourseMember::findBySQL('user_id = ? ORDER BY mkdate ASC', [$user_id])
- );
-
- // filter by semester
- if ($semester) {
-
- $memberships = $memberships->filter(function ($m) use ($semester) {
- return $m->course->isInSemester($semester);
- });
- }
-
- return $memberships;
- }
-
- private function membershipsToJSON($memberships)
- {
- $json = [];
-
- foreach ($memberships as $membership) {
- $course_json = $this->courseToJSON($course = $membership->course);
-
- $json[$this->urlf("/course/%s", [$course->id])] = $course_json;
- }
- return $json;
- }
-
- private function courseToJSON($course)
- {
- $json = [];
-
- $json['course_id'] = $course->id;
- $json['number'] = $course->VeranstaltungsNummer;
- $json['title'] = (string) $course->Name;
- $json['subtitle'] = (string) $course->Untertitel;
- $json['type'] = $course->status;
- $json['description'] = (string) $course->Beschreibung;
- $json['location'] = (string) $course->Ort;
-
- // lecturers
- foreach ($course->getMembersWithStatus('dozent') as $lecturer) {
- $url = $this->urlf('/user/%s', [htmlReady($lecturer->user_id)]);
- $json['lecturers'][$url] = User::getMiniUser($this, $lecturer->user);
- }
-
- // other members
- foreach (words("user autor tutor dozent") as $status) {
- $json['members'][$status] = $this->urlf('/course/%s/members?status=%s', [$course->id, $status]);
- $json['members'][$status . '_count'] = $course->countMembersWithStatus($status);
- }
-
- foreach (words("start_semester end_semester") as $key) {
- $json[$key] = $course->$key ? $this->urlf('/semester/%s', [htmlReady($course->$key->id)]) : null;
- }
-
- $activated = array_map('get_class', $course->getActivatedTools());
-
- $json['modules'] = [];
- foreach (['forum' => 'forum_categories',
- 'documents' => 'top_folder',
- 'wiki' => 'wiki'] as $module => $uri)
- {
- if (in_array('Core' . ucfirst($module), $activated)) {
- $json['modules'][$module] = $this->urlf('/course/%s/%s', [htmlReady($course->id), $uri]);
- }
- }
-
- // Add group if current user is member of the group
- $json['group'] = null;
-
- $member = \CourseMember::find([$course->id, $GLOBALS['user']->id]);
- if ($member) {
- $json['group'] = (int) $member->gruppe;
- }
-
-
- return $json;
- }
-
- private function requireCourse($id)
- {
- if (!$course = \Course::find($id)) {
- $this->notFound("Course not found");
- }
-
- //This route is used in the room management system.
- //Therefore, we need not only to check if the user is in the course,
- //but also, if the user is a global resource admin. In the latter case,
- //access shall also be granted.
- if (!$GLOBALS['perm']->have_studip_perm('user', $id, $GLOBALS['user']->id)
- && !\ResourceManager::userHasGlobalPermission(\User::findCurrent(), 'admin')) {
- $this->error(401);
- }
-
- return $course;
- }
-
- private function membersToJSON($course, $members)
- {
- $json = [];
-
- foreach ($members as $member) {
- $url = $this->urlf('/user/%s', [$member->user_id]);
- $avatar = \Avatar::getAvatar($member->user_id);
- $json[$url] = [
- 'member' => User::getMiniUser($this, $member->user),
- 'status' => $member->status
- ];
- }
- return $json;
- }
-}
diff --git a/app/routes/Discovery.php b/app/routes/Discovery.php
deleted file mode 100644
index c83f524..0000000
--- a/app/routes/Discovery.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @author Jan-Hendrik Willms <tleilax+studip@gmail.com>
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- */
-class Discovery extends \RESTAPI\RouteMap
-{
- /**
- * Schnittstellenbeschreibung
- *
- * @get /discovery
- */
- public function getDiscovery()
- {
- $routes = $this->router->getRoutes(true);
- foreach ($routes as $uri_template => $methods) {
- foreach ($methods as $method => $route) {
- $routes[$uri_template][$method] = $route['description'];
- }
- }
- return $routes;
- }
-}
diff --git a/app/routes/Events.php b/app/routes/Events.php
deleted file mode 100644
index 368d615..0000000
--- a/app/routes/Events.php
+++ /dev/null
@@ -1,186 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-use Config;
-use Resource;
-use Room;
-use Seminar;
-use Issue;
-
-
-/**
- * @author André Klaßen <andre.klassen@elan-ev.de>
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition course_id ^[a-f0-9]{1,32}$
- * @condition user_id ^[a-f0-9]{1,32}$
- * @condition semester_id ^[a-f0-9]{1,32}$
- */
-class Events extends \RESTAPI\RouteMap
-{
-
- /**
- * returns all upcoming events within the next two weeks for a given user
- *
- * @get /user/:user_id/events
- */
- public function getEvents($user_id)
- {
- if ($user_id !== $GLOBALS['user']->id) {
- $this->error(401);
- }
-
- $start = new \DateTime();
- $end = clone $start;
- $end = $end->add(new \DateInterval('P2W'));
-
- $list = array_merge(
- \CalendarCourseDate::getEvents($start, $end, $user_id),
- \CalendarCourseExDate::getEvents($start, $end, $user_id)
- );
-
- $json = [];
- $events = array_slice($list, $this->offset, $this->limit); ;
- foreach ($events as $event) {
-
- $course_uri = $this->urlf('/course/%s', [htmlReady($event->range_id)]);
-
- $json[] = [
- 'event_id' => $event->id,
- 'course' => $course_uri,
- 'start' => $event->date,
- 'end' => $event->end_time,
- 'title' => $event->getTitle(),
- 'description' => $event->getDescription() ?: '',
- 'categories' => $event->getTypeName(),
- 'room' => $event->getRoomName(),
- 'canceled' => $event instanceof \CourseExDate || holiday($event->date),
- ];
- }
-
- $this->etag(md5(serialize($json)));
-
- return $this->paginated($json, count($list), compact('user_id'));
- }
-
- /**
- * returns an iCAL Export of all events for a given user
- *
- * @get /user/:user_id/events.ics
- */
- public function getEventsICAL($user_id)
- {
- if ($user_id !== $GLOBALS['user']->id) {
- $this->error(401);
- }
- $end = new \DateTime();
- $end->setTimestamp(\CalendarDate::NEVER_ENDING);
- $start = new \DateTime();
- $start->modify('-4 week');
- $ical_export = new \ICalendarExport();
- $ical = $ical_export->exportCalendarDates($user_id, $start, $end)
- . $ical_export->exportCourseDates($user_id, $start, $end)
- . $ical_export->exportCourseExDates($user_id, $start, $end);
- $content = $ical_export->writeHeader() . $ical . $ical_export->writeFooter();
-
- $this->contentType('text/calendar');
- $this->headers([
- 'Content-Length' => strlen($content),
- 'Content-Disposition' => 'attachment; ' . encode_header_parameter('filename', 'studip.ics'),
- ]);
- $this->halt(200, $this->response->headers, function () use ($content) {
- echo $content;
- });
- }
-
-
- /**
- * returns events for a given course
- *
- * @get /course/:course_id/events
- */
- public function getEventsForCourse($course_id)
- {
- if (!$GLOBALS['perm']->have_studip_perm('user', $course_id, $GLOBALS['user']->id)) {
- $this->error(401);
- }
-
- $seminar = new Seminar($course_id);
- $dates = getAllSortedSingleDates($seminar);
- $total = sizeof($dates);
-
- $events = [];
- foreach (array_slice($dates, $this->offset, $this->limit) as $date) {
-
- // get issue titles
- $issue_titles = [];
- if (is_array($issues = $date->getIssueIDs())) {
- foreach ($issues as $is) {
- $issue = new Issue(['issue_id' => $is]);
- $issue_titles[] = $issue->getTitle();
- }
- }
-
- $room = self::getRoomForSingleDate($date);
- $events[] = [
- 'event_id' => $date->getSingleDateID(),
- 'start' => $date->getStartTime(),
- 'end' => $date->getEndTime(),
- 'title' => $date->toString(),
- 'description' => implode(', ', $issue_titles),
- 'categories' => $date->getTypeName() ?: '',
- 'room' => $room ?: '',
- 'deleted' => $date->isExTermin(),
- 'canceled' => $date->isHoliday() ?: false,
- ];
- }
-
- $this->etag(md5(serialize($events)));
-
- return $this->paginated($events, $total, compact('course_id'));
- }
-
- private static function getRoomForSingleDate($val) {
-
- /* css-Klasse auswählen, sowie Template-Feld für den Raum mit Text füllen */
- if (Config::get()->RESOURCES_ENABLE) {
-
- if ($val->getResourceID()) {
- $resObj = Resource::find($val->getResourceID());
- if ($resObj) {
- $room_object = $resObj->getDerivedClassInstance();
- if ($room_object instanceof Room) {
- $room = _("Raum: ");
- $room .= $room_object->getActionURL('booking_plan');
- }
- }
- } else {
- $room = _("keine Raumangabe");
-
- if ($val->isExTermin()) {
- if ($name = $val->isHoliday()) {
- $room = '('.$name.')';
- } else {
- $room = '('._('fällt aus').')';
- }
- }
-
- else {
- if ($val->getFreeRoomText()) {
- $room = '('.htmlReady($val->getFreeRoomText()).')';
- }
- }
- }
- } else {
- $room = '';
- if ($val->getFreeRoomText()) {
- $room = '('.htmlReady($val->getFreeRoomText()).')';
- }
- }
-
- return html_entity_decode(strip_tags($room));
- }
-
-}
diff --git a/app/routes/Feedback.php b/app/routes/Feedback.php
deleted file mode 100644
index 9a28347..0000000
--- a/app/routes/Feedback.php
+++ /dev/null
@@ -1,271 +0,0 @@
-<?php
-
-namespace RESTAPI\Routes;
-
-/**
- * @author Nils Gehrke <nils.gehrke@uni-goettingen.de>
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition feedback_id ^\d*$
- * @condition course_id ^[a-f0-9]{32}$
- *
- */
-class Feedback extends \RESTAPI\RouteMap
-{
- /**
- * Create feedback element for a range
- *
- * @post /feedback/range/:range_id/:range_type
- *
- */
- public function createFeedbackElement($range_id, $range_type)
- {
- $course_id = $range_type::find($range_id)->getRangeCourseId();
- if (!\Feedback::hasRangeAccess($range_id, $range_type) || !\Feedback::hasCreatePerm($course_id)) {
- $this->error(403);
- }
- $feedback = \FeedbackElement::build([
- 'range_id' => $range_id,
- 'range_type' => $range_type,
- 'user_id' => $GLOBALS['user']->id,
- 'course_id' => $course_id,
- 'question' => $this->data['question'],
- 'description' => $this->data['description'],
- 'results_visible' => intval($this->data['results_visible']),
- 'commentable' => intval($this->data['commentable']),
- 'mode' => $this->data['mode']
- ]);
- $feedback->store();
- return $feedback->toArray();
- }
-
- /**
- * Get a feedback element
- *
- * @get /feedback/:feedback_id
- *
- */
- public function getFeedbackElement($feedback_id)
- {
- if (!$feedback = \FeedbackElement::find($feedback_id)) {
- $this->error(404);
- }
- if (!\Feedback::hasRangeAccess($feedback->range_id, $feedback->range_type)) {
- $this->error(403);
- }
- return $feedback->toArray();
- }
-
-
- /**
- * Get all entries of a feedback element
- *
- * @get /feedback/:feedback_id/entries
- *
- */
- public function getFeedbackEntries($feedback_id)
- {
- if (!$feedback = \FeedbackElement::find($feedback_id)) {
- $this->error(404);
- }
- if (!\Feedback::hasRangeAccess($feedback->range_id, $feedback->range_type)) {
- $this->error(403);
- }
- if ($feedback->results_visible == 1 && !$feedback->isFeedbackable()) {
- foreach($feedback->entries as $entry) {
- $result['entries'][] = $entry->toArray();
- }
- } elseif (!$feedback->isFeedbackable()) {
- $result['entries'][] = $feedback->getOwnEntry()->toArray();
- } else {
- $result = [];
- }
-
- return $result;
- }
-
- /**
- * Edit a feedback element
- *
- * @put /feedback/:feedback_id
- *
- */
- public function editFeedbackElement($feedback_id)
- {
- if (!$feedback = \FeedbackElement::find($feedback_id)) {
- $this->error(404);
- }
- $course_id = $feedback->course_id;
- if (!\Feedback::hasRangeAccess($feedback->range_id, $feedback->range_type) || !\Feedback::hasAdminPerm($course_id)) {
- $this->error(403);
- }
- $feedback->question = $this->data['question'] !== null ? $this->data['question'] : $feedback->question;
- $feedback->description = $this->data['description'] !== null ? $this->data['description'] : $feedback->description;
- $feedback->results_visible = $this->data['results_visible'] !== null ?
- intval($this->data['results_visible']) : $feedback->results_visible;
- $feedback->store();
- return $feedback->toArray();
- }
-
- /**
- * Delete a feedback element
- *
- * @delete /feedback/:feedback_id
- *
- */
- public function deleteFeedbackElement($feedback_id)
- {
- if (!$feedback = \FeedbackElement::find($feedback_id)) {
- $this->error(404);
- }
- $course_id = $feedback->course_id;
- if (!\Feedback::hasRangeAccess($feedback->range_id, $feedback->range_type) || !\Feedback::hasAdminPerm($course_id)) {
- $this->error(403);
- }
- $feedback->delete();
- $this->halt(200);
- }
-
- /**
- * List all feedback elements for a range
- *
- * @get /feedback/range/:range_id/:range_type
- *
- * @param string $range_id
- * @param string $range_type
- */
- public function getFeedbackElementsForRange($range_id, $range_type)
- {
- if (!\Feedback::hasRangeAccess($range_id, $range_type)) {
- $this->error(403, 'You may not access the given range object.');
- }
- $feedback_elements = \FeedbackElement::findBySQL('range_id = ? AND range_type = ? ORDER BY mkdate DESC', [$range_id, $range_type]);
- foreach($feedback_elements as $feedback) {
- $result['feedback_elements'][] = $feedback->toArray();
- }
- return $result;
- }
-
- /**
- * List all feedback elements of a course
- *
- * @get /course/:course_id/feedback
- *
- */
- public function getFeedbackElementsForCourse($course_id)
- {
- if (!\Feedback::hasAdminPerm($course_id)) {
- $this->error(403, 'You may not list all feedback elements of the course. Only feedback admins can.');
- }
- $feedback_elements = \FeedbackElement::findBySQL('course_id = ? ORDER BY mkdate DESC', [$course_id]);
- foreach($feedback_elements as $feedback) {
- $result['feedback_elements'][] = $feedback->toArray();
- }
- return $result;
- }
-
- /**
- * add an entry for a feedback element
- *
- * @post /feedback/:feedback_id/entry
- *
- */
- public function addFeedbackEntry($feedback_id)
- {
- if (!$feedback = \FeedbackElement::find($feedback_id)) {
- $this->error(404);
- }
- if (!$feedback->isFeedbackable()) {
- $this->error(403, 'You may not add an entry here. Maybe you have already given feedback or you are the author of the feedback element.');
- }
- $entry = \FeedbackEntry::build([
- 'feedback_id' => $feedback->id,
- 'user_id' => $GLOBALS['user']->id
- ]);
-
- $entry->rating = $this->getRating(
- $feedback->mode,
- (int) $this->data['rating']
- );
-
- if ($feedback->commentable) {
- $entry->comment = $this->data['comment'];
- }
-
- $entry->store();
- return $entry->toArray();
- }
-
- /**
- * edit an entry of a feedback element
- *
- * @put /feedback/entry/:entry_id
- *
- */
- public function editFeedbackEntry($entry_id)
- {
- $entry = \FeedbackEntry::find($entry_id);
-
- if (!$entry) {
- $this->notFound();
- }
-
- if (!$entry->isEditable()) {
- $this->error(403);
- }
-
- $entry->rating = $this->getRating(
- $entry->feedback->mode,
- (int) $this->data['rating']
- );
-
- if ($entry->feedback->commentable) {
- $entry->comment = $this->data['comment'] ?? $entry->comment;
- }
-
- $entry->store();
- return $entry->toArray();
- }
-
- /**
- * delete an entry of a feedback element
- *
- * @delete /feedback/entry/:entry_id
- *
- */
- public function deleteFeedbackEntry($entry_id)
- {
- if (!$entry = \FeedbackEntry::find($entry_id)) {
- $this->error(404);
- }
- if ($entry->delete()){
- $this->halt(200);
- }
- }
-
- /**
- * @param int $mode
- * @param int $rating
- * @return int
- */
- private function getRating(int $mode, int $rating): int
- {
- if ($mode === 0) {
- return 0;
- }
-
- if ($rating === 0) {
- return 1;
- }
-
- if ($mode === 1) {
- return min(5, $rating);
- }
-
- if ($mode === 2) {
- return min(10, $rating);
- }
-
- throw new \InvalidArgumentException("Invalid mode {$mode}");
- }
-}
diff --git a/app/routes/FileSystem.php b/app/routes/FileSystem.php
deleted file mode 100644
index 9abd713..0000000
--- a/app/routes/FileSystem.php
+++ /dev/null
@@ -1,684 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * This class implements REST routes for the new Stud.IP file system.
- *
- * @author Moritz Strohm <strohm@data-quest.de>
- * @license GNU General Public License Version 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * Partially based upon the Files.php source code from Jan-Hendrik Willms
- * (tleilax+studip@gmail.com) and mluzena@uos.de which is also
- * licensed under the terms of the GNU General Public License Version 2
- * or later.
- */
-
-class FileSystem extends \RESTAPI\RouteMap
-{
- // FILE REFERENCE AND FILE ROUTES:
-
- /**
- * Get a file reference object (metadata)
- * @get /file/:file_ref_id
- */
- public function getFileRef($file_ref_id)
- {
- return $this->filerefToJSON(
- $this->requireFileRef($file_ref_id),
- (bool) \Request::int('extended')
- );
- }
-
- /**
- * Get the data of a file by the ID of an associated FileRef object
- *
- * @get /file/:file_ref_id/download
- */
- public function getFileRefData($file_ref_id)
- {
- $file_ref = $this->requireFileRef($file_ref_id);
-
- // check if the current user has the permissions to read this file reference:
- $user = \User::findCurrent();
- if (!$file_ref->folder->getTypedFolder()->isFileDownloadable($file_ref_id, $user->id)) {
- $this->error(403, "You may not download the file reference with the id {$file_ref_id}");
- }
-
- // check if file exists:
- if (!$file_ref->file) {
- $this->error(500, 'File reference has no associated file object!');
- }
-
- $data_path = $file_ref->file->getPath();
- if (!file_exists($data_path)) {
- $this->error(500, "File was not found in the operating system's file system!");
- }
-
- $this->lastModified($file_ref->file->chdate);
- $this->sendFile($data_path, ['filename' => $file_ref->name]);
- }
-
- /**
- * Update file data using a FileReference to it.
- *
- * @post /file/:file_ref_id/update
- */
- public function updateFileData($file_ref_id)
- {
- // We only update the first file:
- $uploaded_file = array_shift($this->data['_FILES']);
-
- // FileManager::updateFileRef handles the whole file upload
- // and does all the necessary security checks:
- $result = \FileManager::updateFileRef(
- $this->requireFileRef($file_ref_id),
- \User::findCurrent(),
- $uploaded_file,
- true,
- false
- );
-
- if (!$result instanceof \FileRef) {
- $this->error(500, 'Error while updating a file reference: ' . implode(' ', $result));
- }
-
- return $this->filerefToJSON($result);
- }
-
- /**
- * Edit a file reference.
- *
- * @put /file/:file_ref_id
- */
- public function editFileRef($file_ref_id)
- {
- $result = \FileManager::editFileRef(
- $this->requireFileRef($file_ref_id),
- \User::findCurrent(),
- $this->data['name'],
- $this->data['description'],
- $this->data['content_term_of_use_id'],
- $this->data['license']
- );
-
- if (!$result instanceof \FileRef) {
- $this->error(500, 'Error while editing a file reference: ' . implode(' ', $result));
- }
-
- return $this->filerefToJSON($result);
- }
-
- /**
- * Copies a file reference.
- *
- * @post /file/:file_ref_id/copy/:destination_folder_id
- */
- public function copyFileRef($file_ref_id, $destination_folder_id)
- {
- $result = \FileManager::copyFile(
- $this->requireFileRef($file_ref_id)->getFileType(),
- $this->requireFolder($destination_folder_id)->getTypedFolder(),
- \User::findCurrent()
- );
-
- if (!($result instanceof \FileType)) {
- $this->error(500, 'Error while copying a file reference: ' . implode(' ', $result));
- }
-
- return $this->filerefToJSON($result->getFileRef());
- }
-
- /**
- * Moves a file reference.
- *
- * @post /file/:file_ref_id/move/:destination_folder_id
- */
- public function moveFileRef($file_ref_id, $destination_folder_id)
- {
- $result = \FileManager::moveFile(
- $this->requireFileRef($file_ref_id)->getFileType(),
- $this->requireFolder($destination_folder_id)->getTypedFolder(),
- \User::findCurrent()
- );
-
- if (!($result instanceof \FileType)) {
- $this->error(500, 'Error while moving a file reference: ' . implode(' ', $result));
- }
-
- return $this->filerefToJSON($result->getFileRef());
- }
-
- /**
- * Deletes a file reference.
- *
- * @delete /file/:file_ref_id
- */
- public function deleteFileRef($file_ref_id)
- {
- $result = \FileManager::deleteFileRef(
- $this->requireFileRef($file_ref_id),
- \User::findCurrent()
- );
-
- if (!$result instanceof \FileRef) {
- $this->error(500, 'Error while deleting a file reference: ' . implode(' ', $result));
- }
-
- $this->halt(200);
- }
-
- /**
- * Upload file to given folder.
- * file data has to be attached as multipart/form-data
- *
- * @post /file/:folder_id
- */
- public function uploadFile($folder_id)
- {
- $typed_folder = $this->requireFolder($folder_id)->getTypedFolder();
- if (isset($this->data['_FILES'])) {
- $file_data = array_map(function ($a) {
- return is_array($a) ? $a : [$a];
- }, array_shift($this->data['_FILES']));
- }
- if (is_array($file_data)) {
- $validated_files = \FileManager::handleFileUpload(
- $file_data,
- $typed_folder,
- $this->requireUser()->id
- );
-
- if (count($validated_files['error']) > 0) {
- $this->error(500, 'Error while uploading files: ' . implode(' ', $validated_files['error']));
- }
-
- $uploaded_files = \SimpleCollection::createFromArray($validated_files['files']);
- $default_license = \ContentTermsOfUse::findDefault();
- $uploaded_files->setValue('content_terms_of_use_id', $default_license->id);
- $uploaded_files->store();
- if (count($uploaded_files) === 1) {
- $result = $this->filerefToJSON($uploaded_files->first());
- } else {
- $result = $uploaded_files->map(function ($f) {
- return $this->filerefToJSON($f);
- });
- }
- $this->halt(201, [], $result);
- } else {
- $this->error(400, 'No files found in request.');
- }
- }
-
- // FOLDER ROUTES:
-
- /**
- * Returns a list of defined folder types, separated by range type.
- * @get /studip/file_system/folder_types
- */
- public function getDefinedFolderTypes()
- {
- return \FileManager::getFolderTypes();
- }
-
- /**
- * Get a folder object with its file references, subdirectories and the permissions for the user who has made the API call.
- * @get /folder/:folder_id
- */
- public function getFolder($folder_id)
- {
- return $this->folderToJSON(
- $this->requireFolder($folder_id),
- true
- );
- }
-
- /**
- * Creates a new folder inside of another folder and returns the new object on success.
- * @post /folder/:parent_folder_id/new_folder
- */
- public function createNewFolder($parent_folder_id)
- {
- $user = \User::findCurrent();
- $parent = $this->requireTypedFolder($parent_folder_id);
-
- if (!$parent->isWritable($user->id)) {
- $this->error(403, 'You are not permitted to create a subfolder in the parent folder!');
- }
-
- $result = \FileManager::createSubFolder(
- $parent,
- $user,
- 'StandardFolder', //to be extended
- $this->data['name'],
- $this->data['description']
- );
-
- if (!$result instanceof \FolderType) {
- $this->error(500, 'Error while creating a folder: ' . implode(' ', $result));
- }
-
- return $this->folderToJSON(
- $this->requireFolder($result->getId())
- );
- }
-
- /**
- * Get a list with all FileRef objects of a folder.
- * @get /folder/:folder_id/files
- */
- public function getFileRefsOfFolder($folder_id)
- {
- $folder = $this->requireFolder($folder_id);
-
- $query = "folder_id = :folder_id ORDER BY name ASC";
- $parameters[':folder_id'] = $folder->id;
-
- if ($this->limit || $this->offset) {
- $query .= " LIMIT :limit OFFSET :offset";
- $parameters[':limit'] = $this->limit;
- $parameters[':offset'] = $this->offset;
- }
-
- $file_refs = \FileRef::findAndMapBySql(function (\FileRef $ref) {
- return $this->filerefToJSON($ref);
- }, $query, $parameters);
-
- return $this->paginated(
- $file_refs,
- \FileRef::countByFolder_id($folder->id),
- ['folder_id' => $folder->id]
- );
- }
-
-
- /**
- * Get a list with all FileRef objects of a folder.
- * @get /folder/:folder_id/subfolders
- */
- public function getSubfoldersOfFolder($folder_id)
- {
- $user = $this->requireUser();
- $folder = $this->requireFolder($folder_id);
-
- $query = "parent_id = :parent_id ORDER BY name ASC";
- $parameters = [':parent_id' => $folder->id];
-
- if ($this->limit || $this->offset) {
- $query .= " LIMIT :limit OFFSET :offset";
- $parameters[':limit'] = $this->limit;
- $parameters[':offset'] = $this->offset;
- }
-
- $subfolders = \Folder::findAndMapBySql(function (\Folder $subfolder) use ($user) {
- $type = $subfolder->getTypedFolder();
- if (!$type || !$type->isVisible($user->id)) {
- return false;
- }
- return $this->folderToJSON($subfolder);
- }, $query, $parameters);
-
- return $this->paginated(
- array_filter($subfolders),
- \Folder::countByParent_id($folder_id),
- ['folder_id' => $folder_id]
- );
- }
-
- /**
- * Get a list with permissions the current user has for a folder.
- * @get /folder/:folder_id/permissions
- */
- public function getFolderPermissions($folder_id)
- {
- $user = $this->requireUser();
- $folder = $this->requireFolder($folder_id);
-
- // read permissions of the user and return them:
- return array_merge([
- 'folder_id' => $folder->id,
- 'user_id' => $user->id,
- ], $this->folderPermissionsToJSON($folder));
- }
-
- /**
- * Allows editing the name or the description (or both) of a folder.
- *
- * @put /folder/:folder_id
- */
- public function editFolder($folder_id)
- {
- if (isset($this->data['name']) && !$this->data['name']) {
- $this->error(400, "The name for the folder with the id {$folder_id} must not be empty!");
- }
-
- $user = $this->requireUser();
- $typed_folder = $this->requireTypedFolder($folder_id);
-
- if (!$typed_folder->isEditable($user->id)) {
- $this->error(403, "You may not edit the folder with id {$folder_id}!");
- }
-
- if (!$typed_folder instanceof \StandardFolder) {
- $this->error(501, "Editing is only allowed for folders of type StandardFolder for now!");
- }
-
- if ($this->data['name']) {
- $typed_folder->name = $this->data['name'];
- }
- if (isset($this->data['description'])) {
- $typed_folder->description = $this->data['description'] ?: '';
- }
-
- if (!$typed_folder->store()) {
- $this->error(500, "Could not store folder with id {$folder_id}!");
- }
-
- return $this->folderToJSON(
- $this->requireFolder($folder_id)
- );
- }
-
- /**
- * Copies a folder into another folder.
- *
- * @post /folder/:folder_id/copy/:destination_folder_id
- */
- public function copyFolder($folder_id, $destination_folder_id)
- {
- $result = \FileManager::copyFolder(
- $this->requireTypedFolder($folder_id),
- $this->requireTypedFolder($destination_folder_id),
- \User::findCurrent()
- );
-
- if (!$result instanceof \FolderType) {
- $this->error(500, 'Error while copying a folder: ' . implode(' ', $result));
- }
-
- return $this->folderToJSON(
- $this->requireFolder($result->getId())
- );
- }
-
-
- /**
- * Move a folder into another folder.
- * @post /folder/:folder_id/move/:destination_folder_id
- */
- public function moveFolder($folder_id, $destination_folder_id)
- {
- $result = \FileManager::moveFolder(
- $this->requireTypedFolder($folder_id),
- $this->requireTypedFolder($destination_folder_id),
- \User::findCurrent()
- );
-
- if (!$result instanceof \FolderType) {
- $this->error(500, 'Error while moving a folder: ' . implode(' ', $result));
- }
-
- return $this->folderToJSON(
- $this->requireFolder($folder_id)
- );
- }
-
-
- /**
- * Deletes a folder.
- *
- * @delete /folder/:folder_id
- */
- public function deleteFolder($folder_id)
- {
- $result = \FileManager::deleteFolder(
- $this->requireTypedFolder($folder_id),
- \User::findCurrent()
- );
-
- if (!$result instanceof \FolderType) {
- $this->error(500, 'Error while deleting a folder: ' . implode(' ', $result));
- }
-
- $this->halt(200);
- }
-
- // RELATED OBJECT ROUTES:
-
- /**
- * Get a collection of all ContentTermsOfUse objects
- *
- * @get /studip/content_terms_of_use_list
- */
- public function getContentTermsOfUseList()
- {
- $objects = \ContentTermsOfUse::findBySql(
- '1 ORDER BY name ASC LIMIT :limit OFFSET :offset',
- ['limit' => $this->limit, 'offset' => $this->offset]
- );
-
- return $this->paginated(
- array_map([$this, 'termsOfUseToJSON'], $objects),
- \ContentTermsOfUse::countBySql('1')
- );
- }
-
- // UTILITY METHODS
-
- /**
- * Requires a valid user object.
- * @return \User object
- */
- private function requireUser()
- {
- return \User::findCurrent();
- }
-
- /**
- * Requires a valid file reference object
- * @param mixed $id_or_object Either a file reference id or object
- * @return \FileRef object
- */
- private function requireFileRef($id_or_object)
- {
- if ($id_or_object instanceof \FileRef) {
- $file_ref = $id_or_object;
- } else {
- //check if the file_id references a file reference object:
- $file_ref = \FileRef::find($id_or_object);
- if (!$file_ref) {
- $this->notFound("File reference with id {$id_or_object} not found!");
- }
- }
-
- // check if the file reference is placed inside a folder.
- // (must be present to check for permissions)
- if (!$file_ref->folder) {
- $this->error(500, "File reference with id {$file_ref->id} has no folder!");
- }
-
- $typed_folder = $file_ref->folder->getTypedFolder();
- if (!$typed_folder) {
- $this->error(500, "The folder of file reference with id {$file_ref->id} has no folder type!");
- }
-
- //check if the current user has the permissions to read this file reference:
- if (!$typed_folder->isReadable($this->requireUser()->id)) {
- $this->error(403, "You are not permitted to read the file reference with id {$file_ref->id}!");
- }
-
- return $file_ref;
- }
-
- /**
- * Converts a file reference object to JSON.
- * @param \FileRef $ref File reference object
- * @param boolean $extended Extended output? (includes folder, owner and terms of use)
- * @return array representation for json encoding
- */
- private function filerefToJSON(\FileRef $ref, $extended = false)
- {
- $user = $this->requireUser();
- $typed_folder = $ref->folder->getTypedFolder();
- $filetype = $ref->getFileType();
-
- $result = array_merge($ref->toRawArray(), [
- 'size' => (int) $ref->file->size,
- 'mime_type' => $ref->file->mime_type,
- 'storage' => $ref->file->filetype === "URLFile" ? "url" : "disk",
-
- 'is_readable' => $typed_folder->isReadable($user->id),
- 'is_downloadable' => $filetype->isDownloadable($user->id),
- 'is_editable' => $filetype->isEditable($user->id),
- 'is_writable' => $filetype->isWritable($user->id),
- ]);
-
- $result['downloads'] = (int) $result['downloads'];
- $result['mkdate'] = (int) $result['mkdate'];
- $result['chdate'] = (int) $result['chdate'];
-
- if ($result['storage'] === 'url') {
- $result['url'] = $ref->getFileType()->getDownloadURL();
- }
-
- if ($extended) {
- //folder does exist (since we checked for its existence above)
- $result['folder'] = $this->folderToJSON($ref->folder);
-
- if ($ref->owner) {
- $result['owner'] = User::getMiniUser($this, $ref->owner);
- }
-
- //$result['license'] = $file_ref->license; //to be activated when licenses are defined
-
- if ($ref->terms_of_use) {
- $result['terms_of_use'] = $this->termsOfUseToJSON($ref->terms_of_use);
- }
- }
-
- return $result;
- }
-
- /**
- * Requires a valid folder object
- * @param mixed $id_or_object Either a folder id or object
- * @return Folder object
- */
- private function requireFolder($id_or_object)
- {
- if ($id_or_object instanceof \Folder) {
- $folder = $id_or_object;
- } else {
- $folder = \Folder::find($id_or_object);
- if (!$folder) {
- $this->notFound("Folder with id {$id_or_object} not found!");
- }
- }
-
- $typed_folder = $folder->getTypedFolder();
- if (!$typed_folder) {
- $this->error(500, "Cannot find folder type of folder with id {$folder->id}!");
- return;
- }
-
- if (!$typed_folder->isReadable($this->requireUser()->id)) {
- $this->error(403, "You are not allowed to read the contents of the folder with the id {$folder->id}!");
- }
-
- return $folder;
- }
-
- /**
- * Requires a valid typed folder object
- * @param mixed $id_or_object Either a folder id or object
- * @return FolderType instance
- */
- private function requireTypedFolder($id_or_object)
- {
- return $this->requireFolder($id_or_object)->getTypedFolder();
- }
-
- /**
- * Converts a given folder to JSON.
- * @param Folder $folder Folder object
- * @param boolean $extended Extended output? (includes subfolders and file references)
- * @return array representation for json encoding
- */
- private function folderToJSON(\Folder $folder, $extended = false)
- {
- $result = $this->folderPermissionsToJSON($folder);
-
- if ($result['is_readable']) {
- $result = array_merge($folder->toRawArray(), $result);
-
- $result['mkdate'] = (int) $result['mkdate'];
- $result['chdate'] = (int) $result['chdate'];
-
- //The field "data_content" must be handled differently
- //than the other fields since it contains JSON data.
- $data_content = json_decode($folder->data_content);
- $result['data_content'] = $data_content;
-
- if ($extended) {
- $user = $this->requireUser();
-
- $result['subfolders'] = [];
- foreach ($folder->subfolders as $subfolder) {
- if (!$subfolder->getTypedFolder()->isVisible($user->id)) {
- continue;
- }
- $result['subfolders'][] = $this->folderToJSON($subfolder);
- }
-
- $result['file_refs'] = [];
- foreach ($folder->getTypedFolder()->getFiles() as $file) {
- if (method_exists($file,"getFileRef")) {
- $result['file_refs'][] = $this->filerefToJSON(
- $file->getFileRef()
- );
- }
- }
- }
- }
-
- return $result;
- }
-
- /**
- * Converts permissions of a folder to JSON.
- * @param Folder $folder Folder object
- * @param User $user User object to check permissions against
- * @return array representation for json encoding
- */
- private function folderPermissionsToJSON(\Folder $folder)
- {
- $user = $this->requireUser();
- $type = $folder = $folder->getTypedFolder();
- if (!$type) {
- $this->error(500, 'Folder type not found!');
- }
-
- return [
- 'is_visible' => $type->isVisible($user->id),
- 'is_readable' => $type->isReadable($user->id),
- 'is_writable' => $type->isWritable($user->id),
- ];
- }
-
- /**
- * Converts a terms of use object to JSON.
- * @param ContentTermsOfUse $object Object
- * @return array representation for json encoding
- */
- private function termsOfUseToJSON(\ContentTermsOfUse $object)
- {
- $result = $object->toRawArray();
-
- $result['is_default'] = (bool) $result['is_default'];
-
- $result['mkdate'] = (int) $result['mkdate'];
- $result['chdate'] = (int) $result['chdate'];
-
- return $result;
- }
-}
diff --git a/app/routes/Forum.php b/app/routes/Forum.php
deleted file mode 100644
index 35aad91..0000000
--- a/app/routes/Forum.php
+++ /dev/null
@@ -1,419 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition course_id ^[a-f0-9]{1,32}$
- */
-class Forum extends \RESTAPI\RouteMap
-{
- /**
- * List all categories of a forum
- *
- * @get /course/:course_id/forum_categories
- */
- public function getForumCategories($course_id)
- {
- if (!\ForumPerm::has('view', $course_id)) {
- $this->error(401);
- }
-
- $categories = \ForumCat::findBySeminar_id($course_id, 'ORDER BY pos ASC');
- $total = sizeof($categories);
- $categories = array_splice($categories, (int)$this->offset, (int)$this->limit ?: 10);
-
- $json = [];
- foreach ($categories as $cat) {
- $json_cat = $cat->toArray();
- $uri = $this->urlf('/forum_category/%s', [htmlReady($json_cat['category_id'])]);
- $json_cat['course_id'] = $json_cat['seminar_id'];
- $json[$uri] = $this->categoryToJson($json_cat);
- }
-
- $this->etag(md5(serialize($json)));
-
- return $this->paginated($json, $total, compact('course_id'));
- }
-
- /**
- * Create a new category
- *
- * @post /course/:course_id/forum_categories
- */
- public function createForumCategory($course_id)
- {
- if (!\ForumPerm::has("add_category", $course_id)) {
- $this->error(401);
- }
-
- if (!isset($this->data['name']) || !mb_strlen($name = trim($this->data['name']))) {
- $this->error(400, 'Category name required.');
- }
-
- $category_id = \ForumCat::add($course_id, $name);
- if (!$category_id) {
- $this->error(500, 'Error creating the forum category.');
- }
-
- $this->redirect('forum_category/' . $category_id, 201, 'ok');
- }
-
- /**
- * Read a category
- *
- * @get /forum_category/:category_id
- */
- public function getForumCategory($category_id)
- {
- $category = $this->findCategory($category_id);
- $cid = $category['course_id'];
-
- if (!\ForumPerm::has('view', $cid)) {
- $this->error(401);
- }
-
- $category_json = $this->categoryToJson($category);
- $this->etag(md5(serialize($category_json)));
- return $category_json;
- }
-
- /**
- * Update a category
- *
- * @put /forum_category/:category_id
- */
- public function updateForumCategory($category_id)
- {
- $category = $this->findCategory($category_id);
-
- if (!\ForumPerm::has("edit_category", $category['course_id'])) {
- $this->error(401);
- }
-
- if (!isset($this->data['name']) || !mb_strlen($name = trim($this->data['name']))) {
- $this->error(400, 'Category name required.');
- }
-
- \ForumCat::setName($category_id, $this->data['name']);
-
- $this->status(204);
- }
-
- /**
- * Delete a category
- *
- * @delete /forum_category/:category_id
- */
- public function deleteForumCategory($category_id)
- {
- $category = $this->findCategory($category_id);
- $cid = $category['course_id'];
-
- if (!\ForumPerm::has("remove_category", $cid)) {
- $this->error(401);
- }
-
- \ForumCat::remove($category_id, $cid);
-
- $this->status(204);
- }
-
- /**
- * Show entries of a category
- *
- * @get /forum_category/:category_id/areas
- */
- public function getCategoryEntries($category_id)
- {
- $category = $this->findCategory($category_id);
-
- if (!\ForumPerm::has('view', $category['course_id'])) {
- $this->error(401);
- }
-
- $areas = $this->getAreas($category_id, $this->offset, $this->limit);
-
- $this->etag(md5(serialize($areas)));
- return $this->paginated($areas, $this->countAreas($category_id), compact('category_id'));
- }
-
-
-
- /**
- * Add a new forum entry to an existing one
- *
- * @post /forum_category/:category_id/areas
- */
- public function appendForumEntry($category_id)
- {
- $category = $this->findCategory($category_id);
- $cid = $category['course_id'];
-
- if (!\ForumPerm::has('add_area', $cid)) {
- $this->error(401);
- }
-
- if (!isset($this->data['subject']) || !mb_strlen($subject = trim($this->data['subject']))) {
- $this->error(400, 'Subject required.');
- }
-
- if (!isset($this->data['content'])) {
- $this->error(400, 'Content required.');
- }
- $content = trim($this->data['content']);
-
- $anonymous = isset($this->data['anonymous']) ? intval($this->data['anonymous']) : 0;
-
- $entry_id = $this->createEntry($cid, $cid, $subject, $content, $anonymous);
-
- \ForumCat::addArea($category_id, $entry_id);
-
- $this->redirect('forum_entry/' . $entry_id, 201, "ok");
- }
-
- /**
- * Get a forum entry
- *
- * @get /forum_entry/:entry_id
- */
- public function getForumEntry($entry_id)
- {
- $entry = \ForumEntry::getConstraints($entry_id);
- $cid = $entry['seminar_id'];
-
- if (!\ForumPerm::has('view', $cid)) {
- $this->error(401);
- }
-
- $entry = $this->findEntry($entry_id);
- $this->lastmodified($entry->chdate);
- $this->etag(md5(serialize($entry)));
- return $entry;
- }
-
- /**
- * Add a new forum entry to an existing one
- *
- * @post /forum_entry/:entry_id
- */
- public function addForumEntry($parent_id)
- {
- $parent = \ForumEntry::getConstraints($parent_id);
- $cid = $parent['seminar_id'];
-
- $perm = self::isArea($parent) ? 'add_area' : 'add_entry';
-
- if (!\ForumPerm::has($perm, $cid)) {
- $this->error(401);
- }
-
- $subject = (string) trim($this->data['subject']);
- $content = (string) trim($this->data['content']);
-
- // areas and threads need a subject, postings do not
- if ($parent['depth'] < 3 && !$subject) {
- $this->error(400, 'Subject required.');
- }
-
- // all entries besides the area need content
- if ($parent['depth'] > 1 && !$content) {
- $this->error(400, 'Content required.');
- }
-
- if ($parent['depth'] >= 3 && $subject) {
- $this->error(400, 'Must not have subject here.');
- }
-
- $anonymous = isset($this->data['anonymous']) ? (int) $this->data['anonymous'] : 0;
-
- $entry_id = $this->createEntry($parent_id, $cid, $subject, $content, $anonymous);
-
- $this->redirect('forum_entry/' . $entry_id, 201, "ok");
- }
-
- /**
- * Update an existing one forum entry
- *
- * @put /forum_entry/:entry_id
- */
- public function updateForumEntry($entry_id)
- {
- $entry = \ForumEntry::getConstraints($entry_id);
- $cid = $entry['seminar_id'];
-
- $perm = self::isArea($entry) ? 'edit_area' : 'edit_entry';
-
- if (!\ForumPerm::hasEditPerms($entry_id) || !\ForumPerm::has($perm, $cid)) {
- $this->error(401);
- }
-
- $subject = (string) trim($this->data['subject']);
- $content = (string) trim($this->data['content']);
-
- // areas and threads need a subject, postings do not
- if ($entry['depth'] < 3 && !$subject) {
- $this->error(400, 'Subject required.');
- }
-
- // all entries besides the area need content
- if ($entry['depth'] > 1 && !$content) {
- $this->error(400, 'Content required.');
- }
-
- if ($entry['depth'] >= 3 && $subject) {
- $this->error(400, 'Must not have subject here.');
- }
-
- \ForumEntry::update($entry_id, $subject, $content);
-
- $this->status(204);
- }
-
- /**
- * Delete an entry
- *
- * @delete /forum_entry/:entry_id
- */
- public function deleteForumEntry($entry_id)
- {
- $entry = \ForumEntry::getConstraints($entry_id);
- $cid = $entry['seminar_id'];
-
- if (!\ForumPerm::hasEditPerms($entry_id) || !\ForumPerm::has('remove_entry', $cid)) {
- $this->error(401);
- }
-
- \ForumEntry::delete($entry_id);
-
- $this->status(204);
- }
-
- /*********************
- * *
- * PRIVATE FUNCTIONS *
- * *
- *********************/
-
-
- private function findEntry($entry_id)
- {
- $raw = \ForumEntry::getConstraints($entry_id);
- if ($raw === false) {
- $this->notFound();
- }
-
- $entry = $this->convertEntry($raw);
-
- $children = \ForumEntry::getEntries($entry_id, \ForumEntry::WITHOUT_CHILDS, '', 'ASC', 0, false);
-
- if (isset($children['list'][$entry_id])) {
- unset($children['list'][$entry_id]);
- }
-
- $entry['children'] = [];
- foreach (array_values($children['list']) as $childentry) {
- $entry['children'][] = $this->convertEntry($childentry);
- }
-
- return $entry;
- }
-
- public function convertEntry($raw)
- {
- $entry = [];
- foreach(words("topic_id mkdate chdate anonymous depth") as $key) {
- $entry[$key] = $raw[$key];
- }
-
- $hide_user = $entry['anonymous'] && $raw['user_id'] !== $GLOBALS['user']->id;
-
- $entry['subject'] = $raw['name'];
- $entry['user'] = $hide_user ? null : $this->urlf('/user/%s', [$raw['user_id']]);
- $entry['course'] = $this->urlf('/course/%s', [$raw['seminar_id']]);
- $entry['content_html'] = \ForumEntry::getContentAsHtml($raw['content']);
- $entry['content'] = \ForumEntry::killEdit($raw['content']);
-
- return $entry;
- }
-
-
- private static function isArea($entry)
- {
- return 1 === $entry['depth'];
- }
-
- private function createEntry($parent_id, $course_id, $subject, $content, $anonymous)
- {
- $topic_id = self::generateID();
-
- $data = [
- 'topic_id' => $topic_id,
- 'seminar_id' => $course_id,
- 'user_id' => $GLOBALS['user']->id,
- 'name' => $subject,
- 'content' => $content,
- 'author' => $GLOBALS['user']->getFullName(),
- 'author_host' => $_SERVER['REMOTE_ADDR'],
- 'anonymous' => (int) $anonymous
- ];
- \ForumEntry::insert($data, $parent_id);
-
- return $topic_id;
- }
-
- private function findCategory($category_id)
- {
- $result = [];
-
- if ($cat = \ForumCat::get($category_id)) {
- $result = $cat;
- $result['course_id'] = $cat['seminar_id'];
- $result['name'] = $cat['entry_name'];
- } else {
- $this->error(404);
- }
-
- return $result;
- }
-
- private function categoryToJson($category)
- {
- $json = $category;
-
- $json['course'] = $this->urlf('/course/%s', [htmlReady($json['course_id'])]);
- unset($json['course_id']);
-
- $json['areas'] = $this->urlf('/forum_category/%s/areas', [$json['category_id']]);
- $json['areas_count'] = $this->countAreas($json['category_id']);
-
- return $json;
- }
-
- private function countAreas($category_id)
- {
- return sizeof(\ForumCat::getAreas($category_id));
- }
-
- private function getAreas($category_id, $offset = 0, $limit = 10)
- {
- $offset = (int) $offset;
- $limit = (int) $limit;
-
- $areas = [];
-
- foreach (\ForumCat::getAreas($category_id, $offset, $limit) as $area) {
- $url = $this->urlf('/forum_entry/%s', [htmlReady($area['topic_id'])]);
- $areas[$url] = $this->convertEntry($area);
- }
-
- return $areas;
- }
-
- private static function generateID()
- {
- return md5(uniqid(rand()));
- }
-}
diff --git a/app/routes/Messages.php b/app/routes/Messages.php
deleted file mode 100644
index db9cb2e..0000000
--- a/app/routes/Messages.php
+++ /dev/null
@@ -1,301 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition message_id ^[a-f0-9]{1,32}$
- * @condition user_id ^[a-f0-9]{1,32}$
- * @condition box ^(inbox|outbox)$
- */
-class Messages extends \RESTAPI\RouteMap
-{
- /**
- * Liefert die Anzahl der vorhandenen Nachrichten des autorisierten Nutzers
- * zurück. Der Parameter bestimmt je nach Wert, auf welchen Bereich
- * (Posteingang bzw. Postausgang) zugegriffen werden soll.
- * Die Rückgabe beinhaltet jeweils die Anzahl aller Nachrichten sowie die
- * Anzahl der ungelesenen Nachrichten.
- *
- * @head /user/:user_id/:box
- */
- public function indexOfMessages($user_id, $box)
- {
- if ($user_id !== self::currentUser()) {
- $this->error(401);
- }
-
- $count = $this->countMessages($user_id, $box);
-
- $this->headers([
- 'X-Messages-Total' => $count['total'],
- 'X-Messages-Unread' => $count['unread'],
- ]);
-
- return null;
- }
-
- /**
- * Liefert die vorhandenen Nachrichten des autorisierten Nutzers zurück.
- *
- * @get /user/:user_id/:box
- */
- public function getMessages($user_id, $box)
- {
- if ($user_id !== self::currentUser()) {
- $this->error(401);
- }
-
- $ids = $this->getMessageIds($user_id, $box);
- $total = count($ids);
-
- $ids = array_slice($ids, $this->offset, $this->limit);
-
- $messages = [];
- if (count($ids) > 0) {
- \Message::findEachMany(function ($message) use (&$messages) {
- $url = $this->urlf('/message/%s', $message->id);
- $messages[$url] = $this->messageToJSON($message);
- }, $ids, 'ORDER BY mkdate DESC');
- }
-
- return $this->paginated($messages, $total, compact('user_id', 'box'));
- }
-
- /**
- * Liefert die Daten der angegebenen Nachricht zurück.
- *
- * @get /message/:message_id
- */
- public function showMessage($message_id)
- {
- $message = $this->requireMessage($message_id);
- $message_json = $this->messageToJSON($message);
- $this->etag(md5(serialize($message_json)));
- return $message_json;
- }
-
-
- /**
- * Get the root file folder of a message. The root file folder contains all
- * files that were appended to the message.
- *
- * @get /message/:message_id/file_folder
- */
- public function getTopFolder($message_id)
- {
- //first we check if the user exists:
- $message = \Message::find($message_id);
-
- $user = \User::findCurrent();
-
- if (!$user) {
- $this->halt(404, 'User not found!');
- }
-
- if(!$message->permissionToRead($user->id)) {
- $this->halt(403, 'You are not allowed to read this message or its appended files!');
- }
-
- //we can get the top folder:
- $top_folder = \Folder::findTopFolder($message->id, 'message');
-
- if($top_folder) {
- $file_system_api = new FileSystem();
- return $file_system_api->getFolder($top_folder->id);
- } else {
- $this->halt(404, 'Folder not found!');
- }
- }
-
-
- /**
- * Schreibt eine neue Nachricht.
- *
- * @post /messages
- */
- public function createMessage()
- {
- if (!mb_strlen($subject = trim($this->data['subject'] ?: ''))) {
- $this->error(400, 'No subject provided');
- }
-
- if (!mb_strlen($message = trim($this->data['message'] ?: ''))) {
- $this->error(400, 'No message provided');
- }
-
- $recipients = (array) ($this->data['recipients'] ?: null);
- if (!sizeof($recipients)) {
- $this->error(400, 'No recipient(s) provided');
- }
-
- $usernames = array_map(function ($id) { $user = \User::find($id); return @$user['username']; }, $recipients);
-
- if (sizeof($usernames) !== sizeof(array_filter($usernames))) {
- $this->error(400, "Some recipients do not exist.");
- }
-
- $message = \Message::send($GLOBALS['user']->id, $usernames, $subject, $message);
- if (!$message) {
- $this->error(500, 'Could not create message');
- }
-
- $this->redirect('message/' . $message->id, 201, "ok");
- }
-
-
- /**
- * Eine Nachricht als (un)gelesen markieren.
- *
- * @put /message/:message_id
- */
- public function updateMessage($message_id)
- {
-
- $message = $this->requireMessage($message_id);
- $user_id = $this->currentUser();
-
- if (isset($this->data['unread'])) {
- if ($this->data['unread']) {
- $message->markAsUnread($user_id);
- } else {
- $message->markAsRead($user_id);
- }
- }
-
- $this->halt(204);
- }
-
- /**
- * Löscht eine Nachricht.
- *
- * @delete /message/:message_id
- */
- public function destroyMessage($message_id)
- {
- $message = $this->requireMessage($message_id);
-
- $msgin = new \messaging();
- if (!$msgin->delete_message($message_id, self::currentUser(), true)) {
- $this->error(500);
- }
-
- $this->status(204);
- }
-
- /**************************************************/
- /* PRIVATE HELPER METHODS */
- /**************************************************/
-
- private static function currentUser()
- {
- return $GLOBALS['user']->id;
- }
-
- private function requireMessage($message_id)
- {
- if (!$message = \Message::find($message_id)) {
- $this->notFound("Message not found");
- }
-
- $current_user = self::currentUser();
- $message_user = $message->originator->user_id === $current_user
- ? $message->originator
- : $message->receivers->findOneBy('user_id', $current_user);
-
- if (!$message_user) {
- $this->error(401);
- }
-
- if ($message_user->deleted) {
- $this->notFound("Message not found");
- }
-
- return $message;
- }
-
- private function messageToJSON($message)
- {
- $user_id = self::currentUser();
-
- $my_mu = $message->receivers->filter(function ($mu) use ($user_id) {
- return $mu->user_id === $user_id;
- });
- if ($message->originator->user_id === $user_id) {
- $my_mu[] = $message->originator;
- }
-
- $my_roles = [
- 'snd' => $message->autor_id === $user_id,
- 'rec' => in_array('rec', $my_mu->pluck('snd_rec')),
- ];
-
- $json = $message->toArray(words('message_id subject message mkdate priority'));
-
- // formatted message
- $json['message_html'] = formatReady($json['message']) ?: '';
-
- // Tags
- $json['tags'] = $message->getTags($user_id);
-
- // sender
- $sender = $message->getSender();
- $json['sender'] = $this->urlf('/user/%s', [$message->author->id]);
-
- // recipients
- if ($my_roles['snd']) {
- $json['recipients'] = [];
- foreach ($message->getRecipients() as $r) {
- $json['recipients'][] = $this->urlf('/user/%s', [$r->user_id]);
- }
- } else {
- $json['recipients'] = [$this->urlf('/user/%s', [$user_id])];
- }
-
- // attachments
- if ($message->attachment_folder && count($message->attachment_folder->file_refs) > 0) {
- $json['attachments'] = [];
- foreach ($message->attachment_folder->file_refs as $ref) {
- $json['attachments'][] = $this->urlf('/file/%s', [$ref->id]);
- }
- }
-
- // unread only if in inbox
- if ($my_roles['rec']) {
- foreach ($my_mu as $mu) {
- if ($mu->snd_rec === 'rec') {
- $json['unread'] = !$mu->readed;
- break;
- }
- }
- }
-
- return $json;
- }
-
- private function countMessages($user_id, $box)
- {
- $condition = 'user_id = ? AND snd_rec = ? AND deleted = 0';
- $params = [$user_id, $box === 'inbox' ? 'rec' : 'snd'];
-
- $total = \MessageUser::countBySQL($condition, $params);
- $unread = \MessageUser::countBySQL(
- $condition . ' AND readed = 0',
- $params
- );
-
- return compact('total', 'unread');
- }
-
- private function getMessageIds($user_id, $box)
- {
- return \MessageUser::findAndMapBySQL(function ($row) {
- return $row->message_id;
- }, 'user_id = ? AND snd_rec = ? AND deleted = 0 ORDER BY mkdate DESC', [
- $user_id, $box === 'inbox' ? 'rec' : 'snd'
- ]);
- }
-
-}
diff --git a/app/routes/News.php b/app/routes/News.php
deleted file mode 100644
index c9b258b..0000000
--- a/app/routes/News.php
+++ /dev/null
@@ -1,375 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition news_id ^[0-9a-f]{1,32}$
- * @condition course_id ^[0-9a-f]{1,32}$
- * @condition user_id ^[0-9a-f]{1,32}$
- * @condition comment_id ^[0-9a-f]{1,32}$
- */
-class News extends \RESTAPI\RouteMap
-{
- public static function before()
- {
- require_once 'lib/models/StudipNews.class.php';
- }
-
- /**
- * Globale News auslesen
- *
- * @get /studip/news
- */
- public function getGlobalNews()
- {
- list($json, $total) = $this->getRangedNews('studip');
-
- $this->etag(md5(serialize($json)));
- return $this->paginated($json, $total);
- }
-
- /**
- * News einer Veranstaltung auslesen
- *
- * @get /course/:course_id/news
- */
- public function getCourseNews($course_id)
- {
- list($json, $total) = $this->getRangedNews($course_id);
-
- $this->etag(md5(serialize($json)));
- return $this->paginated($json, $total, compact('course_id'));
- }
-
- /**
- * News eines Nutzers auslesen
- *
- * @get /user/:user_id/news
- */
- public function getUserNews($user_id)
- {
- list($json, $total) = $this->getRangedNews($user_id);
-
- $this->etag(md5(serialize($json)));
- return $this->paginated($json, $total, compact('user_id'));
- }
-
-
- /**
- * News auslesen
- *
- * @get /news/:news_id
- */
- public function getNews($news_id)
- {
- $news = $this->requireNews($news_id);
- $news_json = $this->newsToJson($news);
-
- $this->lastmodified($news->chdate);
- $this->expires($news->expire);
- $this->etag(md5(serialize($news_json)));
-
- return $news_json;
- }
-
- /**
- * News löschen
- *
- * @delete /news/:news_id
- */
- public function destroyNews($news_id)
- {
- $news = $this->requireNews($news_id);
-
- if (!$news->havePermission('delete', '', $GLOBALS['user']->id)) {
- $this->error(401);
- }
-
- $news->delete();
- $this->status(204);
- }
-
-
- /**
- * News updaten
- *
- * @put /news/:news_id
- */
- public function updateNews($news_id)
- {
- $news = $this->requireNews($news_id);
- if (!$news->havePermission('edit', '', $GLOBALS['user']->id)) {
- $this->error(401);
- }
-
- if (isset($this->data['topic'])) {
- if (!mb_strlen(trim($topic = $this->data['topic']))) {
- $this->error(400, 'Topic must not be empty.');
- }
- $news->topic = $topic;
- }
-
- if (isset($this->data['body'])) {
- if (!mb_strlen(trim($body = $this->data['body']))) {
- $this->error(400, 'Body must not be empty.');
- }
- $news->body = $body;
- }
-
- if (isset($this->data['expire'])) {
- $news->expire = (int) $this->data['expire'];
- }
-
- if (isset($this->data['allow_comments'])) {
- $news->allow_comments = (int) $this->data['allow_comments'];
- }
-
- $news->chdate_uid = $GLOBALS['user']->id;
-
- if (!$news->store()) {
- $this->error(500, 'Could not update news');
-
- }
- $this->status(204);
- }
-
- /**
- * News anlegen
- *
- * @post /course/:course_id/news
- * @post /user/:user_id/news
- * @post /studip/news
- */
- public function createNews($range_id = 'studip')
- {
-
- if (!\StudipNews::haveRangePermission('edit', $range_id, $GLOBALS['user']->id)) {
- $this->error(401, "Not authorized to create a news here.");
- }
-
- $news = new \StudipNews();
- $news->setData([
- 'user_id' => $GLOBALS['user']->id,
- 'author' => $GLOBALS['user']->getFullName(),
- 'topic' => trim(@$this->data['topic']),
- 'body' => trim(@$this->data['body']),
- 'date' => time(),
- 'expire' => isset($this->data['expire']) ? intval($this->data['expire']) : 2 * 7 * 24 * 60 * 60,
- 'allow_comments' => isset($this->data['allow_comments']) ? intval($this->data['allow_comments']) : 0
- ]);
- $news->addRange($range_id);
-
- if ($errors = $this->validateNews($news)) {
- $this->error(400, compact('errors'));
- }
-
- if (!$news->store()) {
- $this->error(500);
- }
-
- $news->storeRanges();
-
- $this->redirect('news/' . $news->id, 201, "ok");
- }
-
- /**
- * News-Comments auslesen
- *
- * @get /news/:news_id/comments
- */
- public function getNewsComments($news_id)
- {
- $comments = $this->requireNews($news_id)->comments->orderBy("mkdate asc");
-
- $total = count($comments);
- $json = [];
- foreach ($comments->limit($this->offset, $this->limit) as $comment) {
- $tmp = $comment->toArray("comment_id object_id user_id content mkdate chdate");
- $tmp['content_html'] = htmlReady($comment->content);
- $json[$this->urlf('/comment/%s', [htmlReady($comment->id)])] = $tmp;
- }
-
- $this->etag(md5(serialize($json)));
-
- return $this->paginated($json, $total, compact('news_id'));
- }
-
- /**
- * News-Comment auslesen
- *
- * @get /comment/:comment_id
- */
- public function getComment($comment_id)
- {
- $comment = $this->requireComment($comment_id);
- $comment_json = $this->commentToJson($comment);
-
- $this->lastmodified($comment->chdate);
- $this->etag(md5(serialize($comment_json)));
-
- return $comment_json;
- }
-
- /**
- * News-Comment anlegen
- *
- * @post /news/:news_id/comments
- */
- public function appendComment($news_id)
- {
- $news = $this->requireNews($news_id);
-
- if (!$news->allow_comments) {
- $this->error(409, 'Comments are not allowed');
- }
-
- if (!isset($this->data['content']) || !mb_strlen($content = trim($this->data['content']))) {
- $this->error(400, 'Content required.');
- }
-
- $comment = new \StudipComment();
- $comment->setData(
- [
- 'object_id' => $news_id,
- 'user_id' => $GLOBALS['user']->id,
- 'content' => $content
- ]);
-
- if (!$comment->store()) {
- $this->halt(500, 'Could not create comment.');
- }
-
- $this->redirect('comment/' . $comment->id, 201, "ok");
- }
-
- /**
- * News-Comment löschen
- *
- * @delete /comment/:comment_id
- */
- public function destroyComment($comment_id)
- {
- $comment = $this->requireComment($comment_id);
-
- if (!$comment->delete()) {
- $this->error(500, 'Comment could not be deleted.');
- }
-
- $this->halt(204);
- }
-
-
- /**************************************************/
- /* PRIVATE HELPER METHODS */
- /**************************************************/
-
- private function getRangedNews($range_id)
- {
-
- $news = \StudipNews::getNewsByRange($range_id, true, true);
-
- if (!self::checkRangePermission($range_id, $GLOBALS['user']->id)) {
- $this->error(401);
- }
-
- $total = count($news);
- $news = array_slice($news, $this->offset, $this->limit);
-
- $json = [];
- foreach ($news as $n) {
- $json[$this->urlf('/news/%s', [$n->id])] = $this->newsToJson($n);
- }
-
- return [$json, $total];
- }
-
- private function validateNews($news)
- {
- $errors = [];
-
- $retain = $_SESSION['messages'];
- $_SESSION['messages'] = [];
-
- if (!$news->validate()) {
- foreach ($_SESSION['messages'] as $message_box) {
- $errors[] = $message_box->message;
- }
- }
-
- $_SESSION['messages'] = $retain;
- return $errors;
- }
-
- private static function checkRangePermission($range_id, $user_id)
- {
- return \StudipNews::haveRangePermission('view', $range_id, $user_id);
- }
-
-
- private function requireNews($id)
- {
- if (!$news = \StudipNews::find($id)) {
- $this->notFound("News not found");
- }
-
- if (!$news->havePermission('view', '', $GLOBALS['user']->id)) {
- $this->error(401);
- }
-
- return $news;
- }
-
- private function newsToJson($news)
- {
- $json = $news->toArray(words("news_id topic body date user_id expire allow_comments chdate chdate_uid mkdate"));
-
- $json['topic'] = (string) $news->topic;
- $json['body_html'] = formatReady((string) $news->body);
- $json['chdate_uid'] = trim($json['chdate_uid']);
-
- if ($news->allow_comments) {
- $json['comments'] = $this->urlf('/news/%s/comments', [$news->id]);
- $json['comments_count'] = sizeof($news->comments);
- }
-
- $json['ranges'] = [];
- foreach ($news->news_ranges as $range) {
- if (self::checkRangePermission($range->range_id, $GLOBALS['user']->id)) {
- switch ($range->type) {
- case 'global': $url = $this->url('/studip/news'); break;
- case 'sem': $url = $this->urlf('/course/%s/news', [$range->range_id]); break;
- case 'user': $url = $this->urlf('/user/%s/news', [$range->range_id]); break;
- case 'inst': $url = $this->urlf('/TODO/%s/news', [$range->range_id]); break;
- case 'fak': $url = $this->urlf('/TODO/%s/news', [$range->range_id]); break;
- }
-
- $json['ranges'][] = $url;
- }
- }
- return $json;
- }
-
- private function requireComment($id)
- {
- if (!$comment = \StudipComment::find($id)) {
- $this->notFound("Comment not found");
- }
- if (!$comment->news->havePermission('view', '', $GLOBALS['user']->id)) {
- $this->error(401);
- }
-
- return $comment;
- }
-
- private function commentToJson($comment)
- {
- $json = $comment->toArray(words("comment_id mkdate chdate content"));
- $json['content_html'] = formatReady($json['content']);
- $json['author'] = $this->urlf('/user/%s', [$comment->user_id]);
- $json['news'] = $this->urlf('/news/%s', [$comment->object_id]);
- return $json;
- }
-}
diff --git a/app/routes/ResourceBooking.php b/app/routes/ResourceBooking.php
deleted file mode 100644
index a5d027f..0000000
--- a/app/routes/ResourceBooking.php
+++ /dev/null
@@ -1,192 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * This file contains the REST class for the
- * room and resource management system.
- *
- * @author Moritz Strohm <strohm@data-quest.de>
- * @copyright 2017-2019
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @since 4.5
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- */
-class ResourceBooking extends \RESTAPI\RouteMap
-{
-
- /**
- * Helper method that either returns the specified data
- * or simply an empty string in case that no request result
- * is requested.
- */
- protected function sendReturnData($data)
- {
- if (\Request::submitted('quiet')) {
- //Return nothing.
- return '';
- }
-
- //Return data.
- return $data;
- }
-
-
- /**
- * Moves a resource booking, if permitted.
- *
- * @post /resources/booking/:booking_id/move
- */
- public function move($booking_id)
- {
- $booking = \ResourceBooking::find($booking_id);
- if (!$booking) {
- $this->notFound('Resource booking object not found!');
- }
-
- $current_user = \User::findCurrent();
-
- if ($booking->isReadOnlyForUser($current_user)) {
- throw new \AccessDeniedException();
- }
-
- $resource_id = \Request::get('resource_id');
- $begin_str = \Request::get('begin');
- $end_str = \Request::get('end');
- $interval_id = \Request::get('interval_id');
-
- //Try the ISO format first: YYYY-MM-DDTHH:MM:SS±ZZ:ZZ
- $begin = \DateTime::createFromFormat(\DateTime::RFC3339, $begin_str);
- $end = \DateTime::createFromFormat(\DateTime::RFC3339, $end_str);
- if (!($begin instanceof \DateTime) || !($end instanceof \DateTime)) {
- $tz = new \DateTime();
- $tz = $tz->getTimezone();
- //Try the ISO format without timezone:
- $begin = \DateTime::createFromFormat('Y-m-d\TH:i:s', $begin_str, $tz);
- $end = \DateTime::createFromFormat('Y-m-d\TH:i:s', $end_str, $tz);
- }
-
- //Check if a specific interval has been moved:
- if ($interval_id) {
- $interval = \ResourceBookingInterval::findOneBySql(
- 'interval_id = :interval_id AND booking_id = :booking_id',
- [
- 'interval_id' => $interval_id,
- 'booking_id' => $booking->id
- ]
- );
- if (!$interval) {
- $this->notFound('Resource booking interval not found!');
- }
- $interval_begin = new \DateTime();
- $interval_begin->setTimestamp($interval->begin);
- $interval_end = new \DateTime();
- $interval_end->setTimestamp($interval->end);
-
- //Calculate the difference from the interval time range
- //to the time range from the request. That difference
- //is then applied to the booking.
- $begin_diff = $interval_begin->diff($begin);
- $end_diff = $interval_end->diff($end);
-
- $new_booking_begin = new \DateTime();
- $new_booking_begin->setTimestamp($booking->begin);
- $new_booking_end = new \DateTime();
- $new_booking_end->setTimestamp($booking->end);
-
- $new_booking_begin = $new_booking_begin->add($begin_diff);
- $new_booking_end = $new_booking_end->add($end_diff);
- //We must substract the preparation time to the begin timestamp
- //to get the real begin:
- $real_begin = clone $new_booking_begin;
- if ($booking->preparation_time > 0) {
- $real_begin->sub(new \DateInterval('PT' . ($booking->preparation_time / 60 ) . 'M'));
- }
- $booking->begin = $real_begin->getTimestamp();
- $booking->end = $new_booking_end->getTimestamp();
- } else {
- //We must substract the preparation time to the begin timestamp
- //to get the real begin:
- $real_begin = clone $begin;
- if ($booking->preparation_time > 0) {
- $real_begin->sub(new \DateInterval('PT' . ($booking->preparation_time / 60 ) . 'M'));
- }
- $booking->begin = $real_begin->getTimestamp();
- $booking->end = $end->getTimestamp();
- }
- if ($resource_id) {
- //The resource-ID has changed:
- //The booking was moved from one resource to another.
- $booking->resource_id = $resource_id;
- }
-
- //Update the booking_user_id field:
- $booking->booking_user_id = \User::findCurrent()->id;
-
- try {
- $booking->store();
- return $this->sendReturnData($booking->toRawArray());
- } catch (\Exception $e) {
- $this->halt(500, $e->getMessage());
- }
- }
-
-
- /**
- * Retrieves the intervals of the resource booking.
- * These can be filtered by a time range.
- *
- * @get /resources/booking/:booking_id/intervals
- */
- public function getIntervals($booking_id)
- {
- $booking = \ResourceBooking::find($booking_id);
- if (!$booking) {
- $this->notFound('Resource booking object not found!');
- }
-
- $current_user = \User::findCurrent();
-
- $resource = $booking->resource->getDerivedClassInstance();
- if (!$resource->bookingPlanVisibleForUser($current_user)) {
- throw new \AccessDeniedException();
- }
-
- //Get begin and end:
- $begin_str = \Request::get('begin');
- $end_str = \Request::get('end');
- $begin = null;
- $end = null;
- if ($begin_str && $end_str) {
- //Try the ISO format first: YYYY-MM-DDTHH:MM:SS±ZZ:ZZ
- $begin = \DateTime::createFromFormat(\DateTime::RFC3339, $begin_str);
- $end = \DateTime::createFromFormat(\DateTime::RFC3339, $end_str);
- if (!($begin instanceof \DateTime) || !($end instanceof \DateTime)) {
- $tz = new \DateTime();
- $tz = $tz->getTimezone();
- //Try the ISO format without timezone:
- $begin = \DateTime::createFromFormat('Y-m-d\TH:i:s', $begin_str, $tz);
- $end = \DateTime::createFromFormat('Y-m-d\TH:i:s', $end_str, $tz);
- }
- }
-
- $sql = "booking_id = :booking_id ";
- $sql_data = ['booking_id' => $booking->id];
- if (($begin instanceof \DateTime) && ($end instanceof \DateTime)) {
- $sql .= "AND begin >= :begin AND end <= :end ";
- $sql_data['begin'] = $begin->getTimestamp();
- $sql_data['end'] = $end->getTimestamp();
- }
- if (\Request::submitted('exclude_cancelled_intervals')) {
- $sql .= "AND takes_place = '1' ";
- }
- $sql .= "ORDER BY begin ASC, end ASC";
- $intervals = \ResourceBookingInterval::findBySql($sql, $sql_data);
-
- $result = [];
- foreach ($intervals as $interval) {
- $result[] = $interval->toRawArray();
- }
-
- return $result;
- }
-}
diff --git a/app/routes/ResourceCategories.php b/app/routes/ResourceCategories.php
deleted file mode 100644
index bdd3d15..0000000
--- a/app/routes/ResourceCategories.php
+++ /dev/null
@@ -1,349 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * This file contains API routes related to ResourceCategory objects.
- *
- * @author Moritz Strohm <strohm@data-quest.de>
- * @copyright 2017-2019
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @since 4.5
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- */
-class ResourceCategories extends \RESTAPI\RouteMap
-{
- /**
- * Validate access to each route.
- */
- public function before()
- {
- if (!\ResourceManager::userHasGlobalPermission(\User::findCurrent(), 'admin')) {
- throw new \AccessDeniedException();
- }
- }
-
- /**
- * Returns all defined resource categories.
- *
- * @get /resources/categories
- */
- public function getAllResourceCategories()
- {
- return \ResourceCategory::findAndMapBySql(
- function (\ResourceCategory $category) {
- return $category->toRawArray();
- },
- 'TRUE ORDER BY name ASC'
- );
- }
-
-
- /**
- * Get a resource category object.
- *
- * @get /resources/category/:category_id
- */
- public function getResourceCategory($category_id)
- {
- $category = \ResourceCategory::find($category_id);
- if (!$category) {
- $this->notFound('ResourceCategory object not found!');
- }
-
- return $category->toRawArray();
- }
-
-
- /**
- * Creates a resource category object.
- *
- * @post /resources/new_category
- */
- public function addResourceCategory()
- {
- $name = \Request::get('name');
- $description = \Request::get('description');
- $class_name = \Request::get('class_name');
- $iconnr = \Request::int('iconnr');
-
- $properties_name = \Request::getArray('properties_name');
- $properties_type = \Request::getArray('properties_type');
- $properties_requestable = \Request::getArray('properties_requestable');
- $properties_protected = \Request::getArray('properties_protected');
-
- $set_properties = [];
- foreach ($properties_name as $key => $property_name) {
- $set_properties[] = [
- 'name' => $property_name,
- 'type' => $properties_type[$key],
- 'requestable' => $properties_requestable[$key],
- 'protected' => $properties_protected[$key]
- ];
- }
-
- //validation:
- if (!$name) {
- $this->halt(
- 400,
- _('Der Name der Kategorie ist leer!')
- );
- }
-
- if (!is_a($class_name, 'Resource', true)) {
- $this->halt(
- 400,
- _('Es wurde keine gültige Ressourcen-Datenklasse ausgewählt!')
- );
- }
-
- switch ($class_name) {
- case 'Location':
- $category = \ResourceManager::createLocationCategory(
- $name,
- $description
- );
- break;
- case 'Building':
- $category = \ResourceManager::createBuildingCategory(
- $name,
- $description
- );
- break;
- case 'Room':
- $category = \ResourceManager::createRoomCategory(
- $name,
- $description
- );
- break;
- default:
- $category = \ResourceManager::createCategory(
- $name,
- $description,
- $class_name,
- false,
- $iconnr
- );
- }
-
- if ($category->store() === false) {
- $this->halt(
- 500,
- _('Fehler beim Speichern der Kategorie!')
- );
- }
-
- //After we have stored the category we must store
- //the properties or create them, if necessary:
-
- foreach ($set_properties as $set_property) {
- $category->addProperty(
- $set_property['name'],
- $set_property['type'],
- $set_property['requestable'],
- $set_property['protected']
- );
- }
-
- return $category->toRawArray();
- }
-
- /**
- * Modifies a resource category.
- *
- * @put /resources/category/:category_id
- */
- public function editResourceCategory($category_id)
- {
- $category = \ResourceCategory::find($category_id);
- if (!$category) {
- $this->notFound('ResourceCategory object not found!');
- }
-
- if ($category->system) {
- $this->halt(403, 'System categories must not be modified!');
- return;
- }
-
- $name = $this->data['name'];
- $description = $this->data['description'];
- $iconnr = intval($this->data['iconnr']);
-
- //validation:
- if ($name) {
- $category->name = $name;
- }
- if ($description) {
- $category->description = $description;
- }
- if ($iconnr) {
- $category->iconnr = $iconnr;
- }
-
- if ($category->store() === false) {
- $this->halt(
- 500,
- 'Error while saving the category!'
- );
- }
-
- return $category->toRawArray();
- }
-
-
- /**
- * Deletes a resource category.
- *
- * @delete /resources/category/:category_id
- */
- public function deleteResourceCategory($category_id)
- {
- $category = \ResourceCategory::find($category_id);
- if (!$category) {
- $this->notFound('ResourceCategory object not found!');
- }
-
- if ($category->system) {
- $this->halt(403,'System resource categories must not be deleted!');
- return;
- }
-
- if ($category->delete()) {
- return 'OK';
- } else {
- $this->halt(
- 500,
- 'Error while deleting the resource category!'
- );
- }
- }
-
-
- /**
- * Get all resource category property objects for a resource category.
- *
- * @get /resources/category/:category_id/properties
- */
- public function getResourceCategoryProperties($category_id)
- {
- $category = \ResourceCategory::find($category_id);
- if (!$category) {
- $this->notFound('ResourceCategory object not found!');
- }
-
- $result = [];
- $properties = \ResourceCategoryProperty::findBySql(
- 'INNER JOIN resource_property_definitions rpd
- USING (property_id)
- WHERE category_id = :category_id ORDER BY rpd.name ASC',
- [
- 'category_id' => $category->id
- ]
- );
-
- if ($properties) {
- foreach ($properties as $property) {
- $data = $property->toRawArray();
- $data['name'] = $property->definition->name;
- $data['type'] = $property->definition->type;
- $result[] = $data;
- }
- }
-
- return $result;
- }
-
-
- /**
- * Returns all resources which belong to the specified category.
- * The result set can be limited by the parameters 'offset' and 'limit'.
- * If the parameter 'with_full_name' is set to 1, the resources full name
- * as provided by its responsible class, is added to the result set.
- *
- * @get /resources/category/:category_id/resources
- */
- public function getResourceCategoryResources($category_id)
- {
- $category = \ResourceCategory::find($category_id);
- if (!$category) {
- $this->notFound('ResourceCategory object not found!');
- }
-
- $offset = \Request::int('offset');
- $limit = \Request::int('limit');
- $with_full_name = \Request::get('with_full_name');
-
- $result = [];
-
- $sql = 'category_id = :category_id ORDER BY name ASC ';
- $sql_array = ['category_id' => $category->id];
-
- if ($limit > 0) {
- $sql .= 'limit :limit ';
- $sql_array['limit'] = $limit;
- if ($offset > 0) {
- $sql .= 'offset :offset ';
- $sql_array['offset'] = $offset;
- }
- }
-
- $resources = \Resource::findBySql($sql, $sql_array);
-
- if ($resources) {
- foreach ($resources as $r) {
- if ($with_full_name) {
- $r = $r->getDerivedClassInstance();
- $data = $r->toRawArray();
- $data['full_name'] = $r->getFullName();
- $result[] = $data;
- } else {
- $result[] = $r->toRawArray();
- }
- }
- }
-
- return $result;
- }
-
-
- /**
- * Creates a resource.
- *
- * @post /resources/category/:category_id/create_resource
- */
- public function createResource($category_id)
- {
- $category = \ResourceCategory::find($category_id);
- if (!$category) {
- $this->notFound('ResourceCategory object not found!');
- }
-
-
- $name = \Request::get('name');
- $description = \Request::get('description');
- $parent_id = \Request::get('parent_id');
- $properties = \Request::getArray('properties');
-
- if (!$name) {
- $this->halt(
- 400,
- 'The parameter \'name\' is not set!'
- );
- }
-
- try {
- $resource = $category->createResource(
- $name,
- $description,
- $parent_id,
- $properties
- );
-
- return $resource;
- } catch (\Exception $e) {
- $this->halt(
- 400,
- $e->getMessage()
- );
- }
- }
-}
diff --git a/app/routes/ResourcePermissions.php b/app/routes/ResourcePermissions.php
deleted file mode 100644
index be5c647..0000000
--- a/app/routes/ResourcePermissions.php
+++ /dev/null
@@ -1,585 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * This file contains API routes related to ResourcePermission
- * and ResourceTemporaryPermission objects.
- *
- * @author Moritz Strohm <strohm@data-quest.de>
- * @copyright 2017-2019
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @since 4.5
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- */
-class ResourcePermissions extends \RESTAPI\RouteMap
-{
-
- //Methods for permanent permissions:
-
-
- /**
- * Get the permission levels of users for the specified resource.
- *
- * @param levels: Limit the result set to the specified permission levels.
- * Allowed permission levels: user, autor, tutor, admin.
- * The permission levels have to be comma separated like in the
- * following example: "autor,tutor,admin".
- *
- * @get /resources/permissions/:resource_id
- */
- public function getResourcePermissions($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'admin')) {
- throw new \AccessDeniedException();
- }
-
- $levels_str = \Request::get('levels');
- $levels = [];
- if ($levels_str) {
- $levels = explode(',', $levels_str);
- }
-
- $sql = 'resource_id = :resource_id ';
- $sql_array = [
- 'resource_id' => $resource->id
- ];
-
- if ($levels) {
- $sql .= 'AND perms IN ( :levels ) ';
- $sql_array['levels'] = $levels;
- }
-
- $permissions = \ResourcePermission::findBySql($sql, $sql_array);
-
- $result = [];
- if ($permissions) {
- foreach ($permissions as $permission) {
- $result[] = $permission->toRawArray();
- }
- }
-
- return $result;
- }
-
-
- /**
- * Returns the permissions a specific user has on a specified resource.
- *
- * @get /resources/permissions/:resource_id/:user:_id
- */
- public function getPermission($resource_id, $user_id)
- {
- if ($resource_id !== 'global') {
- if (!\Resource::exists($resource_id)) {
- $this->halt(
- 404,
- 'Resource not found!'
- );
- }
- }
-
- $user = \User::find($user_id);
- if (!$user) {
- $this->halt(
- 400,
- 'No user was provided!'
- );
- }
-
- $current_user = \User::findCurrent();
-
- if (!\ResourceManager::userHasGlobalPermission($current_user, 'admin')) {
- if ($resource_id !== 'global') {
- $resource = \Resource::find($resource_id);
- $resource = $resource->getDerivedClassInstance();
- if (!$resource->userHasPermission($current_user, 'admin')) {
- $this->halt(403);
- }
- } else {
- //$resource_id == 'global': One must be admin
- //to perform this action!
- $this->halt(403);
- }
- }
-
- $permission = \ResourcePermission::findOneBySql(
- "resource_id = :resource_id AND user_id = :user_id",
- [
- 'resource_id' => $resource_id,
- 'user_id' => $user->id
- ]
- );
-
- if ($permission) {
- return $permission->toRawArray();
- } else {
- //The user already had no global permissions!
- return NULL;
- }
- }
-
-
- /**
- * @post /resources/permissions/:resource_id/:user_id
- */
- public function setPermission($resource_id, $user_id)
- {
- if ($resource_id !== 'global') {
- if (!\Resource::exists($resource_id)) {
- $this->halt(
- 404,
- 'Resource not found!'
- );
- return;
- }
- }
-
- $user = \User::find($user_id);
- if (!$user) {
- $this->halt(
- 400,
- 'No user was provided!'
- );
- }
-
- $current_user = \User::findCurrent();
-
- if (!\ResourceManager::userHasGlobalPermission($current_user, 'admin')) {
- if ($resource_id !== 'global') {
- $resource = \Resource::find($resource_id);
- $resource = $resource->getDerivedClassInstance();
- if (!$resource->userHasPermission($current_user, 'admin')) {
- $this->halt(403);
- }
- } else {
- //$resource_id == 'global': One must be admin
- //to perform this action!
- $this->halt(403);
- }
- }
-
- //Verify permission level:
- $perms = \Request::get('perms');
-
- if (!in_array($perms, ['user', 'autor', 'tutor', 'admin'])) {
- $this->halt(
- 400,
- 'Invalid permission level specified!'
- );
- }
-
- //Check if permissions are already present for the user.
- //If not, create a new permission object.
- $permission = \ResourcePermission::findOneBySql(
- "resource_id = :resource_id AND user_id = :user_id",
- [
- 'resource_id' => $resource_id,
- 'user_id' => $user->id
- ]
- );
-
- if (!$permission) {
- $permission = new \ResourcePermission();
- $permission->resource_id = $resource_id;
- $permission->user_id = $user->id;
- }
-
- $permission->perms = $perms;
-
- if ($permission->store() === false) {
- $this->halt(
- 500,
- 'Error while saving permissions!'
- );
- }
-
- return $permission->toRawArray();
- }
-
-
- /**
- * @delete /resources/permissions/:resource_id/:user_id
- */
- public function deletePermission($resource_id, $user_id)
- {
- if ($resource_id !== 'global' && !\Resource::exists($resource_id)) {
- $this->notFound('Resource not found!');
- }
-
- $user = \User::find($user_id);
- if (!$user) {
- $this->halt(
- 400,
- 'No user was provided!'
- );
- }
-
- $current_user = \User::findCurrent();
-
- if (!\ResourceManager::userHasGlobalPermission($current_user, 'admin')) {
- if ($resource_id !== 'global') {
- $resource = \Resource::find($resource_id);
- $resource = $resource->getDerivedClassInstance();
- if (!$resource->userHasPermission($current_user, 'admin')) {
- $this->halt(403);
- }
- } else {
- //$resource_id == 'global': One must be admin
- //to perform this action!
- $this->halt(403);
- }
- }
-
- $permission = \ResourcePermission::findOneBySql(
- "resource_id = :resource_id AND user_id = :user_id",
- [
- 'resource_id' => $resource_id,
- 'user_id' => $user->id
- ]
- );
-
- if (!$permission) {
- //The user already had no global permissions!
- return 'OK';
- }
-
- if ($permission->delete()) {
- return 'OK';
- } else {
- $this->halt(
- 500,
- 'Error while deleting global permissions!'
- );
- }
- }
-
-
- //Methods for temporary permissions:
-
-
- /**
- * Get the temporary permission levels of users for the specified resource.
- * The begin and end parameters are mandatory to determine a time range
- * to collect the temporary permissions in that range.
- *
- * @param begin: The begin timestamp of the time range.
- * @param end: The end timestamp of the time range.
- * @param levels: Limit the result set to the specified temporary permission
- * levels. Allowed permission levels: user, autor, tutor, admin.
- * The permission levels have to be comma separated like in the
- * following example: "autor,tutor,admin".
- *
- * @get /resources/temporary_permissions/:resource_id
- */
- public function getTemporaryResourcePermissions($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'admin')) {
- throw new \AccessDeniedException();
- }
-
- $begin = \Request::get('begin');
- $end = \Request::get('end');
- $levels_str = \Request::get('levels');
- $levels = [];
- if ($levels_str) {
- $levels = explode(',', $levels_str);
- }
-
- if (!$begin or !$end) {
- //Use the current day:
- $begin = strtotime('today 0:00:00');
- $end = strtotime('today 23:59:59');
- }
-
- $sql = 'resource_id = :resource_id
- AND
- ((begin >= :begin AND begin <= :end)
- OR
- (end >= :begin AND end <= :end))
- OR
- (begin < :begin AND end > :end)';
- $sql_array = [
- 'resource_id' => $resource->id,
- 'begin' => $begin,
- 'end' => $end
- ];
-
- if ($levels) {
- $sql .= 'AND perms IN ( :levels ) ';
- $sql_array['levels'] = $levels;
- }
-
- return \ResourceTemporaryPermission::findAndMapBySql(
- function (\ResourceTemporaryPermission $permission) {
- return $permission->toRawArray();
- },
- $sql,
- $sql_array
- );
- }
-
-
- /**
- * Returns the permissions a specific user has on a specified resource.
- *
- * @get /resources/temporary_permissions/:resource_id/:user:_id
- */
- public function getTemporaryPermission($resource_id, $user_id)
- {
- if ($resource_id !== 'global') {
- if (!\Resource::exists($resource_id)) {
- $this->notFound('Resource not found!');
- }
- }
-
- $user = \User::find($user_id);
- if (!$user) {
- $this->halt(
- 400,
- 'No user was provided!'
- );
- }
-
- $current_user = \User::findCurrent();
-
- $begin_str = \Request::get('begin');
- $end_str = \Request::get('end');
- $begin = null;
- $end = null;
- $with_time_range = false;
- if ($begin_str && $end_str) {
- $with_time_range = true;
- $begin = new \DateTime();
- $begin->setTimestamp($begin_str);
- $end = new \DateTime();
- $end->setTimestamp($end_str);
- }
-
- if (!\ResourceManager::userHasGlobalPermission($current_user, 'admin')) {
- if ($resource_id !== 'global') {
- $resource = \Resource::find($resource_id);
- $resource = $resource->getDerivedClassInstance();
- if (!$resource->userHasPermission($current_user, 'admin')) {
- $this->halt(403);
- }
- } else {
- //$resource_id == 'global': One must be admin
- //to perform this action!
- $this->halt(403);
- }
- }
-
- $permissions = null;
- if ($with_time_range) {
- $permissions = \ResourceTemporaryPermission::findBySql(
- "resource_id = :resource_id AND user_id = :user_id
- AND (
- (begin >= :begin AND begin <= :end)
- OR
- (end >= :begin AND end <= :end)
- )",
- [
- 'resource_id' => $resource_id,
- 'user_id' => $user->id,
- 'begin' => $begin->getTimestamp(),
- 'end' => $end->getTimestamp()
- ]
- );
- } else {
- $permissions = \ResourceTemporaryPermission::findBySql(
- "resource_id = :resource_id AND user_id = :user_id",
- [
- 'resource_id' => $resource_id,
- 'user_id' => $user->id
- ]
- );
- }
-
- if ($permissions) {
- $result = [];
- foreach ($permissions as $permission) {
- $result[] = $permission->toRawArray();
- }
- return $result;
- } else {
- //The user already had no global permissions!
- return NULL;
- }
- }
-
-
- /**
- * Sets temporary permissions for a user.
- *
- * @param begin The begin timestamp for the temporary permisssion.
- * @param end The end timestamp for the temporary permission.
- * @param perms The permission level for the temporary permission.
- *
- * @post /resources/temporary_permissions/:resource_id/:user_id
- */
- public function setTemporaryPermission($resource_id, $user_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource not found!');
- }
-
- $user = \User::find($user_id);
- if (!$user) {
- $this->notFound('User not found!');
- }
-
- $current_user = \User::findCurrent();
-
- if (!\ResourceManager::userHasGlobalPermission($current_user, 'admin')
- && !$resource->userHasPermission($current_user, 'admin')) {
- $this->halt(403);
- }
-
- $begin_str = \Request::get('begin');
- $end_str = \Request::get('end');
- if (!$begin_str || !$end_str) {
- $this->halt(
- 400,
- 'No time range specified for temporary permission!'
- );
- }
-
- $begin = new \DateTime();
- $begin->setTimestamp($begin_str);
- $end = new \DateTime();
- $end->setTimestamp($end_str);
-
- //Verify permission level:
- $perms = \Request::get('perms');
-
- if (!in_array($perms, ['user', 'autor', 'tutor', 'admin'])) {
- $this->halt(
- 400,
- 'Invalid permission level specified!'
- );
- }
-
- //Check if permissions are already present for the user.
- //If not, create a new permission object.
- $permission = \ResourceTemporaryPermission::findOneBySql(
- "resource_id = :resource_id AND user_id = :user_id
- AND begin = :begin AND end = :end",
- [
- 'resource_id' => $resource_id,
- 'user_id' => $user->id,
- 'begin' => $begin->getTimestamp(),
- 'end' => $end->getTimestamp()
- ]
- );
-
- if (!$permission) {
- $permission = new \ResourceTemporaryPermission();
- $permission->resource_id = $resource_id;
- $permission->user_id = $user->id;
- $permission->begin = $begin->getTimestamp();
- $permission->end = $end->getTimestamp();
- }
-
- $permission->perms = $perms;
-
- if ($permission->store() === false) {
- $this->halt(
- 500,
- 'Error while saving permissions!'
- );
- }
-
- return $permission->toRawArray();
- }
-
-
- /**
- * Deletes all temporary permissions of a user.
- * If a time interval is given all permissions inside the interval
- * are deleted.
- *
- * @delete /resources/temporary_permissions/:resource_id/:user_id
- */
- public function deleteTemporaryPermission($resource_id, $user_id)
- {
- if ($resource_id !== 'global') {
- if (!\Resource::exists($resource_id)) {
- $this->notFound('Resource not found!');
- }
- }
-
- $user = \User::find($user_id);
- if (!$user) {
- $this->notFound('User not found!');
- }
-
- $current_user = \User::findCurrent();
-
- if (!\ResourceManager::userHasGlobalPermission($current_user, 'admin')) {
- if ($resource_id !== 'global') {
- $resource = \Resource::find($resource_id);
- $resource = $resource->getDerivedClassInstance();
- if (!$resource->userHasPermission($current_user, 'admin')) {
- $this->halt(403);
- }
- } else {
- //$resource_id == 'global': One must be admin
- //to perform this action!
- $this->halt(403);
- }
- }
-
- $begin_str = \Request::get('begin');
- $end_str = \Request::get('end');
- $begin = null;
- $end = null;
- $with_time_range = false;
- if ($begin_str and $end_str) {
- $with_time_range = true;
- $begin = new \DateTime();
- $begin->setTimestamp($begin_str);
- $end = new \DateTime();
- $end->setTimestamp($end_str);
- }
-
- if ($with_time_range) {
- \ResourceTemporaryPermission::deleteBySql(
- "resource_id = :resource_id AND user_id = :user_id
- AND (
- (begin >= :begin AND end <= :end)
- )",
- [
- 'resource_id' => $resource_id,
- 'user_id' => $user->id,
- 'begin' => $begin->getTimestamp(),
- 'end' => $end->getTimestamp()
- ]
- );
- } else {
- \ResourceTemporaryPermission::deleteBySql(
- "resource_id = :resource_id AND user_id = :user_id",
- [
- 'resource_id' => $resource_id,
- 'user_id' => $user->id
- ]
- );
- }
-
- return 'OK';
- }
-}
diff --git a/app/routes/ResourceProperties.php b/app/routes/ResourceProperties.php
deleted file mode 100644
index 2ddbbaf..0000000
--- a/app/routes/ResourceProperties.php
+++ /dev/null
@@ -1,224 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * This file contains API routes related to ResourceProperty objects.
- *
- * @author Moritz Strohm <strohm@data-quest.de>
- * @copyright 2017-2019
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @since 4.5
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- */
-class ResourceProperties extends \RESTAPI\RouteMap
-{
- /**
- * Validate access to each route.
- */
- public function before()
- {
- if (!\ResourceManager::userHasGlobalPermission(\User::findCurrent(), 'admin')) {
- throw new \AccessDeniedException();
- }
- }
-
- /**
- * Returns all resource property definitions.
- *
- * @get /resources/properties
- */
- public function getAllResourcePropertyDefinitions()
- {
- $properties = \ResourcePropertyDefinition::findBySql('TRUE ORDER BY name ASC');
-
- $result = [];
-
- if ($properties) {
- foreach ($properties as $p) {
- $result[] = $p->toRawArray();
- }
- }
-
- return $result;
- }
-
-
- /**
- * Creates a new resource property definition.
- *
- * @post /resources/add_property
- */
- public function addResourcePropertyDefinition()
- {
- $name = \Request::get('name');
- $description = \Request::i18n('description');
- $type = \Request::get('type');
- $write_permission_level = \Request::get('write_permission_level');
- $options = \Request::get('options', '');
- $range_search = \Request::bool('range_search');
-
- if (!$name) {
- $this->halt(
- 400,
- 'The field \'name\' must not be empty!'
- );
- }
- if (!in_array($type, \ResourcePropertyDefinition::getDefinedTypes())) {
- $this->halt(
- 400,
- 'Invalid property type specified!'
- );
- }
- if (!in_array($write_permission_level, ['user', 'autor', 'tutor', 'admin'])) {
- $this->halt(
- 400,
- 'Invalid permission level in field \'write_permission_level\'!'
- );
- }
-
- $property = new \ResourcePropertyDefinition();
- $property->name = $name;
- $property->description = $description;
- $property->type = $type;
- $property->options = $options ?: '';
- $property->range_search = $range_search;
- $property->write_permission_level = $write_permission_level;
-
- if (!$property->store()) {
- $this->halt(
- 500,
- 'Error while saving the property!'
- );
- }
- return $property->toRawArray();
- }
-
-
- /**
- * Get a resource property definition object.
- *
- * @get /resources/property/:property_id
- */
- public function getResourcePropertyDefinition($property_id)
- {
- $property = \ResourcePropertyDefinition::find($property_id);
- if (!$property) {
- $this->notFound('ResourcePropertyDefinition object not found!');
- }
-
- return $property->toRawArray();
- }
-
-
- /**
- * Modifies a resource property definition.
- *
- * @put /resources/property/:property_id
- */
- public function editResourcePropertyDefinition($property_id)
- {
- $property = \ResourcePropertyDefinition::find($property_id);
- if (!$property) {
- $this->notFound('ResourcePropertyDefinition object not found!');
- }
-
- if ($property->system) {
- $this->halt(
- 403,
- 'System properties must not be edited!'
- );
- }
-
- $name = $this->data['name'];
- $description = $this->data['description'];
- $type = $this->data['type'];
- $write_permission_level = $this->data['write_permission_level'];
- $options = $this->data['options'];
- $range_search = $this->data['range_search'];
-
- if ($name) {
- $property->name = $name;
- }
-
- if ($description) {
- $property->description = $description;
- }
-
- if ($type) {
- if (!in_array($type, \ResourcePropertyDefinition::getDefinedTypes())) {
- $this->halt(
- 400,
- 'Invalid property type specified!'
- );
- }
- $property->type = $type;
- }
-
- if ($write_permission_level) {
- if (!in_array($write_permission_level, ['user', 'autor', 'tutor', 'admin'])) {
- $this->halt(
- 400,
- 'Invalid permission level in field \'write_permission_level\'!'
- );
- }
- $property->write_permission_level = $write_permission_level;
- }
-
- if ($options) {
- $property->options = $options;
- }
-
- if ($range_search) {
- $property->range_search = $range_search;
- }
-
- if ($property->isDirty()) {
- if ($property->store()) {
- return $property->toRawArray();
- } else {
- $this->halt(
- 500,
- 'Error while saving the property!'
- );
- }
- }
-
- return $property->toRawArray();
- }
-
-
- /**
- * Deletes a resource property definition object.
- *
- * @delete /resources/property/:property_id
- */
- public function deleteResourcePropertyDefinition($property_id)
- {
- $property = \ResourcePropertyDefinition::find($property_id);
- if (!$property) {
- $this->notFound('ResourcePropertyDefinition object not found!');
- }
-
- if (!\ResourceManager::userHasGlobalPermission(\User::findCurrent(), 'admin')) {
- $this->halt(403);
- }
-
- //Check if the property is in use:
-
- if ($property->isInUse()) {
- $this->halt(
- 403,
- 'The property is in use and can therefore not be deleted!'
- );
- }
-
- if ($property->delete()) {
- return "OK";
- } else {
- $this->halt(
- 500,
- 'Error while deleting resource property definition!'
- );
- }
- }
-}
diff --git a/app/routes/ResourceRequest.php b/app/routes/ResourceRequest.php
deleted file mode 100644
index 24dfd2e..0000000
--- a/app/routes/ResourceRequest.php
+++ /dev/null
@@ -1,138 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * This file contains the REST class for resource requests from the
- * room and resource management system.
- *
- * @author Moritz Strohm <strohm@data-quest.de>
- * @copyright 2017-2019
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @since 4.5
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- */
-class ResourceRequest extends \RESTAPI\RouteMap
-{
-
- /**
- * Helper method that either returns the specified data
- * or simply an empty string in case that no request result
- * is requested.
- */
- protected function sendReturnData($data)
- {
- if (\Request::submitted('quiet')) {
- //Return nothing.
- return '';
- }
-
- //Return data.
- return $data;
- }
-
-
- /**
- * Moves a resource request, if permitted.
- *
- * @post /resources/request/:request_id/move
- */
- public function move($request_id)
- {
- $request = \ResourceRequest::find($request_id);
- if (!$request) {
- $this->notFound('Resource request object not found!');
- }
-
- $current_user = \User::findCurrent();
-
- if ($request->isReadOnlyForUser($current_user)) {
- throw new \AccessDeniedException();
- }
-
- $begin_str = \Request::get('begin');
- $end_str = \Request::get('end');
-
- //Try the ISO format first: YYYY-MM-DDTHH:MM:SS±ZZ:ZZ
- $begin = \DateTime::createFromFormat(\DateTime::RFC3339, $begin_str);
- $end = \DateTime::createFromFormat(\DateTime::RFC3339, $end_str);
- if (!($begin instanceof \DateTime) || !($end instanceof \DateTime)) {
- $tz = new \DateTime();
- $tz = $tz->getTimezone();
- $begin = \DateTime::createFromFormat('Y-m-d\TH:i:s', $begin_str, $tz);
- $end = \DateTime::createFromFormat('Y-m-d\TH:i:s', $end_str, $tz);
- }
-
- $request->begin = $begin->getTimestamp();
- $request->end = $end->getTimestamp();
-
- try {
- $request->store();
- return $this->sendReturnData($request->toRawArray());
- } catch (\Exception $e) {
- $this->halt(500, $e->getMessage());
- }
- }
-
-
- /**
- * Changes the reply comment of a request.
- *
- * @post /resources/request/:request_id/edit_reply_comment
- */
- public function editReplyComment($request_id)
- {
- $request = \ResourceRequest::find($request_id);
- if (!$request) {
- $this->notFound('Resource request object not found!');
- }
-
- $current_user = \User::findCurrent();
-
- if ($request->isReadOnlyForUser($current_user)) {
- throw new \AccessDeniedException();
- }
-
- $request->reply_comment = \Request::get('reply_comment');
-
- try {
- if ($request->store() === false) {
- throw new \RuntimeException('Could not store comment');
- }
- } catch (\Exception $e) {
- $this->halt(500, $e->getMessage());
- }
-
- return $this->sendReturnData($request->toRawArray());
- }
-
-
- /**
- * Changes the reply comment of a request.
- *
- * @post /resources/request/:request_id/toggle_marked
- */
- public function toggleMarkedFlag($request_id)
- {
- $request = \ResourceRequest::find($request_id);
- if (!$request) {
- $this->notFound('Resource request object not found!');
- }
-
- $current_user = \User::findCurrent();
-
- if ($request->isReadOnlyForUser($current_user)) {
- throw new \AccessDeniedException();
- }
-
- //Switch to the next marking state or return to the unmarked state
- //if the next marking state would be after the last defined
- //marking state.
- $request->marked = (++$request->marked % \ResourceRequest::MARKING_STATES);
-
- if ($request->isDirty()) {
- $request->store();
- }
-
- return $request;
- }
-}
diff --git a/app/routes/Resources.php b/app/routes/Resources.php
deleted file mode 100644
index 7117546..0000000
--- a/app/routes/Resources.php
+++ /dev/null
@@ -1,950 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * This file contains the REST class for the
- * room and resource management system.
- *
- * @author Moritz Strohm <strohm@data-quest.de>
- * @copyright 2017-2019
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @since 4.5
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- */
-class Resources extends \RESTAPI\RouteMap
-{
-
- //Resource routes:
-
-
- /**
- * Get a resource object.
- * @param derived_class: If the URL parameter derived_class is set
- * the resource object is converted to an instance of the
- * class that does correct handling of the resource object.
- *
- * @get /resources/resource/:resource_id
- */
- public function getResource($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'user')) {
- throw new \AccessDeniedException();
- }
-
- if (\Request::submitted('derived_classes')) {
- $resource = $resource->getDerivedClassInstance();
- }
-
- $result = $resource->toRawArray();
-
- $result['full_name'] = $resource->getFullName();
- $result['has_children'] = $resource->children ? true : false;
-
- return $result;
- }
-
-
- /**
- * Modifies a resource object.
- *
- * @put /resources/resource/:resource_id
- */
- public function editResource($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'autor')) {
- $this->halt(403);
- return;
- }
-
- $name = $this->data['name'];
- $description = $this->data['description'];
- $parent_id = $this->data['parent_id'];
- $properties = $this->data['properties'];
-
- if ($name) {
- $resource->name = $name;
- }
- if ($description) {
- $resource->description = $description;
- }
- if ($parent_id) {
- if (!\Resource::exists($parent_id)) {
- $this->halt(
- 400,
- 'No resource exists with the ID \'' . $parent_id . '\'!'
- );
- }
- $resource->parent_id = $parent_id;
- }
- if ($properties) {
- foreach ($properties as $name => $value) {
- try {
- $resource->setProperty($name, $value, $GLOBALS['user']->id);
- } catch (\AccessDeniedException $e) {
- $this->halt(
- 403,
- $e->getMessage()
- );
- } catch (\Exception $e) {
- $this->halt(
- 500,
- $e->getMessage()
- );
- }
- }
- }
-
- if ($resource->isDirty()) {
- if ($resource->store()) {
- return $resource->toRawArray();
- } else {
- $this->halt(
- 500,
- 'Error while saving the resource object!'
- );
- }
- }
- return $resource->toRawArray();
- }
-
-
- /**
- * Deletes a resource object.
- *
- * @delete /resources/resource/:resource_id
- */
- public function deleteResource($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'admin')) {
- $this->halt(403);
- return;
- }
-
- if (\Request::submitted('derived_classes')) {
- $resource = $resource->getDerivedClassInstance();
- }
-
- if ($resource->delete()) {
- return 'OK';
- } else {
- $this->halt(
- 500,
- 'Error while deleting the resource object!'
- );
- }
- }
-
-
- /**
- * Returns the child resources of a resource object, if they exist.
- *
- * @get /resources/resource/:resource_id/children
- */
- public function getResourceChildren($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'user')) {
- throw new \AccessDeniedException();
- }
-
- $use_derived_classes = (bool) \Request::submitted('derived_classes');
-
- $result = [];
-
- $children = \Resource::findBySql(
- 'parent_id = :resource_id
- ORDER BY name ASC',
- [
- 'resource_id' => $resource->id
- ]
- );
- if ($children) {
- foreach ($children as $child) {
- if ($use_derived_classes) {
- $child = $child->getDerivedClassInstance();
- }
- $result[] = $child->toRawArray();
- }
- }
- return $result;
- }
-
-
- /**
- * Returns the parent resource of a resource object, if it exists.
- *
- * @get /resources/resource/:resource_id/parent
- */
- public function getResourceParent($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'user')) {
- throw new \AccessDeniedException();
- }
-
- if (!$resource->parent) {
- $this->notFound('This resource has no parent!');
- }
-
- $use_derived_classes = (bool) \Request::submitted('derived_classes');
-
- if ($use_derived_classes) {
- $parent = $resource->parent->getDerivedClassInstance();
- return $parent->toRawArray();
- }
-
- return $resource->parent->toRawArray();
- }
-
-
- /**
- * Get all property objects of a resource.
- *
- * @get /resources/resource/:resource_id/properties
- */
- public function getResourceProperties($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'user')) {
- throw new \AccessDeniedException();
- }
-
- $result = [];
- $properties = \ResourceProperty::findBySql(
- 'INNER JOIN resource_property_definitions rpd
- ON resource_properties.property_id = rpd.property_id
- WHERE
- resource_properties.resource_id = :resource_id
- ORDER BY rpd.name ASC',
- [
- 'resource_id' => $resource->id
- ]
- );
-
- if ($properties) {
- foreach ($properties as $property) {
- $data = $property->toRawArray();
- $data['name'] = $property->definition->name;
- $data['type'] = $property->definition->type;
- if ($data['type'] == 'position') {
- //position properties also get the map-URL:
- $data['map_url'] = \ResourceManager::getMapUrlForResourcePosition(
- $property
- );
- }
- $result[] = $data;
- }
- }
-
- return $result;
- }
-
-
- /**
- * Returns the booking plan of a resource for a week specified
- * by the parameters begin and end.
- *
- * @param begin: The begin timestamp of the time range for the booking plan.
- * @param end: The end timestamp of the time range for the booking plan.
- *
- * @allow_nobody
- *
- * @get /resources/resource/:resource_id/booking_plan
- */
- public function getResourceBookingPlan($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- $current_user = \User::findCurrent();
- $nobody_access = true;
-
- if ($current_user instanceof \User) {
- $nobody_access = false;
- if (!$resource->bookingPlanVisibleForUser($current_user)) {
- throw new \AccessDeniedException();
- }
- } elseif ($resource instanceof \Room) {
- if (!$resource->bookingPlanVisibleForUser($current_user)) {
- throw new \AccessDeniedException();
- }
- }
- $user_is_resource_user = false;
- if ($current_user instanceof \User) {
- $user_is_resource_user = $resource->userHasPermission(
- $current_user,
- 'user'
- );
- }
-
- $display_requests = false;
- if ($current_user instanceof \User) {
- $display_requests = \Request::get('display_requests');
- }
- $display_all_requests = \Request::get('display_all_requests');
-
- if ($display_all_requests && !$user_is_resource_user) {
- //The user is not allowed to see all requests.
- throw new \AccessDeniedException();
- }
-
- $begin_date = \Request::get('start');
- $end_date = \Request::get('end');
- if (!$begin_date || !$end_date) {
- //No time range specified.
- $this->halt(400, 'The parameters "start" and "end" are missing!');
- return;
- }
-
- //Try the ISO format first: YYYY-MM-DDTHH:MM:SS±ZZ:ZZ
- $begin = \DateTime::createFromFormat(\DateTime::RFC3339, $begin_date);
- $end = \DateTime::createFromFormat(\DateTime::RFC3339, $end_date);
-
- if (!($begin instanceof \DateTime) || !($end instanceof \DateTime)) {
- $begin = new \DateTime();
- $end = new \DateTime();
- //Assume the local timezone and use the Y-m-d format:
- $date_regex = '/[0-9]{4}-(0[1-9]|1[0-2])-([0-2][0-9]|3[0-1])/';
- if (preg_match($date_regex, $begin_date)) {
- //$begin is specified in the date formay YYYY-MM-DD:
- $begin_str = explode('-', $begin_date);
- $begin->setDate(
- intval($begin_str[0]),
- intval($begin_str[1]),
- intval($begin_str[2])
- );
- $begin->setTime(0,0,0);
- } else {
- $begin->setTimestamp($begin_date);
- }
- //Now we do the same for $end_timestamp:
- if (preg_match($date_regex, $end_date)) {
- //$begin is specified in the date formay YYYY-MM-DD:
- $end_str = explode('-', $end_date);
- $end->setDate(
- intval($end_str[0]),
- intval($end_str[1]),
- intval($end_str[2])
- );
- $end->setTime(23,59,59);
- } else {
- $end->setTimestamp($end_date);
- }
- }
-
- //Get parameters:
- $booking_types = [];
- if (!$nobody_access) {
- $booking_types = explode(',', \Request::get('booking_types'));
- }
-
- $begin_timestamp = $begin->getTimestamp();
- $end_timestamp = $end->getTimestamp();
-
- //Get the event data sources:
- $bookings = \ResourceBooking::findByResourceAndTimeRanges(
- $resource,
- [
- [
- 'begin' => $begin_timestamp,
- 'end' => $end_timestamp
- ]
- ],
- $booking_types
- );
- $requests = [];
- if ($display_all_requests) {
- $requests = \ResourceRequest::findByResourceAndTimeRanges(
- $resource,
- [
- [
- 'begin' => $begin_timestamp,
- 'end' => $end_timestamp
- ]
- ],
- 0
- );
- } elseif ($display_requests) {
- //Get the users own request only:
- $requests = \ResourceRequest::findByResourceAndTimeRanges(
- $resource,
- [
- [
- 'begin' => $begin_timestamp,
- 'end' => $end_timestamp
- ]
- ],
- 0,
- [],
- 'user_id = :user_id',
- ['user_id' => $current_user->id]
- );
- }
-
- $objects = array_merge($bookings, $requests);
- $event_data = \Studip\Fullcalendar::createData($objects, $begin_timestamp, $end_timestamp);
-
- if ($nobody_access) {
- //For nobody users, the code stops here since
- //nobody users are not allowed to include additional objects.
- return $event_data;
- }
-
- //Check if there are additional objects to be displayed:
- $additional_objects = \Request::getArray('additional_objects');
- $additional_object_colours = \Request::getArray('additional_object_colours');
- if ($additional_objects) {
- foreach ($additional_objects as $object_class => $object_ids) {
- if (!is_a($object_class, '\SimpleORMap', true)) {
- continue;
- }
- if (!is_a($object_class, '\Studip\Calendar\EventSource', true)) {
- continue;
- }
-
- $special_colours = [];
- if ($additional_object_colours[$object_class]) {
- $special_colours = $additional_object_colours[$object_class];
- }
-
- $additional_objects = $object_class::findMany($object_ids);
- foreach ($additional_objects as $additional_object) {
- $event_data = $additional_object->getFilteredEventData(
- $current_user->id,
- null,
- null,
- $begin,
- $end
- );
-
- if ($special_colours) {
- foreach ($event_data as $data) {
- $data->text_colour = $special_colours['fg'];
- $data->background_colour = $special_colours['bg'];
- $data->editable = false;
- $event_data[] = $data->toFullcalendarEvent();
- }
- }
- }
- }
- }
- return $event_data;
- }
-
-
- /**
- * Returns the booking plan of a resource for a selected semester.
- *
- * @param semester_id: The ID of the semester. Defaults to the current
- * semester, if not set.
- *
- * @get /resources/resource/:resource_id/semester_plan
- */
- public function getResourceSemesterBookingPlan($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- $current_user = \User::findCurrent();
-
- if (!$resource->bookingPlanVisibleForUser($current_user)) {
- throw new \AccessDeniedException();
- }
-
- $user_is_resource_user = $resource->userHasPermission(
- $current_user,
- 'user'
- );
-
- $display_requests = \Request::get('display_requests');
- $display_all_requests = \Request::get('display_all_requests');
-
- $begin = new \DateTime();
- $end = new \DateTime();
-
- $semester_id = \Request::get('semester_id');
- $semester = null;
-
- if ($semester_id) {
- $semester = \Semester::find($semester_id);
- if (!$semester) {
- $this->halt(404, 'Specified semester not found!');
- }
- } else {
- $semester = \Semester::findCurrent();
- if (!$semester) {
- $this->halt(500, 'Current semester not available!');
- }
- }
-
- if (\Request::get('semester_timerange') != 'fullsem') {
- $begin->setTimestamp($semester->vorles_beginn);
- $end->setTimestamp($semester->vorles_ende);
- } else {
- $begin->setTimestamp($semester->beginn);
- $end->setTimestamp($semester->ende);
- }
-
- //Get parameters:
- $booking_types = \Request::getArray('booking_types');
-
- $begin_timestamp = $begin->getTimestamp();
- $end_timestamp = $end->getTimestamp();
-
- //Get the event data sources:
- $bookings = \ResourceBooking::findByResourceAndTimeRanges(
- $resource,
- [
- [
- 'begin' => $begin_timestamp,
- 'end' => $end_timestamp
- ]
- ],
- $booking_types
- );
-
- $requests = [];
- if ($display_all_requests || $display_requests) {
- $requests_sql = "INNER JOIN seminar_cycle_dates scd
- USING (metadate_id)
- WHERE
- resource_id = :resource_id
- AND
- closed = '0' ";
- $requests_sql_params = [
- 'begin' => $begin_timestamp,
- 'end' => $end_timestamp,
- 'resource_id' => $resource->id
- ];
- if (!$display_all_requests) {
- $requests_sql .= "AND user_id = :user_id ";
- $requests_sql_params['user_id'] = $current_user->id;
- }
-
- $requests = \ResourceRequest::findBySql(
- $requests_sql,
- $requests_sql_params
- );
- }
-
- $merged_objects = [];
- $metadates = [];
-
- foreach ($bookings as $booking) {
- $booking->resource = $resource;
- $irrelevant_booking = false;
- if ($booking->getRepetitionType() != 'weekly') {
- if (!\Request::get('display_single_bookings')) {
- $irrelevant_booking = true;
- } else if ($booking->end < strtotime('today')) {
- $irrelevant_booking = true;
- }
- }
- if ($booking->getAssignedUserType() === 'course' && in_array($booking->assigned_course_date->metadate_id, $metadates)) {
- $irrelevant_booking = true;
- };
- if (!$irrelevant_booking) {
- //It is an booking with repetitions that has to be included
- //in the semester plan.
- if (in_array($booking->getRepetitionType(), ['single','weekly'])) {
- $event_list = $booking->convertToEventData([\ResourceBookingInterval::build(['interval_id' => md5(uniqid()), 'begin' => $booking->begin - $booking->preparation_time, 'end' => $booking->end])], $current_user);
- } else {
- $event_list = $booking->getFilteredEventData(null,null,null,strtotime('today'), $end_timestamp);
- }
- foreach ($event_list as $event_data) {
- if ($booking->getAssignedUserType() === 'course' && $booking->assigned_course_date->metadate_id) {
- $index = sprintf(
- '%1$s_%2$s_%3$s',
- $booking->assigned_course_date->metadate_id,
- $event_data->begin->format('NHis'),
- $event_data->end->format('NHis')
- );
- $metadates[] = $booking->assigned_course_date->metadate_id;
- } else {
- $index = sprintf(
- '%1$s_%2$s_%3$s',
- $booking->id,
- $event_data->begin->format('NHis'),
- $event_data->end->format('NHis')
- );
- }
-
- //Strip some data that cannot be used effectively in here:
- $event_data->api_urls = [];
- $event_data->editable = false;
-
- $merged_objects[$index] = $event_data;
- }
- }
- }
-
- foreach ($requests as $request) {
- if ($request->cycle instanceof \SeminarCycleDate) {
- $cycle_dates = $request->cycle->getAllDates();
- foreach ($cycle_dates as $cycle_date) {
- $relevant_request = $semester->beginn <= $cycle_date->date
- && $semester->ende >= $cycle_date->date;
- if ($relevant_request) {
- //We have found a date for the current semester
- //that makes the request relevant.
- break;
- }
- }
- if (!$relevant_request) {
- continue;
- }
- $event_data_list = $request->getFilteredEventData(
- $current_user->id
- );
-
- foreach ($event_data_list as $event_data) {
- $index = sprintf(
- '%1$s_%2$s_%3$s',
- $request->metadate_id,
- $event_data->begin->format('NHis'),
- $event_data->end->format('NHis')
- );
-
- //Strip some data that cannot be used effectively in here:
- $event_data->view_urls = [];
- $event_data->api_urls = [];
-
- $merged_objects[$index] = $event_data;
- }
- }
- }
-
- //Convert the merged events to Fullcalendar events:
- $data = [];
- foreach ($merged_objects as $obj) {
- $data[] = $obj->toFullCalendarEvent();
- }
-
- return $data;
- }
-
-
- /**
- * Gets request of a resource. At your option the requests can be
- * limited to a specific time range, specified by the parameters
- * begin and end. Furthermore the requests can be filtered by user-ID.
- *
- * @param begin: A timestamp specifying the begin of the time range.
- * @param end: A timestamp specifying the end of the time range.
- * @param user_id: This parameter limits the result set to requests
- * of the user specified by the user-ID provided in this parameter.
- *
- * @get /resources/resource/:resource_id/requests
- */
- public function getResourceRequests($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'user')) {
- throw new \AccessDeniedException();
- }
-
- $begin = $this->data['begin'];
- $end = $this->data['end'];
- $user_id = $this->data['user_id'];
-
- $sql = 'resource_id = :resource_id ';
- $sql_array = [
- 'resource_id' => $resource->id
- ];
-
- if ($begin and $end) {
- $sql .= 'AND ((begin >= :begin AND begin <= :end)
- OR
- (end >= :begin AND end <= :end)) ';
- $sql_array['begin'] = $begin;
- $sql_array['end'] = $end;
- }
-
- if ($user_id) {
- $sql .= 'AND user_id = :user_id ';
- $sql_array['user_id'] = $user_id;
- }
-
- $sql .= 'ORDER BY mkdate ASC';
-
- $requests = \ResourceRequest::findBySql($sql, $sql_array);
-
- $result = [];
- foreach ($requests as $request) {
- $result[] = $request->toRawArray();
- }
-
- return $result;
- }
-
-
- /**
- *
- * @param begin: A timestamp specifying the begin of the time range.
- * @param end: A timestamp specifying the end of the time range.
- * @param user_id: This parameter limits the result set to bookings
- * of the user specified by the user-ID provided in this parameter.
- * @param types: Limits the result to booking types specified in this
- * parameter. The allowed types are comma separated like this: "1,2,3".
- * The defined types are:
- * 0 = normal booking, 1 = reservation, 2 = lock.
- *
- * @get /resources/resource/:resource_id/bookings
- */
- public function getResourceBookings($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'user')) {
- throw new \AccessDeniedException();
- }
-
- $begin = \Request::get('begin');
- $end = \Request::get('end');
- $user_id = \Request::get('user_id');
- $types = [];
- $types_str = \Request::get('types');
- if ($types_str) {
- $types = explode(',', $types_str);
- }
-
- $sql = 'resource_id = :resource_id ';
- $sql_array = [
- 'resource_id' => $resource->id
- ];
-
- if ($begin and $end) {
- $sql .= 'AND ((begin >= :begin AND begin <= :end)
- OR
- (end >= :begin AND end <= :end)) ';
- $sql_array['begin'] = $begin;
- $sql_array['end'] = $end;
- }
-
- if ($user_id) {
- $sql .= 'AND user_id = :user_id ';
- $sql_array['user_id'] = $user_id;
- }
- if ($types) {
- $sql .= 'AND booking_type IN ( :types ) ';
- $sql_array['types'] = $types;
- }
-
- $sql .= 'ORDER BY mkdate ASC';
-
- $bookings = \ResourceBooking::findBySql($sql, $sql_array);
-
- $result = [];
- if ($bookings) {
- foreach ($bookings as $booking) {
- $result[] = $booking->toRawArray();
- }
- }
-
- return $result;
- }
-
-
- /**
- * Creates a booking/reservation/lock for a resource.
- *
- * @param begin: The begin timestamp for the booking.
- * @param end: The end timestamp for the booking.
- * @param preparation_time: The amount of seconds for preparation time
- * before the begin timestamp.
- * @param internal_comment: A comment that is only visible for some
- * parts of the staff.
- * @param booking_type: The booking type:
- * 0 = normal booking
- * 1 = reservation
- * 2 = lock
- *
- * @post /resources/resource/:resource_id/assign
- */
- public function createResourceBooking($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'user')) {
- throw new \AccessDeniedException();
- }
-
- $begin_str = \Request::get('begin');
- $end_str = \Request::get('end');
- $preparation_time = \Request::int('preparation_time');
- $internal_comment = \Request::get('internal_comment');
- $booking_type = \Request::int('booking_type');
-
- $begin = new \DateTime();
- $begin->setTimestamp($begin_str);
- $end = new \DateTime();
- $end->setTimestamp($end_str);
-
- try {
- $booking = $resource->createSimpleBooking(
- \User::findCurrent(),
- $begin,
- $end,
- $preparation_time,
- $internal_comment,
- $booking_type
- );
- return $booking;
- } catch (\Exception $e) {
- $this->halt(
- 400,
- $e->getMessage()
- );
- }
- }
-
-
- /**
- * Creates a resource request.
- *
- * @post /resources/resource/:resource_id/request_simple
- */
- public function createSimpleResourceRequest($resource_id)
- {
- $resource = \Resource::find($resource_id);
- if (!$resource) {
- $this->notFound('Resource object not found!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- $user = \User::findCurrent();
- if (!$resource->userHasPermission($user, 'user')) {
- throw new \AccessDeniedException();
- }
-
- $begin_str = \Request::get('begin');
- $end_str = \Request::get('end');
- $comment = \Request::get('comment');
-
- $begin = new \DateTime();
- $begin->setTimestamp($begin_str);
- $end = new \DateTime();
- $end->setTimestamp($end_str);
-
- try {
- $request = $resource->createSimpleRequest(
- $user,
- $begin,
- $end,
- $comment
- );
- return $request;
- } catch (\Exception $e) {
- $this->halt(
- 400,
- $e->getMessage()
- );
- }
- }
-
-
- /**
- * Change the status of a resource booking interval:
- * @post /resources/booking_interval/:interval_id/toggle_takes_place
- */
- public function toggleResourceBookingIntervalTakesPlaceField($interval_id)
- {
- $interval = \ResourceBookingInterval::find($interval_id);
- if (!$interval) {
- $this->notFound('ResourceBookingInterval object not found!');
- }
-
- //Get the resource and check the permissions of the user:
- $resource = $interval->resource;
- if (!$resource) {
- $this->halt(500, 'ResourceBookingInterval not linked with a resource!');
- }
-
- $resource = $resource->getDerivedClassInstance();
-
- if (!$resource->userHasPermission(\User::findCurrent(), 'autor', [$interval->begin, $interval->end])) {
- $this->halt(403, 'You do not have sufficient permissions to modify the interval!');
- }
-
- if (
- !$interval->takes_place
- && $resource->isAssigned(new \DateTime('@' . $interval->begin), new \DateTime('@' . $interval->end))
- ) {
- $this->halt(409, 'Already booked');
- }
- //Switch the takes_place field:
- $interval->takes_place = $interval->takes_place ? '0' : '1';
-
- if ($interval->store()) {
- return [
- 'takes_place' => $interval->takes_place
- ];
- } else {
- $this->halt(500, 'Error while storing the interval!');
- }
- }
-}
diff --git a/app/routes/RoomClipboard.php b/app/routes/RoomClipboard.php
deleted file mode 100644
index ffcafe6..0000000
--- a/app/routes/RoomClipboard.php
+++ /dev/null
@@ -1,322 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * This file contains the REST class for room clipboards
- * (clipboards containing room resources).
- *
- * @author Moritz Strohm <strohm@data-quest.de>
- * @copyright 2017-2019
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @since 4.5
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- */
-class RoomClipboard extends \RESTAPI\RouteMap
-{
- //Room clipboard routes:
-
- /**
- * Returns the request/booking plan for a room clipboard.
- *
- * @get /room_clipboard/:clipboard_id/booking_plan
- */
- public function getPlan($clipboard_id = null)
- {
- if (!$clipboard_id) {
- $this->notFound('ID of clipboard has not been provided!');
- }
-
- $clipboard = \Clipboard::find($clipboard_id);
- if (!$clipboard) {
- $this->notFound('Clipboard object not found!');
- }
-
- $current_user = \User::findCurrent();
-
- //Permission check:
- if ($clipboard->user_id !== $current_user->id) {
- throw new \AccessDeniedException();
- }
-
- $display_requests = \Request::bool('display_requests');
- $display_all_requests = \Request::bool('display_all_requests');
-
- $begin_date = \Request::get('start');
- $end_date = \Request::get('end');
- if (!$begin_date || !$end_date) {
- //No time range specified.
- $this->halt(400, 'The parameters "start" and "end" are missing!');
- return;
- }
-
- //Try the ISO format first: YYYY-MM-DDTHH:MM:SS±ZZ:ZZ
- $begin = \DateTime::createFromFormat(\DateTime::RFC3339, $begin_date);
- $end = \DateTime::createFromFormat(\DateTime::RFC3339, $end_date);
-
- if (!($begin instanceof \DateTime) || !($end instanceof \DateTime)) {
- $begin = new \DateTime();
- $end = new \DateTime();
- //Assume the local timezone and use the Y-m-d format:
- $date_regex = '/[0-9]{4}-(0[1-9]|1[0-2])-([0-2][0-9]|3[0-1])/';
- if (preg_match($date_regex, $begin_date)) {
- //$begin is specified in the date formay YYYY-MM-DD:
- $begin_str = explode('-', $begin_date);
- $begin->setDate(
- intval($begin_str[0]),
- intval($begin_str[1]),
- intval($begin_str[2])
- );
- $begin->setTime(0,0,0);
- } else {
- $begin->setTimestamp($begin_date);
- }
- //Now we do the same for $end_timestamp:
- if (preg_match($date_regex, $end_date)) {
- //$begin is specified in the date formay YYYY-MM-DD:
- $end_str = explode('-', $end_date);
- $end->setDate(
- intval($end_str[0]),
- intval($end_str[1]),
- intval($end_str[2])
- );
- $end->setTime(23,59,59);
- } else {
- $end->setTimestamp($end_date);
- }
- }
-
- //Check if a clipboard is selected:
- $selected_clipboard_id = $_SESSION['selected_clipboard_id'];
-
- $rooms = [];
- if ($clipboard_id) {
- $clipboard = \Clipboard::find($clipboard_id);
- } elseif ($selected_clipboard_id) {
- $clipboard = \Clipboard::find($selected_clipboard_id);
- } else {
- $this->halt(400, 'No clipboard selected!');
- }
- if ($clipboard) {
- $rooms = \Room::findMany($clipboard->getAllRangeIds('Room'));
- } else {
- $this->halt(404, 'Clipboard not found!');
- }
-
- $booking_types = \Request::getArray('booking_types');
-
- //Room permission check:
- $plan_objects = [];
- foreach ($rooms as $room) {
- if ($room->bookingPlanVisibleForuser($current_user)) {
- $plan_objects = array_merge(
- $plan_objects,
- \ResourceManager::getBookingPlanObjects(
- $room,
- [
- [
- 'begin' => $begin->getTimestamp(),
- 'end' => $end->getTimestamp()
- ]
- ],
- $booking_types,
- $display_all_requests ? 'all' : $display_requests
- )
- );
- }
- }
-
- $data = \Studip\Fullcalendar::createData($plan_objects, $begin, $end);
-
- return $data;
- }
-
-
- /**
- * Returns the semester plan for a room clipboard.
- *
- * @get /room_clipboard/:clipboard_id/semester_plan
- */
- public function getSemeterPlan($clipboard_id = null)
- {
- if (!$clipboard_id) {
- $this->notFound('ID of clipboard has not been provided!');
- }
-
- $clipboard = \Clipboard::find($clipboard_id);
- if (!$clipboard) {
- $this->notFound('Clipboard object not found!');
- }
-
- $current_user = \User::findCurrent();
-
- //Permission check:
- if ($clipboard->user_id !== $current_user->id) {
- throw new \AccessDeniedException();
- }
-
- $display_requests = \Request::bool('display_requests');
- $display_all_requests = \Request::bool('display_all_requests');
-
- $begin = new \DateTime();
- $end = new \DateTime();
-
- $semester_id = \Request::get('semester_id');
- $semester = null;
-
- if ($semester_id) {
- $semester = \Semester::find($semester_id);
- if (!$semester) {
- $this->halt(404, 'Specified semester not found!');
- }
- } else {
- $semester = \Semester::findCurrent();
- if (!$semester) {
- $this->halt(500, 'Current semester not available!');
- }
- }
-
- if (\Request::get('semester_timerange') == 'vorles') {
- $begin->setTimestamp($semester->vorles_beginn);
- $end->setTimestamp($semester->vorles_ende);
- } else {
- $begin->setTimestamp($semester->beginn);
- $end->setTimestamp($semester->ende);
- }
-
- //Check if a clipboard is selected:
- $selected_clipboard_id = $_SESSION['selected_clipboard_id'];
-
- $rooms = [];
- if ($clipboard_id) {
- $clipboard = \Clipboard::find($clipboard_id);
- } elseif ($selected_clipboard_id) {
- $clipboard = \Clipboard::find($selected_clipboard_id);
- } else {
- $this->halt(400, 'No clipboard selected!');
- }
- if ($clipboard) {
- $rooms = \Room::findMany($clipboard->getAllRangeIds('Room'));
- } else {
- $this->halt(404, 'Clipboard not found!');
- }
-
- //Get parameters:
- $booking_types = \Request::getArray('booking_types');
-
- //Get the event data sources:
- $plan_objects = [];
-
- foreach ($rooms as $room) {
- if ($room->bookingPlanVisibleForuser($current_user)) {
- $plan_objects = array_merge(
- $plan_objects,
- \ResourceManager::getBookingPlanObjects(
- $room,
- [
- [
- 'begin' => $begin->getTimestamp(),
- 'end' => $end->getTimestamp()
- ]
- ],
- $booking_types,
- $display_all_requests ? 'all' : $display_requests
- )
- );
- }
- }
-
- $merged_objects = [];
- $metadates = [];
- foreach ($plan_objects as $plan_object) {
- if ($plan_object instanceof \ResourceBooking) {
- $irrelevant_booking =
- $plan_object->getRepetitionType() != 'weekly' ||
- ($plan_object->getAssignedUserType() === 'course' && in_array($plan_object->assigned_course_date->metadate_id, $metadates));
- if ($irrelevant_booking) {
- continue;
- }
-
- //It is a booking with repetitions that has to be included
- //in the semester plan.
-
- $real_begin = $plan_object->begin;
- if ($plan_object->preparation_time > 0) {
- $real_begin -= $plan_object->preparation_time;
- }
- $event_data = $plan_object->convertToEventData([\ResourceBookingInterval::build(['interval_id' => md5(uniqid()), 'begin' => $real_begin, 'end' => $plan_object->end])], $current_user);
-
- //Merge event data from the same booking that have the
- //same weekday and begin and end time into one event.
- //If no repetition interval is set and the booking belongs
- //to a course date, use the corresponding metadate ID or the
- //course date ID in the index. Otherwise use the booking's
- //ID (specified by event_data->object_id).
- foreach ($event_data as $event) {
- if ($plan_object->getAssignedUserType() === 'course') {
- $index = sprintf(
- '%1$s_%2$s_%3$s',
- $plan_object->assigned_course_date->metadate_id,
- $event->begin->format('NHis'),
- $event->end->format('NHis')
- );
- $metadates[] = $plan_object->assigned_course_date->metadate_id;
- } else {
- $index = sprintf(
- '%1$s_%2$s_%3$s',
- $plan_object->id,
- $event->begin->format('NHis'),
- $event->end->format('NHis')
- );
- }
-
- //Strip some data that cannot be used effectively in here:
- $event->api_urls = [];
-
- $merged_objects[$index] = $event;
- }
- } elseif ($plan_object instanceof \ResourceRequest) {
- if ($plan_object->cycle instanceof \SeminarCycleDate) {
- $cycle_dates = $plan_object->cycle->getAllDates();
- foreach ($cycle_dates as $cycle_date) {
- $relevant_request = $semester->beginn <= $cycle_date->date
- && $semester->ende >= $cycle_date->date;
- if ($relevant_request) {
- //We have found a date for the current semester
- //that makes the request relevant.
- break;
- }
- }
- if (!$relevant_request) {
- continue;
- }
- $event_data_list = $plan_object->getFilteredEventData(
- $current_user->id
- );
-
- foreach ($event_data_list as $event_data) {
- $index = sprintf(
- '%1$s_%2$s_%3$s',
- $plan_object->metadate_id,
- $event_data->begin->format('NHis'),
- $event_data->end->format('NHis')
- );
-
- //Strip some data that cannot be used effectively in here:
- $event_data->view_urls = [];
- $event_data->api_urls = [];
-
- $merged_objects[$index] = $event_data;
- }
- }
- }
- }
-
- //Convert the merged events to Fullcalendar events:
- $data = [];
- foreach ($merged_objects as $obj) {
- $data[] = $obj->toFullCalendarEvent();
- }
-
- return $data;
- }
-}
diff --git a/app/routes/Schedule.php b/app/routes/Schedule.php
deleted file mode 100644
index 2341f73..0000000
--- a/app/routes/Schedule.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @author André Klaßen <andre.klassen@elan-ev.de>
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition user_id ^[a-f0-9]{1,32}$
- * @condition semester_id ^[a-f0-9]{1,32}$
- */
-class Schedule extends \RESTAPI\RouteMap
-{
- /**
- * returns schedule for a given user and semester
- *
- * @get /user/:user_id/schedule/:semester_id
- * @get /user/:user_id/schedule
- */
- public function getSchedule($user_id, $semester_id = null)
- {
- if ($user_id !== $GLOBALS['user']->id) {
- $this->error(401);
- }
-
- $current_semester = isset($semester_id)
- ? \Semester::find($semester_id)
- : \Semester::findCurrent();
-
- if (!$current_semester) {
- $this->notFound('No such semester.');
- }
-
- $schedule_settings = \UserConfig::get($user_id)->SCHEDULE_SETTINGS;
- $days = \CalendarScheduleModel::getDisplayedDays($schedule_settings['glb_days']);
-
- $entries = \CalendarScheduleModel::getEntries(
- $user_id, $current_semester,
- $schedule_settings['glb_start_time'], $schedule_settings['glb_end_time'],
- $days,
- $visible = false
- );
-
- $json = [];
- foreach ($entries as $number_of_day => $schedule_of_day) {
- $entries = [];
- foreach ($schedule_of_day->entries as $entry) {
- $entries[$entry['id']] = self::entryToJson($entry);
- }
- $json[$number_of_day] = $entries;
- }
-
- $this->etag(md5(serialize($json)));
-
- return array_reverse($json, true);
- }
-
-
- private static function entryToJson($entry)
- {
- $json = [];
- foreach (['start', 'end', 'content', 'title', 'color', 'type'] as $key) {
- $json[$key] = in_array($key, ['start', 'end'])
- ? (int) $entry[$key]
- : $entry[$key];
- }
-
- return $json;
- }
-}
diff --git a/app/routes/Semester.php b/app/routes/Semester.php
deleted file mode 100644
index bdb1ee7..0000000
--- a/app/routes/Semester.php
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @author Jan-Hendrik Willms <tleilax+studip@gmail.com>
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition semester_id ^[0-9a-f]{1,32}$
- */
-class Semester extends \RESTAPI\RouteMap
-{
- public function __construct()
- {
- parent::__construct();
- if (!\Request::int('limit')) {
- $this->limit = count(\Semester::getAll());
- }
- }
-
- /**
- * Returns a list of all semesters.
- *
- * @get /semesters
- * @allow_nobody
- */
- public function getSemesters()
- {
- $semesters = \Semester::getAll();
-
- // paginate
- $total = count($semesters);
- $semesters = array_slice($semesters, $this->offset, $this->limit);
-
- $json = [];
- foreach ($semesters as $semester) {
- $url = $this->urlf('/semester/%s', $semester['semester_id']);
- $json[$url] = $this->semesterToJSON($semester);
- }
-
- return $this->paginated($json, $total);
- }
-
- /**
- * Returns the semester week as string for a given string
- *
- * @get /semester/:timestamp/week
- * @allow_nobody
- */
- public function getSemesterWeek(int $timestamp)
- {
- $semester = \Semester::findByTimestamp($timestamp);
- if (!$semester) {
- return null;
- }
- $timestamp = strtotime('today', $timestamp);
- $week_begin_timestamp = strtotime('monday this week', $semester->vorles_beginn);
- $end_date = $semester->vorles_ende;
-
- $i = 0;
- $result = [
- 'semester_name' => (string)$semester->name,
- 'week_number' => sprintf(_('KW %u'), date('W', $timestamp)),
- 'current_day' => strftime('%x', $timestamp)
- ];
- while ($week_begin_timestamp < $end_date) {
- $next_week_timestamp = strtotime('+1 week', $week_begin_timestamp);
- if ($week_begin_timestamp <= $timestamp && $timestamp < $next_week_timestamp) {
- $result['sem_week'] = sprintf(
- _('%u. Vorlesungswoche (ab %s)'),
- $i + 1,
- strftime('%x', $week_begin_timestamp));
- break;
- }
- $i += 1;
-
- $week_begin_timestamp = $next_week_timestamp;
- }
-
- return $result;
- }
-
- /**
- * Returns a single semester.
- *
- * @get /semester/:semester_id
- */
- public function getSemester($id)
- {
- $semester = \Semester::find($id);
- if (!$semester) {
- $this->notFound();
- }
-
- $semester_json = $this->semesterToJSON($semester);
- $this->etag(md5(serialize($semester_json)));
-
- return $semester_json;
- }
-
- private function semesterToJSON($semester)
- {
- return [
- 'id' => $semester['semester_id'],
- 'title' => (string) $semester['name'],
- 'token' => (string) $semester['semester_token'],
- 'begin' => (int) $semester['beginn'],
- 'end' => (int) $semester['ende'],
- 'seminars_begin' => (int) $semester['vorles_beginn'],
- 'seminars_end' => (int) $semester['vorles_ende'],
- 'visible' => (int) $semester['visible'],
- ];
- }
-}
diff --git a/app/routes/Studip.php b/app/routes/Studip.php
deleted file mode 100644
index 749a53a..0000000
--- a/app/routes/Studip.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-use Config;
-use SemClass;
-use SemType;
-
-/**
- * @author Jan-Hendrik Willms <tleilax+studip@gmail.com>
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- */
-class Studip extends \RESTAPI\RouteMap
-{
- /**
- * Grundlegende Systemeinstellungen
- *
- * @get /studip/settings
- */
- public function getSettings()
- {
- $sem_types = array_map(function ($item) {
- return [
- 'name' => $item['name'],
- 'class' => $item['class'],
- ];
- }, SemType::getTypes());
-
- $sem_classes = array_map(function ($item) {
- $item = (array) $item;
- return reset($item);
- }, SemClass::getClasses());
-
- return [
- 'ALLOW_CHANGE_USERNAME' => Config::get()->ALLOW_CHANGE_USERNAME,
- 'ALLOW_CHANGE_EMAIL' => Config::get()->ALLOW_CHANGE_EMAIL,
- 'ALLOW_CHANGE_NAME' => Config::get()->ALLOW_CHANGE_NAME,
- 'ALLOW_CHANGE_TITLE' => Config::get()->ALLOW_CHANGE_TITLE,
- 'INST_TYPE' => $GLOBALS['INST_TYPE'],
- 'SEM_TYPE' => $sem_types,
- 'SEM_CLASS' => $sem_classes,
- 'TERMIN_TYP' => $GLOBALS['TERMIN_TYP'],
- 'PERS_TERMIN_KAT' => $GLOBALS['PERS_TERMIN_KAT'],
- 'SUPPORT_EMAIL' => $GLOBALS['UNI_CONTACT'],
- 'TITLES' => $GLOBALS['DEFAULT_TITLE_FOR_STATUS'],
- 'UNI_NAME_CLEAN' => Config::get()->UNI_NAME_CLEAN,
- ];
- }
-
- /**
- * Farbeinstellungen
- *
- * @get /studip/colors
- */
- public function getColors()
- {
- // TODO: Move these definitions somewhere else (but where!?)
- return [
- 'background' => '#e1e4e9',
- 'dark' => '#34578c',
- 'light' => '#899ab9',
- ];
- }
-}
diff --git a/app/routes/User.php b/app/routes/User.php
deleted file mode 100644
index d3cce26..0000000
--- a/app/routes/User.php
+++ /dev/null
@@ -1,300 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @author André Klaßen <andre.klassen@elan-ev.de>
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition user_id ^[0-9a-f]{1,32}$
- */
-class User extends \RESTAPI\RouteMap
-{
- /**************************************************/
- /* PUBLIC STATIC HELPER METHODS */
- /**************************************************/
-
- public static function getMiniUser($routemap, $user)
- {
- $avatar = \Avatar::getAvatar($user->id);
-
- return [
- 'id' => $user->id,
- 'href' => $routemap->urlf('/user/%s', [htmlReady($user->id)]),
- 'name' => self::getNamesOfUser($user),
- 'avatar_small' => $avatar->getURL(\Avatar::SMALL),
- 'avatar_medium' => $avatar->getURL(\Avatar::MEDIUM),
- 'avatar_normal' => $avatar->getURL(\Avatar::NORMAL),
- 'avatar_original' => $avatar->getURL(\Avatar::NORMAL)
- ];
- }
-
- public static function getNamesOfUser($user)
- {
- $name = [
- 'username' => $user->username,
- 'formatted' => $user->getFullName(),
- 'family' => $user->nachname,
- 'given' => $user->vorname,
- 'prefix' => $user->title_front,
- 'suffix' => $user->title_rear
- ];
- return $name;
- }
-
-
- /**************************************************/
- /* ROUTES */
- /**************************************************/
-
- /**
- * Searches for users by a given keyword.
- *
- * @get /users
- */
- public function searchUsers()
- {
- $needle = \Request::get('q') ?? \Request::get('needle');
- if (!$needle) {
- $this->halt(400, 'Missing search paramter ?q=');
- }
-
- $query = \GlobalSearchUsers::getSQL($needle, [], $this->offset + $this->limit);
- $result = \DBManager::get()->fetchAll($query);
- $total = (int) \DBManager::get()->fetchColumn('SELECT FOUND_ROWS() as found_rows');
-
- $user_ids = array_column($result, 'user_id');
- $users = \User::findMany($user_ids);
-
- return $this->paginated(
- array_map(function ($user) {
- return self::getMiniUser($this, $user);
- }, $users),
- $total
- );
- }
-
-
- /**
- * getUser - retrieves data of a user
- *
- * @get /user/:user_id
- * @get /user
- */
- public function getUser($user_id = '')
- {
- $user_id = $user_id ?: $GLOBALS['user']->id;
-
- $user = \User::findFull($user_id);
- if (!$user) {
- $this->halt(404, sprintf('User %s not found', $user_id));
- }
-
- $visibilities = get_local_visibility_by_id($user_id, 'homepage');
- if (is_array(json_decode($visibilities, true))) {
- $visibilities = json_decode($visibilities, true);
- } else {
- $visibilities = [];
- }
-
- $get_field = function ($field, $visibility) use ($user_id, $user, $visibilities) {
- if (!$user[$field]
- || !is_element_visible_for_user($GLOBALS['user']->id, $user_id, $visibilities[$visibility]))
- {
- return '';
- }
- return $user[$field];
- };
-
- $avatar = \Avatar::getAvatar($user_id);
-
- $user = [
- 'user_id' => $user_id,
- 'username' => $user['username'],
- 'name' => self::getNamesOfUser($user),
- 'perms' => $user['perms'],
- 'email' => get_visible_email($user_id),
- 'avatar_small' => $avatar->getURL(\Avatar::SMALL),
- 'avatar_medium' => $avatar->getURL(\Avatar::MEDIUM),
- 'avatar_normal' => $avatar->getURL(\Avatar::NORMAL),
- 'avatar_original' => $avatar->getURL(\Avatar::NORMAL),
- 'phone' => $get_field('privatnr', 'private_phone'),
- 'homepage' => $get_field('Home', 'homepage'),
- 'privadr' => strip_tags($get_field('privadr', 'privadr')),
- ];
-
- // Data fields
- $datafields = [];
- foreach (\DataFieldEntry::getDataFieldEntries($user_id, 'user') as $entry) {
- if (!$entry->isVisible()) {
- continue;
- }
- if (!\Visibility::verify($entry->getID(), $user_id)) {
- continue;
- }
- $datafields[] = [
- 'type' => $entry->getType(),
- 'id' => $entry->getId(),
- 'name' => (string) $entry->getName(),
- 'value' => $entry->getValue(),
- ];
- }
- $user['datafields'] = $datafields;
-
- $this->etag(md5(serialize($user)));
-
- return $user;
-
- }
-
-
- /**
- * deleteUser - deletes a user
- *
- * @delete /user/:user_id
- */
- public function deleteUser($user_id)
- {
- if (!$GLOBALS['perm']->have_perm('root')) {
- $this->error(401);
- }
-
- if (!$GLOBALS['user']->id === $user_id) {
- $this->error(400, 'Must not delete yourself');
- }
-
- $user = \User::find($user_id);
- $user->delete();
-
- $this->status(204);
- }
-
-
- /**
- * returns institutes for a given user
- *
- * @get /user/:user_id/institutes
- */
- public function getInstitutes($user_id)
- {
- $user = \User::find($user_id);
- if (!$user) {
- $this->notFound(sprintf('User %s not found', $user_id));
- }
-
- $query = "SELECT i0.Institut_id AS institute_id, i0.Name AS name,
- inst_perms AS perms, sprechzeiten AS consultation,
- raum AS room, ui.telefon AS phone, ui.fax,
- i0.Strasse AS street, i0.Plz AS city,
- i1.Name AS faculty_name, i1.Strasse AS faculty_street,
- i1.Plz AS faculty_city
- FROM user_inst AS ui
- JOIN Institute AS i0 USING (Institut_id)
- LEFT JOIN Institute AS i1 ON (i0.fakultaets_id = i1.Institut_id)
- WHERE visible = 1 AND user_id = :user_id
- ORDER BY priority ASC";
- $statement = \DBManager::get()->prepare($query);
- $statement->bindValue(':user_id', $user_id);
- $statement->execute();
-
- $institutes = [
- 'work' => [],
- 'study' => [],
- ];
-
- foreach ($statement->fetchAll(\PDO::FETCH_ASSOC) as $row) {
- if ($row['perms'] === 'user') {
- $institutes['study'][] = $row;
- } else {
- $institutes['work'][] = $row;
- }
- }
-
- $this->etag(md5(serialize($institutes)));
-
- $result = array_slice($institutes, $this->offset, $this->limit);
- return $this->paginated(
- $result,
- count($institutes['study']) + count($institutes['work']),
- compact('user_id')
- );
- }
-
-
- /**
- * Get the root file folder of a user's file area.
- *
- * @get /user/:user_id/top_folder
- */
- public function getTopFolder($user_id)
- {
- $user = \User::find($user_id);
- if (!$user) {
- $this->notFound("User with id {$user_id} not found!");
- }
-
- if ($user->id !== \User::findCurrent()->id) {
- $this->error(403, 'You are not allowed to see another user\'s personal file area!');
- }
-
- $top_folder = \Folder::findTopFolder($user->id, 'user');
-
- if (!$top_folder) {
- $this->notFound("No folder found for user with id {$user_id}!");
- }
-
- return (new FileSystem())->getFolder($top_folder->id);
- }
-
- /**
- * Patches the course member data of a user and course. Pass data to be
- * patched via a valid json object in the body. Fields that my be patched:
- *
- * - group - the associated group in the overview of the users's courses
- * - visibility - visible state of the course
- *
- * @patch /user/:user_id/courses/:course_id
- *
- * @todo more patchable fields?
- */
- public function patchCourseGroup($user_id, $course_id)
- {
- $user = \User::find($user_id);
- if (!$user) {
- $this->notFound('User not found');
- }
-
- if ($user->id !== $GLOBALS['user']->id) {
- $this->halt(403, "You may not alter this user's data");
- }
-
- $member = \CourseMember::find([$course_id, $user->id]);
- if (!$member) {
- $this->notFound('You are not a member of the course');
- }
-
- if (isset($this->data['group'])) {
- if (!is_numeric($this->data['group']) || $this->data['group'] < 0 || $this->data['group'] > 8) {
- $this->halt(400, 'Given group is not inside the valid range 0..8');
- }
- $member->gruppe = $this->data['group'];
- }
-
- if (isset($this->data['visibility'])) {
- if (in_array($member->status, ['tutor', 'dozent'])) {
- $this->halt(400, 'You may not change the visibility status for this course since you are a teacher.');
- }
- if (!in_array($this->data['visibility'], ['yes', 'no'])) {
- $this->halt(400, 'Visibility may only be "yes" or "no".');
- }
- $member->visible = $this->data['visibility'];
- }
-
- if ($member->isDirty()) {
- $member->store();
- }
-
- $this->halt(204);
- }
-}
diff --git a/app/routes/UserConfig.php b/app/routes/UserConfig.php
deleted file mode 100644
index ba01538..0000000
--- a/app/routes/UserConfig.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-use RESTAPI\RouteMap;
-use RESTAPI\Router;
-
-/**
- * API routes for accessing user config values.
- *
- * @author Jan-Hendrik Willms <tleilax+studip@gmail.com>
- * @license GPL2 or any later version
- * @since Stud.IP 3.4
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition user_id ^[0-9a-f]{1,32}$
- *
- * @status 404 if user does not exist
- * @status 403 if user may access the request config item
- */
-class UserConfig extends RouteMap
-{
- // Stores the user's config instance
- private $config;
-
- /**
- * Performs checks if the user exists and may actually access the
- * requested config.
- *
- * @param Router $router Instance of the api router
- * @param array $handler Detected handler router
- * @param array $parameters Parameters of the called route
- */
- public function before(Router $router, array $handler, array $parameters)
- {
- // Check whether user exist
- if (\User::find($parameters['user_id']) === null) {
- $this->error(404, sprintf('User %s not found', $parameters['user_id']));
- }
-
- // Check whether user accesses own config or user is root
- if ($parameters['user_id'] !== $GLOBALS['user']->id && $GLOBALS['user']->perms !== 'root') {
- $this->error(403, 'User may only access own config');
- }
-
- $this->config = \UserConfig::get($parameters['user_id']);
- }
-
- /**
- * Returns the value of a specific config entry for a given user
- *
- * @get /user/:user_id/config/:field
- *
- * @return mixed Value for the request config item
- * @status 404 if config item does not exist
- */
- public function getConfig($user_id, $field)
- {
- // Check whether key exists in config
- if (!isset($this->config[$field])) {
- $this->error(404, sprintf('No config item for field %s and user %s',
- $field, $user_id));
- }
-
- return $this->config[$field];
- }
-
- /**
- * Stored the value of a specific config entry for a given user
- *
- * @put /user/:user_id/config/:field
- *
- * @status 204 on success
- * @status 400 if no value is given
- */
- public function setConfig($user_id, $field)
- {
- if (!isset($this->data['value'])) {
- $this->error(400, 'No value given in request');
- }
-
- $this->config->store($field, $this->data['value']);
-
- $this->status(204);
- }
-
- /**
- * Removes a specific config entry for a given user
- *
- * @delete /user/:user_id/config/:field
- *
- * @status 204 on success
- */
- public function deleteConfig($user_id, $field)
- {
- $this->config->delete($field);
-
- $this->status(204);
- }
-}
diff --git a/app/routes/Wiki.php b/app/routes/Wiki.php
deleted file mode 100644
index 7f54628..0000000
--- a/app/routes/Wiki.php
+++ /dev/null
@@ -1,148 +0,0 @@
-<?php
-namespace RESTAPI\Routes;
-
-/**
- * @author <mlunzena@uos.de>
- * @license GPL 2 or later
- * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0.
- *
- * @condition range_id ^[0-9a-f]{1,32}$
- */
-class Wiki extends \RESTAPI\RouteMap
-{
- public function before()
- {
- require_once 'User.php';
- }
-
- /**
- * Wikiseitenindex einer Veranstaltung
- *
- * @get /course/:range_id/wiki
- */
- public function getCourseWiki($range_id)
- {
- $pages = \WikiPage::findBySQL("`range_id` = ? ORDER BY `name` ASC", [$range_id]);
-
- if (!$pages[0]->isReadable()) {
- $this->error(401);
- }
-
- $total = sizeof($pages);
- $pages = $pages->limit($this->offset, $this->limit);
-
- $linked_pages = [];
- foreach ($pages as $page) {
- $url = $this->urlf('/course/%s/wiki/%s', [$range_id, htmlReady($page['keyword'])]);
- $linked_pages[$url] = $this->wikiPageToJson($page, ["content"]);
- }
-
- $this->etag(md5(serialize($linked_pages)));
-
- return $this->paginated($linked_pages, $total, compact('range_id'));
- }
-
- /**
- * Wikiseite auslesen
- *
- * @get /course/:range_id/wiki/:keyword
- * @get /course/:range_id/wiki/:keyword/:version
- */
- public function getCourseWikiKeyword($range_id, $keyword, $version = null)
- {
- $page = $this->requirePage($range_id, $keyword, $version);
- $wiki_json = $this->wikiPageToJson($page);
- $this->etag(md5(serialize($wiki_json)));
- $this->lastmodified($page->chdate);
- return $wiki_json;
- }
-
- /**
- * Wikiseite ändern/hinzufügen
- *
- * @put /course/:range_id/wiki/:keyword
- */
- public function putCourseWikiKeyword($range_id, $keyword)
- {
- if (!isset($this->data['content'])) {
- $this->error(400, 'No content provided');
- }
-
- $page =\WikiPage::findOneBySQL("`range_id` = ? AND `name` = ?", [$range_id, $keyword]);
- if (!$page) {
- $page = new \WikiPage();
- $page->range_id = $range_id;
- $page->name = $keyword;
- }
-
- if (!$page->isEditable()) {
- $this->error(401);
- }
-
- $page->content = $this->data['content'];
- $page->store();
-
- $url = sprintf('course/%s/wiki/%s/%d', htmlReady($range_id), htmlReady($keyword), count($page->versions) + 1);
- $this->redirect($url, 201, 'ok');
- }
-
- /**************************************************/
- /* PRIVATE HELPER METHODS */
- /**************************************************/
-
- private function requirePage($range_id, $keyword, $version = null)
- {
- $page = \WikiPage::findOneBySQL("`range_id` = ? AND `name` = ?", [$range_id, $keyword]);
-
- if (!$page) {
- $this->notFound();
- }
-
- if (!$page->isReadable($GLOBALS['user']->id)) {
- $this->error(401);
- }
- if ($version !== null && $version !== count($page->versions) + 1) {
- return $page->versions[count($page->versions) - 1 - $version];
- } else {
- return $page;
- }
- }
-
- private function wikiPageToJson($page, $without = [])
- {
- $json = [
- 'range_id' => $page->range_id,
- 'keyword' => $page->name,
- 'chdate' => $page->chdate,
- 'version' => 1
- ];
-
- // (pre-rendered) content
- if (!in_array('content', $without)) {
- $json['content'] = $page->content;
- $json['content_html'] = wikiReady($page->content, true, $page->range_id, $page->id);
- }
- if (!in_array('user', $without)) {
- if ($page->author) {
- $json['user'] = User::getMiniUser($this, $page->user_id);
- }
- }
-
- foreach ($without as $key) {
- if (isset($json[$key])) {
- unset($json[$key]);
- }
- }
-
- // string to int conversions as SORM does not know about ints
- foreach (['chdate', 'mkdate', 'filesize', 'downloads'] as $key) {
- if (isset($json[$key])) {
- $json[$key] = (int) $json[$key];
- }
- }
-
- return $json;
- }
-
-
-}