From 790a04dc14839cb243034942518dc9dc54816f15 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Sun, 30 Jul 2023 18:23:01 +0200 Subject: [PATCH] Schedule Import: Moved file, initial cleanup, updated schedules --- config/routes.php | 10 +- includes/includes.php | 2 - .../Controllers/Admin/ScheduleController.php | 229 ++++++++---------- .../Schedule/Assets/schedule-basic.xml | 6 +- .../Schedule/Assets/schedule-extended.xml | 16 +- .../Schedule/Assets/schedule-minimal.xml | 4 +- 6 files changed, 115 insertions(+), 152 deletions(-) rename includes/pages/schedule/ImportSchedule.php => src/Controllers/Admin/ScheduleController.php (74%) diff --git a/config/routes.php b/config/routes.php index 8e500162..237e2a63 100644 --- a/config/routes.php +++ b/config/routes.php @@ -187,11 +187,11 @@ $route->addGroup( $route->addGroup( '/schedule', function (RouteCollector $route): void { - $route->get('', 'Admin\\Schedule\\ImportSchedule@index'); - $route->get('/edit[/{schedule_id:\d+}]', 'Admin\\Schedule\\ImportSchedule@edit'); - $route->post('/edit[/{schedule_id:\d+}]', 'Admin\\Schedule\\ImportSchedule@save'); - $route->get('/load/{schedule_id:\d+}', 'Admin\\Schedule\\ImportSchedule@loadSchedule'); - $route->post('/import/{schedule_id:\d+}', 'Admin\\Schedule\\ImportSchedule@importSchedule'); + $route->get('', 'Admin\\ScheduleController@index'); + $route->get('/edit[/{schedule_id:\d+}]', 'Admin\\ScheduleController@edit'); + $route->post('/edit[/{schedule_id:\d+}]', 'Admin\\ScheduleController@save'); + $route->get('/load/{schedule_id:\d+}', 'Admin\\ScheduleController@loadSchedule'); + $route->post('/import/{schedule_id:\d+}', 'Admin\\ScheduleController@importSchedule'); } ); diff --git a/includes/includes.php b/includes/includes.php index d8df64f7..36a05271 100644 --- a/includes/includes.php +++ b/includes/includes.php @@ -59,8 +59,6 @@ $includeFiles = [ __DIR__ . '/../includes/pages/admin_user.php', __DIR__ . '/../includes/pages/user_myshifts.php', __DIR__ . '/../includes/pages/user_shifts.php', - - __DIR__ . '/../includes/pages/schedule/ImportSchedule.php', ]; foreach ($includeFiles as $file) { diff --git a/includes/pages/schedule/ImportSchedule.php b/src/Controllers/Admin/ScheduleController.php similarity index 74% rename from includes/pages/schedule/ImportSchedule.php rename to src/Controllers/Admin/ScheduleController.php index fed44373..9ac6702d 100644 --- a/includes/pages/schedule/ImportSchedule.php +++ b/src/Controllers/Admin/ScheduleController.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Engelsystem\Controllers\Admin\Schedule; +namespace Engelsystem\Controllers\Admin; use Engelsystem\Controllers\NotificationType; use Engelsystem\Helpers\Carbon; @@ -17,7 +17,7 @@ use Engelsystem\Helpers\Uuid; use Engelsystem\Http\Request; use Engelsystem\Http\Response; use Engelsystem\Models\Location; -use Engelsystem\Models\Shifts\Schedule as ScheduleUrl; +use Engelsystem\Models\Shifts\Schedule as ScheduleModel; use Engelsystem\Models\Shifts\ScheduleShift; use Engelsystem\Models\Shifts\Shift; use Engelsystem\Models\Shifts\ShiftType; @@ -25,56 +25,28 @@ use Engelsystem\Models\User\User; use ErrorException; use GuzzleHttp\Client as GuzzleClient; use GuzzleHttp\Exception\ConnectException; +use GuzzleHttp\Exception\GuzzleException; use Illuminate\Database\Connection as DatabaseConnection; -use Illuminate\Database\Eloquent\Builder as QueryBuilder; -use Illuminate\Database\Eloquent\Collection as DatabaseCollection; use Illuminate\Support\Collection; use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -class ImportSchedule extends BaseController +class ScheduleController extends BaseController { use HasUserNotifications; - /** @var DatabaseConnection */ - protected $db; - - /** @var LoggerInterface */ - protected $log; - protected array $permissions = [ 'schedule.import', ]; - /** @var XmlParser */ - protected $parser; - - /** @var Response */ - protected $response; - - /** @var SessionInterface */ - protected $session; - - /** @var string */ - protected $url = '/admin/schedule'; - - /** @var GuzzleClient */ - protected $guzzle; + protected string $url = '/admin/schedule'; public function __construct( - Response $response, - SessionInterface $session, - GuzzleClient $guzzle, - XmlParser $parser, - DatabaseConnection $db, - LoggerInterface $log + protected Response $response, + protected GuzzleClient $guzzle, + protected XmlParser $parser, + protected DatabaseConnection $db, + protected LoggerInterface $log ) { - $this->guzzle = $guzzle; - $this->parser = $parser; - $this->response = $response; - $this->session = $session; - $this->db = $db; - $this->log = $log; } public function index(): Response @@ -82,8 +54,8 @@ class ImportSchedule extends BaseController return $this->response->withView( 'admin/schedule/index.twig', [ - 'is_index' => true, - 'schedules' => ScheduleUrl::all(), + 'is_index' => true, + 'schedules' => ScheduleModel::all(), ] ); } @@ -91,24 +63,27 @@ class ImportSchedule extends BaseController public function edit(Request $request): Response { $scheduleId = $request->getAttribute('schedule_id'); // optional - $schedule = ScheduleUrl::find($scheduleId); + $schedule = ScheduleModel::find($scheduleId); return $this->response->withView( 'admin/schedule/edit.twig', [ - 'schedule' => $schedule, + 'schedule' => $schedule, 'shift_types' => ShiftType::all()->sortBy('name')->pluck('name', 'id'), 'locations' => Location::all()->sortBy('name')->pluck('name', 'id'), ] ); } + /** + * @throws ErrorException + */ public function save(Request $request): Response { $scheduleId = $request->getAttribute('schedule_id'); // optional - /** @var ScheduleUrl $schedule */ - $schedule = ScheduleUrl::findOrNew($scheduleId); + /** @var ScheduleModel $schedule */ + $schedule = ScheduleModel::findOrNew($scheduleId); if ($request->request->has('delete')) { return $this->delete($schedule); @@ -121,12 +96,12 @@ class ImportSchedule extends BaseController } $data = $this->validate($request, [ - 'name' => 'required', - 'url' => 'required', - 'shift_type' => 'required|int', + 'name' => 'required', + 'url' => 'required', + 'shift_type' => 'required|int', 'needed_from_shift_type' => 'optional|checked', 'minutes_before' => 'int', - 'minutes_after' => 'int', + 'minutes_after' => 'int', ] + $locationsValidation); if (!ShiftType::find($data['shift_type'])) { @@ -158,12 +133,12 @@ class ImportSchedule extends BaseController 'Schedule {name}: Url {url}, Shift Type {shift_type}, ({need}), ' . 'minutes before/after {before}/{after}, for: {locations}', [ - 'name' => $schedule->name, - 'url' => $schedule->name, + 'name' => $schedule->name, + 'url' => $schedule->name, 'shift_type' => $schedule->shift_type, 'need' => $schedule->needed_from_shift_type ? 'from shift type' : 'from room', - 'before' => $schedule->minutes_before, - 'after' => $schedule->minutes_after, + 'before' => $schedule->minutes_before, + 'after' => $schedule->minutes_after, 'locations' => $for->implode(', '), ] ); @@ -173,7 +148,7 @@ class ImportSchedule extends BaseController return redirect('/admin/schedule/load/' . $schedule->id); } - protected function delete(ScheduleUrl $schedule): Response + protected function delete(ScheduleModel $schedule): Response { foreach ($schedule->scheduleShifts as $scheduleShift) { // Only guid is needed here @@ -196,6 +171,7 @@ class ImportSchedule extends BaseController } $schedule->delete(); + $this->log->info('Schedule {name} deleted', ['name' => $schedule->name]); $this->addNotification('schedule.delete.success'); return redirect('/admin/schedule'); } @@ -204,15 +180,15 @@ class ImportSchedule extends BaseController { try { /** - * @var Event[] $newEvents - * @var Event[] $changeEvents - * @var Event[] $deleteEvents - * @var Room[] $newRooms - * @var int $shiftType - * @var ScheduleUrl $scheduleUrl - * @var Schedule $schedule - * @var int $minutesBefore - * @var int $minutesAfter + * @var Event[] $newEvents + * @var Event[] $changeEvents + * @var Event[] $deleteEvents + * @var Room[] $newRooms + * @var int $shiftType + * @var ScheduleModel $scheduleModel + * @var Schedule $schedule + * @var int $minutesBefore + * @var int $minutesAfter */ list( $newEvents, @@ -220,7 +196,7 @@ class ImportSchedule extends BaseController $deleteEvents, $newRooms, , - $scheduleUrl, + $scheduleModel, $schedule ) = $this->getScheduleData($request); } catch (ErrorException $e) { @@ -231,13 +207,13 @@ class ImportSchedule extends BaseController return $this->response->withView( 'admin/schedule/load.twig', [ - 'schedule_id' => $scheduleUrl->id, - 'schedule' => $schedule, - 'locations' => [ + 'schedule_id' => $scheduleModel->id, + 'schedule' => $schedule, + 'locations' => [ 'add' => $newRooms, ], - 'shifts' => [ - 'add' => $newEvents, + 'shifts' => [ + 'add' => $newEvents, 'update' => $changeEvents, 'delete' => $deleteEvents, ], @@ -249,12 +225,12 @@ class ImportSchedule extends BaseController { try { /** - * @var Event[] $newEvents - * @var Event[] $changeEvents - * @var Event[] $deleteEvents - * @var Room[] $newRooms - * @var int $shiftType - * @var ScheduleUrl $scheduleUrl + * @var Event[] $newEvents + * @var Event[] $changeEvents + * @var Event[] $deleteEvents + * @var Room[] $newRooms + * @var int $shiftType + * @var ScheduleModel $schedule */ list( $newEvents, @@ -262,14 +238,14 @@ class ImportSchedule extends BaseController $deleteEvents, $newRooms, $shiftType, - $scheduleUrl + $schedule ) = $this->getScheduleData($request); } catch (ErrorException $e) { $this->addNotification($e->getMessage(), NotificationType::ERROR); return back(); } - $this->log('Started schedule "{name}" import', ['name' => $scheduleUrl->name]); + $this->log->info('Started schedule "{name}" import', ['name' => $schedule->name]); foreach ($newRooms as $room) { $this->createLocation($room); @@ -283,7 +259,7 @@ class ImportSchedule extends BaseController $locations ->where('name', $event->getRoom()->getName()) ->first(), - $scheduleUrl + $schedule ); } @@ -294,16 +270,16 @@ class ImportSchedule extends BaseController $locations ->where('name', $event->getRoom()->getName()) ->first(), - $scheduleUrl + $schedule ); } foreach ($deleteEvents as $event) { - $this->deleteEvent($event, $scheduleUrl); + $this->deleteEvent($event, $schedule); } - $scheduleUrl->touch(); - $this->log('Ended schedule "{name}" import', ['name' => $scheduleUrl->name]); + $schedule->touch(); + $this->log->info('Ended schedule "{name}" import', ['name' => $schedule->name]); $this->addNotification('schedule.import.success'); return redirect($this->url, 303); @@ -315,7 +291,7 @@ class ImportSchedule extends BaseController $location->name = $room->getName(); $location->save(); - $this->log('Created schedule location "{location}"', ['location' => $room->getName()]); + $this->log->info('Created schedule location "{location}"', ['location' => $room->getName()]); } protected function fireDeleteShiftEntryEvents(Event $event, ScheduleUrl $schedule): void @@ -337,19 +313,19 @@ class ImportSchedule extends BaseController foreach ($shiftEntries as $shiftEntry) { event('shift.entry.deleting', [ - 'user' => User::find($shiftEntry->user_id), - 'start' => Carbon::make($shiftEntry->start), - 'end' => Carbon::make($shiftEntry->end), - 'name' => $shiftEntry->name, - 'title' => $shiftEntry->title, - 'type' => $shiftEntry->type, - 'location' => Location::find($shiftEntry->location_id), + 'user' => User::find($shiftEntry->user_id), + 'start' => Carbon::make($shiftEntry->start), + 'end' => Carbon::make($shiftEntry->end), + 'name' => $shiftEntry->name, + 'title' => $shiftEntry->title, + 'type' => $shiftEntry->type, + 'location' => Location::find($shiftEntry->location_id), 'freeloaded' => $shiftEntry->freeloaded, ]); } } - protected function createEvent(Event $event, int $shiftTypeId, Location $location, ScheduleUrl $scheduleUrl): void + protected function createEvent(Event $event, int $shiftTypeId, Location $location, ScheduleModel $scheduleUrl): void { $user = auth()->user(); $eventTimeZone = Carbon::now()->timezone; @@ -370,14 +346,14 @@ class ImportSchedule extends BaseController $scheduleShift->shift()->associate($shift); $scheduleShift->save(); - $this->log( + $this->log->info( 'Created schedule shift "{shift}" in "{location}" ({from} {to}, {guid})', [ - 'shift' => $shift->title, + 'shift' => $shift->title, 'location' => $shift->location->name, - 'from' => $shift->start->format(DateTimeInterface::RFC3339), - 'to' => $shift->end->format(DateTimeInterface::RFC3339), - 'guid' => $scheduleShift->guid, + 'from' => $shift->start->format(DateTimeInterface::RFC3339), + 'to' => $shift->end->format(DateTimeInterface::RFC3339), + 'guid' => $scheduleShift->guid, ] ); } @@ -402,14 +378,14 @@ class ImportSchedule extends BaseController $this->fireUpdateShiftUpdateEvent($oldShift, $shift); - $this->log( + $this->log->info( 'Updated schedule shift "{shift}" in "{location}" ({from} {to}, {guid})', [ - 'shift' => $shift->title, + 'shift' => $shift->title, 'location' => $shift->location->name, - 'from' => $shift->start->format(DateTimeInterface::RFC3339), - 'to' => $shift->end->format(DateTimeInterface::RFC3339), - 'guid' => $scheduleShift->guid, + 'from' => $shift->start->format(DateTimeInterface::RFC3339), + 'to' => $shift->end->format(DateTimeInterface::RFC3339), + 'guid' => $scheduleShift->guid, ] ); } @@ -424,14 +400,14 @@ class ImportSchedule extends BaseController $this->fireDeleteShiftEntryEvents($event, $schedule); - $this->log( + $this->log->info( 'Deleted schedule shift "{shift}" in {location} ({from} {to}, {guid})', [ - 'shift' => $shift->title, + 'shift' => $shift->title, 'location' => $shift->location->name, - 'from' => $shift->start->format(DateTimeInterface::RFC3339), - 'to' => $shift->end->format(DateTimeInterface::RFC3339), - 'guid' => $scheduleShift->guid, + 'from' => $shift->start->format(DateTimeInterface::RFC3339), + 'to' => $shift->end->format(DateTimeInterface::RFC3339), + 'guid' => $scheduleShift->guid, ] ); } @@ -445,20 +421,19 @@ class ImportSchedule extends BaseController } /** - * @param Request $request * @return Event[]|Room[]|Location[] * @throws ErrorException */ - protected function getScheduleData(Request $request) + protected function getScheduleData(Request $request): array { $scheduleId = (int) $request->getAttribute('schedule_id'); - /** @var ScheduleUrl $scheduleUrl */ - $scheduleUrl = ScheduleUrl::findOrFail($scheduleId); + /** @var ScheduleModel $scheduleUrl */ + $scheduleUrl = ScheduleModel::findOrFail($scheduleId); try { $scheduleResponse = $this->guzzle->get($scheduleUrl->url); - } catch (ConnectException $e) { + } catch (ConnectException | GuzzleException) { throw new ErrorException('schedule.import.request-error'); } @@ -503,16 +478,11 @@ class ImportSchedule extends BaseController } /** - * @param Schedule $schedule - * @param ScheduleUrl $scheduleUrl - * @param int $shiftType - * @param int $minutesBefore - * @param int $minutesAfter * @return Event[] */ protected function shiftsDiff( Schedule $schedule, - ScheduleUrl $scheduleUrl, + ScheduleModel $scheduleUrl, int $shiftType, int $minutesBefore, int $minutesAfter @@ -554,6 +524,7 @@ class ImportSchedule extends BaseController $guid = $scheduleShift->guid; $shift = $scheduleShift->shift; $event = $scheduleEvents[$guid]; + /** @var Location $location */ $location = $locations->where('name', $event->getRoom()->getName())->first(); if ( @@ -607,17 +578,17 @@ class ImportSchedule extends BaseController /** * @return Location[]|Collection */ - protected function getAllLocations(): Collection + protected function getAllLocations(): Collection | array { return Location::all(); } /** - * @param ScheduleUrl $scheduleUrl - * @param string[] $events - * @return QueryBuilder[]|DatabaseCollection|Collection|ScheduleShift[] + * @param string[] $events + * + * @return Collection|ScheduleShift[] */ - protected function getScheduleShiftsByGuid(ScheduleUrl $scheduleUrl, array $events) + protected function getScheduleShiftsByGuid(ScheduleModel $scheduleUrl, array $events): Collection | array { return ScheduleShift::with('shift.location') ->whereIn('guid', $events) @@ -626,24 +597,14 @@ class ImportSchedule extends BaseController } /** - * @param ScheduleUrl $scheduleUrl - * @param string[] $events - * @return QueryBuilder[]|DatabaseCollection|Collection|ScheduleShift[] + * @param string[] $events + * @return Collection|ScheduleShift[] */ - protected function getScheduleShiftsWhereNotGuid(ScheduleUrl $scheduleUrl, array $events) + protected function getScheduleShiftsWhereNotGuid(ScheduleModel $scheduleUrl, array $events): Collection | array { return ScheduleShift::with('shift.location') ->whereNotIn('guid', $events) ->where('schedule_id', $scheduleUrl->id) ->get(); } - - /** - * @param string $message - * @param array $context - */ - protected function log(string $message, array $context = []): void - { - $this->log->info($message, $context); - } } diff --git a/tests/Unit/Helpers/Schedule/Assets/schedule-basic.xml b/tests/Unit/Helpers/Schedule/Assets/schedule-basic.xml index 516041d4..83bb609d 100644 --- a/tests/Unit/Helpers/Schedule/Assets/schedule-basic.xml +++ b/tests/Unit/Helpers/Schedule/Assets/schedule-basic.xml @@ -1,12 +1,12 @@ dolor Basic Test Event - Test2 + test-2 2042-01-03 2042-01-03 1 @@ -21,7 +21,7 @@ 14:15 00:45 Some Room - lorem/ipsum + lorem-42-ipsum WTFPL true diff --git a/tests/Unit/Helpers/Schedule/Assets/schedule-extended.xml b/tests/Unit/Helpers/Schedule/Assets/schedule-extended.xml index 351eb819..8ea32dcf 100644 --- a/tests/Unit/Helpers/Schedule/Assets/schedule-extended.xml +++ b/tests/Unit/Helpers/Schedule/Assets/schedule-extended.xml @@ -1,20 +1,22 @@ + Some version string Test Event - Test3 - 2042-01-01 - 2042-01-01 + test-3 + 2042-01-01T01:00:00+02:00 + 2042-01-01T22:59:00+02:00 1 00:15 https://foo.bar/baz/schedule/ + Europe/Berlin - + 2042-01-01T12:30:00+02:00 Foo Bar Test @@ -22,10 +24,12 @@ 12:30 00:30 Rooming - foo-bar-test + some-3-test WTFPL false + https://recorder.test/some-3-test/recorded + https://recorder.test/some-3-test https://foo.bar/baz/schedule/ipsum/recording.mp4 Testing diff --git a/tests/Unit/Helpers/Schedule/Assets/schedule-minimal.xml b/tests/Unit/Helpers/Schedule/Assets/schedule-minimal.xml index 22c93138..b0d5fecd 100644 --- a/tests/Unit/Helpers/Schedule/Assets/schedule-minimal.xml +++ b/tests/Unit/Helpers/Schedule/Assets/schedule-minimal.xml @@ -2,7 +2,7 @@ 0.0.1 Some Test Event - Test1 + test-1 @@ -13,7 +13,7 @@ 13:30 00:30 Rooming - minimum-setup-test + minimum-1-setup Testing Talk A minimal description