Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Public Member Functions | Data Fields | Protected Member Functions | Protected Attributes
Structure Class Reference

Public Member Functions

 __construct (array $elements=null)
 
 importElements (array $elements)
 
 exportElements ()
 
 createElement ($elementId, array $data)
 
 getElement ($elementId)
 
 hasElement ($elementId)
 
 unsetElement ($elementId, $recursive=true)
 
 setAttribute ($elementId, $attribute, $value)
 
 getAttribute ($elementId, $attribute)
 
 renameElement ($oldId, $newId)
 
 setAsChild ($elementId, $parentId, $alias='', $position=null)
 
 unsetChild ($elementId, $alias=null)
 
 reorderChild ($parentId, $childId, $position)
 
 reorderToSibling ($parentId, $childId, $siblingId, $offset)
 
 getChildId ($parentId, $alias)
 
 getChildren ($parentId)
 
 getParentId ($childId)
 
 getChildAlias ($parentId, $childId)
 
 addToParentGroup ($childId, $groupName)
 
 getGroupChildNames ($parentId, $groupName)
 

Data Fields

const PARENT = 'parent'
 
const CHILDREN = 'children'
 
const GROUPS = 'groups'
 

Protected Member Functions

 _assertParentRelation ($elementId)
 
 _getChildOffset ($parentId, $childId)
 
 _insertChild ($targetParentId, $elementId, $offset, $alias)
 

Protected Attributes

 $_elements = []
 

Detailed Description

An associative data structure, that features "nested set" parent-child relations

Definition at line 14 of file Structure.php.

Constructor & Destructor Documentation

◆ __construct()

__construct ( array  $elements = null)

Set elements in constructor

Parameters
array$elements

Definition at line 35 of file Structure.php.

36  {
37  if (null !== $elements) {
38  $this->importElements($elements);
39  }
40  }
importElements(array $elements)
Definition: Structure.php:49

Member Function Documentation

◆ _assertParentRelation()

_assertParentRelation (   $elementId)
protected

Verify relations of parent-child

Parameters
string$elementId
Returns
void
Exceptions
LocalizedException

Definition at line 87 of file Structure.php.

88  {
89  $element = $this->_elements[$elementId];
90 
91  // element presence in its parent's nested set
92  if (isset($element[self::PARENT])) {
93  $parentId = $element[self::PARENT];
94  $this->_assertElementExists($parentId);
95  if (empty($this->_elements[$parentId][self::CHILDREN][$elementId])) {
96  throw new LocalizedException(
97  new \Magento\Framework\Phrase(
98  'The "%1" is not in the nested set of "%2", causing the parent-child relation to break. '
99  . 'Verify and try again.',
100  [$elementId, $parentId]
101  )
102  );
103  }
104  }
105 
106  // element presence in its children
107  if (isset($element[self::CHILDREN])) {
109  $this->_assertArray($children);
110  if ($children !== array_flip(array_flip($children))) {
111  throw new LocalizedException(
112  new \Magento\Framework\Phrase(
113  'The "%1" format of children is invalid. Verify and try again.',
114  [var_export($children, 1)]
115  )
116  );
117  }
118  foreach (array_keys($children) as $childId) {
119  $this->_assertElementExists($childId);
120  if (!isset(
121  $this->_elements[$childId][self::PARENT]
122  ) || $elementId !== $this->_elements[$childId][self::PARENT]
123  ) {
124  throw new LocalizedException(
125  new \Magento\Framework\Phrase(
126  'The "%1" doesn\'t have "%2" as parent, causing the parent-child relation to break. '
127  . 'Verify and try again.',
128  [$childId, $elementId]
129  )
130  );
131  }
132  }
133  }
134  }
$children
Definition: actions.phtml:11
$element
Definition: element.phtml:12

◆ _getChildOffset()

_getChildOffset (   $parentId,
  $childId 
)
protected

Calculate a relative offset of a child element in specified parent

Parameters
string$parentId
string$childId
Returns
int
Exceptions
LocalizedExceptionif specified elements have no parent-child relation

Definition at line 548 of file Structure.php.

549  {
550  $index = array_search($childId, array_keys($this->getChildren($parentId)));
551  if (false === $index) {
552  throw new LocalizedException(
553  new \Magento\Framework\Phrase(
554  'The "%1" is not a child of "%2". Resolve the issue and try again.',
555  [$childId, $parentId]
556  )
557  );
558  }
559  return $index;
560  }
$index
Definition: list.phtml:44

