CoolCMS API

MessageManager extends Manager
in package
uses TreeTrait, ElasticReindexTrait

Abstract admin manager generic over the entity type and its service.

Tags
extends

Table of Contents

Properties

$service  : TService
Manager service; subclasses narrow the type (`@property` in the Api/Admin/Front manager).
$appContext  : AppContext
$cacheTagInvalidator  : CacheTagInvalidator|null
Post-commit invalidator of the wire-payload query cache (tag bump per entity class).
$languageContext  : LanguageContext|null
$paramsConfig  : Config|null
Neon parameters (`%params%`: server paths and directories), set by the decorator (`decorators.neon`) like `setAppContext()`.
$presenterContext  : PresenterContext
$settingContext  : SettingContext
$esDocumentSource  : MessageDocumentSource
$esIndexer  : EsEntityIndexer

Methods

__construct()  : mixed
delete()  : Result
deleteAll()  : Result
deleteNode()  : Result
Deletes a thread node and syncs Elasticsearch right away.
find()  : SingleQuery<string|int, T>
Finds one entity by id (returns a `SingleQuery` object).
findAll()  : Query<string|int, T>
Finds all entities (returns a `Query` object).
findBy()  : SingleQuery<string|int, T>
Finds one entity by filters (returns a `SingleQuery` object).
getAppContext()  : AppContext
getLanguageContext()  : LanguageContext|null
getPresenterContext()  : PresenterContext
getSettingContext()  : SettingContext
getSettings()  : array<int, array<string, mixed>>
getTotalCount()  : int|null
Returns the total count of the last `findAll()` of this manager's service, computed only when the query asked for it (`findAll(..., computeTotalCount: true)`); otherwise the last stored value.
initializeAllContexts()  : void
insertTreeNode()  : Result
Computes `lft`, `rgt` and `level` for a newly inserted node (after `save()`, when it has `parent_id` but zero `lft`/`rgt`); it becomes the last sibling.
moveDown()  : Result
moveSubtree()  : Result
Moves a subtree and reindexes the moved node.
moveSubtreeTo()  : Result
Same level change as {@see moveSubtree()}, with a target position (grid `TreeMoveTrait`).
moveUp()  : Result
reorderChildren()  : Result
Reorders the direct children of a parent (with subtrees) in one operation under the tree lock on the Api.
save()  : Result
setAppContext()  : $this
setCacheTagInvalidator()  : static
setLanguageContext()  : $this
setParamsConfig()  : static
setPresenterContext()  : $this
setSettingContext()  : $this
updateColumn()  : Result
updateColumns()  : Result
bumpCacheTags()  : void
Bumps cache tags for the entity after commit: its class, the owned-cascade classes from metadata and the optional `additionalCacheTags()` of the manager.
bumpCacheTagsExplicit()  : void
Bumps the given classes explicitly (raw-DBAL paths with a cross-entity effect).
bumpCacheTagsForClass()  : void
Bumps cache tags by class name when there is no instance (bulk delete, `updateColumns()`, raw DBAL, tree operations).
classCacheTags()  : array<string|int, string>
Returns extra tags for a bump that has no entity, typically tree operations ({@see \App\Core\Traits\Api\Models\Managers\TreeTrait::treeTransaction()}) that rewrite `lft`/`rgt` on many rows.
esReindexBestEffort()  : void
Catches ES up after an admin mutation; it never breaks a write that is already in the database.
getService()  : TService
Returns the service for the traits.
touchForEsWatermark()  : void
Bumps the entity update timestamp so the watermark sync also sees an admin edit (a second safety net next to the direct reindex). An entity may have no timestamp, so the default is a no-op; a manager overrides it (`ProductSet::setUpdateTime()`, `Article::setUpdateDatetime()`, ...).
moveTreeNode()  : Result
requireServiceTreeMethod()  : void
Loud guard against silent failure: a bridge tree operation runs only when the next service has the same tree method.

Properties

$service

Manager service; subclasses narrow the type (`@property` in the Api/Admin/Front manager).

public TService $service

$cacheTagInvalidator

Post-commit invalidator of the wire-payload query cache (tag bump per entity class).

