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

BaseContainer   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 215
Duplicated Lines 0 %

Test Coverage

Coverage 58.2%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 27
eloc 50
c 1
b 0
f 0
dl 0
loc 215
ccs 39
cts 67
cp 0.582
rs 10

19 Methods

Rating   Name   Duplication   Size   Complexity  
A getQuery() 0 2 1
A addChild() 0 5 2
A rewind() 0 2 1
A getTopLevel() 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 __construct() 0 2 1
A getTopLevelQuery() 0 2 1
A sort() 0 4 1
A get() 0 9 3
A sortBy() 0 4 1
A insert() 0 8 4
A addSorter() 0 4 1
A key() 0 2 1
A count() 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 174
	public function __construct($id) {
38 174
		$this->id = $id;
39 174
	}
40
41
	/**
42
	 * Returns the value count
43
	 *
44
	 * @return int
45
	 */
46 36
	public function count() : int {
47 36
		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 105
	public function get() : array {
56 105
		if (count($this->children) > 0) {
57 49
			$values = [$this->values];
58 49
			foreach ($this->children as $child) {
59 49
				$values[] = $child->get();
60
			}
61 49
			return array_merge(...$values);
62
		}
63 105
		return $this->values;
64
	}
65
66
	/**
67
	 * Get all top-level values from the container
68
	 *
69
	 * @return array All values
70
	 */
71 7
	public function getTopLevel() : array {
72 7
		return $this->values;
73
	}
74
75
	public function getTopLevelQuery() : ContainerQuery {
76
		return new ContainerQuery($this, true);
77
	}
78
79
	public function getQuery() : ContainerQuery {
80
		return new ContainerQuery($this);
81
	}
82
83
	/**
84
	 * Get the current value
85
	 *
86
	 * @return mixed
87
	 */
88
	public function current() {
89
		return $this->get()[$this->currentIndex];
90
	}
91
92
	/**
93
	 * Move pointer to next
94
	 */
95
	public function next() : void {
96
		++$this->currentIndex;
97
	}
98
99
	/**
100
	 * Return the current key
101
	 *
102
	 * @return int
103
	 */
104
	public function key() : int {
105
		return $this->currentIndex;
106
	}
107
108
	/**
109
	 * Check if the current value exists
110
	 *
111
	 * @return bool
112
	 */
113
	public function valid() : bool {
114
		return isset($this->get()[$this->currentIndex]);
115
	}
116
117
	/**
118
	 * Rewind the iterator
119
	 */
120
	public function rewind() : void {
121
		$this->currentIndex = 0;
122
	}
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 133
	public function insert(...$values) : BaseContainer {
134 133
		foreach ($values as $value) {
135 133
			$this->values[] = $value;
136 133
			if (is_object($value) && method_exists($value, 'getContainer')) {
137 64
				$this->addChild($value->getContainer());
138
			}
139
		}
140 133
		return $this;
141
	}
142
143
	/**
144
	 * Adds a child container
145
	 *
146
	 * @param BaseContainer $container
147
	 *
148
	 * @return $this
149
	 */
150 64
	public function addChild(BaseContainer $container) : BaseContainer {
151 64
		if (!isset($this->children[$container->id])) {
152 64
			$this->children[$container->id] = $container;
153
		}
154 64
		return $this;
155
	}
156
157
	/**
158
	 * Gets all ids of the leaf containers
159
	 *
160
	 * @return string[]|int[]
161
	 */
162 48
	public function getLeafIds() : array {
163 48
		if (count($this->children) > 0) {
164 9
			$ids = [];
165 9
			foreach ($this->children as $child) {
166 9
				$ids[] = $child->getLeafIds();
167
			}
168 9
			return array_merge(...$ids);
169
		}
170 48
		return [$this->id];
171
	}
172
173
	/**
174
	 * Add a filter callback
175
	 *
176
	 * @param Closure $callback
177
	 *
178
	 * @return ContainerQuery
179
	 */
180
	public function filter(Closure $callback) : ContainerQuery {
181
		$query = new ContainerQuery($this);
182
		$query->filter($callback);
183
		return $query;
184
	}
185
186
	/**
187
	 * Sort a result using a callback - maintaining the index association
188
	 *
189
	 * @param Closure $callback
190
	 *
191
	 * @return ContainerQuery
192
	 */
193
	public function sort(Closure $callback) : ContainerQuery {
194
		$query = new ContainerQuery($this);
195
		$query->sort($callback);
196
		return $query;
197
	}
198
199
	/**
200
	 * Sort a result set by a given property
201
	 *
202
	 * @warning Sort callback has a priority.
203
	 *
204
	 * @param string $property
205
	 *
206
	 * @return ContainerQuery
207
	 */
208
	public function sortBy(string $property) : ContainerQuery {
209
		$query = new ContainerQuery($this);
210
		$query->sortBy($property);
211
		return $query;
212
	}
213
214
	/**
215
	 * @param BaseSorter $sorter
216
	 *
217
	 * @return ContainerQuery
218
	 */
219 48
	public function addSorter(BaseSorter $sorter) : ContainerQuery {
220 48
		$query = new ContainerQuery($this);
221 48
		$query->addSorter($sorter);
222 48
		return $query;
223
	}
224
225
	/**
226
	 * Get only unique values
227
	 *
228
	 * @return ContainerQuery
229
	 */
230 102
	public function unique() : ContainerQuery {
231 102
		$query = new ContainerQuery($this);
232 102
		$query->unique();
233 102
		return $query;
234
	}
235
}