-
-
Notifications
You must be signed in to change notification settings - Fork 219
/
TraversableNodes.php
149 lines (132 loc) · 4.84 KB
/
TraversableNodes.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<?php
declare(strict_types=1);
namespace Neos\ContentRepository\Domain\Projection\Content;
/*
* This file is part of the Neos.ContentRepository package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/
use Neos\Flow\Annotations as Flow;
/**
* @Flow\Proxy(false)
*/
final class TraversableNodes implements \IteratorAggregate, \Countable
{
/**
* @var TraversableNodeInterface[]
*/
private $nodes;
private function __construct(array $nodes)
{
$this->nodes = $nodes;
}
public static function fromArray(array $nodes): self
{
foreach ($nodes as $node) {
if (!$node instanceof TraversableNodeInterface) {
throw new \InvalidArgumentException(sprintf('TraversableNodes only support instances of %s, given: %s', TraversableNodeInterface::class, is_object($node) ? get_class($node): gettype($node)), 1542893076);
}
}
return new static($nodes);
}
public function merge(self $other): self
{
return new static(array_merge($this->nodes, $other->nodes));
}
public function isEmpty(): bool
{
return $this->nodes === [];
}
public function count(): int
{
return count($this->nodes);
}
private function getNodeIndex(TraversableNodeInterface $subject): int
{
foreach ($this->nodes as $index => $node) {
if ($node->equals($subject)) {
return $index;
}
}
throw new \InvalidArgumentException(sprintf('The node %s does not exist in this set', $subject->getNodeAggregateIdentifier()), 1542901216);
}
/**
* Returns the node before the given $referenceNode in this set - or throws an exception if $referenceNode does not exist or is the first node in the set
*
* @param TraversableNodeInterface $referenceNode
* @return TraversableNodeInterface
*/
public function previous(TraversableNodeInterface $referenceNode): TraversableNodeInterface
{
$referenceNodeIndex = $this->getNodeIndex($referenceNode);
if ($referenceNodeIndex === 0) {
throw new \InvalidArgumentException(sprintf('The node %s is the first node in the set, so there is no previous node.', $referenceNode->getNodeAggregateIdentifier()), 1542902422);
}
return $this->nodes[$referenceNodeIndex - 1];
}
/**
* Returns all nodes before the given $referenceNode in this set
*
* @param TraversableNodeInterface $referenceNode
* @return TraversableNodes
*/
public function previousAll(TraversableNodeInterface $referenceNode): self
{
$referenceNodeIndex = $this->getNodeIndex($referenceNode);
return new static(array_slice($this->nodes, 0, $referenceNodeIndex));
}
/**
* Returns the node after the given $referenceNode in this set - or throws an exception if $referenceNode does not exist or is the last node in the set
*
* @param TraversableNodeInterface $referenceNode
* @return TraversableNodeInterface
*/
public function next(TraversableNodeInterface $referenceNode): TraversableNodeInterface
{
$referenceNodeIndex = $this->getNodeIndex($referenceNode);
if ($referenceNodeIndex === $this->count() - 1) {
throw new \InvalidArgumentException(sprintf('The node %s is the last node in the set, so there is no next node.', $referenceNode->getNodeAggregateIdentifier()), 1542902858);
}
return $this->nodes[$referenceNodeIndex + 1];
}
/**
* Returns all nodes after the given $referenceNode in this set
*
* @param TraversableNodeInterface $referenceNode
* @return TraversableNodes
*/
public function nextAll(TraversableNodeInterface $referenceNode): self
{
$referenceNodeIndex = $this->getNodeIndex($referenceNode);
return new static(array_slice($this->nodes, $referenceNodeIndex + 1));
}
/**
* Returns all nodes after the given $referenceNode in this set
*
* @param TraversableNodeInterface $referenceNode
* @return TraversableNodes
*/
public function until(TraversableNodeInterface $referenceNode): self
{
$referenceNodeIndex = $this->getNodeIndex($referenceNode);
return new static(array_slice($this->nodes, $referenceNodeIndex + 1));
}
/**
* @return TraversableNodeInterface[]|\ArrayIterator<TraversableNodeInterface>
*/
public function getIterator(): \ArrayIterator
{
return new \ArrayIterator($this->nodes);
}
/**
* @return TraversableNodeInterface[]|array<TraversableNodeInterface>
*/
public function toArray(): array
{
return array_values($this->nodes);
}
}