protected CacheTagInvalidator|null $cacheTagInvalidator = null

Set by the decorator (decorators.neon) like setParamsConfig(). Nullable and fail-open: without wiring (or without Redis) a bump is a no-op.

$paramsConfig

Neon parameters (`%params%`: server paths and directories), set by the decorator (`decorators.neon`) like `setAppContext()`.

protected Config|null $paramsConfig = null

Write logic (asset directories) reads paths from here, not from getSettings() or the setting context, which may be filled by the client without server paths. The property cannot be named $config: it collides with the promoted $config in some managers.

Methods

deleteAll()

public deleteAll([array<string|int, mixed> $filters = [] ]) : Result
Parameters
$filters : array<string|int, mixed> = []
Return values
Result

deleteNode()

Deletes a thread node and syncs Elasticsearch right away.

public deleteNode(int $id[, TreeConfig $config = new TreeConfig() ]) : Result

Tree deletion (deleteTreeNode() on the service) fires no hooks, so a deleted root would stay in the index until the sync orphan cleanup or the nightly reindex. fetchFresh does not find the deleted id, so the indexer deletes its documents.

Parameters
$id : int
$config : TreeConfig = new TreeConfig()
Return values
Result

find()

Finds one entity by id (returns a `SingleQuery` object).

public find(int $id[, string|array<string|int, mixed> $includes = [] ]) : SingleQuery<string|int, T>
Parameters
$id : int

entity id

$includes : string|array<string|int, mixed> = []

relations to load (['translations', 'routes'] or '*' for all)

Return values
SingleQuery<string|int, T>

findAll()

Finds all entities (returns a `Query` object).

public findAll([array<string|int, mixed>|null $filters = [] ][, array<string|int, mixed>|null $orderBy = null ][, int|null $offset = null ][, int|null $limit = null ][, array<string|int, mixed>|null $columns = null ][, string|array<string|int, mixed> $includes = [] ][, bool $computeTotalCount = false ]) : Query<string|int, T>
Parameters
$filters : array<string|int, mixed>|null = []

filters for the where conditions

$orderBy : array<string|int, mixed>|null = null

ordering ['column' => 'ASC/DESC']

$offset : int|null = null

offset for pagination

$limit : int|null = null

result limit

$columns : array<string|int, mixed>|null = null

specific columns to load

$includes : string|array<string|int, mixed> = []

relations to load (['translations', 'routes.translations'] or '*' for all)

$computeTotalCount : bool = false

whether to compute the total count for pagination

Return values
Query<string|int, T>

findBy()

Finds one entity by filters (returns a `SingleQuery` object).

public findBy([array<string|int, mixed> $filters = [] ][, string|array<string|int, mixed> $includes = [] ]) : SingleQuery<string|int, T>
Parameters
$filters : array<string|int, mixed> = []

filters for the where conditions

$includes : string|array<string|int, mixed> = []

relations to load (['translations', 'routes'] or '*' for all)

Return values
SingleQuery<string|int, T>

getSettings()

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

getTotalCount()

Returns the total count of the last `findAll()` of this manager's service, computed only when the query asked for it (`findAll(..., computeTotalCount: true)`); otherwise the last stored value.

public getTotalCount() : int|null

Same value as Query::getTotalCount() of that query.

Return values
int|null

insertTreeNode()

Computes `lft`, `rgt` and `level` for a newly inserted node (after `save()`, when it has `parent_id` but zero `lft`/`rgt`); it becomes the last sibling.

public insertTreeNode(int $id[, TreeConfig $config = new TreeConfig() ]) : Result
Parameters
$id : int
$config : TreeConfig = new TreeConfig()
Return values
Result

moveSubtree()

Moves a subtree and reindexes the moved node.

public moveSubtree(int $id, int|null $newParentId[, TreeConfig $config = new TreeConfig() ]) : Result

IMPORTANT: a move changes level, and only thread roots are indexed. A reply promoted to a root must enter the index and a root nested under another thread must leave it; without the reindex the promoted reply is missing from search and the watermark sync never sees it (Message has no update timestamp). Descendants never gain or lose level 1, so the node id is enough.

