CoolCMS API

DashboardAttention extends BaseComponent
in package

FinalYes

Dashboard band of cards for what waits for action in the admin.

A card exists only when its count is nonzero; the empty state is one "nothing waits" sentence. Rules:

  • Zero counts are not shown (a row of ten zero cards looks like a broken page).
  • Nothing is counted that the user cannot see: isAllowed() is asked before counting, not in the template, so no query runs for a user without the list privilege.
  • A link leads to where there is something to do: when the grid has a matching search column, the filter is passed via grid-filters.

Each card costs one count query plus one single-row select (limit: 1, computeTotalCount: true). Counts are deliberately not cached: a stale value on a to-do counter is worse than an extra query.

The admin layer does not touch Api or Front, so payment states are a local copy of App\UI\Api\System\Enums\PaymentStatus in PAYMENT_STATUS_START; when the code list changes, change it here too.

Table of Contents

Constants

KEY_STATE_EXPIRED  : mixed = 'expired'
KEY_STATE_EXPIRING  : mixed = 'expiring'
Application key states as returned by the Api in `keys[].state`.
PAYMENT_STATUS_START  : mixed = 2
Payment in the "started" state: the customer left for the gateway and never came back.
STUCK_PAYMENT_HOURS  : mixed = 1
Hours in the "started" state after which a payment counts as stuck. A card payment finishes within a minute and a bank transfer within two days, so one hour is a safe threshold that does not catch normal traffic.

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
$apiClientManager  : ApiClientManager
$apiOverview  : array{clients: list>, defaultLimits: array}|null|false
Overview of applications with Api access, loaded once for both key cards.
$bazaarAdvertManager  : AdvertManager
$bazaarResponseManager  : ResponseManager
$comcatAdvertManager  : AdvertManager
$comcatResponseManager  : ResponseManager
$commentManager  : CommentManager
$complaintManager  : ComplaintManager
$emailQueueManager  : EmailQueueManager
$invoiceManager  : InvoiceManager
$orderManager  : OrderManager
$paymentManager  : PaymentManager
$ratingManager  : RatingManager

Methods

__call()  : mixed
Dispatches `renderXyz()` to `render('Xyz', ...$args)`.
__construct()  : mixed
countKeysInState()  : int
Counts keys in state `$state` of clients that are not revoked. The key state (`active`/`expiring`/`expired`/`revoked`) is computed by the Api; the "soon" threshold lives only there (`Api\ApiClientManager::EXPIRING_SOON_DAYS`) and is not duplicated here.
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
hasServiceByType()  : bool
Returns whether the container has a service of the given type.
initializeAllContexts()  : void
injectDeviceDetector()  : 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
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).
getTranslator()  : ITranslator
setTemplateFile()  : void
setTranslator()  : self
buildHref()  : string|null
Returns the link to the target list, or `null` when the target does not exist in this installation.
collectCards()  : array<int, array{key: string, icon: string, count: int, href: string, tone: string}>
Cards with a nonzero count in order of urgency: money and customer first, cleanup last.
countApiKeys()  : int
Returns the number of application keys in the given state; on an Api read failure returns 0 and logs.
countBy()  : int
Counts records matching the filters.
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).
definitions()  : array<int, array{key: string, privilege: string, icon: string, tone: string, destination: string, params: array, count: callable}>
Card definitions. Array order is page order.
isAllowedDestination()  : bool
Whether the user may open the target list. Read from the array loaded in the presenter's `startup()`, no extra query.
logDashboardFailure()  : void
A failure of one card is logged and the rest continues. Without the log a query error would show only as a vanished card, indistinguishable from "nothing to do".
pluralLabel()  : string
Returns the card label in the right plural form for the count.

Constants

KEY_STATE_EXPIRING

Application key states as returned by the Api in `keys[].state`.

private mixed KEY_STATE_EXPIRING = 'expiring'

PAYMENT_STATUS_START

Payment in the "started" state: the customer left for the gateway and never came back.

private mixed PAYMENT_STATUS_START = 2

Matches App\UI\Api\System\Enums\PaymentStatus::START.

STUCK_PAYMENT_HOURS

Hours in the "started" state after which a payment counts as stuck. A card payment finishes within a minute and a bank transfer within two days, so one hour is a safe threshold that does not catch normal traffic.

private mixed STUCK_PAYMENT_HOURS = 1

Properties

$componentParameters

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

component parameters set by setComponentParameter()

$translatorDomain

