Reimplemented shifts json export
This commit is contained in:
parent
b0b4cb54ec
commit
7eccf2c535
|
@ -100,6 +100,7 @@ $route->get('/api[/{resource:.+}]', 'ApiController@index');
|
||||||
$route->get('/atom', 'FeedController@atom');
|
$route->get('/atom', 'FeedController@atom');
|
||||||
$route->get('/ical', 'FeedController@ical');
|
$route->get('/ical', 'FeedController@ical');
|
||||||
$route->get('/rss', 'FeedController@rss');
|
$route->get('/rss', 'FeedController@rss');
|
||||||
|
$route->get('/shifts-json-export', 'FeedController@shifts');
|
||||||
|
|
||||||
// Design
|
// Design
|
||||||
$route->get('/design', 'DesignController@index');
|
$route->get('/design', 'DesignController@index');
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Carbon\CarbonTimeZone;
|
|
||||||
use Engelsystem\Http\Exceptions\HttpForbidden;
|
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Shifts\NeededAngelType;
|
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||||
use Engelsystem\Models\Shifts\ScheduleShift;
|
use Engelsystem\Models\Shifts\ScheduleShift;
|
||||||
|
@ -378,84 +376,3 @@ function shift_next_controller()
|
||||||
|
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(page_link_to('user_shifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Export filtered shifts via JSON.
|
|
||||||
* (Like shifts view)
|
|
||||||
*/
|
|
||||||
function shifts_json_export_controller()
|
|
||||||
{
|
|
||||||
$user = auth()->userFromApi();
|
|
||||||
|
|
||||||
if (!$user) {
|
|
||||||
throw new HttpForbidden('{"error":"Missing or invalid ?key="}', ['content-type' => 'application/json']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!auth()->can('shifts_json_export')) {
|
|
||||||
throw new HttpForbidden('{"error":"Not allowed"}', ['content-type' => 'application/json']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$shifts = Shifts_by_user(auth()->user()->id);
|
|
||||||
$shifts->sortBy('start_date');
|
|
||||||
$timeZone = CarbonTimeZone::create(config('timezone'));
|
|
||||||
|
|
||||||
$shiftsData = [];
|
|
||||||
foreach ($shifts as $shift) {
|
|
||||||
// Data required for the Fahrplan app integration https://github.com/johnjohndoe/engelsystem
|
|
||||||
// See engelsystem-base/src/main/kotlin/info/metadude/kotlin/library/engelsystem/models/Shift.kt
|
|
||||||
$data = [
|
|
||||||
// Name of the shift (type)
|
|
||||||
'name' => $shift->shiftType->name,
|
|
||||||
// Shift / Talk title
|
|
||||||
'title' => $shift->title,
|
|
||||||
// Shift description
|
|
||||||
'description' => $shift->description,
|
|
||||||
|
|
||||||
// Users comment
|
|
||||||
'Comment' => $shift->user_comment,
|
|
||||||
|
|
||||||
// Shift id
|
|
||||||
'SID' => $shift->id,
|
|
||||||
// Shift type id
|
|
||||||
'shifttype_id' => $shift->shift_type_id,
|
|
||||||
// Talk URL
|
|
||||||
'URL' => $shift->url,
|
|
||||||
|
|
||||||
// Room name
|
|
||||||
'Name' => $shift->room->name,
|
|
||||||
// Location map url
|
|
||||||
'map_url' => $shift->room->map_url,
|
|
||||||
|
|
||||||
// Start timestamp
|
|
||||||
/** @deprecated start_date should be used */
|
|
||||||
'start' => $shift->start->timestamp,
|
|
||||||
// Start date
|
|
||||||
'start_date' => $shift->start->toRfc3339String(),
|
|
||||||
// End timestamp
|
|
||||||
/** @deprecated end_date should be used */
|
|
||||||
'end' => $shift->end->timestamp,
|
|
||||||
// End date
|
|
||||||
'end_date' => $shift->end->toRfc3339String(),
|
|
||||||
|
|
||||||
// Timezone offset like "+01:00"
|
|
||||||
/** @deprecated should be retrieved from start_date or end_date */
|
|
||||||
'timezone' => $timeZone->toOffsetName(),
|
|
||||||
// The events timezone like "Europe/Berlin"
|
|
||||||
'event_timezone' => $timeZone->getName(),
|
|
||||||
];
|
|
||||||
|
|
||||||
$shiftsData[] = [
|
|
||||||
// Model data
|
|
||||||
...$shift->toArray(),
|
|
||||||
|
|
||||||
// legacy fields (ignoring created / updated (at/by) data)
|
|
||||||
'RID' => $shift->room_id,
|
|
||||||
|
|
||||||
// Fahrplan app required data
|
|
||||||
...$data
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
|
||||||
raw_output(json_encode($shiftsData));
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
|
|
||||||
namespace Engelsystem\Controllers;
|
namespace Engelsystem\Controllers;
|
||||||
|
|
||||||
|
use Carbon\CarbonTimeZone;
|
||||||
use Engelsystem\Helpers\Authenticator;
|
use Engelsystem\Helpers\Authenticator;
|
||||||
use Engelsystem\Http\Request;
|
use Engelsystem\Http\Request;
|
||||||
use Engelsystem\Http\Response;
|
use Engelsystem\Http\Response;
|
||||||
use Engelsystem\Models\News;
|
use Engelsystem\Models\News;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class FeedController extends BaseController
|
class FeedController extends BaseController
|
||||||
|
@ -15,6 +17,7 @@ class FeedController extends BaseController
|
||||||
'atom' => 'atom',
|
'atom' => 'atom',
|
||||||
'rss' => 'atom',
|
'rss' => 'atom',
|
||||||
'ical' => 'ical',
|
'ical' => 'ical',
|
||||||
|
'shifts' => 'shifts_json_export',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
@ -52,6 +55,75 @@ class FeedController extends BaseController
|
||||||
->withView('api/ical', ['shiftEntries' => $shifts]);
|
->withView('api/ical', ['shiftEntries' => $shifts]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shifts(): Response
|
||||||
|
{
|
||||||
|
/** @var Collection|ShiftEntry[] $shiftEntries */
|
||||||
|
$shiftEntries = $this->getShifts();
|
||||||
|
$timeZone = CarbonTimeZone::create(config('timezone'));
|
||||||
|
|
||||||
|
$response = [];
|
||||||
|
foreach ($shiftEntries as $entry) {
|
||||||
|
$shift = $entry->shift;
|
||||||
|
// Data required for the Fahrplan app integration https://github.com/johnjohndoe/engelsystem
|
||||||
|
// See engelsystem-base/src/main/kotlin/info/metadude/kotlin/library/engelsystem/models/Shift.kt
|
||||||
|
// ! All attributes not defined in $data might change at any time !
|
||||||
|
$data = [
|
||||||
|
// Name of the shift (type)
|
||||||
|
'name' => $shift->shiftType->name,
|
||||||
|
// Shift / Talk title
|
||||||
|
'title' => $shift->title,
|
||||||
|
// Shift description
|
||||||
|
'description' => $shift->description,
|
||||||
|
|
||||||
|
// Users comment
|
||||||
|
'Comment' => $entry->user_comment,
|
||||||
|
|
||||||
|
// Shift id
|
||||||
|
'SID' => $shift->id,
|
||||||
|
// Shift type id
|
||||||
|
'shifttype_id' => $shift->shiftType->id,
|
||||||
|
// Talk URL
|
||||||
|
'URL' => $shift->url,
|
||||||
|
|
||||||
|
// Room id
|
||||||
|
'RID' => $shift->room->id,
|
||||||
|
// Room name
|
||||||
|
'Name' => $shift->room->name,
|
||||||
|
// Location map url
|
||||||
|
'map_url' => $shift->room->map_url,
|
||||||
|
|
||||||
|
// Start timestamp
|
||||||
|
/** @deprecated start_date should be used */
|
||||||
|
'start' => $shift->start->timestamp,
|
||||||
|
// Start date
|
||||||
|
'start_date' => $shift->start->toRfc3339String(),
|
||||||
|
// End timestamp
|
||||||
|
/** @deprecated end_date should be used */
|
||||||
|
'end' => $shift->end->timestamp,
|
||||||
|
// End date
|
||||||
|
'end_date' => $shift->end->toRfc3339String(),
|
||||||
|
|
||||||
|
// Timezone offset like "+01:00"
|
||||||
|
/** @deprecated should be retrieved from start_date or end_date */
|
||||||
|
'timezone' => $timeZone->toOffsetName(),
|
||||||
|
// The events timezone like "Europe/Berlin"
|
||||||
|
'event_timezone' => $timeZone->getName(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$response[] = [
|
||||||
|
// Model data
|
||||||
|
...$entry->toArray(),
|
||||||
|
|
||||||
|
// Fahrplan app required data
|
||||||
|
...$data
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->response
|
||||||
|
->withAddedHeader('content-type', 'application/json; charset=utf-8')
|
||||||
|
->withContent(json_encode($response));
|
||||||
|
}
|
||||||
|
|
||||||
protected function getNews(): Collection
|
protected function getNews(): Collection
|
||||||
{
|
{
|
||||||
$news = $this->request->has('meetings')
|
$news = $this->request->has('meetings')
|
||||||
|
|
|
@ -21,7 +21,6 @@ class LegacyMiddleware implements MiddlewareInterface
|
||||||
'rooms',
|
'rooms',
|
||||||
'shift_entries',
|
'shift_entries',
|
||||||
'shifts',
|
'shifts',
|
||||||
'shifts_json_export',
|
|
||||||
'users',
|
'users',
|
||||||
'user_driver_licenses',
|
'user_driver_licenses',
|
||||||
'admin_shifts_history',
|
'admin_shifts_history',
|
||||||
|
@ -77,10 +76,6 @@ class LegacyMiddleware implements MiddlewareInterface
|
||||||
protected function loadPage(string $page): array
|
protected function loadPage(string $page): array
|
||||||
{
|
{
|
||||||
switch ($page) {
|
switch ($page) {
|
||||||
case 'shifts_json_export':
|
|
||||||
require_once realpath(__DIR__ . '/../../includes/controller/shifts_controller.php');
|
|
||||||
shifts_json_export_controller();
|
|
||||||
break;
|
|
||||||
case 'public_dashboard':
|
case 'public_dashboard':
|
||||||
return public_dashboard_controller();
|
return public_dashboard_controller();
|
||||||
case 'angeltypes':
|
case 'angeltypes':
|
||||||
|
|
|
@ -51,6 +51,16 @@ class ShiftEntry extends BaseModel
|
||||||
'freeloaded_comment' => '',
|
'freeloaded_comment' => '',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/** @var array<string, string> */
|
||||||
|
protected $casts = [ // phpcs:ignore
|
||||||
|
'freeloaded' => 'bool',
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @var array<string> Attributes which should not be serialized */
|
||||||
|
protected $hidden = [ // phpcs:ignore
|
||||||
|
'freeloaded_comment',
|
||||||
|
];
|
||||||
|
|
||||||
public function shift(): BelongsTo
|
public function shift(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Shift::class);
|
return $this->belongsTo(Shift::class);
|
||||||
|
|
|
@ -110,6 +110,59 @@ class FeedControllerTest extends ControllerTest
|
||||||
$controller->ical();
|
$controller->ical();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Controllers\FeedController::shifts
|
||||||
|
* @covers \Engelsystem\Controllers\FeedController::getShifts
|
||||||
|
*/
|
||||||
|
public function testShifts(): void
|
||||||
|
{
|
||||||
|
$this->request = $this->request->withQueryParams(['key' => 'fo0']);
|
||||||
|
$this->auth = new Authenticator(
|
||||||
|
$this->request,
|
||||||
|
new Session(new MockArraySessionStorage()),
|
||||||
|
new User(),
|
||||||
|
);
|
||||||
|
$controller = new FeedController($this->auth, $this->request, $this->response);
|
||||||
|
|
||||||
|
/** @var User $user */
|
||||||
|
$user = User::factory()->create(['api_key' => 'fo0']);
|
||||||
|
ShiftEntry::factory(3)->create(['user_id' => $user->id]);
|
||||||
|
|
||||||
|
$this->setExpects(
|
||||||
|
$this->response,
|
||||||
|
'withAddedHeader',
|
||||||
|
['content-type', 'application/json; charset=utf-8'],
|
||||||
|
$this->response
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->response->expects($this->once())
|
||||||
|
->method('withContent')
|
||||||
|
->willReturnCallback(function ($jsonData) {
|
||||||
|
$data = json_decode($jsonData, true);
|
||||||
|
$this->assertIsArray($data);
|
||||||
|
|
||||||
|
$this->assertCount(3, $data);
|
||||||
|
$this->assertTrue($data[0]['start'] < $data[1]['start']);
|
||||||
|
|
||||||
|
// Ensure dates exist used by Fahrplan app
|
||||||
|
foreach (
|
||||||
|
[
|
||||||
|
'name', 'title', 'description',
|
||||||
|
'Comment',
|
||||||
|
'SID', 'shifttype_id', 'URL',
|
||||||
|
'RID', 'Name', 'map_url',
|
||||||
|
'start', 'start_date', 'end', 'end_date',
|
||||||
|
'timezone', 'event_timezone',
|
||||||
|
] as $requiredAttribute
|
||||||
|
) {
|
||||||
|
$this->assertArrayHasKey($requiredAttribute, $data[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->response;
|
||||||
|
});
|
||||||
|
$controller->shifts();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getNewsMeetingsDataProvider(): array
|
public function getNewsMeetingsDataProvider(): array
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,5 +33,7 @@ class ShiftEntryTest extends ModelTest
|
||||||
$this->assertEquals($shift->id, $model->shift->id);
|
$this->assertEquals($shift->id, $model->shift->id);
|
||||||
$this->assertEquals($angelType->id, $model->angelType->id);
|
$this->assertEquals($angelType->id, $model->angelType->id);
|
||||||
$this->assertEquals($user->id, $model->user->id);
|
$this->assertEquals($user->id, $model->user->id);
|
||||||
|
|
||||||
|
$this->assertArrayNotHasKey('freeloaded_comment', $model->toArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue