rename rooms to locations (#1226)

This commit is contained in:
xuwhite 2023-10-13 11:53:13 +02:00 committed by GitHub
parent 9f113958ca
commit 00f4afa2ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 73 additions and 105 deletions

View File

@ -102,7 +102,7 @@ function shift_edit_controller()
$rid = $request->input('rid'); $rid = $request->input('rid');
} else { } else {
$valid = false; $valid = false;
error(__('Please select a room.')); error(__('Please select a location.'));
} }
if ($request->has('shifttype_id') && isset($shifttypes[$request->input('shifttype_id')])) { if ($request->has('shifttype_id') && isset($shifttypes[$request->input('shifttype_id')])) {
@ -209,7 +209,7 @@ function shift_edit_controller()
form([ form([
form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id), form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id),
form_text('title', __('Title'), $title), form_text('title', __('Title'), $title),
form_select('rid', __('Room:'), $rooms, $rid), form_select('rid', __('Location:'), $rooms, $rid),
form_text('start', __('Start:'), $start->format('Y-m-d H:i')), form_text('start', __('Start:'), $start->format('Y-m-d H:i')),
form_text('end', __('End:'), $end->format('Y-m-d H:i')), form_text('end', __('End:'), $end->format('Y-m-d H:i')),
form_textarea('description', __('Additional description'), $description), form_textarea('description', __('Additional description'), $description),

View File

@ -466,7 +466,7 @@ function admin_shifts()
div('col-md-6 col-xl-5', [ div('col-md-6 col-xl-5', [
form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id), form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id),
form_text('title', __('Title'), $title), form_text('title', __('Title'), $title),
form_select('rid', __('Room'), $room_array, $rid), form_select('rid', __('Location'), $room_array, $rid),
]), ]),
div('col-md-6 col-xl-7', [ div('col-md-6 col-xl-7', [
form_textarea('description', __('Additional description'), $description), form_textarea('description', __('Additional description'), $description),
@ -544,7 +544,7 @@ function admin_shifts()
form_info(__('Needed angels')), form_info(__('Needed angels')),
form_radio( form_radio(
'angelmode', 'angelmode',
__('Take needed angels from room settings'), __('Take needed angels from location settings'),
$angelmode == 'location', $angelmode == 'location',
'location' 'location'
), ),

View File

@ -261,7 +261,7 @@ class ImportSchedule extends BaseController
$roomModel->name = $room->getName(); $roomModel->name = $room->getName();
$roomModel->save(); $roomModel->save();
$this->log('Created schedule room "{room}"', ['room' => $room->getName()]); $this->log('Created schedule location "{location}"', ['location' => $room->getName()]);
} }
protected function fireDeleteShiftEntryEvents(Event $event): void protected function fireDeleteShiftEntryEvents(Event $event): void
@ -316,13 +316,13 @@ class ImportSchedule extends BaseController
$scheduleShift->save(); $scheduleShift->save();
$this->log( $this->log(
'Created schedule shift "{shift}" in "{room}" ({from} {to}, {guid})', 'Created schedule shift "{shift}" in "{location}" ({from} {to}, {guid})',
[ [
'shift' => $shift->title, 'shift' => $shift->title,
'room' => $shift->room->name, 'location' => $shift->room->name,
'from' => $shift->start->format(DateTimeInterface::RFC3339), 'from' => $shift->start->format(DateTimeInterface::RFC3339),
'to' => $shift->end->format(DateTimeInterface::RFC3339), 'to' => $shift->end->format(DateTimeInterface::RFC3339),
'guid' => $scheduleShift->guid, 'guid' => $scheduleShift->guid,
] ]
); );
} }
@ -345,13 +345,13 @@ class ImportSchedule extends BaseController
$shift->save(); $shift->save();
$this->log( $this->log(
'Updated schedule shift "{shift}" in "{room}" ({from} {to}, {guid})', 'Updated schedule shift "{shift}" in "{location}" ({from} {to}, {guid})',
[ [
'shift' => $shift->title, 'shift' => $shift->title,
'room' => $shift->room->name, 'location' => $shift->room->name,
'from' => $shift->start->format(DateTimeInterface::RFC3339), 'from' => $shift->start->format(DateTimeInterface::RFC3339),
'to' => $shift->end->format(DateTimeInterface::RFC3339), 'to' => $shift->end->format(DateTimeInterface::RFC3339),
'guid' => $scheduleShift->guid, 'guid' => $scheduleShift->guid,
] ]
); );
} }
@ -364,13 +364,13 @@ class ImportSchedule extends BaseController
$shift->delete(); $shift->delete();
$this->log( $this->log(
'Deleted schedule shift "{shift}" in {room} ({from} {to}, {guid})', 'Deleted schedule shift "{shift}" in {location} ({from} {to}, {guid})',
[ [
'shift' => $shift->title, 'shift' => $shift->title,
'room' => $shift->room->name, 'location' => $shift->room->name,
'from' => $shift->start->format(DateTimeInterface::RFC3339), 'from' => $shift->start->format(DateTimeInterface::RFC3339),
'to' => $shift->end->format(DateTimeInterface::RFC3339), 'to' => $shift->end->format(DateTimeInterface::RFC3339),
'guid' => $scheduleShift->guid, 'guid' => $scheduleShift->guid,
] ]
); );
} }