◆ _insertChild()

_insertChild (   $targetParentId,
  $elementId,
  $offset,
  $alias 
)
protected

Insert an existing element as a child to existing element

The element must not be a child to any other element The target parent element must not have it as a child already

Offset – into which position to insert: 0 – set as 1st 1, 2 – after 1st, second, etc... -1, -2 – before last, before second last, etc... null – set as last

Parameters
string$targetParentId
string$elementId
int | null$offset
string$alias
Returns
void
Exceptions
LocalizedException

Definition at line 600 of file Structure.php.

601  {
602  $alias = $alias ?: $elementId;
603 
604  // validate
605  $this->_assertElementExists($elementId);
606  if (!empty($this->_elements[$elementId][self::PARENT])) {
607  throw new LocalizedException(
608  new \Magento\Framework\Phrase(
609  'The element "%1" can\'t have a parent because "%2" is already the parent of "%1".',
610  [$elementId, $this->_elements[$elementId][self::PARENT]]
611  )
612  );
613  }
614  $this->_assertElementExists($targetParentId);
615  $children = $this->getChildren($targetParentId);
616  if (isset($children[$elementId])) {
617  throw new LocalizedException(
618  new \Magento\Framework\Phrase(
619  'The element "%1" is already a child of "%2".',
620  [$elementId, $targetParentId]
621  )
622  );
623  }
624  if (false !== array_search($alias, $children)) {
625  throw new LocalizedException(
626  new \Magento\Framework\Phrase(
627  'The element "%1" can\'t have a child because "%1" already has a child with alias "%2".',
628  [$targetParentId, $alias]
629  )
630  );
631  }
632 
633  // insert
634  if (null === $offset) {
635  $offset = count($children);
636  }
637  $this->_elements[$targetParentId][self::CHILDREN] = array_merge(
638  array_slice($children, 0, $offset),
639  [$elementId => $alias],
640  array_slice($children, $offset)
641  );
642  $this->_elements[$elementId][self::PARENT] = $targetParentId;
643  }
$children
Definition: actions.phtml:11
if(!trim($html)) $alias
Definition: details.phtml:20

◆ addToParentGroup()

addToParentGroup (   $childId,
  $groupName 
)

Add element to parent group

Parameters
string$childId
string$groupName
Returns
bool

Definition at line 505 of file Structure.php.

506  {
507  $parentId = $this->getParentId($childId);
508  if ($parentId) {
509  $this->_assertElementExists($parentId);
510  $this->_elements[$parentId][self::GROUPS][$groupName][$childId] = $childId;
511  return true;
512  }
513  return false;
514  }

◆ createElement()

createElement (   $elementId,
array  $data 
)

Create new element

Parameters
string$elementId
array$data
Returns
void
Exceptions
LocalizedExceptionif an element with this id already exists

Definition at line 154 of file Structure.php.

155  {
156  if (isset($this->_elements[$elementId])) {
157  throw new LocalizedException(
158  new \Magento\Framework\Phrase('An element with a "%1" ID already exists.', [$elementId])
159  );
160  }
161  $this->_elements[$elementId] = [];
162  foreach ($data as $key => $value) {
163  $this->setAttribute($elementId, $key, $value);
164  }
165  }
setAttribute($elementId, $attribute, $value)
Definition: Structure.php:226
$value
Definition: gender.phtml:16

◆ exportElements()

exportElements ( )

Dump all elements

Returns
array

Definition at line 141 of file Structure.php.

142  {
143  return $this->_elements;
144  }

◆ getAttribute()

getAttribute (   $elementId,
  $attribute 
)

Get element attribute

Parameters
string$elementId
string$attribute
Returns
mixed

Definition at line 248 of file Structure.php.

249  {
250  $this->_assertElementExists($elementId);
251  if (isset($this->_elements[$elementId][$attribute])) {
252  return $this->_elements[$elementId][$attribute];
253  }
254  return false;
255  }

◆ getChildAlias()

getChildAlias (   $parentId,
  $childId 
)

Get element alias by name

Parameters
string$parentId
string$childId
Returns
string|bool

Definition at line 490 of file Structure.php.

491  {
492  if (isset($this->_elements[$parentId][self::CHILDREN][$childId])) {
493  return $this->_elements[$parentId][self::CHILDREN][$childId];
494  }
495  return false;
496  }

