TreeBehavior
extends Behavior
in package
Makes the table to which this is attached to behave like a nested set and provides methods for managing and retrieving information out of the derived hierarchical structure.
Tables attaching this behavior are required to have a column referencing the parent row, and two other numeric columns (lft and rght) where the implicit order will be cached.
For more information on what is a nested set and a how it works refer to https://www.sitepoint.com/hierarchical-data-database-2/
Table of Contents
Properties
- $_config : array<string, mixed>
- Runtime config
- $_configInitialized : bool
- Whether the config property has already been configured with defaults
- $_defaultConfig : array<string, mixed>
- Default config
- $_primaryKey : string
- Cached copy of the first column in a table's primary key.
- $_reflectionCache : array<string, array<string|int, mixed>>
- Reflection method cache for behaviors.
- $_table : Table
- Table instance.
Methods
- __construct() : mixed
- Constructor
- afterSave() : void
- After save listener.
- beforeDelete() : void
- Also deletes the nodes in the subtree of the entity to be delete
- beforeSave() : void
- Before save listener.
- childCount() : int
- Get the number of children nodes.
- configShallow() : $this
- Merge provided config with existing config. Unlike `config()` which does a recursive merge for nested keys, this method does a simple merge.
- findChildren() : Query
- Get the children nodes of the current model
- findPath() : Query
- Custom finder method which can be used to return the list of nodes from the root to a specific node in the tree. This custom finder requires that the key 'for' is passed in the options containing the id of the node to get its path for.
- findTreeList() : Query
- Gets a representation of the elements in the tree as a flat list where the keys are the primary key for the table and the values are the display field for the table.
- formatTreeList() : Query
- Formats query as a flat list where the keys are the primary key for the table and the values are the display field for the table. Values are prefixed to visually indicate relative depth in the tree.
- getConfig() : mixed
- Returns the config.
- getConfigOrFail() : mixed
- Returns the config for this specific key.
- getLevel() : int|false
- Returns the depth level of a node in the tree.
- getTable() : Table
- Get the table instance this behavior is bound to.
- implementedEvents() : array<string, mixed>
- Gets the Model callbacks this behavior is interested in.
- implementedFinders() : array<string|int, mixed>
- implementedFinders
- implementedMethods() : array<string|int, mixed>
- implementedMethods
- initialize() : void
- Constructor hook method.
- moveDown() : EntityInterface|false
- Reorders the node without changing the parent.
- moveUp() : EntityInterface|false
- Reorders the node without changing its parent.
- recover() : void
- Recovers the lft and right column values out of the hierarchy defined by the parent column.
- removeFromTree() : EntityInterface|false
- Removes the current node from the tree, by positioning it as a new root and re-parents all children up one level.
- setConfig() : $this
- Sets the config.
- table() : Table
- Get the table instance this behavior is bound to.
- verifyConfig() : void
- verifyConfig
- _configDelete() : void
- Deletes a single config key.
- _configRead() : mixed
- Reads a config key.
- _configWrite() : void
- Writes a config key.
- _ensureFields() : void
- Ensures that the provided entity contains non-empty values for the left and right fields
- _getMax() : int
- Returns the maximum index value in the table.
- _getNode() : EntityInterface
- Returns a single node from the tree from its primary key
- _getPrimaryKey() : string
- Returns a single string value representing the primary key of the attached table
- _moveDown() : EntityInterface
- Helper function used with the actual code for moveDown
- _moveUp() : EntityInterface
- Helper function used with the actual code for moveUp
- _recoverTree() : int
- Recursive method used to recover a single level of the tree
- _reflectionCache() : array<string|int, mixed>
- Gets the methods implemented by this behavior
- _removeFromTree() : EntityInterface|false
- Helper function containing the actual code for removeFromTree
- _resolveMethodAliases() : array<string|int, mixed>
- Removes aliased methods that would otherwise be duplicated by userland configuration.
- _scope() : Query
- Alters the passed query so that it only returns scoped records as defined in the tree configuration.
- _setAsRoot() : void
- Updates the left and right column for the passed entity so it can be set as a new root in the tree. It also modifies the ordering in the rest of the tree so the structure remains valid
- _setChildrenLevel() : void
- Set level for descendants.
- _setParent() : void
- Sets the correct left and right values for the passed entity so it can be updated to a new parent. It also makes the hole in the tree so the node move can be done without corrupting the structure.
- _sync() : void
- Auxiliary function used to automatically alter the value of both the left and right columns by a certain amount that match the passed conditions
- _unmarkInternalTree() : void
- Helper method used to invert the sign of the left and right columns that are less than 0. They were set to negative values before so their absolute value wouldn't change while performing other tree transformations.
Properties
$_config
Runtime config
protected
array<string, mixed>
$_config
= []
$_configInitialized
Whether the config property has already been configured with defaults
protected
bool
$_configInitialized
= false
$_defaultConfig
Default config
protected
array<string, mixed>
$_defaultConfig
= ['implementedFinders' => ['path' => 'findPath', 'children' => 'findChildren', 'treeList' => 'findTreeList'], 'implementedMethods' => ['childCount' => 'childCount', 'moveUp' => 'moveUp', 'moveDown' => 'moveDown', 'recover' => 'recover', 'removeFromTree' => 'removeFromTree', 'getLevel' => 'getLevel', 'formatTreeList' => 'formatTreeList'], 'parent' => 'parent_id', 'left' => 'lft', 'right' => 'rght', 'scope' => null, 'level' => null, 'recoverOrder' => null, 'cascadeCallbacks' => false]
These are merged with user-provided configuration when the behavior is used.
$_primaryKey
Cached copy of the first column in a table's primary key.
protected
string
$_primaryKey
$_reflectionCache
Reflection method cache for behaviors.
protected
static array<string, array<string|int, mixed>>
$_reflectionCache
= []
Stores the reflected method + finder methods per class. This prevents reflecting the same class multiple times in a single process.
$_table
Table instance.
protected
Table
$_table
Methods
__construct()
Constructor
public
__construct(Table $table[, array<string, mixed> $config = [] ]) : mixed
Merges config with the default and store in the config property
Parameters
- $table : Table
-
The table this behavior is attached to.
- $config : array<string, mixed> = []
-
The config for this behavior.
afterSave()
After save listener.
public
afterSave(EventInterface $event, EntityInterface $entity) : void
Manages updating level of descendants of currently saved entity.
Parameters
- $event : EventInterface
-
The afterSave event that was fired
- $entity : EntityInterface
-
the entity that is going to be saved
beforeDelete()
Also deletes the nodes in the subtree of the entity to be delete
public
beforeDelete(EventInterface $event, EntityInterface $entity) : void
Parameters
- $event : EventInterface
-
The beforeDelete event that was fired
- $entity : EntityInterface
-
The entity that is going to be saved
beforeSave()
Before save listener.
public
beforeSave(EventInterface $event, EntityInterface $entity) : void
Transparently manages setting the lft and rght fields if the parent field is included in the parameters to be saved.
Parameters
- $event : EventInterface
-
The beforeSave event that was fired
- $entity : EntityInterface
-
the entity that is going to be saved
Tags
childCount()
Get the number of children nodes.
public
childCount(EntityInterface $node[, bool $direct = false ]) : int
Parameters
- $node : EntityInterface
-
The entity to count children for
- $direct : bool = false
-
whether to count all nodes in the subtree or just direct children
Return values
int —Number of children nodes.
configShallow()
Merge provided config with existing config. Unlike `config()` which does a recursive merge for nested keys, this method does a simple merge.
public
configShallow(array<string, mixed>|string $key[, mixed|null $value = null ]) : $this
Setting a specific value:
$this->configShallow('key', $value);
Setting a nested value:
$this->configShallow('some.nested.key', $value);
Updating multiple config settings at the same time:
$this->configShallow(['one' => 'value', 'another' => 'value']);
Parameters
- $key : array<string, mixed>|string
-
The key to set, or a complete array of configs.
- $value : mixed|null = null
-
The value to set.
Return values
$thisfindChildren()
Get the children nodes of the current model
public
findChildren(Query $query, array<string, mixed> $options) : Query
Available options are:
- for: The id of the record to read.
- direct: Boolean, whether to return only the direct (true), or all (false) children, defaults to false (all children).
If the direct option is set to true, only the direct children are returned (based upon the parent_id field)
Parameters
- $query : Query
-
Query.
- $options : array<string, mixed>
-
Array of options as described above
Tags
Return values
QueryfindPath()
Custom finder method which can be used to return the list of nodes from the root to a specific node in the tree. This custom finder requires that the key 'for' is passed in the options containing the id of the node to get its path for.
public
findPath(Query $query, array<string, mixed> $options) : Query
Parameters
- $query : Query
-
The constructed query to modify
- $options : array<string, mixed>
-
the list of options for the query
Tags
Return values
QueryfindTreeList()
Gets a representation of the elements in the tree as a flat list where the keys are the primary key for the table and the values are the display field for the table.
public
findTreeList(Query $query, array<string, mixed> $options) : Query
Values are prefixed to visually indicate relative depth in the tree.
Options
- keyPath: A dot separated path to fetch the field to use for the array key, or a closure to return the key out of the provided row.
- valuePath: A dot separated path to fetch the field to use for the array value, or a closure to return the value out of the provided row.
- spacer: A string to be used as prefix for denoting the depth in the tree for each item
Parameters
- $query : Query
-
Query.
- $options : array<string, mixed>
-
Array of options as described above.
Return values
QueryformatTreeList()
Formats query as a flat list where the keys are the primary key for the table and the values are the display field for the table. Values are prefixed to visually indicate relative depth in the tree.
public
formatTreeList(Query $query[, array<string, mixed> $options = [] ]) : Query
Options
- keyPath: A dot separated path to the field that will be the result array key, or a closure to return the key from the provided row.
- valuePath: A dot separated path to the field that is the array's value, or a closure to return the value from the provided row.
- spacer: A string to be used as prefix for denoting the depth in the tree for each item.
Parameters
- $query : Query
-
The query object to format.
- $options : array<string, mixed> = []
-
Array of options as described above.
Return values
Query —Augmented query.
getConfig()
Returns the config.
public
getConfig([string|null $key = null ][, mixed $default = null ]) : mixed
Usage
Reading the whole config:
$this->getConfig();
Reading a specific value:
$this->getConfig('key');
Reading a nested value:
$this->getConfig('some.nested.key');
Reading with default value:
$this->getConfig('some-key', 'default-value');
Parameters
- $key : string|null = null
-
The key to get or null for the whole config.
- $default : mixed = null
-
The return value when the key does not exist.
Return values
mixed —Configuration data at the named key or null if the key does not exist.
getConfigOrFail()
Returns the config for this specific key.
public
getConfigOrFail(string $key) : mixed
The config value for this key must exist, it can never be null.
Parameters
- $key : string
-
The key to get.
Tags
Return values
mixed —Configuration data at the named key
getLevel()
Returns the depth level of a node in the tree.
public
getLevel(EntityInterface|string|int $entity) : int|false
Parameters
- $entity : EntityInterface|string|int
-
The entity or primary key get the level of.
Return values
int|false —Integer of the level or false if the node does not exist.
getTable()
Get the table instance this behavior is bound to.
public
getTable() : Table
Use table() instead.
Return values
Table —The bound table instance.
implementedEvents()
Gets the Model callbacks this behavior is interested in.
public
implementedEvents() : array<string, mixed>
By defining one of the callback methods a behavior is assumed to be interested in the related event.
Override this method if you need to add non-conventional event listeners. Or if you want your behavior to listen to non-standard events.
Return values
array<string, mixed>implementedFinders()
implementedFinders
public
implementedFinders() : array<string|int, mixed>
Provides an alias->methodname map of which finders a behavior implements. Example:
[
'this' => 'findThis',
'alias' => 'findMethodName'
]
With the above example, a call to $table->find('this')
will call $behavior->findThis()
and a call to $table->find('alias')
will call $behavior->findMethodName()
It is recommended, though not required, to define implementedFinders in the config property of child classes such that it is not necessary to use reflections to derive the available method list. See core behaviors for examples
Tags
Return values
array<string|int, mixed>implementedMethods()
implementedMethods
public
implementedMethods() : array<string|int, mixed>
Provides an alias->methodname map of which methods a behavior implements. Example:
[
'method' => 'method',
'aliasedMethod' => 'somethingElse'
]
With the above example, a call to $table->method()
will call $behavior->method()
and a call to $table->aliasedMethod()
will call $behavior->somethingElse()
It is recommended, though not required, to define implementedFinders in the config property of child classes such that it is not necessary to use reflections to derive the available method list. See core behaviors for examples
Tags
Return values
array<string|int, mixed>initialize()
Constructor hook method.
public
initialize(array<string|int, mixed> $config) : void
Parameters
- $config : array<string|int, mixed>
-
The configuration settings provided to this behavior.
Tags
moveDown()
Reorders the node without changing the parent.
public
moveDown(EntityInterface $node[, int|true $number = 1 ]) : EntityInterface|false
If the node is the last child, or is a top level node with no subsequent node this method will return the same node without any changes
Parameters
- $node : EntityInterface
-
The node to move
- $number : int|true = 1
-
How many places to move the node or true to move to last position
Tags
Return values
EntityInterface|false —the entity after being moved or false if $number
is < 1
moveUp()
Reorders the node without changing its parent.
public
moveUp(EntityInterface $node[, int|true $number = 1 ]) : EntityInterface|false
If the node is the first child, or is a top level node with no previous node this method will return the same node without any changes
Parameters
- $node : EntityInterface
-
The node to move
- $number : int|true = 1
-
How many places to move the node, or true to move to first position
Tags
Return values
EntityInterface|false —$node The node after being moved or false if $number
is < 1
recover()
Recovers the lft and right column values out of the hierarchy defined by the parent column.
public
recover() : void
removeFromTree()
Removes the current node from the tree, by positioning it as a new root and re-parents all children up one level.
public
removeFromTree(EntityInterface $node) : EntityInterface|false
Note that the node will not be deleted just moved away from its current position without moving its children with it.
Parameters
- $node : EntityInterface
-
The node to remove from the tree
Return values
EntityInterface|false —the node after being removed from the tree or false on error
setConfig()
Sets the config.
public
setConfig(array<string, mixed>|string $key[, mixed|null $value = null ][, bool $merge = true ]) : $this
Usage
Setting a specific value:
$this->setConfig('key', $value);
Setting a nested value:
$this->setConfig('some.nested.key', $value);
Updating multiple config settings at the same time:
$this->setConfig(['one' => 'value', 'another' => 'value']);
Parameters
- $key : array<string, mixed>|string
-
The key to set, or a complete array of configs.
- $value : mixed|null = null
-
The value to set.
- $merge : bool = true
-
Whether to recursively merge or overwrite existing config, defaults to true.
Tags
Return values
$thistable()
Get the table instance this behavior is bound to.
public
table() : Table
Return values
Table —The bound table instance.
verifyConfig()
verifyConfig
public
verifyConfig() : void
Checks that implemented keys contain values pointing at callable.
Tags
_configDelete()
Deletes a single config key.
protected
_configDelete(string $key) : void
Parameters
- $key : string
-
Key to delete.
Tags
_configRead()
Reads a config key.
protected
_configRead(string|null $key) : mixed
Parameters
- $key : string|null
-
Key to read.
_configWrite()
Writes a config key.
protected
_configWrite(array<string, mixed>|string $key, mixed $value[, string|bool $merge = false ]) : void
Parameters
- $key : array<string, mixed>|string
-
Key to write to.
- $value : mixed
-
Value to write.
- $merge : string|bool = false
-
True to merge recursively, 'shallow' for simple merge, false to overwrite, defaults to false.
Tags
_ensureFields()
Ensures that the provided entity contains non-empty values for the left and right fields
protected
_ensureFields(EntityInterface $entity) : void
Parameters
- $entity : EntityInterface
-
The entity to ensure fields for
_getMax()
Returns the maximum index value in the table.
protected
_getMax() : int
Return values
int_getNode()
Returns a single node from the tree from its primary key
protected
_getNode(mixed $id) : EntityInterface
Parameters
- $id : mixed
-
Record id.
Tags
Return values
EntityInterface_getPrimaryKey()
Returns a single string value representing the primary key of the attached table
protected
_getPrimaryKey() : string
Return values
string_moveDown()
Helper function used with the actual code for moveDown
protected
_moveDown(EntityInterface $node, int|true $number) : EntityInterface
Parameters
- $node : EntityInterface
-
The node to move
- $number : int|true
-
How many places to move the node, or true to move to last position
Tags
Return values
EntityInterface —$node The node after being moved
_moveUp()
Helper function used with the actual code for moveUp
protected
_moveUp(EntityInterface $node, int|true $number) : EntityInterface
Parameters
- $node : EntityInterface
-
The node to move
- $number : int|true
-
How many places to move the node, or true to move to first position
Tags
Return values
EntityInterface —$node The node after being moved
_recoverTree()
Recursive method used to recover a single level of the tree
protected
_recoverTree([int $lftRght = 1 ][, mixed $parentId = null ][, int $level = 0 ]) : int
Parameters
- $lftRght : int = 1
-
The starting lft/rght value
- $parentId : mixed = null
-
the parent id of the level to be recovered
- $level : int = 0
-
Node level
Return values
int —The next lftRght value
_reflectionCache()
Gets the methods implemented by this behavior
protected
_reflectionCache() : array<string|int, mixed>
Uses the implementedEvents() method to exclude callback methods.
Methods starting with _
will be ignored, as will methods
declared on Cake\ORM\Behavior
Tags
Return values
array<string|int, mixed>_removeFromTree()
Helper function containing the actual code for removeFromTree
protected
_removeFromTree(EntityInterface $node) : EntityInterface|false
Parameters
- $node : EntityInterface
-
The node to remove from the tree
Return values
EntityInterface|false —the node after being removed from the tree or false on error
_resolveMethodAliases()
Removes aliased methods that would otherwise be duplicated by userland configuration.
protected
_resolveMethodAliases(string $key, array<string, mixed> $defaults, array<string, mixed> $config) : array<string|int, mixed>
Parameters
- $key : string
-
The key to filter.
- $defaults : array<string, mixed>
-
The default method mappings.
- $config : array<string, mixed>
-
The customized method mappings.
Return values
array<string|int, mixed> —A de-duped list of config data.
_scope()
Alters the passed query so that it only returns scoped records as defined in the tree configuration.
protected
_scope(Query $query) : Query
Parameters
- $query : Query
-
the Query to modify
Return values
Query_setAsRoot()
Updates the left and right column for the passed entity so it can be set as a new root in the tree. It also modifies the ordering in the rest of the tree so the structure remains valid
protected
_setAsRoot(EntityInterface $entity) : void
Parameters
- $entity : EntityInterface
-
The entity to set as a new root
_setChildrenLevel()
Set level for descendants.
protected
_setChildrenLevel(EntityInterface $entity) : void
Parameters
- $entity : EntityInterface
-
The entity whose descendants need to be updated.
_setParent()
Sets the correct left and right values for the passed entity so it can be updated to a new parent. It also makes the hole in the tree so the node move can be done without corrupting the structure.
protected
_setParent(EntityInterface $entity, mixed $parent) : void
Parameters
- $entity : EntityInterface
-
The entity to re-parent
- $parent : mixed
-
the id of the parent to set
Tags
_sync()
Auxiliary function used to automatically alter the value of both the left and right columns by a certain amount that match the passed conditions
protected
_sync(int $shift, string $dir, string $conditions[, bool $mark = false ]) : void
Parameters
- $shift : int
-
the value to use for operating the left and right columns
- $dir : string
-
The operator to use for shifting the value (+/-)
- $conditions : string
-
a SQL snipped to be used for comparing left or right against it.
- $mark : bool = false
-
whether to mark the updated values so that they can not be modified by future calls to this function.
_unmarkInternalTree()
Helper method used to invert the sign of the left and right columns that are less than 0. They were set to negative values before so their absolute value wouldn't change while performing other tree transformations.
protected
_unmarkInternalTree() : void