View File

@ -136,7 +136,7 @@ function load_rooms(bool $onlyWithActiveShifts = false)
$rooms = $rooms->get(); $rooms = $rooms->get();
if ($rooms->isEmpty()) { if ($rooms->isEmpty()) {
error(__('The administration has not configured any rooms yet.')); error(__('The administration has not configured any locations yet.'));
throw_redirect(page_link_to('/')); throw_redirect(page_link_to('/'));
} }
@ -298,7 +298,7 @@ function view_user_shifts()
$rooms, $rooms,
$shiftsFilter->getRooms(), $shiftsFilter->getRooms(),
'rooms', 'rooms',
icon('pin-map-fill') . __('Rooms') icon('pin-map-fill') . __('Locations')
), ),
'start_select' => html_select_key( 'start_select' => html_select_key(
'start_day', 'start_day',

View File

@ -157,7 +157,7 @@ function make_room_navigation($menu)
$rooms = Room::orderBy('name')->get(); $rooms = Room::orderBy('name')->get();
$room_menu = []; $room_menu = [];
if (auth()->can('admin_rooms')) { if (auth()->can('admin_rooms')) {
$room_menu[] = toolbar_dropdown_item(page_link_to('admin/rooms'), __('Manage rooms'), false, 'list'); $room_menu[] = toolbar_dropdown_item(page_link_to('admin/rooms'), __('Manage locations'), false, 'list');
} }
if (count($room_menu) > 0) { if (count($room_menu) > 0) {
$room_menu[] = toolbar_dropdown_item_divider(); $room_menu[] = toolbar_dropdown_item_divider();
@ -166,7 +166,7 @@ function make_room_navigation($menu)
$room_menu[] = toolbar_dropdown_item(room_link($room), $room->name, false, 'pin-map-fill'); $room_menu[] = toolbar_dropdown_item(room_link($room), $room->name, false, 'pin-map-fill');
} }
if (count($room_menu) > 0) { if (count($room_menu) > 0) {
$menu[] = toolbar_dropdown(__('Rooms'), $room_menu); $menu[] = toolbar_dropdown(__('Locations'), $room_menu);
} }
return $menu; return $menu;
} }

View File

@ -264,10 +264,10 @@ msgid "worklog.delete.success"
msgstr "Arbeitseinsatz erfolgreich gelöscht." msgstr "Arbeitseinsatz erfolgreich gelöscht."
msgid "room.edit.success" msgid "room.edit.success"
msgstr "Raum erfolgreich bearbeitet." msgstr "Ort erfolgreich bearbeitet."
msgid "room.delete.success" msgid "room.delete.success"
msgstr "Raum erfolgreich gelöscht." msgstr "Ort erfolgreich gelöscht."
msgid "validation.name.exists" msgid "validation.name.exists"
msgstr "Der Name wird bereits verwendet." msgstr "Der Name wird bereits verwendet."

View File