◆ getChildId()

getChildId (   $parentId,
  $alias 
)

Get child ID by parent ID and alias

Parameters
string$parentId
string$alias
Returns
string|bool

Definition at line 451 of file Structure.php.

452  {
453  if (isset($this->_elements[$parentId][self::CHILDREN])) {
454  return array_search($alias, $this->_elements[$parentId][self::CHILDREN]);
455  }
456  return false;
457  }
if(!trim($html)) $alias
Definition: details.phtml:20

◆ getChildren()

getChildren (   $parentId)

Get all children

Returns in format 'id' => 'alias'

Parameters
string$parentId
Returns
array

Definition at line 467 of file Structure.php.

468  {
469  return $this->_elements[$parentId][self::CHILDREN] ?? [];
470  }

◆ getElement()

getElement (   $elementId)

Get existing element

Parameters
string$elementId
Returns
array|bool

Definition at line 173 of file Structure.php.

174  {
175  return $this->_elements[$elementId] ?? false;
176  }

◆ getGroupChildNames()

getGroupChildNames (   $parentId,
  $groupName 
)

Get element IDs for specified group

Note that it is expected behavior if a child has been moved out from this parent, but still remained in the group of old parent. The method will return only actual children. This is intentional, in case if the child returns back to the old parent.

Parameters
string$parentIdName of an element containing group
string$groupName
Returns
array

Definition at line 527 of file Structure.php.

528  {
529  $result = [];
530  if (isset($this->_elements[$parentId][self::GROUPS][$groupName])) {
531  foreach ($this->_elements[$parentId][self::GROUPS][$groupName] as $childId) {
532  if (isset($this->_elements[$parentId][self::CHILDREN][$childId])) {
533  $result[] = $childId;
534  }
535  }
536  }
537  return $result;
538  }

◆ getParentId()

getParentId (   $childId)

Get name of parent element

Parameters
string$childId
Returns
string|bool

Definition at line 478 of file Structure.php.

479  {
480  return $this->_elements[$childId][self::PARENT] ?? false;
481  }

◆ hasElement()

hasElement (   $elementId)

Whether specified element exists

Parameters
string$elementId
Returns
bool

Definition at line 184 of file Structure.php.

185  {
186  return isset($this->_elements[$elementId]);
187  }

◆ importElements()

importElements ( array  $elements)

Set elements from external source

Parameters
array$elements
Returns
void
Exceptions
LocalizedExceptionif any format issues identified

Definition at line 49 of file Structure.php.

50  {
51  $this->_elements = $elements;
52  foreach ($elements as $elementId => $element) {
53  if (is_numeric($elementId)) {
54  throw new LocalizedException(
55  new \Magento\Framework\Phrase("Element ID must not be numeric: '%1'.", [$elementId])
56  );
57  }
58  $this->_assertParentRelation($elementId);
59  if (isset($element[self::GROUPS])) {
60  $groups = $element[self::GROUPS];
61  $this->_assertArray($groups);
62  foreach ($groups as $groupName => $group) {
63  $this->_assertArray($group);
64  if ($group !== array_flip($group)) {
65  throw new LocalizedException(
66  new \Magento\Framework\Phrase(
67  '"%2" is an invalid format of "%1" group. Verify the format and try again.',
68  [$groupName, var_export($group, 1)]
69  )
70  );
71  }
72  foreach ($group as $groupElementId) {
73  $this->_assertElementExists($groupElementId);
74  }
75  }
76  }
77  }
78  }
$group
Definition: sections.phtml:16
$element
Definition: element.phtml:12

◆ renameElement()

renameElement (   $oldId,
  $newId 
)

Rename element ID

Parameters
string$oldId
string$newId
Returns
$this
Exceptions
LocalizedExceptionif trying to overwrite another element

Definition at line 265 of file Structure.php.

