diff options
| author | Jan-Hendrik Willms <tleilax+studip@gmail.com> | 2023-04-20 10:34:33 +0000 |
|---|---|---|
| committer | David Siegfried <david.siegfried@uni-vechta.de> | 2023-04-20 10:34:33 +0000 |
| commit | 85588e617bcfb7e79d5b65ddd26a920ecb480ce6 (patch) | |
| tree | a2f90248313d68a4f36ddbd55385e7291e982fc2 /lib | |
| parent | d9f6695cd6b12fdc2c2a2748811a414ae09cc57e (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.php | 4 | ||||
| -rw-r--r-- | lib/classes/JsonApi/Routes/Holidays/HolidaysShow.php | 172 |
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); + } +} |