@ -293,8 +293,8 @@ msgstr ""
"Diese Schicht wurde aus einem Fahrplan importiert. " "Diese Schicht wurde aus einem Fahrplan importiert. "
"Dadurch werden einige Änderungen beim nächsten Import überschrieben." "Dadurch werden einige Änderungen beim nächsten Import überschrieben."
msgid "Please select a room." msgid "Please select a location."
msgstr "Bitte einen Raum auswählen." msgstr "Bitte einen Ort auswählen."
msgid "Please select a shifttype." msgid "Please select a shifttype."
msgstr "Bitte einen Schichttyp wählen." msgstr "Bitte einen Schichttyp wählen."
@ -323,8 +323,8 @@ msgstr "Schichttyp"
msgid "Title" msgid "Title"
msgstr "Titel" msgstr "Titel"
msgid "Room:" msgid "Location:"
msgstr "Raum:" msgstr "Ort:"
msgid "Start:" msgid "Start:"
msgstr "Start:" msgstr "Start:"
@ -796,13 +796,6 @@ msgstr "Überprüfen"
msgid "Import" msgid "Import"
msgstr "Importieren" msgstr "Importieren"
msgid ""
"This import will create/update/delete rooms and shifts by given FRAB-export "
"file. The needed file format is xcal."
msgstr ""
"Dieser Import erzeugt, ändert und löscht Räume und Schichten anhand einer "
"FRAB-Export Datei. Das benötigte Format ist xcal."
msgid "Add minutes to start" msgid "Add minutes to start"
msgstr "Minuten vor Talk-Beginn hinzufügen" msgstr "Minuten vor Talk-Beginn hinzufügen"
@ -815,12 +808,6 @@ msgstr "xcal-Datei (.xcal)"
msgid "Missing import file." msgid "Missing import file."
msgstr "Import-Datei nicht vorhanden." msgstr "Import-Datei nicht vorhanden."
msgid "Rooms to create"
msgstr "Anzulegende Räume"
msgid "Rooms to delete"
msgstr "Zu löschende Räume"
msgid "Shifts to create" msgid "Shifts to create"
msgstr "Anzulegende Schichten" msgstr "Anzulegende Schichten"
@ -836,8 +823,8 @@ msgstr "Ende"
msgid "Shift type" msgid "Shift type"
msgstr "Schichttyp" msgstr "Schichttyp"
msgid "Room" msgid "Location"
msgstr "Raum" msgstr "Ort"
msgid "Shifts to update" msgid "Shifts to update"
msgstr "Zu aktualisierende Schichten" msgstr "Zu aktualisierende Schichten"
@ -881,8 +868,8 @@ msgstr "Beantwortet am"
msgid "Asked at" msgid "Asked at"
msgstr "Gefragt am" msgstr "Gefragt am"
msgid "Rooms" msgid "Locations"
msgstr "Räume" msgstr "Orte"
msgid "This name is already in use." msgid "This name is already in use."
msgstr "Dieser Name ist bereits vergeben." msgstr "Dieser Name ist bereits vergeben."
@ -890,16 +877,6 @@ msgstr "Dieser Name ist bereits vergeben."
msgid "Please enter needed angels for type %s." msgid "Please enter needed angels for type %s."
msgstr "Bitte gib die Anzahl der benötigten Engel vom Typ %s an." msgstr "Bitte gib die Anzahl der benötigten Engel vom Typ %s an."
msgid "Room saved."
msgstr "Raum gespeichert."
msgid "Map URL"
msgstr "Karten URL"
msgid "The map url is used to display an iframe on the room page."
msgstr ""
"Die Karten URL wird benutzt um auf der Raum-Seite ein iframe anzuzeigen."
msgid "Description" msgid "Description"
msgstr "Beschreibung" msgstr "Beschreibung"
@ -909,12 +886,6 @@ msgstr "Bitte benutze Markdown für die Beschreibung."
msgid "Needed angels:" msgid "Needed angels:"
msgstr "Benötigte Engel:" msgstr "Benötigte Engel:"
msgid "Room %s deleted."
msgstr "Raum %s gelöscht."
msgid "Do you want to delete room %s?"
msgstr "Möchest Du den Raum %s wirklich löschen?"
msgid "add" msgid "add"
msgstr "Neu" msgstr "Neu"
@ -930,9 +901,6 @@ msgstr "Zusätzliche Beschreibung"
msgid "This description is for single shifts, otherwise please use the description in shift type." msgid "This description is for single shifts, otherwise please use the description in shift type."
msgstr "Diese Beschreibung ist für einzelne Schichten, ansonsten nutze bitte die Beschreibung im Schichttyp." msgstr "Diese Beschreibung ist für einzelne Schichten, ansonsten nutze bitte die Beschreibung im Schichttyp."
msgid "Please select a location."
msgstr "Bitte einen Ort auswählen."
msgid "Please select a start time." msgid "Please select a start time."
msgstr "Bitte eine Startzeit auswählen." msgstr "Bitte eine Startzeit auswählen."
@ -990,8 +958,8 @@ msgstr "Schichtwechsel-Stunden"
msgid "Create a shift over midnight." msgid "Create a shift over midnight."
msgstr "" msgstr ""
msgid "Take needed angels from room settings" msgid "Take needed angels from location settings"
msgstr "Übernehme benötigte Engel von den Raum-Einstellungen" msgstr "Übernehme benötigte Engel von den Ort-Einstellungen"
msgid "The following angels are needed" msgid "The following angels are needed"
msgstr "Die folgenden Engel werden benötigt" msgstr "Die folgenden Engel werden benötigt"
@ -1187,8 +1155,8 @@ msgstr "-> Nicht OK. Bitte erneut versuchen."
msgid "Your password is to short (please use at least 6 characters)." msgid "Your password is to short (please use at least 6 characters)."
msgstr "Dein Passwort ist zu kurz (Bitte mindestens 6 Zeichen nutzen)." msgstr "Dein Passwort ist zu kurz (Bitte mindestens 6 Zeichen nutzen)."
msgid "The administration has not configured any rooms yet." msgid "The administration has not configured any locations yet."
msgstr "Die Administratoren habe noch keine Räume eingerichtet." msgstr "Die Administratoren habe noch keine Orte eingerichtet."
msgid "The administration has not configured any shifts yet." msgid "The administration has not configured any shifts yet."
msgstr "Die Administratoren haben noch keine Schichten angelegt." msgstr "Die Administratoren haben noch keine Schichten angelegt."
@ -1272,8 +1240,8 @@ msgstr "Logout"
msgid "Admin" msgid "Admin"
msgstr "Admin" msgstr "Admin"
msgid "Manage rooms" msgid "Manage locations"
msgstr "Verwalte Räume" msgstr "Orte verwalten"
msgid "No data found." msgid "No data found."
msgstr "Nichts gefunden." msgstr "Nichts gefunden."
@ -1983,7 +1951,7 @@ msgstr "Aktualisiert am: %s"
msgid "schedule.import.text" msgid "schedule.import.text"
msgstr "" msgstr ""
"Importe erstellen Räume und erstellen, aktualisieren und löschen Schichten anhand eines schedule.xml exportes." "Importe erstellen Orte und erstellen, aktualisieren und löschen Schichten anhand eines schedule.xml exportes."
msgid "schedule.import.load.title" msgid "schedule.import.load.title"
msgstr "Programm importieren: Vorschau" msgstr "Programm importieren: Vorschau"
@ -2007,7 +1975,7 @@ msgid "schedule.minutes-after"
msgstr "Minuten nach Talk ende hinzufügen" msgstr "Minuten nach Talk ende hinzufügen"
msgid "schedule.import.rooms.add" msgid "schedule.import.rooms.add"
msgstr "Neue Räume" msgstr "Neue Orte"
msgid "schedule.import.shifts.add" msgid "schedule.import.shifts.add"
msgstr "Neue Schichten" msgstr "Neue Schichten"
@ -2031,7 +1999,7 @@ msgid "schedule.import.shift.title"
msgstr "Titel" msgstr "Titel"
msgid "schedule.import.shift.room" msgid "schedule.import.shift.room"
msgstr "Raum" msgstr "Ort"
msgid "shifts_history.schedule" msgid "shifts_history.schedule"
msgstr "Programm: %s" msgstr "Programm: %s"
@ -2424,7 +2392,7 @@ msgid "registration.register"
msgstr "Registrieren" msgstr "Registrieren"
msgid "room.rooms" msgid "room.rooms"
msgstr "Räume" msgstr "Orte"
msgid "room.name" msgid "room.name"
msgstr "Name" msgstr "Name"
@ -2442,13 +2410,13 @@ msgid "room.required_angels"
msgstr "Benötigte Engel" msgstr "Benötigte Engel"
msgid "room.map_url.info" msgid "room.map_url.info"
msgstr "Die Karte wird auf der Raum-Seite als iframe eingebettet." msgstr "Die Karte wird auf der Ort-Seite als iframe eingebettet."
msgid "room.create.title" msgid "room.create.title"
msgstr "Raum erstellen" msgstr "Ort erstellen"
msgid "room.edit.title" msgid "room.edit.title"
msgstr "Raum bearbeiten" msgstr "Ort bearbeiten"
msgid "event.day" msgid "event.day"
msgstr "Tag %1$d" msgstr "Tag %1$d"