266  {
267  $this->_assertElementExists($oldId);
268  if (!$newId || isset($this->_elements[$newId])) {
269  throw new LocalizedException(
270  new \Magento\Framework\Phrase('An element with a "%1" ID is already defined.', [$newId])
271  );
272  }
273 
274  // rename in registry
275  $this->_elements[$newId] = $this->_elements[$oldId];
276 
277  // rename references in children
278  if (isset($this->_elements[$oldId][self::CHILDREN])) {
279  foreach (array_keys($this->_elements[$oldId][self::CHILDREN]) as $childId) {
280  $this->_assertElementExists($childId);
281  $this->_elements[$childId][self::PARENT] = $newId;
282  }
283  }
284 
285  // rename key in its parent's children array
286  if (isset($this->_elements[$oldId][self::PARENT]) && ($parentId = $this->_elements[$oldId][self::PARENT])) {
287  $alias = $this->_elements[$parentId][self::CHILDREN][$oldId];
288  $offset = $this->_getChildOffset($parentId, $oldId);
289  unset($this->_elements[$parentId][self::CHILDREN][$oldId]);
290  $this->setAsChild($newId, $parentId, $alias, $offset);
291  }
292 
293  unset($this->_elements[$oldId]);
294  return $this;
295  }
setAsChild($elementId, $parentId, $alias='', $position=null)
Definition: Structure.php:308
_getChildOffset($parentId, $childId)
Definition: Structure.php:548
if(!trim($html)) $alias
Definition: details.phtml:20

◆ reorderChild()

reorderChild (   $parentId,
  $childId,
  $position 
)

Reorder a child element relatively to specified position

Returns new position of the reordered element

Parameters
string$parentId
string$childId
int | null$position
Returns
int
See also
_insertChild() for position explanation

Definition at line 373 of file Structure.php.

374  {
375  $alias = $this->getChildAlias($parentId, $childId);
376  $currentOffset = $this->_getChildOffset($parentId, $childId);
377  $offset = $position;
378  if ($position > 0) {
379  if ($position >= $currentOffset + 1) {
380  $offset -= 1;
381  }
382  } elseif ($position < 0) {
383  if ($position < $currentOffset + 1 - count($this->_elements[$parentId][self::CHILDREN])) {
384  if ($position === -1) {
385  $offset = null;
386  } else {
387  $offset += 1;
388  }
389  }
390  }
391  $this->unsetChild($childId)->_insertChild($parentId, $childId, $offset, $alias);
392  return $this->_getChildOffset($parentId, $childId) + 1;
393  }
getChildAlias($parentId, $childId)
Definition: Structure.php:490
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
unsetChild($elementId, $alias=null)
Definition: Structure.php:344
_getChildOffset($parentId, $childId)
Definition: Structure.php:548
if(!trim($html)) $alias
Definition: details.phtml:20

◆ reorderToSibling()

reorderToSibling (   $parentId,
  $childId,
  $siblingId,
  $offset 
)

Reorder an element relatively to its sibling

$offset possible values: 1, 2 – set after the sibling towards end – by 1, by 2 positions, etc -1, -2 – set before the sibling towards start – by 1, by 2 positions, etc...

Both $childId and $siblingId must be children of the specified $parentId Returns new position of the reordered element

Parameters
string$parentId
string$childId
string$siblingId
int$offset
Returns
int

Definition at line 411 of file Structure.php.

412  {
413  $this->_getChildOffset($parentId, $childId);
414  if ($childId === $siblingId) {
415  $newOffset = $this->_getRelativeOffset($parentId, $siblingId, $offset);
416  return $this->reorderChild($parentId, $childId, $newOffset);
417  }
418  $alias = $this->getChildAlias($parentId, $childId);
419  $newOffset = $this->unsetChild($childId)->_getRelativeOffset($parentId, $siblingId, $offset);
420  $this->_insertChild($parentId, $childId, $newOffset, $alias);
421  return $this->_getChildOffset($parentId, $childId) + 1;
422  }
getChildAlias($parentId, $childId)
Definition: Structure.php:490
unsetChild($elementId, $alias=null)
Definition: Structure.php:344
reorderChild($parentId, $childId, $position)
Definition: Structure.php:373
_getChildOffset($parentId, $childId)
Definition: Structure.php:548
if(!trim($html)) $alias
Definition: details.phtml:20
_insertChild($targetParentId, $elementId, $offset, $alias)
Definition: Structure.php:600

◆ setAsChild()

setAsChild (   $elementId,
  $parentId,
  $alias = '',
  $position = null 
)

Set element as a child to another element

Parameters
string$elementId
string$parentId
string$alias
int | null$position
See also
_insertChild() for position explanation
Returns
void
Exceptions
LocalizedExceptionif attempting to set parent as child to its child (recursively)

Definition at line 308 of file Structure.php.

