aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJan-Hendrik Willms <tleilax+studip@gmail.com>2023-04-20 10:34:33 +0000
committerDavid Siegfried <david.siegfried@uni-vechta.de>2023-04-20 10:34:33 +0000
commit85588e617bcfb7e79d5b65ddd26a920ecb480ce6 (patch)
treea2f90248313d68a4f36ddbd55385e7291e982fc2 /lib
parentd9f6695cd6b12fdc2c2a2748811a414ae09cc57e (diff)
introduce datepicker/datetimepicker 'disable_holidays: true' to disable holidays in the calendar, fixes #2267
Closes #2267 Merge request studip/studip!1632
Diffstat (limited to 'lib')
-rw-r--r--lib/classes/JsonApi/RouteMap.php4
-rw-r--r--lib/classes/JsonApi/Routes/Holidays/HolidaysShow.php172
2 files changed, 175 insertions, 1 deletions
diff --git a/lib/classes/JsonApi/RouteMap.php b/lib/classes/JsonApi/RouteMap.php
index 0709ef3..bffa13a 100644
--- a/lib/classes/JsonApi/RouteMap.php
+++ b/lib/classes/JsonApi/RouteMap.php
@@ -7,6 +7,7 @@ use JsonApi\Middlewares\Authentication;
use JsonApi\Middlewares\DangerousRouteHandler;
use JsonApi\Middlewares\JsonApi as JsonApiMiddleware;
use JsonApi\Middlewares\StudipMockNavigation;
+use JsonApi\Routes\Holidays\HolidaysShow;
use Slim\Routing\RouteCollectorProxy;
/**
@@ -143,6 +144,8 @@ class RouteMap
{
\PluginEngine::sendMessage(JsonApiPlugin::class, 'registerUnauthenticatedRoutes', $group);
+ $group->get('/holidays', HolidaysShow::class);
+
$group->get('/semesters', Routes\SemestersIndex::class);
$group->get('/semesters/{id}', Routes\SemestersShow::class)->setName('get-semester');
@@ -561,4 +564,3 @@ class RouteMap
$group->map(['GET', 'PATCH', 'POST', 'DELETE'], $url, $handler);
}
}
-
diff --git a/lib/classes/JsonApi/Routes/Holidays/HolidaysShow.php b/lib/classes/JsonApi/Routes/Holidays/HolidaysShow.php
new file mode 100644
index 0000000..ef3fa61
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Holidays/HolidaysShow.php
@@ -0,0 +1,172 @@
+<?php
+
+namespace JsonApi\Routes\Holidays;
+
+use GuzzleHttp\Psr7;
+use JsonApi\JsonApiIntegration\QueryParserInterface;
+use JsonApi\NonJsonApiController;
+use Neomerx\JsonApi\Exceptions\JsonApiException;
+use Neomerx\JsonApi\Schema\Error;
+use Neomerx\JsonApi\Schema\ErrorCollection;
+use Psr\Container\ContainerInterface;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use Psr\Http\Message\ResponseInterface as Response;
+
+/**
+ * List all holidays for a specific time period.
+ *
+ * Filter are allowed for year, month and days. You must specify a year in order
+ * to filter by a month and you must specify a month in order to filter by a
+ * day.
+ *
+ * If no filter is set, a filter the current year is assumed.
+ */
+final class HolidaysShow extends NonJsonApiController
+{
+ private $query_parser;
+
+ protected $allowedFilteringParameters = ['year', 'month', 'day'];
+
+ public function __construct(
+ ContainerInterface $container,
+ QueryParserInterface $queryParser
+ ) {
+ parent::__construct($container);
+
+ $this->query_parser = $queryParser;
+ }
+
+ public function __invoke(Request $request, Response $response, $args): Response
+ {
+ [$current, $end] = $this->getTimespanByFilters();
+
+ $holidays = [];
+ while ($current < $end) {
+ $holiday = holiday($current);
+ if ($holiday) {
+ $holidays[date('Y-m-d', $current)] = [
+ 'holiday' => $holiday['name'],
+ 'mandatory' => $holiday['col'] === 3,
+ ];
+ }
+
+ $current = strtotime('+1 day', $current);
+ }
+
+ return $response
+ ->withHeader('Content-Type', 'application/json')
+ ->withBody(Psr7\Utils::streamFor(json_encode($holidays)));
+ }
+
+ private function getTimespanByFilters(): array
+ {
+ $filters = $this->getFilters();
+
+ $begin = mktime(
+ 0,
+ 0,
+ 0,
+ $filters['month'] ?? 1,
+ $filters['day'] ?? 1,
+ $filters['year']
+ );
+
+ $end = mktime(
+ 23,
+ 59,
+ 59,
+ $filters['month'] ?? 12,
+ $filters['day'] ?? $this->getLastDayOfMonth($filters['year'], $filters['month'] ?? 12),
+ $filters['year']
+ );
+
+ return [$begin, $end];
+ }
+
+ private function getLastDayOfMonth(int $year, int $month): int
+ {
+ $first_of_month = mktime(0, 0, 0, $month, 1, $year);
+ $last_day_of_month = strtotime('last day of this month', $first_of_month);
+ return (int) date('d', $last_day_of_month);
+ }
+
+ /**
+ * @todo imporove error handling
+ * @return array
+ */
+ private function getFilters(): array
+ {
+ $errors = new ErrorCollection();
+
+ // Get filters
+ $filters = $this->query_parser->getFilteringParameters();
+
+ // Validate allowed filters
+ foreach ($filters as $key => $value) {
+ if (!in_array($key, $this->allowedFilteringParameters)) {
+ $errors->add(new Error(
+ 'invalid-filter-field',
+ null, null,
+ null, null,
+ 'Filter should contain only allowed values.',
+ "Cannot filter by {$key}",
+ ['filter' => $key]
+ ));
+ }
+ }
+
+ // Validate month
+ if (isset($filters['month']) && !isset($filters['year'])) {
+ $errors->add(new Error(
+ 'missing-year-filter',
+ null, null,
+ null, null,
+ 'You must not define a month filter without a year filter'
+ ));
+ } elseif (
+ isset($filters['month'])
+ && ($filters['month'] < 1 || $filters['month'] > 12)
+ ) {
+ $errors->add(new Error(
+ 'invalid-filter-value',
+ null, null,
+ null, null,
+ 'Filter should contain only allowed values.',
+ "Invalid value {$filters['month']} for month filter",
+ ['filter' => 'month', 'value' => $filters['month']]
+ ));
+ }
+
+ // Validate day
+ if (isset($filters['day']) && !isset($filters['month'])) {
+ $errors->add(new Error(
+ 'missing-month-filter',
+ null, null,
+ null, null,
+ 'You must not define a day filter without a month filter'
+ ));
+ } elseif (
+ isset($filters['day'])
+ && (
+ $filters['day'] < 1
+ || $filters['day'] > $this->getLastDayOfMonth((int) $filters['year'] ?? date('Y'), $filters['month'])
+ )
+ ) {
+ $errors->add(new Error(
+ 'invalid-filter-value',
+ null, null,
+ null, null,
+ 'Filter should contain only allowed values.',
+ "Invalid value {$filters['day']} for day filter",
+ ['filter' => 'day', 'value' => $filters['day']]
+ ));
+ }
+
+ if ($errors->count() > 0) {
+ throw new JsonApiException($errors, JsonApiException::HTTP_CODE_BAD_REQUEST);
+ }
+
+ // Apply defaults
+ return array_merge(['year' => date('Y')], $filters);
+ }
+}