View File

@ -263,10 +263,10 @@ msgid "worklog.delete.success"
msgstr "Work log successfully deleted." msgstr "Work log successfully deleted."
msgid "room.edit.success" msgid "room.edit.success"
msgstr "Room edited successfully." msgstr "Location edited successfully."
msgid "room.delete.success" msgid "room.delete.success"
msgstr "Room successfully deleted." msgstr "Location successfully deleted."
msgid "validation.name.exists" msgid "validation.name.exists"
msgstr "The name is already used." msgstr "The name is already used."

View File

@ -98,7 +98,7 @@ msgid "schedule.last_update"
msgstr "Last updated: %s" msgstr "Last updated: %s"
msgid "schedule.import.text" msgid "schedule.import.text"
msgstr "Imports create rooms and create, update and delete shifts according to a schedule.xml export." msgstr "Imports create locations and create, update and delete shifts according to a schedule.xml export."
msgid "schedule.import.load.title" msgid "schedule.import.load.title"
msgstr "Import schedule: Preview" msgstr "Import schedule: Preview"
@ -125,7 +125,7 @@ msgid "schedule.import.request_error"
msgstr "Unable to load schedule." msgstr "Unable to load schedule."
msgid "schedule.import.rooms.add" msgid "schedule.import.rooms.add"
msgstr "Rooms to create" msgstr "Locations to create"
msgid "schedule.import.shifts.add" msgid "schedule.import.shifts.add"
msgstr "Shifts to create" msgstr "Shifts to create"
@ -149,7 +149,7 @@ msgid "schedule.import.shift.title"
msgstr "Title" msgstr "Title"
msgid "schedule.import.shift.room" msgid "schedule.import.shift.room"
msgstr "Room" msgstr "Location"
msgid "shifts_history.schedule" msgid "shifts_history.schedule"
msgstr "Schedule: %s" msgstr "Schedule: %s"
@ -559,7 +559,7 @@ msgid "registration.register"
msgstr "Register" msgstr "Register"
msgid "room.rooms" msgid "room.rooms"
msgstr "Rooms" msgstr "Locations"
msgid "room.name" msgid "room.name"
msgstr "Name" msgstr "Name"
@ -577,13 +577,13 @@ msgid "room.required_angels"
msgstr "Required angels" msgstr "Required angels"
msgid "room.map_url.info" msgid "room.map_url.info"
msgstr "The map will be embedded on the room page as an iframe." msgstr "The map will be embedded on the location page as an iframe."
msgid "room.create.title" msgid "room.create.title"
msgstr "Create room" msgstr "Create location"
msgid "room.edit.title" msgid "room.edit.title"
msgstr "Edit room" msgstr "Edit location"
msgid "event.day" msgid "event.day"
msgstr "Day %1$d" msgstr "Day %1$d"