309  {
310  if ($elementId == $parentId) {
311  throw new LocalizedException(
312  new \Magento\Framework\Phrase(
313  'The "%1" was incorrectly set as a child to itself. Resolve the issue and try again.',
314  [$elementId]
315  )
316  );
317  }
318  if ($this->_isParentRecursively($elementId, $parentId)) {
319  throw new LocalizedException(
320  new \Magento\Framework\Phrase(
321  'The "%3" cannot be set as child to "%1" because "%1" is a parent of "%2" recursively. '
322  . 'Resolve the issue and try again.',
323  [$elementId, $parentId, $elementId]
324  )
325  );
326  }
327  $this->unsetChild($elementId);
328  unset($this->_elements[$parentId][self::CHILDREN][$elementId]);
329  $this->_insertChild($parentId, $elementId, $position, $alias);
330  }
unsetChild($elementId, $alias=null)
Definition: Structure.php:344
if(!trim($html)) $alias
Definition: details.phtml:20
_insertChild($targetParentId, $elementId, $offset, $alias)
Definition: Structure.php:600

◆ setAttribute()

setAttribute (   $elementId,
  $attribute,
  $value 
)

Set an arbitrary value to specified element attribute

Parameters
string$elementId
string$attribute
mixed$value
Exceptions

Definition at line 226 of file Structure.php.

227  {
228  $this->_assertElementExists($elementId);
229  switch ($attribute) {
230  case self::PARENT:
231  // break is intentionally omitted
232  case self::CHILDREN:
233  case self::GROUPS:
234  throw new \InvalidArgumentException("The '{$attribute}' attribute is reserved and can't be set.");
235  default:
236  $this->_elements[$elementId][$attribute] = $value;
237  }
238  return $this;
239  }
$value
Definition: gender.phtml:16

◆ unsetChild()

unsetChild (   $elementId,
  $alias = null 
)

Unset element as a child of another element

Note that only parent-child relations will be deleted. Element itself will be retained. The method is polymorphic: 1 argument: element ID which is supposedly a child of some element 2 arguments: parent element ID and child alias

Parameters
string$elementIdID of an element or its parent element
string | null$alias
Returns
$this

Definition at line 344 of file Structure.php.

345  {
346  if (null === $alias) {
347  $childId = $elementId;
348  } else {
349  $childId = $this->getChildId($elementId, $alias);
350  }
351  $parentId = $this->getParentId($childId);
352  unset($this->_elements[$childId][self::PARENT]);
353  if ($parentId) {
354  unset($this->_elements[$parentId][self::CHILDREN][$childId]);
355  if (empty($this->_elements[$parentId][self::CHILDREN])) {
356  unset($this->_elements[$parentId][self::CHILDREN]);
357  }
358  }
359  return $this;
360  }
getChildId($parentId, $alias)
Definition: Structure.php:451
if(!trim($html)) $alias
Definition: details.phtml:20

◆ unsetElement()

unsetElement (   $elementId,
  $recursive = true 
)

Remove element with specified ID from the structure

Can recursively delete all child elements. Returns false if there was no element found, therefore was nothing to delete.

Parameters
string$elementId
bool$recursive
Returns
bool

Definition at line 199 of file Structure.php.

200  {
201  if (isset($this->_elements[$elementId][self::CHILDREN])) {
202  foreach (array_keys($this->_elements[$elementId][self::CHILDREN]) as $childId) {
203  $this->_assertElementExists($childId);
204  if ($recursive) {
205  $this->unsetElement($childId, $recursive);
206  } else {
207  unset($this->_elements[$childId][self::PARENT]);
208  }
209  }
210  }
211  $this->unsetChild($elementId);
212  $wasFound = isset($this->_elements[$elementId]);
213  unset($this->_elements[$elementId]);
214  return $wasFound;
215  }
unsetChild($elementId, $alias=null)
Definition: Structure.php:344
unsetElement($elementId, $recursive=true)
Definition: Structure.php:199

Field Documentation

◆ $_elements

$_elements = []
protected

Definition at line 28 of file Structure.php.

◆ CHILDREN

const CHILDREN = 'children'

Definition at line 21 of file Structure.php.

◆ GROUPS

const GROUPS = 'groups'

Definition at line 23 of file Structure.php.

◆ PARENT

const PARENT = 'parent'

Reserved keys for storing structural relations

Definition at line 19 of file Structure.php.


The documentation for this class was generated from the following file: