Completed
Push — master ( 0c6e4d...a1420e )
by Tomáš
02:54
created

BaseContainer   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 217
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 28
eloc 51
c 1
b 0
f 0
dl 0
loc 217
ccs 68
cts 68
cp 1
rs 10

19 Methods

Rating   Name   Duplication   Size   Complexity  
A getTopLevel() 0 2 1
A __construct() 0 2 1
A get() 0 9 3
A insert() 0 8 4
A count() 0 2 1
A getQuery() 0 2 1
A addChild() 0 7 3
A rewind() 0 2 1
A current() 0 2 1
A getLeafIds() 0 9 3
A next() 0 2 1
A unique() 0 4 1
A filter() 0 4 1
A getTopLevelQuery() 0 2 1
A sort() 0 4 1
A sortBy() 0 4 1
A addSorter() 0 4 1
A key() 0 2 1
A valid() 0 2 1
1
<?php
2
3
4
namespace TournamentGenerator\Containers;
5
6
use Closure;
7
use Countable;
8
use Iterator;
9
use TournamentGenerator\Helpers\Sorter\BaseSorter;
10
11
/**
12
 * Class BaseContainer
13
 *
14
 * Container is a helper class for a tree-like structure. It can be used to create a hierarchy and store objects.
15
 *
16
 * @package TournamentGenerator\Containers
17
 * @author  Tomáš Vojík <[email protected]>
18
 */
19
class BaseContainer implements Countable, Iterator
20
{
21
22
	/** @var string|int Identifier */
23
	public $id;
24
	/** @var BaseContainer[] Direct child containers */
25
	protected array $children = [];
26
	/** @var array Any value that the container holds */
27
	protected array $values = [];
28
29
	/** @var int Current iterator index */
30
	protected int $currentIndex = 0;
31
32
	/**
33
	 * BaseContainer constructor.
34
	 *
35
	 * @param string|int $id
36
	 */
37 180
	public function __construct($id) {
38 180
		$this->id = $id;
39 180
	}
40
41
	/**
42
	 * Returns the value count
43
	 *
44
	 * @return int
45
	 */
46 38
	public function count() : int {
47 38
		return count($this->get());
48
	}
49
50
	/**
51
	 * Get all values from the container - including child nodes
52
	 *
53
	 * @return array All values
54
	 */
55 109
	public function get() : array {
56 109
		if (count($this->children) > 0) {
57 53
			$values = [$this->values];
58 53
			foreach ($this->children as $child) {
59 53
				$values[] = $child->get();
60
			}
61 53
			return array_merge(...$values);
62
		}
63 109
		return $this->values;
64
	}
65
66
	/**
67
	 * Get all top-level values from the container
68
	 *
69
	 * @return array All values
70
	 */
71 10
	public function getTopLevel() : array {
72 10
		return $this->values;
73
	}
74
75 1
	public function getTopLevelQuery() : ContainerQuery {
76 1
		return new ContainerQuery($this, true);
77
	}
78
79 1
	public function getQuery() : ContainerQuery {
80 1
		return new ContainerQuery($this);
81
	}
82
83
	/**
84
	 * Get the current value
85
	 *
86
	 * @return mixed
87
	 */
88 2
	public function current() {
89 2
		return $this->get()[$this->currentIndex];
90
	}
91
92
	/**
93
	 * Move pointer to next
94
	 */
95 2
	public function next() : void {
96 2
		++$this->currentIndex;
97 2
	}
98
99
	/**
100
	 * Return the current key
101
	 *
102
	 * @return int
103
	 */
104 1
	public function key() : int {
105 1
		return $this->currentIndex;
106
	}
107
108
	/**
109
	 * Check if the current value exists
110
	 *
111
	 * @return bool
112
	 */
113 2
	public function valid() : bool {
114 2
		return isset($this->get()[$this->currentIndex]);
115
	}
116
117
	/**
118
	 * Rewind the iterator
119
	 */
120 2
	public function rewind() : void {
121 2
		$this->currentIndex = 0;
122 2
	}
123
124
	/**
125
	 * Insert a value into container
126
	 *
127
	 * @param array $values Any value to insert into container
128
	 *
129
	 * @post If the value has a container -> add it to the hierarchy
130
	 *
131
	 * @return $this
132
	 */
133 138
	public function insert(...$values) : BaseContainer {
134 138
		foreach ($values as $value) {
135 138
			$this->values[] = $value;
136 138
			if (is_object($value) && method_exists($value, 'getContainer')) {
137 66
				$this->addChild($value->getContainer());
138
			}
139
		}
140 138
		return $this;
141
	}
142
143
	/**
144
	 * Adds a child container
145
	 *
146
	 * @param BaseContainer[] $containers
147
	 *
148
	 * @return $this
149
	 */
150 69
	public function addChild(BaseContainer ...$containers) : BaseContainer {
151 69
		foreach ($containers as $container) {
152 69
			if (!isset($this->children[$container->id])) {
153 69
				$this->children[$container->id] = $container;
154
			}
155
		}
156 69
		return $this;
157
	}
158
159
	/**
160
	 * Gets all ids of the leaf containers
161
	 *
162
	 * @return string[]|int[]
163
	 */
164 50
	public function getLeafIds() : array {
165 50
		if (count($this->children) > 0) {
166 11
			$ids = [];
167 11
			foreach ($this->children as $child) {
168 11
				$ids[] = $child->getLeafIds();
169
			}
170 11
			return array_merge(...$ids);
171
		}
172 50
		return [$this->id];
173
	}
174
175
	/**
176
	 * Add a filter callback
177
	 *
178
	 * @param Closure $callback
179
	 *
180
	 * @return ContainerQuery
181
	 */
182 1
	public function filter(Closure $callback) : ContainerQuery {
183 1
		$query = new ContainerQuery($this);
184 1
		$query->filter($callback);
185 1
		return $query;
186
	}
187
188
	/**
189
	 * Sort a result using a callback - maintaining the index association
190
	 *
191
	 * @param Closure $callback
192
	 *
193
	 * @return ContainerQuery
194
	 */
195 1
	public function sort(Closure $callback) : ContainerQuery {
196 1
		$query = new ContainerQuery($this);
197 1
		$query->sort($callback);
198 1
		return $query;
199
	}
200
201
	/**
202
	 * Sort a result set by a given property
203
	 *
204
	 * @warning Sort callback has a priority.
205
	 *
206
	 * @param string $property
207
	 *
208
	 * @return ContainerQuery
209
	 */
210 1
	public function sortBy(string $property) : ContainerQuery {
211 1
		$query = new ContainerQuery($this);
212 1
		$query->sortBy($property);
213 1
		return $query;
214
	}
215
216
	/**
217
	 * @param BaseSorter $sorter
218
	 *
219
	 * @return ContainerQuery
220
	 */
221 48
	public function addSorter(BaseSorter $sorter) : ContainerQuery {
222 48
		$query = new ContainerQuery($this);
223 48
		$query->addSorter($sorter);
224 48
		return $query;
225
	}
226
227
	/**
228
	 * Get only unique values
229
	 *
230
	 * @return ContainerQuery
231
	 */
232 103
	public function unique() : ContainerQuery {
233 103
		$query = new ContainerQuery($this);
234 103
		$query->unique();
235 103
		return $query;
236
	}
237
}