summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Helpers/Schedule/CalculatesTime.php24
-rw-r--r--src/Helpers/Schedule/Conference.php129
-rw-r--r--src/Helpers/Schedule/Day.php88
-rw-r--r--src/Helpers/Schedule/Event.php345
-rw-r--r--src/Helpers/Schedule/Room.php52
-rw-r--r--src/Helpers/Schedule/Schedule.php111
-rw-r--r--src/Helpers/Schedule/XmlParser.php172
-rw-r--r--src/Http/HttpClientServiceProvider.php25
-rw-r--r--src/Http/RedirectServiceProvider.php13
-rw-r--r--src/Http/Redirector.php55
-rw-r--r--src/Http/Response.php60
-rw-r--r--src/Middleware/ErrorHandler.php25
-rw-r--r--src/Middleware/LegacyMiddleware.php20
-rw-r--r--src/Models/Shifts/Schedule.php31
-rw-r--r--src/Models/Shifts/ScheduleShift.php38
-rw-r--r--src/helpers.php40
16 files changed, 1191 insertions, 37 deletions
diff --git a/src/Helpers/Schedule/CalculatesTime.php b/src/Helpers/Schedule/CalculatesTime.php
new file mode 100644
index 00000000..c9dbeea1
--- /dev/null
+++ b/src/Helpers/Schedule/CalculatesTime.php
@@ -0,0 +1,24 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Engelsystem\Helpers\Schedule;
+
+trait CalculatesTime
+{
+ /**
+ * @param string $time
+ * @return int
+ */
+ protected function secondsFromTime(string $time): int
+ {
+ $seconds = 0;
+ $duration = explode(':', $time);
+
+ foreach (array_slice($duration, 0, 2) as $key => $times) {
+ $seconds += [60 * 60, 60][$key] * $times;
+ }
+
+ return $seconds;
+ }
+}
diff --git a/src/Helpers/Schedule/Conference.php b/src/Helpers/Schedule/Conference.php
new file mode 100644
index 00000000..0819d059
--- /dev/null
+++ b/src/Helpers/Schedule/Conference.php
@@ -0,0 +1,129 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Engelsystem\Helpers\Schedule;
+
+class Conference
+{
+ use CalculatesTime;
+
+ /** @var string required */
+ protected $title;
+
+ /** @var string required */
+ protected $acronym;
+
+ /** @var string|null */
+ protected $start;
+
+ /** @var string|null */
+ protected $end;
+
+ /** @var int|null */
+ protected $days;
+
+ /** @var string|null */
+ protected $timeslotDuration;
+
+ /** @var string|null */
+ protected $baseUrl;
+
+ /**
+ * Event constructor.
+ *
+ * @param string $title
+ * @param string $acronym
+ * @param string|null $start
+ * @param string|null $end
+ * @param int|null $days
+ * @param string|null $timeslotDuration
+ * @param string|null $baseUrl
+ */
+ public function __construct(
+ string $title,
+ string $acronym,
+ ?string $start = null,
+ ?string $end = null,
+ ?int $days = null,
+ ?string $timeslotDuration = null,
+ ?string $baseUrl = null
+ ) {
+ $this->title = $title;
+ $this->acronym = $acronym;
+ $this->start = $start;
+ $this->end = $end;
+ $this->days = $days;
+ $this->timeslotDuration = $timeslotDuration;
+ $this->baseUrl = $baseUrl;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTitle(): string
+ {
+ return $this->title;
+ }
+
+ /**
+ * @return string
+ */
+ public function getAcronym(): string
+ {
+ return $this->acronym;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getStart(): ?string
+ {
+ return $this->start;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getEnd(): ?string
+ {
+ return $this->end;
+ }
+
+ /**
+ * @return int|null
+ */
+ public function getDays(): ?int
+ {
+ return $this->days;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getTimeslotDuration(): ?string
+ {
+ return $this->timeslotDuration;
+ }
+
+ /**
+ * @return int|null
+ */
+ public function getTimeslotDurationSeconds(): ?int
+ {
+ $duration = $this->getTimeslotDuration();
+ if (!$duration) {
+ return null;
+ }
+
+ return $this->secondsFromTime($duration);
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getBaseUrl(): ?string
+ {
+ return $this->baseUrl;
+ }
+}
diff --git a/src/Helpers/Schedule/Day.php b/src/Helpers/Schedule/Day.php
new file mode 100644
index 00000000..03106e8f
--- /dev/null
+++ b/src/Helpers/Schedule/Day.php
@@ -0,0 +1,88 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Engelsystem\Helpers\Schedule;
+
+use Carbon\Carbon;
+
+class Day
+{
+ /** @var string required */
+ protected $date;
+
+ /** @var Carbon required */
+ protected $start;
+
+ /** @var Carbon required */
+ protected $end;
+
+ /** @var int required */
+ protected $index;
+
+ /** @var Room[] */
+ protected $room;
+
+ /**
+ * Day constructor.
+ *
+ * @param string $date
+ * @param Carbon $start
+ * @param Carbon $end
+ * @param int $index
+ * @param Room[] $rooms
+ */
+ public function __construct(
+ string $date,
+ Carbon $start,
+ Carbon $end,
+ int $index,
+ array $rooms = []
+ ) {
+ $this->date = $date;
+ $this->start = $start;
+ $this->end = $end;
+ $this->index = $index;
+ $this->room = $rooms;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDate(): string
+ {
+ return $this->date;
+ }
+
+ /**
+ * @return Carbon
+ */
+ public function getStart(): Carbon
+ {
+ return $this->start;
+ }
+
+ /**
+ * @return Carbon
+ */
+ public function getEnd(): Carbon
+ {
+ return $this->end;
+ }
+
+ /**
+ * @return int
+ */
+ public function getIndex(): int
+ {
+ return $this->index;
+ }
+
+ /**
+ * @return Room[]
+ */
+ public function getRoom(): array
+ {
+ return $this->room;
+ }
+}
diff --git a/src/Helpers/Schedule/Event.php b/src/Helpers/Schedule/Event.php
new file mode 100644
index 00000000..ab3b39a5
--- /dev/null
+++ b/src/Helpers/Schedule/Event.php
@@ -0,0 +1,345 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Engelsystem\Helpers\Schedule;
+
+use Carbon\Carbon;
+
+class Event
+{
+ use CalculatesTime;
+
+ /** @var string required globally unique */
+ protected $guid;
+
+ /** @var int required globally unique */
+ protected $id;
+
+ /** @var Room required, string in XML */
+ protected $room;
+
+ /** @var string required */
+ protected $title;
+
+ /** @var string required */
+ protected $subtitle;
+
+ /** @var string required */
+ protected $type;
+
+ /** @var Carbon required */
+ protected $date;
+
+ /** @var string required time (hh:mm:ss || hh:mm) */
+ protected $start;
+
+ /** @var string required (h?h:mm:ss || h?h:mm) */
+ protected $duration;
+
+ /** @var string required */
+ protected $abstract;
+
+ /** @var string required globally unique */
+ protected $slug;
+
+ /** @var string required */
+ protected $track;
+
+ /** @var string|null */
+ protected $logo;
+
+ /** @var string[] id => name */
+ protected $persons;
+
+ /** @var string|null two letter code */
+ protected $language;
+
+ /** @var string|null */
+ protected $description;
+
+ /** @var string|null license (and opt out in XML, null if not recorded, empty if no license defined) */
+ protected $recording;
+
+ /** @var array href => title */
+ protected $links;
+
+ /** @var array href => name */
+ protected $attachments;
+
+ /** @var string|null */
+ protected $url;
+
+ /** @var string|null */
+ protected $videoDownloadUrl;
+
+ /** @var Carbon Calculated */
+ protected $endDate;
+
+ /**
+ * Event constructor.
+ *
+ * @param string $guid
+ * @param int $id
+ * @param Room $room
+ * @param string $title
+ * @param string $subtitle
+ * @param string $type
+ * @param Carbon $date
+ * @param string $start
+ * @param string $duration
+ * @param string $abstract
+ * @param string $slug
+ * @param string $track
+ * @param string|null $logo
+ * @param string[] $persons
+ * @param string|null $language
+ * @param string|null $description
+ * @param string|null $recording license
+ * @param array $links
+ * @param array $attachments
+ * @param string|null $url
+ * @param string|null $videoDownloadUrl
+ */
+ public function __construct(
+ string $guid,
+ int $id,
+ Room $room,
+ string $title,
+ string $subtitle,
+ string $type,
+ Carbon $date,
+ string $start,
+ string $duration,
+ string $abstract,
+ string $slug,
+ string $track,
+ ?string $logo = null,
+ array $persons = [],
+ ?string $language = null,
+ ?string $description = null,
+ string $recording = '',
+ array $links = [],
+ array $attachments = [],
+ ?string $url = null,
+ ?string $videoDownloadUrl = null
+ ) {
+ $this->guid = $guid;
+ $this->id = $id;
+ $this->room = $room;
+ $this->title = $title;
+ $this->subtitle = $subtitle;
+ $this->type = $type;
+ $this->date = $date;
+ $this->start = $start;
+ $this->duration = $duration;
+ $this->abstract = $abstract;
+ $this->slug = $slug;
+ $this->track = $track;
+ $this->logo = $logo;
+ $this->persons = $persons;
+ $this->language = $language;
+ $this->description = $description;
+ $this->recording = $recording;
+ $this->links = $links;
+ $this->attachments = $attachments;
+ $this->url = $url;
+ $this->videoDownloadUrl = $videoDownloadUrl;
+
+ $this->endDate = $this->date
+ ->copy()
+ ->addSeconds($this->getDurationSeconds());
+ }
+
+ /**
+ * @return string
+ */
+ public function getGuid(): string
+ {
+ return $this->guid;
+ }
+
+ /**
+ * @return int
+ */
+ public function getId(): int
+ {
+ return $this->id;
+ }
+
+ /**
+ * @return Room
+ */
+ public function getRoom(): Room
+ {
+ return $this->room;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTitle(): string
+ {
+ return $this->title;
+ }
+
+ /**
+ * @param string $title
+ */
+ public function setTitle(string $title): void
+ {
+ $this->title = $title;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSubtitle(): string
+ {
+ return $this->subtitle;
+ }
+
+ /**
+ * @return string
+ */
+ public function getType(): string
+ {
+ return $this->type;
+ }
+
+ /**
+ * @return Carbon
+ */
+ public function getDate(): Carbon
+ {
+ return $this->date;
+ }
+
+ /**
+ * @return string
+ */
+ public function getStart(): string
+ {
+ return $this->start;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDuration(): string
+ {
+ return $this->duration;
+ }
+
+ /**
+ * @return int
+ */
+ public function getDurationSeconds(): int
+ {
+ return $this->secondsFromTime($this->duration);
+ }
+
+ /**
+ * @return string
+ */
+ public function getAbstract(): string
+ {
+ return $this->abstract;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSlug(): string
+ {
+ return $this->slug;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTrack(): string
+ {
+ return $this->track;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getLogo(): ?string
+ {
+ return $this->logo;
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getPersons(): array
+ {
+ return $this->persons;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getLanguage(): ?string
+ {
+ return $this->language;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getDescription(): ?string
+ {
+ return $this->description;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getRecording(): ?string
+ {
+ return $this->recording;
+ }
+
+ /**
+ * @return array
+ */
+ public function getLinks(): array
+ {
+ return $this->links;
+ }
+
+ /**
+ * @return array
+ */
+ public function getAttachments(): array
+ {
+ return $this->attachments;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getUrl(): ?string
+ {
+ return $this->url;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getVideoDownloadUrl(): ?string
+ {
+ return $this->videoDownloadUrl;
+ }
+
+ /**
+ * @return Carbon
+ */
+ public function getEndDate(): Carbon
+ {
+ return $this->endDate;
+ }
+}
diff --git a/src/Helpers/Schedule/Room.php b/src/Helpers/Schedule/Room.php
new file mode 100644
index 00000000..45a09f5f
--- /dev/null
+++ b/src/Helpers/Schedule/Room.php
@@ -0,0 +1,52 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Engelsystem\Helpers\Schedule;
+
+class Room
+{
+ /** @var string required */
+ protected $name;
+
+ /** @var Event[] */
+ protected $event;
+
+ /**
+ * Room constructor.
+ *
+ * @param string $name
+ * @param Event[] $events
+ */
+ public function __construct(
+ string $name,
+ array $events = []
+ ) {
+ $this->name = $name;
+ $this->event = $events;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName(): string
+ {
+ return $this->name;
+ }
+
+ /**
+ * @return Event[]
+ */
+ public function getEvent(): array
+ {
+ return $this->event;
+ }
+
+ /**
+ * @param Event[] $event
+ */
+ public function setEvent(array $event): void
+ {
+ $this->event = $event;
+ }
+}
diff --git a/src/Helpers/Schedule/Schedule.php b/src/Helpers/Schedule/Schedule.php
new file mode 100644
index 00000000..7150480c
--- /dev/null
+++ b/src/Helpers/Schedule/Schedule.php
@@ -0,0 +1,111 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Engelsystem\Helpers\Schedule;
+
+use Carbon\Carbon;
+
+class Schedule
+{
+ /** @var string */
+ protected $version;
+
+ /** @var Conference */
+ protected $conference;
+
+ /** @var Day[] */
+ protected $day;
+
+ /**
+ * @param string $version
+ * @param Conference $conference
+ * @param Day[] $days
+ */
+ public function __construct(
+ string $version,
+ Conference $conference,
+ array $days
+ ) {
+ $this->version = $version;
+ $this->conference = $conference;
+ $this->day = $days;
+ }
+
+ /**
+ * @return string
+ */
+ public function getVersion(): string
+ {
+ return $this->version;
+ }
+
+ /**
+ * @return Conference
+ */
+ public function getConference(): Conference
+ {
+ return $this->conference;
+ }
+
+ /**
+ * @return Day[]
+ */
+ public function getDay(): array
+ {
+ return $this->day;
+ }
+
+ /**
+ * @return Room[]
+ */
+ public function getRooms(): array
+ {
+ $rooms = [];
+ foreach ($this->day as $day) {
+ foreach ($day->getRoom() as $room) {
+ $name = $room->getName();
+ $rooms[$name] = $room;
+ }
+ }
+
+ return $rooms;
+ }
+
+
+ /**
+ * @return Carbon|null
+ */
+ public function getStartDateTime(): ?Carbon
+ {
+ $start = null;
+ foreach ($this->day as $day) {
+ $time = $day->getStart();
+ if ($time > $start && $start) {
+ continue;
+ }
+
+ $start = $time;
+ }
+
+ return $start;
+ }
+
+ /**
+ * @return Carbon|null
+ */
+ public function getEndDateTime(): ?Carbon
+ {
+ $end = null;
+ foreach ($this->day as $day) {
+ $time = $day->getEnd();
+ if ($time < $end && $end) {
+ continue;
+ }
+
+ $end = $time;
+ }
+
+ return $end;
+ }
+}
diff --git a/src/Helpers/Schedule/XmlParser.php b/src/Helpers/Schedule/XmlParser.php
new file mode 100644
index 00000000..1492aaca
--- /dev/null
+++ b/src/Helpers/Schedule/XmlParser.php
@@ -0,0 +1,172 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Engelsystem\Helpers\Schedule;
+
+use Carbon\Carbon;
+use SimpleXMLElement;
+
+class XmlParser
+{
+ /** @var SimpleXMLElement */
+ protected $scheduleXML;
+
+ /** @var Schedule */
+ protected $schedule;
+
+ /**
+ * @param string $xml
+ * @return bool
+ */
+ public function load(string $xml): bool
+ {
+ $this->scheduleXML = simplexml_load_string($xml);
+
+ if (!$this->scheduleXML) {
+ return false;
+ }
+
+ $this->parseXml();
+
+ return true;
+ }
+
+ /**
+ * Parse the predefined XML content
+ */
+ protected function parseXml(): void
+ {
+ $version = $this->getFirstXpathContent('version');
+ $conference = new Conference(
+ $this->getFirstXpathContent('conference/title'),
+ $this->getFirstXpathContent('conference/acronym'),
+ $this->getFirstXpathContent('conference/start'),
+ $this->getFirstXpathContent('conference/end'),
+ (int)$this->getFirstXpathContent('conference/days'),
+ $this->getFirstXpathContent('conference/timeslot_duration'),
+ $this->getFirstXpathContent('conference/base_url')
+ );
+ $days = [];
+
+ foreach ($this->scheduleXML->xpath('day') as $day) {
+ $rooms = [];
+
+ foreach ($day->xpath('room') as $roomElement) {
+ $room = new Room(
+ (string)$roomElement->attributes()['name']
+ );
+
+ $events = $this->parseEvents($roomElement->xpath('event'), $room);
+ $room->setEvent($events);
+ $rooms[] = $room;
+ }
+
+ $days[] = new Day(
+ (string)$day->attributes()['date'],
+ new Carbon($day->attributes()['start']),
+ new Carbon($day->attributes()['end']),
+ (int)$day->attributes()['index'],
+ $rooms
+ );
+ }
+
+ $this->schedule = new Schedule(
+ $version,
+ $conference,
+ $days
+ );
+ }
+
+ /**
+ * @param SimpleXMLElement[] $eventElements
+ * @param Room $room
+ * @return array
+ */
+ protected function parseEvents(array $eventElements, Room $room): array
+ {
+ $events = [];
+
+ foreach ($eventElements as $event) {
+ $persons = $this->getListFromSequence($event, 'persons', 'person', 'id');
+ $links = $this->getListFromSequence($event, 'links', 'link', 'href');
+ $attachments = $this->getListFromSequence($event, 'attachments', 'attachment', 'href');
+
+ $recording = '';
+ $recordingElement = $event->xpath('recording')[0];
+ if ($this->getFirstXpathContent('optout', $recordingElement) == 'false') {
+ $recording = $this->getFirstXpathContent('license', $recordingElement);
+ }
+
+ $events[] = new Event(
+ (string)$event->attributes()['guid'],
+ (int)$event->attributes()['id'],
+ $room,
+ $this->getFirstXpathContent('title', $event),
+ $this->getFirstXpathContent('subtitle', $event),
+ $this->getFirstXpathContent('type', $event),
+ new Carbon($this->getFirstXpathContent('date', $event)),
+ $this->getFirstXpathContent('start', $event),
+ $this->getFirstXpathContent('duration', $event),
+ $this->getFirstXpathContent('abstract', $event),
+ $this->getFirstXpathContent('slug', $event),
+ $this->getFirstXpathContent('track', $event),
+ $this->getFirstXpathContent('logo', $event) ?: null,
+ $persons,
+ $this->getFirstXpathContent('language', $event) ?: null,
+ $this->getFirstXpathContent('description', $event) ?: null,
+ $recording,
+ $links,
+ $attachments,
+ $this->getFirstXpathContent('url', $event) ?: null,
+ $this->getFirstXpathContent('video_download_url', $event) ?: null
+ );
+ }
+
+ return $events;
+ }
+
+ /**
+ * @param string $path
+ * @param SimpleXMLElement|null $xml
+ * @return string
+ */
+ protected function getFirstXpathContent(string $path, ?SimpleXMLElement $xml = null): string
+ {
+ $element = ($xml ?: $this->scheduleXML)->xpath($path);
+
+ return $element ? (string)$element[0] : '';
+ }
+
+ /**
+ * Resolves a list from a sequence of elements
+ *
+ * @param SimpleXMLElement $element
+ * @param string $firstElement
+ * @param string $secondElement
+ * @param string $idAttribute
+ * @return array
+ */
+ protected function getListFromSequence(
+ SimpleXMLElement $element,
+ string $firstElement,
+ string $secondElement,
+ string $idAttribute
+ ): array {
+ $items = [];
+
+ foreach ($element->xpath($firstElement)[0]->xpath($secondElement) as $item) {
+ $items[(string)$item->attributes()[$idAttribute]] = (string)$item;
+ }
+
+ return $items;
+ }
+
+ /**
+ * @return Schedule
+ */
+ public function getSchedule(): Schedule
+ {
+ return $this->schedule;
+ }
+}
diff --git a/src/Http/HttpClientServiceProvider.php b/src/Http/HttpClientServiceProvider.php
new file mode 100644
index 00000000..113af713
--- /dev/null
+++ b/src/Http/HttpClientServiceProvider.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Engelsystem\Http;
+
+use Engelsystem\Container\ServiceProvider;
+use GuzzleHttp\Client as GuzzleClient;
+
+class HttpClientServiceProvider extends ServiceProvider
+{
+ public function register()
+ {
+ $this->app->when(GuzzleClient::class)
+ ->needs('$config')
+ ->give(
+ function () {
+ return [
+ // No exception on >= 400 responses
+ 'http_errors' => false,
+ // Wait max n seconds for a response
+ 'timeout' => 2.0,
+ ];
+ }
+ );
+ }
+}
diff --git a/src/Http/RedirectServiceProvider.php b/src/Http/RedirectServiceProvider.php
new file mode 100644
index 00000000..70238d91
--- /dev/null
+++ b/src/Http/RedirectServiceProvider.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Engelsystem\Http;
+
+use Engelsystem\Container\ServiceProvider;
+
+class RedirectServiceProvider extends ServiceProvider
+{
+ public function register()
+ {
+ $this->app->bind('redirect', Redirector::class);
+ }
+}
diff --git a/src/Http/Redirector.php b/src/Http/Redirector.php
new file mode 100644
index 00000000..4149a8ec
--- /dev/null
+++ b/src/Http/Redirector.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Engelsystem\Http;
+
+class Redirector
+{
+ /** @var Request */
+ protected $request;
+
+ /** @var Response */
+ protected $response;
+
+ /**
+ * @param Request $request
+ * @param Response $response
+ */
+ public function __construct(Request $request, Response $response)
+ {
+ $this->request = $request;
+ $this->response = $response;
+ }
+
+ /**
+ * @param string $path
+ * @param int $status
+ * @param array $headers
+ * @return Response
+ */
+ public function to(string $path, int $status = 302, array $headers = []): Response
+ {
+ return $this->response->redirectTo($path, $status, $headers);
+ }
+
+ /**
+ * @param int $status
+ * @param array $headers
+ * @return Response
+ */
+ public function back(int $status = 302, array $headers = []): Response
+ {
+ return $this->to($this->getPreviousUrl(), $status, $headers);
+ }
+
+ /**
+ * @return string
+ */
+ protected function getPreviousUrl(): string
+ {
+ if ($header = $this->request->getHeader('referer')) {
+ return array_pop($header);
+ }
+
+ return '/';
+ }
+}
diff --git a/src/Http/Response.php b/src/Http/Response.php
index a6b4ab74..43bcb5d8 100644
--- a/src/Http/Response.php
+++ b/src/Http/Response.php
@@ -6,27 +6,37 @@ use Engelsystem\Renderer\Renderer;
use InvalidArgumentException;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
class Response extends SymfonyResponse implements ResponseInterface
{
use MessageTrait;
+ /**
+ * @var SessionInterface
+ */
+ protected $session;
+
/** @var Renderer */
protected $renderer;
/**
- * @param string $content
- * @param int $status
- * @param array $headers
- * @param Renderer $renderer
+ * @param string $content
+ * @param int $status
+ * @param array $headers
+ * @param Renderer $renderer
+ * @param SessionInterface $session
*/
public function __construct(
$content = '',
int $status = 200,
array $headers = [],
- Renderer $renderer = null
+ Renderer $renderer = null,
+ SessionInterface $session = null
) {
$this->renderer = $renderer;
+ $this->session = $session;
+
parent::__construct($content, $status, $headers);
}
@@ -155,4 +165,44 @@ class Response extends SymfonyResponse implements ResponseInterface
{
$this->renderer = $renderer;
}
+
+ /**
+ * Sets a session attribute (which is mutable)
+ *
+ * @param string $key
+ * @param mixed|mixed[] $value
+ * @return Response
+ */
+ public function with(string $key, $value)
+ {
+ if (!$this->session instanceof SessionInterface) {
+ throw new InvalidArgumentException('Session not defined');
+ }
+
+ $data = $this->session->get($key);
+ if (is_array($data) && is_array($value)) {
+ $value = array_merge_recursive($data, $value);
+ }
+
+ $this->session->set($key, $value);
+
+ return $this;
+ }
+
+ /**
+ * Sets form data to the mutable session
+ *
+ * @param array $input
+ * @return Response
+ */
+ public function withInput(array $input)
+ {
+ if (!$this->session instanceof SessionInterface) {
+ throw new InvalidArgumentException('Session not defined');
+ }
+
+ $this->session->set('form-data', $input);
+
+ return $this;
+ }
}
diff --git a/src/Middleware/ErrorHandler.php b/src/Middleware/ErrorHandler.php
index 46e6e5a8..85f315d4 100644
--- a/src/Middleware/ErrorHandler.php
+++ b/src/Middleware/ErrorHandler.php
@@ -63,17 +63,11 @@ class ErrorHandler implements MiddlewareInterface
} catch (HttpException $e) {
$response = $this->createResponse($e->getMessage(), $e->getStatusCode(), $e->getHeaders());
} catch (ValidationException $e) {
- $response = $this->createResponse('', 302, ['Location' => $this->getPreviousUrl($request)]);
+ $response = $this->redirectBack();
+ $response->with('errors', ['validation' => $e->getValidator()->getErrors()]);
if ($request instanceof Request) {
- $session = $request->getSession();
- $errors = array_merge_recursive(
- $session->get('errors', []),
- ['validation' => $e->getValidator()->getErrors()]
- );
- $session->set('errors', $errors);
-
- $session->set('form-data', Arr::except($request->request->all(), $this->formIgnore));
+ $response->withInput(Arr::except($request->request->all(), $this->formIgnore));
}
}
@@ -140,15 +134,12 @@ class ErrorHandler implements MiddlewareInterface
}
/**
- * @param ServerRequestInterface $request
- * @return string
+ * Create a redirect back response
+ *
+ * @return Response
*/
- protected function getPreviousUrl(ServerRequestInterface $request)
+ protected function redirectBack()
{
- if ($header = $request->getHeader('referer')) {
- return array_pop($header);
- }
-
- return '/';
+ return back();
}
}
diff --git a/src/Middleware/LegacyMiddleware.php b/src/Middleware/LegacyMiddleware.php
index 8a0ff002..5e08858d 100644
--- a/src/Middleware/LegacyMiddleware.php
+++ b/src/Middleware/LegacyMiddleware.php
@@ -205,10 +205,6 @@ class LegacyMiddleware implements MiddlewareInterface
$title = admin_groups_title();
$content = admin_groups();
return [$title, $content];
- case 'admin_import':
- $title = admin_import_title();
- $content = admin_import();
- return [$title, $content];
case 'admin_shifts':
$title = admin_shifts_title();
$content = admin_shifts();
@@ -219,7 +215,7 @@ class LegacyMiddleware implements MiddlewareInterface
return [$title, $content];
}
- redirect(page_link_to('login'));
+ throw_redirect(page_link_to('login'));
return [];
}
@@ -239,9 +235,15 @@ class LegacyMiddleware implements MiddlewareInterface
return response($content, (int)$page);
}
- return response(view('layouts/app', [
- 'title' => $title,
- 'content' => msg() . $content,
- ]), 200);
+ return response(
+ view(
+ 'layouts/app',
+ [
+ 'title' => $title,
+ 'content' => msg() . $content,
+ ]
+ ),
+ 200
+ );
}
}
diff --git a/src/Models/Shifts/Schedule.php b/src/Models/Shifts/Schedule.php
new file mode 100644
index 00000000..c1eb2d9e
--- /dev/null
+++ b/src/Models/Shifts/Schedule.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Engelsystem\Models\Shifts;
+
+use Engelsystem\Models\BaseModel;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Database\Eloquent\Relations\HasMany;
+use Illuminate\Database\Query\Builder as QueryBuilder;
+
+/**
+ * @property int $id
+ * @property string $url
+ *
+ * @property-read QueryBuilder|Collection|ScheduleShift[] $scheduleShifts
+ *
+ * @method static QueryBuilder|Schedule[] whereId($value)
+ * @method static QueryBuilder|Schedule[] whereUrl($value)
+ */
+class Schedule extends BaseModel
+{
+ /** @var array Values that are mass assignable */
+ protected $fillable = ['url'];
+
+ /**
+ * @return HasMany
+ */
+ public function scheduleShifts()
+ {
+ return $this->hasMany(ScheduleShift::class);
+ }
+}
diff --git a/src/Models/Shifts/ScheduleShift.php b/src/Models/Shifts/ScheduleShift.php
new file mode 100644
index 00000000..368c60b1
--- /dev/null
+++ b/src/Models/Shifts/ScheduleShift.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Engelsystem\Models\Shifts;
+
+use Engelsystem\Models\BaseModel;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Query\Builder as QueryBuilder;
+
+/**
+ * @property int $shift_id
+ * @property int $schedule_id
+ * @property string $guid
+ *
+ * @property-read QueryBuilder|Schedule $schedule
+ *
+ * @method static QueryBuilder|ScheduleShift[] whereShiftId($value)
+ * @method static QueryBuilder|ScheduleShift[] whereScheduleId($value)
+ * @method static QueryBuilder|ScheduleShift[] whereGuid($value)
+ */
+class ScheduleShift extends BaseModel
+{
+ /** @var string The primary key for the model */
+ protected $primaryKey = 'shift_id';
+
+ /** @var string Required because it is not schedule_shifts */
+ protected $table = 'schedule_shift';
+
+ /** @var array Values that are mass assignable */
+ protected $fillable = ['shift_id', 'schedule_id', 'guid'];
+
+ /**
+ * @return BelongsTo
+ */
+ public function schedule()
+ {
+ return $this->belongsTo(Schedule::class);
+ }
+}
diff --git a/src/helpers.php b/src/helpers.php
index de140c4e..7cb17ea9 100644
--- a/src/helpers.php
+++ b/src/helpers.php
@@ -4,6 +4,7 @@ use Engelsystem\Application;
use Engelsystem\Config\Config;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Helpers\Translation\Translator;
+use Engelsystem\Http\Redirector;
use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
use Engelsystem\Http\UrlGeneratorInterface;
@@ -28,7 +29,7 @@ function app($id = null)
/**
* @return Authenticator
*/
-function auth()
+function auth(): Authenticator
{
return app('authenticator');
}
@@ -37,12 +38,25 @@ function auth()
* @param string $path
* @return string
*/
-function base_path($path = '')
+function base_path($path = ''): string
{
return app('path') . (empty($path) ? '' : DIRECTORY_SEPARATOR . $path);
}
/**
+ * @param int $status
+ * @param array $headers
+ * @return Response
+ */
+function back($status = 302, $headers = []): Response
+{
+ /** @var Redirector $redirect */
+ $redirect = app('redirect');
+
+ return $redirect->back($status, $headers);
+}
+
+/**
* Get or set config values
*
* @param string|array $key
@@ -70,12 +84,26 @@ function config($key = null, $default = null)
* @param string $path
* @return string
*/
-function config_path($path = '')
+function config_path($path = ''): string
{
return app('path.config') . (empty($path) ? '' : DIRECTORY_SEPARATOR . $path);
}
/**
+ * @param string $path
+ * @param int $status
+ * @param array $headers
+ * @return Response
+ */
+function redirect(string $path, $status = 302, $headers = []): Response
+{
+ /** @var Redirector $redirect */
+ $redirect = app('redirect');
+
+ return $redirect->to($path, $status, $headers);
+}
+
+/**
* @param string $key
* @param mixed $default
* @return Request|mixed
@@ -97,7 +125,7 @@ function request($key = null, $default = null)
* @param array $headers
* @return Response
*/
-function response($content = '', $status = 200, $headers = [])
+function response($content = '', $status = 200, $headers = []): Response
{
/** @var Response $response */
$response = app('psr7.response');
@@ -155,7 +183,7 @@ function trans($key = null, $replace = [])
* @param array $replace
* @return string
*/
-function __($key, $replace = [])
+function __($key, $replace = []): string
{
/** @var Translator $translator */
$translator = app('translator');
@@ -172,7 +200,7 @@ function __($key, $replace = [])
* @param array $replace
* @return string
*/
-function _e($key, $keyPlural, $number, $replace = [])
+function _e($key, $keyPlural, $number, $replace = []): string
{
/** @var Translator $translator */
$translator = app('translator');