CoolCMS API

MyWorkDetail extends BaseComponent
in package
uses InitTrait, SignalTrait, FormTrait

FinalYes

Detail of one job of the client: the job header, the table of work items and the expansion of one work item (persistent `$work`): description, hours/rate/price and the comment thread with a form for adding a message.

A job outside the ownership (foreign or nonexistent) gives one uniform "job not found" empty state; setWorkListId() only passes the id and the ownership is verified on the server: the job header is looked up in the client's own myList result and the work items come from myItems (WorkItemManager::findForOwnedList()).

Same approach as BookingCalendarComponent (persistent parameter + signal + memoized fetch available before render(), see InitTrait).

Table of Contents

Constants

ERROR_MESSAGE_KEYS  : array<string|int, mixed> = [2 => 'comments.form.messages.errors.validation...
`code` of the Api response (`mixed` because of `ReflectionException`) mapped to the translated message key.

Properties

$container  : Container
$routerDispatcher  : RouterDispatcher
$translator  : ITranslator
$work  : int|null
Expanded work item; `null` means only the job table without a work item detail.
$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
$itemsCache  : WorkSheet>, unreadComments: array}|null
Memoizes {@see WorkItemManager::findMyItems()} within one request, for the same reason as `$listsCache`: the guard "the chosen work item belongs to this job" of `prepareWorkDetail()` (see `InitTrait::fetchItems()`) needs the same data as the grouping by work sheet in `prepareDetail()`, and a signal/form success calls `prepareWorkDetail()` separately, possibly before `prepareDetail()`.
$listsCache  : WorkList>, totalCount: int, workItemCounts: array}|null
Memoizes {@see WorkListManager::findMyLists()} within one request; the comment form can be created before `render()` (a signal/form POST calls `createComponent*()` first), see `InitTrait::fetchLists()`.
$workItemManager  : WorkItemManager
$workListId  : int
Id of the displayed job; set by the presenter ({@see setWorkListId()}) after `actionDetail()`.
$workListManager  : WorkListManager

Methods

__call()  : mixed
Dispatches `renderXyz()` to `render('Xyz', ...$args)`.
__construct()  : mixed
createComponent()  : IComponent|null
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
handleSelectWork()  : void
hasServiceByType()  : bool
Returns whether the container has a service of the given type.
initializeAllContexts()  : void
injectDeviceDetector()  : void
onCommentFormSuccess()  : void
onCreate()  : void
render()  : void
setAppContext()  : $this
setComponentParameter()  : void
Sets a component parameter.
setCurrencyContext()  : $this
setLanguageContext()  : $this
setLocalizationContext()  : $this
setSettingContext()  : $this
setThemeContext()  : $this
setup()  : void
setupAppContext()  : void
setWorkListId()  : self
typedComponent()  : T
Returns a subcomponent with a verified type.
createComponentCommentForm()  : Form
frontPresenter()  : BasePresenter|null
Returns the front presenter the component is attached to (null outside the front end or when detached).
getTranslator()  : ITranslator
setTemplateFile()  : void
setTranslator()  : self
belongsToCurrentList()  : bool
Tells whether the expanded work item belongs to the job `$this->workListId` (replaces the removed `WorkItem::getWorkListId()`, see {@see prepareWorkDetail()}). `myItems` returns only the work items of this job (the server verified ownership), so membership in the {@see fetchItems()} result is the answer.
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).
fetchItems()  : WorkSheet>, unreadComments: array}
Returns `WorkItemManager::findMyItems()` memoized for the lifetime of this component instance, for the same reason as {@see fetchLists()}: the guard of `prepareWorkDetail()` ({@see belongsToCurrentList()}) can run before `render()` and `prepareDetail()` calls it again; without memoization that would be two bridge queries per request.
fetchLists()  : WorkList>, totalCount: int, workItemCounts: array}
Returns `WorkListManager::findMyLists()` memoized for the lifetime of this component instance (one request). Required because the comment form can be created before `render()` (a form POST calls `createComponent*()` first); same as {@see \App\UI\Front\Company\Components\BookingCalendarComponent\Traits\InitTrait::fetchAvailability()}.
findOwnedList()  : WorkList|null
Returns the owned job from `myList` by `$this->workListId`, or `null` (foreign or nonexistent).
groupItemsBySheet()  : array<int, WorkItem>, sumHours: string, sumPrice: string}>
Groups work items by work sheet for the template (sheet heading + its items + hours/price sum per group).
prepareDetail()  : void
prepareEmptyWorkDetail()  : void
prepareWorkDetail()  : void
resolveMessageKey()  : string
An unknown or missing code gives the generic message.
str()  : string
`ArrayHash` values are `mixed`; safely narrows to string (a non-string becomes empty).
sumGroupHours()  : string
Returns the hours sum of a group: the same value as shown on the row (`actualHours ?? estimatedHours`, {@see \App\UI\Front\Company\Components\MyWorkDetailComponent\Templates\Default\Sections\Items.latte}), so the sum matches the table above it.
sumGroupPrice()  : string