protected string|null $translatorDomain = 'admin.system.components.dashboardAttention'

$apiOverview

Overview of applications with Api access, loaded once for both key cards.

private array{clients: list>, defaultLimits: array}|null|false $apiOverview = false

false means not loaded yet (null is a valid value: the Api returned no data).

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(OrderManager $orderManager, ComplaintManager $complaintManager, InvoiceManager $invoiceManager, PaymentManager $paymentManager, AdvertManager $bazaarAdvertManager, ResponseManager $bazaarResponseManager, AdvertManager $comcatAdvertManager, ResponseManager $comcatResponseManager, CommentManager $commentManager, RatingManager $ratingManager, EmailQueueManager $emailQueueManager, ApiClientManager $apiClientManager) : mixed
Parameters
$orderManager : OrderManager
$complaintManager : ComplaintManager
$invoiceManager : InvoiceManager
$paymentManager : PaymentManager
$bazaarAdvertManager : AdvertManager
$bazaarResponseManager : ResponseManager
$comcatAdvertManager : AdvertManager
$comcatResponseManager : ResponseManager
$commentManager : CommentManager
$ratingManager : RatingManager
$emailQueueManager : EmailQueueManager
$apiClientManager : ApiClientManager

countKeysInState()

Counts keys in state `$state` of clients that are not revoked. The key state (`active`/`expiring`/`expired`/`revoked`) is computed by the Api; the "soon" threshold lives only there (`Api\ApiClientManager::EXPIRING_SOON_DAYS`) and is not duplicated here.

public static countKeysInState(array<int, array<string, mixed>> $clients, string $state) : int
Parameters
$clients : array<int, array<string, mixed>>

rows from the Api overview

$state : string
Return values
int

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

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

setComponentParameter()

Sets a component parameter.

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

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

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

buildHref()

Returns the link to the target list, or `null` when the target does not exist in this installation.

private buildHref(string $destination, array<string, mixed> $params) : string|null

Not every project has all modules; a link to a missing presenter would break the whole dashboard with InvalidLinkException, so the card is dropped.

Parameters
$destination : string
$params : array<string, mixed>
Return values
string|null

collectCards()

Cards with a nonzero count in order of urgency: money and customer first, cleanup last.

private collectCards() : array<int, array{key: string, icon: string, count: int, href: string, tone: string}>
Return values
array<int, array{key: string, icon: string, count: int, href: string, tone: string}>

countApiKeys()

Returns the number of application keys in the given state; on an Api read failure returns 0 and logs.

private countApiKeys(string $state) : int
Parameters
$state : string
Return values
int

countBy()

Counts records matching the filters.

private countBy(Manager $manager, array<int, object> $filters) : int

limit: 1: getTotalCount() runs execute() internally, so without a limit the whole table would be loaded for one number.

An error (missing module, renamed column) is swallowed to zero: the dashboard must not break admin entry because of a supplementary card. A missing card behaves the same as a zero count.

Parameters
$manager : Manager
$filters : array<int, object>
Return values
int

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

definitions()

Card definitions. Array order is page order.

private definitions() : array<int, array{key: string, privilege: string, icon: string, tone: string, destination: string, params: array, count: callable}>

tone sets the color by what the card means:

  • urgent — someone waits for money or goods,
  • review — waits for an admin decision,
  • notice — operational notice, can wait until tomorrow.
Return values
array<int, array{key: string, privilege: string, icon: string, tone: string, destination: string, params: array, count: callable}>

isAllowedDestination()

Whether the user may open the target list. Read from the array loaded in the presenter's `startup()`, no extra query.

private isAllowedDestination(string $privilege) : bool

Fail-closed: a presenter without isAllowed() (theoretically another context) hides the card instead of exposing the count.

Parameters
$privilege : string
Return values
bool

logDashboardFailure()

A failure of one card is logged and the rest continues. Without the log a query error would show only as a vanished card, indistinguishable from "nothing to do".

private logDashboardFailure(Throwable $e) : void
Parameters
$e : Throwable

pluralLabel()

Returns the card label in the right plural form for the count.

private pluralLabel(string $key, int $count) : string

The label needs several plural forms (one / few / many) and a wrong form makes the page look unfinished. The translation holds the forms in Symfony notation ({1} … |[2,4] … |]4,Inf[ …), the translator picks by the second argument.

Translated in PHP, not in the template: in Latte the count would have to be passed through {_} and the notation would become unreadable.

Parameters
$key : string
$count : int
Return values
string
On this page

Search results