View File

@ -1234,7 +1234,7 @@ msgid "Shift change hours"
msgstr "Mudança de horário do turno" msgstr "Mudança de horário do turno"
#: includes/pages/admin_shifts.php:335 #: includes/pages/admin_shifts.php:335
msgid "Take needed angels from room settings" msgid "Take needed angels from location settings"
msgstr "Pegar os anjos necessários a partir das configurações das salas" msgstr "Pegar os anjos necessários a partir das configurações das salas"
#: includes/pages/admin_shifts.php:336 #: includes/pages/admin_shifts.php:336

View File

@ -114,7 +114,7 @@ class RoomsController extends BaseController
} }
$this->log->info( $this->log->info(
'Updated room "{name}": {description} {dect} {map_url} {angels}', 'Updated location "{name}": {description} {dect} {map_url} {angels}',
[ [
'name' => $room->name, 'name' => $room->name,
'description' => $room->description, 'description' => $room->description,
@ -155,7 +155,7 @@ class RoomsController extends BaseController
} }
$room->delete(); $room->delete();
$this->log->info('Deleted room {room}', ['room' => $room->name]); $this->log->info('Deleted location {location}', ['location' => $room->name]);
$this->addNotification('room.delete.success'); $this->addNotification('room.delete.success');
return $this->redirect->to('/admin/rooms'); return $this->redirect->to('/admin/rooms');

View File

@ -109,7 +109,7 @@ class RoomsControllerTest extends ControllerTest
$this->setExpects($this->redirect, 'to', ['/admin/rooms']); $this->setExpects($this->redirect, 'to', ['/admin/rooms']);
$this->request = $this->request->withParsedBody([ $this->request = $this->request->withParsedBody([
'name' => 'Testroom', 'name' => 'Testlocation',
'description' => 'Something', 'description' => 'Something',
'dect' => 'DECTNR', 'dect' => 'DECTNR',
'map_url' => 'https://osm.url/#map=h/x/y', 'map_url' => 'https://osm.url/#map=h/x/y',
@ -119,9 +119,9 @@ class RoomsControllerTest extends ControllerTest
$controller->save($this->request); $controller->save($this->request);
$this->assertTrue($this->log->hasInfoThatContains('Updated room')); $this->assertTrue($this->log->hasInfoThatContains('Updated location'));
$this->assertHasNotification('room.edit.success'); $this->assertHasNotification('room.edit.success');
$this->assertCount(1, Room::whereName('Testroom')->get()); $this->assertCount(1, Room::whereName('Testlocation')->get());
$neededAngelType = NeededAngelType::whereRoomId(1) $neededAngelType = NeededAngelType::whereRoomId(1)
->where('angel_type_id', 2) ->where('angel_type_id', 2)
@ -138,10 +138,10 @@ class RoomsControllerTest extends ControllerTest
/** @var RoomsController $controller */ /** @var RoomsController $controller */
$controller = $this->app->make(RoomsController::class); $controller = $this->app->make(RoomsController::class);
$controller->setValidator(new Validator()); $controller->setValidator(new Validator());
Room::factory()->create(['name' => 'Testroom']); Room::factory()->create(['name' => 'Testlocation']);
$this->request = $this->request->withParsedBody([ $this->request = $this->request->withParsedBody([
'name' => 'Testroom', 'name' => 'Testlocation',
]); ]);
$this->expectException(ValidationException::class); $this->expectException(ValidationException::class);
@ -206,7 +206,7 @@ class RoomsControllerTest extends ControllerTest
$controller->delete($this->request); $controller->delete($this->request);
$this->assertNull(Room::find($room->id)); $this->assertNull(Room::find($room->id));
$this->assertTrue($this->log->hasInfoThatContains('Deleted room')); $this->assertTrue($this->log->hasInfoThatContains('Deleted location'));
$this->assertHasNotification('room.delete.success'); $this->assertHasNotification('room.delete.success');
} }

View File

@ -202,10 +202,10 @@ class StatsTest extends TestCase
*/ */
public function testRooms(): void public function testRooms(): void
{ {
(new Room(['name' => 'Room 1']))->save(); (new Room(['name' => 'Location 1']))->save();
(new Room(['name' => 'Second room']))->save(); (new Room(['name' => 'Second location']))->save();
(new Room(['name' => 'Another room']))->save(); (new Room(['name' => 'Another location']))->save();
(new Room(['name' => 'Old room']))->save(); (new Room(['name' => 'Old location']))->save();
$stats = new Stats($this->database); $stats = new Stats($this->database);
$this->assertEquals(4, $stats->rooms()); $this->assertEquals(4, $stats->rooms());

View File

@ -16,7 +16,7 @@ class RoomTest extends ModelTest
*/ */
public function testShifts(): void public function testShifts(): void
{ {
$room = new Room(['name' => 'Test room']); $room = new Room(['name' => 'Test location']);
$room->save(); $room->save();
/** @var Shift $shift */ /** @var Shift $shift */