Constants

ERROR_MESSAGE_KEYS

`code` of the Api response (`mixed` because of `ReflectionException`) mapped to the translated message key.

private array<string|int, mixed> ERROR_MESSAGE_KEYS = [2 => 'comments.form.messages.errors.validationFailed', 404 => 'comments.form.messages.errors.rateLimitExceeded']

Properties

$work

Expanded work item; `null` means only the job table without a work item detail.

public int|null $work = null
Attributes
#[Persistent]

$componentParameters

protected array<string, mixed> $componentParameters = []

component parameters set by setComponentParameter()

$translatorDomain

protected string|null $translatorDomain = 'front.company.components.myWorkDetail'

$itemsCache

Memoizes {@see WorkItemManager::findMyItems()} within one request, for the same reason as `$listsCache`: the guard "the chosen work item belongs to this job" of `prepareWorkDetail()` (see `InitTrait::fetchItems()`) needs the same data as the grouping by work sheet in `prepareDetail()`, and a signal/form success calls `prepareWorkDetail()` separately, possibly before `prepareDetail()`.

private WorkSheet>, unreadComments: array}|null $itemsCache = null

$listsCache

Memoizes {@see WorkListManager::findMyLists()} within one request; the comment form can be created before `render()` (a signal/form POST calls `createComponent*()` first), see `InitTrait::fetchLists()`.

private WorkList>, totalCount: int, workItemCounts: array}|null $listsCache = null

$workListId

Id of the displayed job; set by the presenter ({@see setWorkListId()}) after `actionDetail()`.

private int $workListId = 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>

createComponent()

public createComponent(string $name) : IComponent|null
Parameters
$name : string
Return values
IComponent|null

getComponentParameter()

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
Container

getSettings()

public getSettings() : array<int, array<string, mixed>>
Return values
array<int, array<string, mixed>>

handleSelectWork()

public handleSelectWork(int $workId) : void
Parameters
$workId : int

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
phpstan-assert-if-true

class-string $className

Return values
bool

onCommentFormSuccess()

public onCommentFormSuccess(Form $form, ArrayHash $values) : void
Parameters
$form : Form
$values : ArrayHash

render()

public render([string $style = 'Detail' ]) : void
Parameters
$style : string = 'Detail'

setComponentParameter()

Sets a component parameter.

public setComponentParameter(string $name, mixed $value) : void
Parameters
$name : string
$value : mixed

setWorkListId()

public setWorkListId(int $workListId) : self
Parameters
$workListId : int
Return values
self

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
template
Return values
T

createComponentCommentForm()

protected createComponentCommentForm() : Form
Return values
Form

frontPresenter()

Returns the front presenter the component is attached to (null outside the front end or when detached).

protected frontPresenter() : BasePresenter|null
Return values
BasePresenter|null

getTranslator()

protected getTranslator() : ITranslator
Return values
ITranslator

setTemplateFile()

protected setTemplateFile(string $dir, string $filename) : void
Parameters
$dir : string
$filename : string

setTranslator()

