SlotModal
extends BaseComponent
in package
uses
ModalAwareTrait, PrivilegeGuardTrait
Time slot edit modal of the admin calendar.
The only entry point is a click on a block of the day timeline (day.latte) or on a bubble
of the week grid (week.latte). The clicked block type selects one of three modes:
- MODE_FILL (free): a new reservation on a free interval, or a block of the same range. The range is editable because the time slot does not exist yet.
- MODE_RESERVATION (pending or confirmed): edits the client details and state, with tools to shorten or split the time slot and to cancel the reservation. The range is static text: only shortening or splitting may change the time of an occupied row.
- MODE_BLOCKED (blocked): read-only context plus canceling the block. A block has no client whose time slot could be shortened, so the admin deletes it and creates a new one.
IMPORTANT: admin AJAX modal pitfalls this component works around on purpose:
- The context is not carried as a persistent parameter, because
link('this')of the form does not carry it (see CommentThread). It goes into the signal as an explicit parameter and into the form as a hidden field, and is read back from the POST on submit (hydrateContext()). - No field has
setRequired(). Native HTML5requiredon a field that belongs to another button of the same form silently blocks the submit in the browser, even when the server validation of that button ignores the field. All validation is server-side, authoritative in the Api managers. - Fields are added conditionally by mode. The mode comes from a private property when
opened by a signal and from a hidden POST field on submit, because
handleOpen*()does not run then. $presenter->flashMessage()is invisible in a component template, so messages live in the per-request buffer $notice and_modal.latterenders them itself (final text, not a key, to avoid a double domain prefix).- No
redirect()on AJAX, because it would close the modal. After an action the modal is refilled (showModal()) and the underlying timeline is redrawn withredrawControl($this->returnSnippet). - State is reloaded after every write: mutations through the Api bridge do not change the already hydrated Admin objects, so re-rendering must use freshly read data.
The component neither locks nor validates times. All writes go through the Admin bridge to the Api managers, which run under the per-day lock (TimeSlotManager::dayLockName()); form values are only a proposal.
Table of Contents
Constants
- FILL_ACTION_BLOCK : string = 'block'
- `fillAction` switch (mode A): `TimeSlotManager::save()` with `type=blocked`.
- FILL_ACTION_OPEN_WINDOW : string = 'openWindow'
- `fillAction` switch (mode A): {@see TimeSlotManager::openWindow()}, creating a time slot on closed time.
- FILL_ACTION_RESERVE : string = 'reserve'
- `fillAction` switch (mode A): {@see ReservationManager::bookByAdmin()}.
- MODE_BLOCKED : string = 'blocked'
- Click on a `blocked` block: an admin block without a client.
- MODE_FILL : string = 'fill'
- Click on a `free` block: a new reservation or block.
- MODE_RESERVATION : string = 'reservation'
- Click on a `confirmed`/`pending` block: an existing reservation.
- SNIPPET_DAY : string = 'dayTimeline'
- Day timeline snippet (`day.latte`); the default redraw target.
- SNIPPET_WEEK : string = 'weekGrid'
- Week grid snippet (`week.latte`).
- TIME_ACTION_KEEP : string = 'keep'
- `timeAction` switch (mode B): keeps the range and calls only `updateByAdmin()`.
- TIME_ACTION_SHORTEN : string = 'shorten'
- `timeAction` switch (mode B): additionally calls {@see TimeSlotManager::shorten()}.
- TIME_ACTION_SPLIT : string = 'split'
- `timeAction` switch (mode B): additionally calls {@see TimeSlotManager::split()}.
- EDIT_PRIVILEGE : string = ':Admin:Company:TimeSlot:edit'
- Same key as `SchedulePresenter::handleMergeSlots()` and `TimeSlotPresenter::actionEdit()`.
Properties
- $container : Container
- $routerDispatcher : RouterDispatcher
- $translator : ITranslator
- $appContext : AppContext
- $componentParameters : array<string, mixed>
- $currencyContext : CurrencyContext|null
- $deviceDetector : DeviceDetector|null
- $languageContext : LanguageContext|null
- $localizationContext : LocalizationContext|null
- $settingContext : SettingContext
- $themeContext : ThemeContext|null
- $translatorDomain : string|null
- $allCalendars : bool
- Week view of all calendars; must survive the redraw.
- $calendarId : int
- $calendarManager : CalendarManager
- $companyId : int
- Company the view is rendered for; context for redrawing the timeline only.
- $date : string
- `Y-m-d` of the day whose timeline or grid the modal serves.
- $done : bool
- The action finished and nothing is left to offer (canceled reservation or deleted block).
- $fromMin : int
- Range of the clicked free block in minutes after midnight ({@see MODE_FILL} only).
- $mode : string
- Active mode; `''` means the modal does not open in this request.
- $notice : array{type: string, text: string}|null
- Per-request message rendered inside the modal (pitfall 4 in the class docblock).
- $reservation : Reservation|null
- Active reservation on {@see $slot} ({@see MODE_RESERVATION}).
- $reservationManager : ReservationManager
- $returnSnippet : string
- Snippet to redraw after an action: `dayTimeline` or `weekGrid`.
- $slot : TimeSlot|null
- Calendar row ({@see MODE_RESERVATION}/{@see MODE_BLOCKED} modes).
- $timeSlotManager : TimeSlotManager
- $toMin : int
Methods
- __call() : mixed
- Dispatches `renderXyz()` to `render('Xyz', ...$args)`.
- __construct() : mixed
- createComponent() : IComponent|null
- createComponentSlotForm() : Form
- Builds one form whose fields depend on the mode (pitfalls 2 and 3 in the class docblock).
- getAppContext() : AppContext
- getComponentParameter() : mixed
- Returns a component parameter, or null when it is not set.
- getContainer() : Container
- getCurrencyContext() : CurrencyContext|null
- getLanguageContext() : LanguageContext|null
- getLocalizationContext() : LocalizationContext|null
- getRouterDispatcher() : RouterDispatcher
- getSettingContext() : SettingContext
- getSettings() : array<int, array<string, mixed>>
- getThemeContext() : ThemeContext|null
- getViewContext() : array{companyId: int, calendarId: int, date: string, allCalendars: bool}|null
- Returns the view context after the signal was handled.
- handleOpenBlocked() : void
- Click on a block of a time block ({@see MODE_BLOCKED} mode).
- handleOpenFree() : void
- Click on a free block of the day timeline ({@see MODE_FILL} mode).
- handleOpenReservation() : void
- Click on a block with an active reservation ({@see MODE_RESERVATION} mode).
- hasServiceByType() : bool
- Returns whether the container has a service of the given type.
- initializeAllContexts() : void
- injectDeviceDetector() : void
- onCancelReservation() : void
- Mode B, cancel reservation: reuses {@see ReservationManager::cancel()}.
- onCreate() : void
- onDeleteBlock() : void
- Mode C, cancel block: reuses {@see TimeSlotManager::delete()}.
- onFillSave() : void
- Mode A, single button: calls {@see ReservationManager::bookByAdmin()} or `TimeSlotManager::save()` with `type=blocked`, chosen by the submitted value of the `blocked` switch, not by which button caught the click.
- onReservationSave() : void
- Mode B, single save button: always calls {@see ReservationManager::updateByAdmin()} (name, e-mail, phone, note, state; never the time), and additionally acts on the submitted value of the `timeAction` switch: `keep` does nothing more, `shorten`/`split` also call {@see TimeSlotManager::shorten()}/`::split()`.
- render() : void
- Renders nothing into the page; it exists for its signals and to fill the shared {@see \App\UI\Admin\System\Components\ModalWindowComponent\ModalWindow} from `@layout.latte`.
- setAppContext() : $this
- setComponentParameter() : void
- Sets a component parameter.
- setCurrencyContext() : $this
- setLanguageContext() : $this
- setLocalizationContext() : $this
- setSettingContext() : $this
- setThemeContext() : $this
- setup() : void
- setupAppContext() : void
- typedComponent() : T
- Returns a subcomponent with a verified type.
- frontPresenter() : BasePresenter|null
- Returns the front presenter the component is attached to (null outside the front end or when detached).
- getModalWindow() : ModalWindow
- getTranslator() : ITranslator
- isTargetAllowed() : bool
- Returns whether the logged-in user may open the given admin target. For visibility (tiles, autocomplete, buttons); it does not throw.
- requirePrivilege() : void
- Throws 403 when the logged-in user lacks the given admin privilege.
- resolvePageTarget() : string|null
- Returns the RBAC key of the target page: `<presenter>:<action>`, e.g. `:Admin:System:User:show`.
- setTemplateFile() : void
- setTranslator() : self
- addBlockedFields() : void
- Mode C: a block with no editable fields; the only action is canceling it.
- addFillFields() : void
- Mode A: a new reservation on a free interval, or a block of the same range.
- addReservationFields() : void
- Mode B: an existing reservation with details and state, shorten/split tools and cancellation.
- createMultiplierComponent() : Multiplier<string|int, IComponent>
- Creates a multiplier for the component.
- createNewComponentInstance() : IComponent|null
- Creates a new component instance without adding it to the presenter; used by the multiplier.
- createStandardComponent() : IComponent|null
- Creates a standard component (not a multiplier).
- failAndReopen() : void
- Turns an Api action failure into a readable message inside the modal (no flash, pitfall 4).
- fillActionOptions() : array<string, string>
- Returns the `fillAction` options as translation keys, like {@see timeActionOptions()} (`addRadioList()` translates them through the form `useDomainTranslator()`).
- findCalendar() : Calendar|null
- findSlot() : TimeSlot|null
- finish() : void
- Refills the modal and redraws the underlying timeline or grid (pitfall 5 in the class docblock).
- formatDate() : string
- Converts `Y-m-d` to `j. n. Y`; an invalid date is returned unchanged.
- formatMinutes() : string
- Converts minutes after midnight to `HH:MM`, like Api `TimeSlotManager::formatMinutes()`.
- hydrateContext() : void
- Restores the view context from the submitted hidden fields, because the signal link of the form does not carry it (pitfall 1 in the class docblock). Calendar and day of modes B and C are loaded from the time slot, not from here.
- int() : int
- loadReservationContext() : void
- Loads a fresh row and its active reservation (pitfall 6 in the class docblock: hydrated objects do not update after a bridge write).
- normalizeSnippet() : string
- Allows only the two known values; a foreign string would crash the request in `redrawControl()`.
- noticeError() : void
- noticeSuccess() : void
- parseTime() : DateTime|null
- Converts the value of `<input type=time>` to `DateTime`, or null when empty or invalid.
- renderModalContent() : string
- Renders the modal content to a string for `ModalWindow`.
- requireCalendarInCompany() : void
- 403 when an existing calendar does not belong to the company the modal was opened from.
- requireReservationOfSlot() : void
- 403 when the posted reservation id points to a reservation of a different slot.
- requireSlotInCompany() : void
- 403 when an existing slot does not belong to the company the modal was opened from.
- resolveMode() : string
- Returns the mode used to build the form.
- saveBlock() : Result
- Saves a block through `save()` with an entity of `type = blocked` (no dedicated Api action; the same path as `TimeSlotFormTrait`).
- saveReservation() : Result
- saveWindow() : Result
- Creates a time slot through {@see TimeSlotManager::openWindow()}.
- showModal() : void
- Fills and opens the shared admin modal with the current state.
- stateOptions() : array<string, string>
- str() : string
- strOrNull() : string|null
- text() : string
- Returns final translated text (not a key) for the {@see $notice} buffer and select options.
- timeActionOptions() : array<string, string>
- Returns the `timeAction` options as translation keys.
- values() : array<string, mixed>
- Returns the form values.
Constants
FILL_ACTION_BLOCK
`fillAction` switch (mode A): `TimeSlotManager::save()` with `type=blocked`.
public
string
FILL_ACTION_BLOCK
= 'block'
FILL_ACTION_OPEN_WINDOW
`fillAction` switch (mode A): {@see TimeSlotManager::openWindow()}, creating a time slot on closed time.
public
string
FILL_ACTION_OPEN_WINDOW
= 'openWindow'
Unlike FILL_ACTION_RESERVE no reservation is created; the time is permanently opened for future booking (front end and further admin writes).
FILL_ACTION_RESERVE
`fillAction` switch (mode A): {@see ReservationManager::bookByAdmin()}.
public
string
FILL_ACTION_RESERVE
= 'reserve'
Always enforceWindow=false: bookByAdmin() ignores the offer windows because the admin
sees the whole day. A click on a free and on a closed block takes the same path, so
no separate origin distinction is needed (see handleOpenFree()).
MODE_BLOCKED
Click on a `blocked` block: an admin block without a client.
public
string
MODE_BLOCKED
= 'blocked'
MODE_FILL
Click on a `free` block: a new reservation or block.
public
string
MODE_FILL
= 'fill'
MODE_RESERVATION
Click on a `confirmed`/`pending` block: an existing reservation.
public
string
MODE_RESERVATION
= 'reservation'
SNIPPET_DAY
Day timeline snippet (`day.latte`); the default redraw target.
public
string
SNIPPET_DAY
= 'dayTimeline'
SNIPPET_WEEK
Week grid snippet (`week.latte`).
public
string
SNIPPET_WEEK
= 'weekGrid'
TIME_ACTION_KEEP
`timeAction` switch (mode B): keeps the range and calls only `updateByAdmin()`.
public
string
TIME_ACTION_KEEP
= 'keep'
TIME_ACTION_SHORTEN
`timeAction` switch (mode B): additionally calls {@see TimeSlotManager::shorten()}.
public
string
TIME_ACTION_SHORTEN
= 'shorten'
TIME_ACTION_SPLIT
`timeAction` switch (mode B): additionally calls {@see TimeSlotManager::split()}.
public
string
TIME_ACTION_SPLIT
= 'split'
EDIT_PRIVILEGE
Same key as `SchedulePresenter::handleMergeSlots()` and `TimeSlotPresenter::actionEdit()`.
private
string
EDIT_PRIVILEGE
= ':Admin:Company:TimeSlot:edit'
Properties
$container
public
Container
$container
Attributes
- #[Inject]
$routerDispatcher
public
RouterDispatcher
$routerDispatcher
$translator
public
ITranslator
$translator
Tags
$appContext
protected
AppContext
$appContext
$componentParameters
protected
array<string, mixed>
$componentParameters
= []
component parameters set by setComponentParameter()
$currencyContext
protected
CurrencyContext|null
$currencyContext
= NULL
$deviceDetector
protected
DeviceDetector|null
$deviceDetector
= NULL
$languageContext
protected
LanguageContext|null
$languageContext
= NULL
$localizationContext
protected
LocalizationContext|null
$localizationContext
= NULL
$settingContext
protected
SettingContext
$settingContext
$themeContext
protected
ThemeContext|null
$themeContext
= NULL
$translatorDomain
protected
string|null
$translatorDomain
= 'admin.company.components.slotModal'
$allCalendars
Week view of all calendars; must survive the redraw.
private
bool
$allCalendars
= false
$calendarId
private
int
$calendarId
= 0
$calendarManager read-only
private
CalendarManager
$calendarManager
$companyId
Company the view is rendered for; context for redrawing the timeline only.
private
int
$companyId
= 0
$date
`Y-m-d` of the day whose timeline or grid the modal serves.
private
string
$date
= ''
$done
The action finished and nothing is left to offer (canceled reservation or deleted block).
private
bool
$done
= false
$fromMin
Range of the clicked free block in minutes after midnight ({@see MODE_FILL} only).
private
int
$fromMin
= 0
$mode
Active mode; `''` means the modal does not open in this request.
private
string
$mode
= ''
$notice
Per-request message rendered inside the modal (pitfall 4 in the class docblock).
private
array{type: string, text: string}|null
$notice
= null
Holds final text, not a translation key.
$reservation
Active reservation on {@see $slot} ({@see MODE_RESERVATION}).
private
Reservation|null
$reservation
= null
$reservationManager read-only
private
ReservationManager
$reservationManager
$returnSnippet
Snippet to redraw after an action: `dayTimeline` or `weekGrid`.
private
string
$returnSnippet
= self::SNIPPET_DAY
$slot
Calendar row ({@see MODE_RESERVATION}/{@see MODE_BLOCKED} modes).
private
TimeSlot|null
$slot
= null
$timeSlotManager read-only
private
TimeSlotManager
$timeSlotManager
$toMin
private
int
$toMin
= 0
Methods
__call()
Dispatches `renderXyz()` to `render('Xyz', ...$args)`.
public
__call(string $name, array<string|int, mixed> $args) : mixed
Called only when the component has no renderXyz() method of its own.
Parameters
- $name : string
- $args : array<string|int, mixed>
__construct()
public
__construct(TimeSlotManager $timeSlotManager, ReservationManager $reservationManager, CalendarManager $calendarManager) : mixed
Parameters
- $timeSlotManager : TimeSlotManager
- $reservationManager : ReservationManager
- $calendarManager : CalendarManager
createComponent()
public
createComponent(string $name) : IComponent|null
Parameters
- $name : string
Return values
IComponent|nullcreateComponentSlotForm()
Builds one form whose fields depend on the mode (pitfalls 2 and 3 in the class docblock).
public
createComponentSlotForm() : Form
No field has setRequired(); only the server (Api managers) validates.
Return values
FormgetAppContext()
public
getAppContext() : AppContext
Return values
AppContextgetComponentParameter()
Returns a component parameter, or null when it is not set.
public
getComponentParameter(string $name) : mixed
Parameters
- $name : string
getContainer()
public
getContainer() : Container
Return values
ContainergetCurrencyContext()
public
getCurrencyContext() : CurrencyContext|null
Return values
CurrencyContext|nullgetLanguageContext()
public
getLanguageContext() : LanguageContext|null
Return values
LanguageContext|nullgetLocalizationContext()
public
getLocalizationContext() : LocalizationContext|null
Return values
LocalizationContext|nullgetRouterDispatcher()
public
getRouterDispatcher() : RouterDispatcher
Return values
RouterDispatchergetSettingContext()
public
getSettingContext() : SettingContext
Return values
SettingContextgetSettings()
public
getSettings() : array<int, array<string, mixed>>
Return values
array<int, array<string, mixed>>getThemeContext()
public
getThemeContext() : ThemeContext|null
Return values
ThemeContext|nullgetViewContext()
Returns the view context after the signal was handled.
public
getViewContext() : array{companyId: int, calendarId: int, date: string, allCalendars: bool}|null
The presenter overrides its GET parameter values with it, because those do not reach the
component signal link (Nette prefixes all arguments with the component name, so ?date=...
is missing on the signal path and renderDay() would redraw a different day).
null means no modal signal ran in this request (a plain GET), so the presenter reads the
context as usual.
Return values
array{companyId: int, calendarId: int, date: string, allCalendars: bool}|nullhandleOpenBlocked()
Click on a block of a time block ({@see MODE_BLOCKED} mode).
public
handleOpenBlocked(int $companyId, int $timeSlotId[, string $returnSnippet = self::SNIPPET_DAY ][, bool $allCalendars = false ]) : void
Parameters
- $companyId : int
- $timeSlotId : int
- $returnSnippet : string = self::SNIPPET_DAY
- $allCalendars : bool = false
handleOpenFree()
Click on a free block of the day timeline ({@see MODE_FILL} mode).
public
handleOpenFree(int $companyId, int $calendarId, string $date, int $fromMin, int $toMin[, string $returnSnippet = self::SNIPPET_DAY ][, bool $allCalendars = false ]) : void
Parameters
- $companyId : int
- $calendarId : int
- $date : string
- $fromMin : int
- $toMin : int
- $returnSnippet : string = self::SNIPPET_DAY
- $allCalendars : bool = false
handleOpenReservation()
Click on a block with an active reservation ({@see MODE_RESERVATION} mode).
public
handleOpenReservation(int $companyId, int $timeSlotId[, string $returnSnippet = self::SNIPPET_DAY ][, bool $allCalendars = false ]) : void
Parameters
- $companyId : int
- $timeSlotId : int
- $returnSnippet : string = self::SNIPPET_DAY
- $allCalendars : bool = false
hasServiceByType()
Returns whether the container has a service of the given type.
public
hasServiceByType(string $className) : bool
The name is composed dynamically (module plus component), so class_exists() runs first, and
a true result guarantees a valid type.
Parameters
- $className : string
Tags
Return values
boolinitializeAllContexts()
public
initializeAllContexts() : void
injectDeviceDetector()
public
injectDeviceDetector(DeviceDetector $detector) : void
Parameters
- $detector : DeviceDetector
onCancelReservation()
Mode B, cancel reservation: reuses {@see ReservationManager::cancel()}.
public
onCancelReservation(SubmitButton $button) : void
Parameters
- $button : SubmitButton
onCreate()
public
onCreate() : void
onDeleteBlock()
Mode C, cancel block: reuses {@see TimeSlotManager::delete()}.
public
onDeleteBlock(SubmitButton $button) : void
Parameters
- $button : SubmitButton
onFillSave()
Mode A, single button: calls {@see ReservationManager::bookByAdmin()} or `TimeSlotManager::save()` with `type=blocked`, chosen by the submitted value of the `blocked` switch, not by which button caught the click.
public
onFillSave(SubmitButton $button) : void
Parameters
- $button : SubmitButton
onReservationSave()
Mode B, single save button: always calls {@see ReservationManager::updateByAdmin()} (name, e-mail, phone, note, state; never the time), and additionally acts on the submitted value of the `timeAction` switch: `keep` does nothing more, `shorten`/`split` also call {@see TimeSlotManager::shorten()}/`::split()`.
public
onReservationSave(SubmitButton $button) : void
IMPORTANT: both operations run under their own per-day lock (updateByAdmin() and
shorten()/split() take and release it themselves), so together they are not one
atomic transaction. When updateByAdmin() succeeds and the following shorten()/split()
fails (for example the new range collides), the field changes stay saved but the time does
not change. The admin gets an error message and the form reopens with the current, partly
saved state (loadReservationContext() always runs, even after an error). This is
accepted for a low-traffic admin UI instead of a new atomic Api method.
Parameters
- $button : SubmitButton
render()
Renders nothing into the page; it exists for its signals and to fill the shared {@see \App\UI\Admin\System\Components\ModalWindowComponent\ModalWindow} from `@layout.latte`.
public
render() : void
Templates do not mount it with {control slotModal}; they only generate
{link slotModal:open...!} links from it.
setAppContext()
public
setAppContext(AppContext $appContext) : $this
Parameters
- $appContext : AppContext
Return values
$thissetComponentParameter()
Sets a component parameter.
public
setComponentParameter(string $name, mixed $value) : void
Parameters
- $name : string
- $value : mixed
setCurrencyContext()
public
setCurrencyContext(CurrencyContext|null $currencyContext) : $this
Parameters
- $currencyContext : CurrencyContext|null
Return values
$thissetLanguageContext()
public
setLanguageContext(LanguageContext|null $languageContext) : $this
Parameters
- $languageContext : LanguageContext|null
Return values
$thissetLocalizationContext()
public
setLocalizationContext(LocalizationContext|null $localizationContext) : $this
Parameters
- $localizationContext : LocalizationContext|null
Return values
$thissetSettingContext()
public
setSettingContext(SettingContext $settingContext) : $this
Parameters
- $settingContext : SettingContext
Return values
$thissetThemeContext()
public
setThemeContext(ThemeContext|null $themeContext) : $this
Parameters
- $themeContext : ThemeContext|null
Return values
$thissetup()
public
setup(BasePresenter|BasePresenter $presenter) : void
Parameters
- $presenter : BasePresenter|BasePresenter
setupAppContext()
public
setupAppContext(AppContext $appContext) : void
Parameters
- $appContext : AppContext
typedComponent()
Returns a subcomponent with a verified type.
public
typedComponent(string $name, T> $type) : T
Use it instead of an inline @var above $this['x'] (which does not narrow the type) and
instead of the generic IComponent that $this['x'] returns. See
Form::typedComponent().
Parameters
- $name : string
- $type : T>
Tags
Return values
TfrontPresenter()
Returns the front presenter the component is attached to (null outside the front end or when detached).
protected
frontPresenter() : BasePresenter|null
Return values
BasePresenter|nullgetModalWindow()
protected
getModalWindow() : ModalWindow
Return values
ModalWindowgetTranslator()
protected
getTranslator() : ITranslator
Return values
ITranslatorisTargetAllowed()
Returns whether the logged-in user may open the given admin target. For visibility (tiles, autocomplete, buttons); it does not throw.
protected
isTargetAllowed(string|null $key) : bool
IMPORTANT: fail-closed like requirePrivilege(): an empty key and a presenter
without isAllowed() both mean no. A component that skips this question lists the
target to everyone.
Parameters
- $key : string|null
Return values
boolrequirePrivilege()
Throws 403 when the logged-in user lacks the given admin privilege.
protected
requirePrivilege(string $key) : void
Call it as the first statement of a mutating signal, before loading data, so the check cannot be bypassed by something being written first.
Parameters
- $key : string
resolvePageTarget()
Returns the RBAC key of the target page: `<presenter>:<action>`, e.g. `:Admin:System:User:show`.
protected
static resolvePageTarget(object|null $page) : string|null
Same interpretation as Menu::filterByPrivileges(), BasePresenter::authorizeListing() and PrivilegeCheckTrait::checkCurrentPrivilege(). The key is derived from the page target only, never from a file or class name.
Returns null when the page is missing or has no presenter, so there is nothing to allow.
Parameters
- $page : object|null
-
AdminPageentity (hydrated, hence justobject)
Return values
string|nullsetTemplateFile()
protected
setTemplateFile(string $dir, string $filename) : void
Parameters
- $dir : string
- $filename : string
setTranslator()
protected
setTranslator(ITranslator $translator) : self
Parameters
- $translator : ITranslator
Return values
selfaddBlockedFields()
Mode C: a block with no editable fields; the only action is canceling it.
private
addBlockedFields(Form $form) : void
Parameters
- $form : Form
addFillFields()
Mode A: a new reservation on a free interval, or a block of the same range.
private
addFillFields(Form $form) : void
Parameters
- $form : Form
addReservationFields()
Mode B: an existing reservation with details and state, shorten/split tools and cancellation.
private
addReservationFields(Form $form) : void
Parameters
- $form : Form
createMultiplierComponent()
Creates a multiplier for the component.
private
createMultiplierComponent(string $name) : Multiplier<string|int, IComponent>
Parameters
- $name : string
Return values
Multiplier<string|int, IComponent>createNewComponentInstance()
Creates a new component instance without adding it to the presenter; used by the multiplier.
private
createNewComponentInstance(string $baseName[, int|string|null $uniqueKey = null ]) : IComponent|null
Parameters
- $baseName : string
- $uniqueKey : int|string|null = null
Return values
IComponent|nullcreateStandardComponent()
Creates a standard component (not a multiplier).
private
createStandardComponent(string $name) : IComponent|null
Parameters
- $name : string
Return values
IComponent|nullfailAndReopen()
Turns an Api action failure into a readable message inside the modal (no flash, pitfall 4).
private
failAndReopen(Result $result) : void
Parameters
- $result : Result
fillActionOptions()
Returns the `fillAction` options as translation keys, like {@see timeActionOptions()} (`addRadioList()` translates them through the form `useDomainTranslator()`).
private
fillActionOptions() : array<string, string>
Return values
array<string, string>findCalendar()
private
findCalendar(int $calendarId) : Calendar|null
Parameters
- $calendarId : int
Return values
Calendar|nullfindSlot()
private
findSlot(int $timeSlotId) : TimeSlot|null
Parameters
- $timeSlotId : int
Return values
TimeSlot|nullfinish()
Refills the modal and redraws the underlying timeline or grid (pitfall 5 in the class docblock).
private
finish() : void
formatDate()
Converts `Y-m-d` to `j. n. Y`; an invalid date is returned unchanged.
private
formatDate(string $date) : string
Parameters
- $date : string
Return values
stringformatMinutes()
Converts minutes after midnight to `HH:MM`, like Api `TimeSlotManager::formatMinutes()`.
private
static formatMinutes(int $minutes) : string
Parameters
- $minutes : int
Return values
stringhydrateContext()
Restores the view context from the submitted hidden fields, because the signal link of the form does not carry it (pitfall 1 in the class docblock). Calendar and day of modes B and C are loaded from the time slot, not from here.
private
hydrateContext(array<string, mixed> $values) : void
Parameters
- $values : array<string, mixed>
int()
private
int(mixed $value) : int
Parameters
- $value : mixed
Return values
intloadReservationContext()
Loads a fresh row and its active reservation (pitfall 6 in the class docblock: hydrated objects do not update after a bridge write).
private
loadReservationContext(int $timeSlotId) : void
Without an active reservation the mode falls back to "not found", so the modal does not offer actions on something that no longer exists.
Parameters
- $timeSlotId : int
normalizeSnippet()
Allows only the two known values; a foreign string would crash the request in `redrawControl()`.
private
static normalizeSnippet(string $snippet) : string
Parameters
- $snippet : string
Return values
stringnoticeError()
private
noticeError(string $text) : void
Parameters
- $text : string
noticeSuccess()
private
noticeSuccess(string $text) : void
Parameters
- $text : string
parseTime()
Converts the value of `<input type=time>` to `DateTime`, or null when empty or invalid.
private
parseTime(mixed $value) : DateTime|null
Parameters
- $value : mixed
Return values
DateTime|nullrenderModalContent()
Renders the modal content to a string for `ModalWindow`.
private
renderModalContent() : string
Return values
stringrequireCalendarInCompany()
403 when an existing calendar does not belong to the company the modal was opened from.
private
requireCalendarInCompany(int $calendarId, int $companyId) : void
Parameters
- $calendarId : int
- $companyId : int
requireReservationOfSlot()
403 when the posted reservation id points to a reservation of a different slot.
private
requireReservationOfSlot(int $reservationId, int $timeSlotId) : void
Parameters
- $reservationId : int
- $timeSlotId : int
requireSlotInCompany()
403 when an existing slot does not belong to the company the modal was opened from.
private
requireSlotInCompany(int $timeSlotId, int $companyId) : void
A missing slot passes — the regular "not found" flow handles it without leaking data.
Parameters
- $timeSlotId : int
- $companyId : int
resolveMode()
Returns the mode used to build the form.
private
resolveMode() : string
When opened, the property holds it (set by handleOpen*()); on submit no handleOpen*()
ran, so it is read from the hidden POST field. Without that the form would be built with
the fields of another mode and the submit would break.
Return values
stringsaveBlock()
Saves a block through `save()` with an entity of `type = blocked` (no dedicated Api action; the same path as `TimeSlotFormTrait`).
private
saveBlock(array<string, mixed> $values) : Result
Parameters
- $values : array<string, mixed>
Return values
ResultsaveReservation()
private
saveReservation(array<string, mixed> $values) : Result
Parameters
- $values : array<string, mixed>
Return values
ResultsaveWindow()
Creates a time slot through {@see TimeSlotManager::openWindow()}.
private
saveWindow(array<string, mixed> $values) : Result
Unlike saveBlock() it has no input validation of its own: an empty or invalid time and a reversed range are rejected by the Api method with the same message as the other guards.
Parameters
- $values : array<string, mixed>
Return values
ResultshowModal()
Fills and opens the shared admin modal with the current state.
private
showModal() : void
Idempotent: after a submit it is called again and redraws only the inside (the modal stays
open, see ModalWindow::open()).
stateOptions()
private
stateOptions() : array<string, string>
Return values
array<string, string>str()
private
str(mixed $value) : string
Parameters
- $value : mixed
Return values
stringstrOrNull()
private
strOrNull(mixed $value) : string|null
Parameters
- $value : mixed
Return values
string|nulltext()
Returns final translated text (not a key) for the {@see $notice} buffer and select options.
private
text(string $key) : string
Parameters
- $key : string
Return values
stringtimeActionOptions()
Returns the `timeAction` options as translation keys.
private
timeActionOptions() : array<string, string>
Unlike stateOptions() they are not pre-translated: addRadioList() has no
setTranslator(null), so the label and items go through the form translator
(useDomainTranslator()) automatically. Reuses the keys shorten.submit and split.submit.
Return values
array<string, string>values()
Returns the form values.
private
values(SubmitButton $button) : array<string, mixed>
Uses getUntrustedValues() on purpose: the form has no validation rule at all (pitfall 2
in the class docblock), so this is the only meaningful source and the only one that
survives a validation scope.
Parameters
- $button : SubmitButton