Parameters
$id : int
$newParentId : int|null
$config : TreeConfig = new TreeConfig()
Return values
Result

reorderChildren()

Reorders the direct children of a parent (with subtrees) in one operation under the tree lock on the Api.

public reorderChildren(int|null $parentId, array<int, int> $orderedIds[, TreeConfig $config = new TreeConfig() ]) : Result

A mismatching set of children gives TREE_STALE; data.changed is the number of moved children.

Parameters
$parentId : int|null

null is the root level

$orderedIds : array<int, int>

ids of all children of the parent in the new order

$config : TreeConfig = new TreeConfig()
Return values
Result

setParamsConfig()

public setParamsConfig(Config $paramsConfig) : static
Parameters
$paramsConfig : Config
Return values
static

updateColumn()

public updateColumn(int|array<string|int, int> $entityId, string $property, mixed $value) : Result
Parameters
$entityId : int|array<string|int, int>
$property : string
$value : mixed
Return values
Result

updateColumns()

public updateColumns(int|array<string|int, int> $entityId, array<string, mixed> $values) : Result
Parameters
$entityId : int|array<string|int, int>
$values : array<string, mixed>
Return values
Result

bumpCacheTags()

Bumps cache tags for the entity after commit: its class, the owned-cascade classes from metadata and the optional `additionalCacheTags()` of the manager.

protected bumpCacheTags(object $entity) : void

Fail-open (the invalidator swallows exceptions). Called from the manager Save/Delete/Tree traits after the commit.

Parameters
$entity : object

bumpCacheTagsExplicit()

Bumps the given classes explicitly (raw-DBAL paths with a cross-entity effect).

protected bumpCacheTagsExplicit(array<string|int, string> $classes) : void
Parameters
$classes : array<string|int, string>

bumpCacheTagsForClass()

Bumps cache tags by class name when there is no instance (bulk delete, `updateColumns()`, raw DBAL, tree operations).

protected bumpCacheTagsForClass(class-string $rootClass[, array<string|int, string> $extraTags = [] ]) : void

Bumps the root class and its owned-cascade classes.

Parameters
$rootClass : class-string
$extraTags : array<string|int, string> = []

classCacheTags()

Returns extra tags for a bump that has no entity, typically tree operations ({@see \App\Core\Traits\Api\Models\Managers\TreeTrait::treeTransaction()}) that rewrite `lft`/`rgt` on many rows.

protected classCacheTags() : array<string|int, string>

IMPORTANT: additionalCacheTags(object) receives an entity, so a class-level bump cannot use it; without this hook a delete would lose the cross-entity tag (Comment to CommentThread). A manager whose cross-entity tag does not depend on a particular entity returns it here.

NOTE: unlike additionalCacheTags(), this hook is declared (with an empty default) instead of being an opt-in through method_exists(); method_exists() is always true in a manager that has the method, which phpstan reports as alreadyNarrowedType.

Return values
array<string|int, string>

esReindexBestEffort()

Catches ES up after an admin mutation; it never breaks a write that is already in the database.

protected esReindexBestEffort(array<string|int, int> $ids) : void
Parameters
$ids : array<string|int, int>

getService()

Returns the service for the traits.

protected getService() : TService
Return values
TService

touchForEsWatermark()

Bumps the entity update timestamp so the watermark sync also sees an admin edit (a second safety net next to the direct reindex). An entity may have no timestamp, so the default is a no-op; a manager overrides it (`ProductSet::setUpdateTime()`, `Article::setUpdateDatetime()`, ...).

protected touchForEsWatermark(BaseEntity $entity) : void
Parameters
$entity : BaseEntity

requireServiceTreeMethod()

Loud guard against silent failure: a bridge tree operation runs only when the next service has the same tree method.

private requireServiceTreeMethod(string $method) : void

IMPORTANT: TreeTrait must be used per entity on every layer (manager, service, mapper, repository); it is not inherited from the Admin/Front base. When one is missing the call throws a LogicException (logged) instead of a silent INVALID_OPERATION that hides where the wiring is broken.

Parameters
$method : string
On this page

Search results