protected setTranslator(ITranslator $translator) : self
Parameters
$translator : ITranslator
Return values
self

belongsToCurrentList()

Tells whether the expanded work item belongs to the job `$this->workListId` (replaces the removed `WorkItem::getWorkListId()`, see {@see prepareWorkDetail()}). `myItems` returns only the work items of this job (the server verified ownership), so membership in the {@see fetchItems()} result is the answer.

private belongsToCurrentList(WorkItem $detail) : bool
Parameters
$detail : WorkItem
Return values
bool

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|null

createStandardComponent()

Creates a standard component (not a multiplier).

private createStandardComponent(string $name) : IComponent|null
Parameters
$name : string
Return values
IComponent|null

fetchItems()

Returns `WorkItemManager::findMyItems()` memoized for the lifetime of this component instance, for the same reason as {@see fetchLists()}: the guard of `prepareWorkDetail()` ({@see belongsToCurrentList()}) can run before `render()` and `prepareDetail()` calls it again; without memoization that would be two bridge queries per request.

private fetchItems() : WorkSheet>, unreadComments: array}
Return values
WorkSheet>, unreadComments: array}

fetchLists()

Returns `WorkListManager::findMyLists()` memoized for the lifetime of this component instance (one request). Required because the comment form can be created before `render()` (a form POST calls `createComponent*()` first); same as {@see \App\UI\Front\Company\Components\BookingCalendarComponent\Traits\InitTrait::fetchAvailability()}.

private fetchLists() : WorkList>, totalCount: int, workItemCounts: array}
Return values
WorkList>, totalCount: int, workItemCounts: array}

findOwnedList()

Returns the owned job from `myList` by `$this->workListId`, or `null` (foreign or nonexistent).

private findOwnedList() : WorkList|null
Return values
WorkList|null

groupItemsBySheet()

Groups work items by work sheet for the template (sheet heading + its items + hours/price sum per group).

private groupItemsBySheet(array<int, WorkItem> $items, array<int, WorkSheet> $sheets) : array<int, WorkItem>, sumHours: string, sumPrice: string}>

IMPORTANT: the group order follows the first occurrence in $items. The Api returns them already sorted work_sheets.order -> work_items.order -> id (WorkItemManager::sortForInvoice()), i.e. exactly in the order they would go on the invoice. They are not sorted again here, only grouped, so the order never differs from what the client sees on the document.

An item without _references (should not happen, every work item has a sheet) gets sheet: null; the template then shows the work item without a sheet header rather than silently dropping it (degrade, not fatal, as in EntityHydrator).

Sums are computed by the server (PHP), not in the template; bcadd is used because of the decimal columns (decimal in the DB, string on the entity), like WorkListManager::sumItemPrices().

Parameters
$items : array<int, WorkItem>
$sheets : array<int, WorkSheet>
Return values
array<int, WorkItem>, sumHours: string, sumPrice: string}>

prepareDetail()

private prepareDetail() : void

prepareEmptyWorkDetail()

private prepareEmptyWorkDetail() : void

prepareWorkDetail()

private prepareWorkDetail() : void

resolveMessageKey()

An unknown or missing code gives the generic message.

private static resolveMessageKey(bool $success, bool $approved, mixed $code) : string
Parameters
$success : bool
$approved : bool
$code : mixed
Return values
string

str()

`ArrayHash` values are `mixed`; safely narrows to string (a non-string becomes empty).

private static str(mixed $value) : string
Parameters
$value : mixed
Return values
string

sumGroupHours()

Returns the hours sum of a group: the same value as shown on the row (`actualHours ?? estimatedHours`, {@see \App\UI\Front\Company\Components\MyWorkDetailComponent\Templates\Default\Sections\Items.latte}), so the sum matches the table above it.

private sumGroupHours(array<int, WorkItem> $items) : string
Parameters
$items : array<int, WorkItem>
Return values
string

sumGroupPrice()

private sumGroupPrice(array<int, WorkItem> $items) : string
Parameters
$items : array<int, WorkItem>
Return values
string
On this page

Search results