Completed
Push — patch_1-1-4 ( 3f780f...826343 )
by Emanuele
25:17 queued 11:40
created

Priority   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 296
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 38.66%

Importance

Changes 0
Metric Value
dl 0
loc 296
rs 9.44
c 0
b 0
f 0
ccs 46
cts 119
cp 0.3866
wmc 37
lcom 1
cbo 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A add() 0 7 2
A addBefore() 0 4 1
A addAfter() 0 4 1
A addEnd() 0 7 2
A addBegin() 0 7 2
B remove() 0 23 6
A removeAll() 0 11 1
D sort() 0 85 16
A hasEntities() 0 11 4
A getEntities() 0 4 1
A getSortedEntities() 0 4 1
1
<?php
2
3
/**
4
 * An abstract class to deal with priority
5
 *
6
 * @name      ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
9
 *
10
 * @version 1.1.4
11
 *
12
 */
13
14
/**
15
 * Priority Class An abstract class to deal with priority
16
 * of template layers
17
 */
18
class Priority
19
{
20
	/**
21
	 * An array containing all the entities added
22
	 * @var array
23
	 */
24
	protected $_all_general = array();
25
26
	/**
27
	 * An array containing all the entities that should go *after* another one
28
	 * @var array
29
	 */
30
	protected $_all_after = array();
31
32
	/**
33
	 * An array containing all the entities that should go *before* another one
34
	 * @var array
35
	 */
36
	protected $_all_before = array();
37
38
	/**
39
	 * An array containing all the entities that should go at the end of the list
40
	 * @var array
41
	 */
42
	protected $_all_end = array();
43
44
	/**
45
	 * An array containing all the entities that should go at the beginning
46
	 * @var array
47
	 */
48
	protected $_all_begin = array();
49
50
	/**
51
	 * The highest priority assigned at a certain moment for $_all_general
52
	 * @var int
53
	 */
54
	protected $_general_highest_priority = 0;
55
56
	/**
57
	 * The highest priority assigned at a certain moment for $_all_end
58
	 * @var int
59
	 */
60
	protected $_end_highest_priority = 10000;
61
62
	/**
63
	 * The highest priority assigned at a certain moment for $_all_begin
64
	 * Highest priority at "begin" is sort of tricky, because the value is negative
65
	 * @var int
66
	 */
67
	protected $_begin_highest_priority = -10000;
68
69
	/**
70
	 * Array of sorted entities
71
	 * @var array
72
	 */
73
	protected $_sorted_entities = null;
74
75
	/**
76
	 * Default priority
77
	 */
78
	const STDPRIORITY = 0;
79
80
	/**
81
	 * Add a new entity to the pile
82
	 *
83
	 * @param string   $entity name of a entity
84
	 * @param int|null $priority an integer defining the priority of the entity.
85
	 */
86 11
	public function add($entity, $priority = null)
87
	{
88 11
		$this->_all_general[$entity] = $priority === null
89 11
			? $this->_general_highest_priority
90 8
			: (int) $priority;
91 11
		$this->_general_highest_priority = max($this->_all_general) + 100;
92 11
	}
93
94
	/**
95
	 * Add an entity to the pile before another existing entity
96
	 *
97
	 * @param string $entity the name of a entity
98
	 * @param string $following the name of the entity before which $entity must be added
99
	 */
100
	public function addBefore($entity, $following)
101
	{
102
		$this->_all_before[$entity] = $following;
103
	}
104
105
	/**
106
	 * Add a entity to the pile after another existing entity
107
	 *
108
	 * @param string $entity the name of a entity
109
	 * @param string $previous the name of the entity after which $entity must be added
110
	 */
111
	public function addAfter($entity, $previous)
112
	{
113
		$this->_all_after[$entity] = $previous;
114
	}
115
116
	/**
117
	 * Add a entity at the end of the pile
118
	 *
119
	 * @param string   $entity name of a entity
120
	 * @param int|null $priority an integer defining the priority of the entity.
121
	 */
122
	public function addEnd($entity, $priority = null)
123
	{
124
		$this->_all_end[$entity] = $priority === null
125
			? $this->_end_highest_priority
126
			: (int) $priority;
127
		$this->_end_highest_priority = max($this->_all_end) + 100;
128
	}
129
130
	/**
131
	 * Add a entity at the beginning of the pile
132
	 *
133
	 * @param string   $entity name of a entity
134
	 * @param int|null $priority an integer defining the priority of the entity.
135
	 */
136 7
	public function addBegin($entity, $priority = null)
137
	{
138 7
		$this->_all_begin[$entity] = $priority === null
139 7
			? $this->_begin_highest_priority
140 7
			: (int) -$priority;
141 7
		$this->_begin_highest_priority = max($this->_all_begin) + 100;
142 7
	}
143
144
	/**
145
	 * Remove a entity by name
146
	 *
147
	 * @param string $entity the name of a entity
148
	 */
149 5
	public function remove($entity)
150
	{
151 5
		if (isset($this->_all_general[$entity]))
152 5
		{
153 5
			unset($this->_all_general[$entity]);
154 5
		}
155
		elseif (isset($this->_all_after[$entity]))
156
		{
157
			unset($this->_all_after[$entity]);
158
		}
159
		elseif (isset($this->_all_before[$entity]))
160
		{
161
			unset($this->_all_before[$entity]);
162
		}
163
		elseif (isset($this->_all_end[$entity]))
164
		{
165
			unset($this->_all_end[$entity]);
166
		}
167
		elseif (isset($this->_all_begin[$entity]))
168
		{
169
			unset($this->_all_begin[$entity]);
170
		}
171 5
	}
172
173
	/**
174
	 * Remove all the entities added up to the moment the function is called
175
	 */
176
	public function removeAll()
177
	{
178
		$this->_all_general = array();
179
		$this->_all_after = array();
180
		$this->_all_before = array();
181
		$this->_all_end = array();
182
		$this->_all_begin = array();
183
		$this->_general_highest_priority = 0;
184
		$this->_end_highest_priority = 10000;
185
		$this->_begin_highest_priority = -10000;
186
	}
187
188
	/**
189
	 * The function sorts the entities according to the priority and saves the
190
	 * result in $_sorted_entities
191
	 *
192
	 * @return array the sorted entities with priority
193
	 */
194 4
	public function sort()
195
	{
196 4
		$this->_sorted_entities = array();
197
198
		// Sorting
199 4
		asort($this->_all_begin);
200 4
		asort($this->_all_general);
201 4
		asort($this->_all_end);
202
203
		// The easy ones: just merge
204 4
		$all_entities = array_merge(
205 4
			$this->_all_begin,
206 4
			$this->_all_general,
207 4
			$this->_all_end
208 4
		);
209
210
		// Now the funny part, let's start with some cleanup: collecting all the entities we know and pruning those that cannot be placed somewhere
211 4
		$all_known = array_merge(array_keys($all_entities), array_keys($this->_all_after), array_keys($this->_all_before));
212
213
		$all = array(
214 4
			'before' => array(),
215 4
			'after' => array()
216 4
		);
217
218 4
		foreach ($this->_all_before as $key => $value)
219
		{
220
			if (in_array($value, $all_known))
221
			{
222
				$all['before'][$key] = $value;
223
			}
224 4
		}
225
226 4
		foreach ($this->_all_after as $key => $value)
227
		{
228
			if (in_array($value, $all_known))
229
			{
230
				$all['after'][$key] = $value;
231
			}
232 4
		}
233
234
		// This is terribly optimized, though it shouldn't loop over too many things (hopefully)
235
		// It "iteratively" adds all the after/before entities shifting priority
236
		// of all the other entities to ensure each one has a different value
237 4
		while (!empty($all['after']) || !empty($all['before']))
238
		{
239
			foreach (array('after' => 1, 'before' => -1) as $where => $inc)
240
			{
241
				if (empty($all[$where]))
242
				{
243
					continue;
244
				}
245
246
				foreach ($all[$where] as $entity => $reference)
247
				{
248
					if (isset($all_entities[$reference]))
249
					{
250
						$priority_threshold = $all_entities[$reference];
251
						foreach ($all_entities as $key => $val)
252
							switch ($where)
253
							{
254
								case 'after':
255
									if ($val <= $priority_threshold)
256
									{
257
										$all_entities[$key] -= $inc;
258
									}
259
									break;
260
								case 'before':
261
									if ($val >= $priority_threshold)
262
									{
263
										$all_entities[$key] -= $inc;
264
									}
265
									break;
266
							}
267
						unset($all[$where][$entity]);
268
						$all_entities[$entity] = $priority_threshold;
269
					}
270
				}
271
			}
272
		}
273
274 4
		asort($all_entities);
275 4
		$this->_sorted_entities = array_keys($all_entities);
276
277 4
		return $all_entities;
278
	}
279
280
	/**
281
	 * Check if at least one entity has been added
282
	 *
283
	 * @return bool true if at least one entity has been added
284
	 * @todo at that moment _all_after and _all_before are not considered because they may not be "forced"
285
	 */
286 4
	public function hasEntities()
287
	{
288 4
		if ($this->_sorted_entities === null)
289 4
		{
290
			return (!empty($this->_all_general) || !empty($this->_all_begin) || !empty($this->_all_end));
291
		}
292
		else
293
		{
294 4
			return !empty($this->_sorted_entities);
295
		}
296
	}
297
298
	/**
299
	 * Return the entities that have been loaded
300
	 */
301
	public function getEntities()
302
	{
303
		return array_keys(array_merge($this->_all_general, $this->_all_begin, $this->_all_end, $this->_all_after, $this->_all_before));
304
	}
305
306
	/**
307
	 * Return the entities that have been loaded
308
	 */
309 3
	public function getSortedEntities()
310
	{
311 3
		return $this->_sorted_entities;
312
	}
313
}
314