Passed
Push — master ( a357e7...195a07 )
by Anton
04:22 queued 01:11
created

Block::buildContents()   B

Complexity

Conditions 8
Paths 72

Size

Total Lines 55
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 55
rs 7.4033
c 0
b 0
f 0
cc 8
eloc 18
nc 72
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * @package Framework\Template
5
 * @author Anton Romanov
6
 * @copyright Copyright (c) 2015-2016, Anton Romanov
7
 * @link http://cadmium-cms.com
8
 */
9
10
namespace Template {
11
12
	use Language, Str, Template;
13
14
	class Block extends Group {
15
16
		private $contents = '', $enabled = true;
17
18
		private $blocks = [], $loops = [], $widgets = [], $variables = [], $phrases = [];
19
20
		/**
21
		 * Parse structures
22
		 */
23
24
		private function parseStructures() {
25
26
			preg_match_all(REGEX_TEMPLATE_STRUCTURE, $this->contents, $matches);
27
28
			foreach ($matches[0] as $key => $match) {
29
30
				$toggle = (($matches[1][$key] === '!') ? 'disable' : 'enable');
31
32
				$type = $matches[2][$key]; $name = $matches[3][$key]; $contents = ($matches[4][$key] ?? '');
33
34
				if (!preg_match(REGEX_TEMPLATE_COMPONENT_NAME, $name)) continue;
35
36
				$this->contents = str_replace($match, ('{ ' . $type . ':' . $name . ' / }'), $this->contents);
37
38
				if ($type === 'block') $this->blocks[$name] = (new Block($contents))->$toggle();
39
40
				else if ($type === 'for') $this->loops[$name] = new Loop($contents);
41
42
				else if ($type === 'widget') $this->widgets[] = $name;
43
			}
44
		}
45
46
		/**
47
		 * Parse elementaries
48
		 */
49
50
		private function parseElementaries() {
51
52
			$variables = ['pattern' => REGEX_TEMPLATE_VARIABLE, 'stack' => &$this->variables ];
53
54
			$phrases = ['pattern' => REGEX_TEMPLATE_PHRASE, 'stack' => &$this->phrases ];
55
56
			foreach ([$variables, $phrases] as $elementaries) {
57
58
				preg_match_all($elementaries['pattern'], $this->contents, $matches);
59
60
				foreach ($matches[1] as $index => $name) {
61
62
					if (!preg_match(REGEX_TEMPLATE_COMPONENT_NAME, $name)) continue;
63
64
					$elementaries['stack'][$name] = false;
65
				}
66
			}
67
		}
68
69
		/**
70
		 * Build the block contents
71
		 */
72
73
		protected function buildContents() : string {
74
75
			$insertions = [];
76
77
			# Process blocks
78
79
			foreach ($this->blocks as $name => $block) {
80
81
				$insertions['{ block:' . $name . ' / }'] = $block->getContents();
82
			}
83
84
			# Process loops
85
86
			foreach ($this->loops as $name => $loop) {
87
88
				$insertions['{ for:' . $name . ' / }'] = $loop->getContents();
89
			}
90
91
			# Process widgets
92
93
			foreach ($this->widgets as $name) {
94
95
				$widget = Template::getWidget($name);
96
97
				$contents = ((false !== $widget) ? $widget->getContents() : '');
98
99
				$insertions['{ widget:' . $name . ' / }'] = $contents;
100
			}
101
102
			# Process variables
103
104
			foreach ($this->variables as $name => $value) {
105
106
				$value = ((false === $value) ? Template::getGlobal($name) : $value);
107
108
				$insertions['$' . $name . '$'] = Str::formatOutput($value);
109
			}
110
111
			# Process phrases
112
113
			foreach ($this->phrases as $name => $value) {
114
115
				$value = Language::get($name);
116
117
				$insertions['%' . $name . '%'] = Str::formatOutput($value);
118
			}
119
120
			# Process insertions
121
122
			$contents = str_replace(array_keys($insertions), array_values($insertions), $this->contents);
123
124
			# ------------------------
125
126
			return $contents;
127
		}
128
129
		/**
130
		 * Constructor
131
		 */
132
133
		public function __construct(string $contents = '') {
134
135
			$this->contents = $contents;
136
137
			$this->parseStructures(); $this->parseElementaries();
138
		}
139
140
		/**
141
		 * Cloner
142
		 */
143
144
		public function __clone() {
145
146
			foreach ($this->blocks as $name => $block) $this->blocks[$name] = clone $block;
147
148
			foreach ($this->loops as $name => $loop) $this->loops[$name] = clone $loop;
149
150
			foreach ($this->items as $name => $item) $this->items[$name] = clone $item;
151
		}
152
153
		/**
154
		 * Set a block, a loop, or a variable
155
		 *
156
		 * @return the current block object
157
		 */
158
159
		public function set(string $name, $value) : Block {
160
161
			if ($value instanceof Block) $this->setBlock($name, $value);
162
163
			else if (is_array($value)) $this->setLoop($name, $value);
164
165
			else if (is_scalar($value)) $this->setVar($name, $value);
166
167
			# ------------------------
168
169
			return $this;
170
		}
171
172
		/**
173
		 * Set multiple components (blocks, loops, or variables)
174
		 *
175
		 * @return the current block object
176
		 */
177
178
		public function setArray(array $components) : Block {
179
180
			foreach ($components as $name => $component) $this->set($name, $component);
181
182
			return $this;
183
		}
184
185
		/**
186
		 * Set a block
187
		 *
188
		 * @return the current block object
189
		 */
190
191
		public function setBlock(string $name, Block $block) : Block {
192
193
			if (isset($this->blocks[$name])) $this->blocks[$name] = $block;
194
195
			return $this;
196
		}
197
198
		/**
199
		 * Set a loop
200
		 *
201
		 * @return the current block object
202
		 */
203
204
		public function setLoop(string $name, array $items) : Block {
205
206
			if (isset($this->loops[$name])) $this->loops[$name]->setItems($items);
207
208
			return $this;
209
		}
210
211
		/**
212
		 * Set a variable
213
		 *
214
		 * @return the current block object
215
		 */
216
217
		public function setVar(string $name, string $value) : Block {
218
219
			if (isset($this->variables[$name])) $this->variables[$name] = $value;
220
221
			return $this;
222
		}
223
224
		/**
225
		 * Get a block, a loop, or a variable
226
		 *
227
		 * @return the component or false if the component with the given name does not exist
228
		 */
229
230
		public function get(string $name) {
231
232
			return ($this->blocks[$name] ?? $this->loops[$name] ?? $this->variables[$name] ?? false);
233
		}
234
235
		/**
236
		 * Get a block. It's recommended to use this method instead of magic getter to avoid an error on getting nonexistent block
237
		 *
238
		 * @return the block or an empty block if the block with the given name does not exist
239
		 */
240
241
		public function getBlock(string $name) : Block {
242
243
			return ($this->blocks[$name] ?? new Block);
244
		}
245
246
		/**
247
		 * Get the blocks list
248
		 */
249
250
		public function getBlocks() : array {
251
252
			return $this->blocks;
253
		}
254
255
		/**
256
		 * Get a loop. It's recommended to use this method instead of magic getter to avoid an error on getting nonexistent loop
257
		 *
258
		 * @return the loop or an empty loop if the loop with the given name does not exist
259
		 */
260
261
		public function getLoop(string $name) : Loop {
262
263
			return ($this->loops[$name] ?? new Loop);
264
		}
265
266
		/**
267
		 * Get the loops list
268
		 */
269
270
		public function getLoops() : array {
271
272
			return $this->loops;
273
		}
274
275
		/**
276
		 * Get a variable
277
		 *
278
		 * @return the value or false if the variable with the given name does not exist
279
		 */
280
281
		public function getVar(string $name) {
282
283
			return ($this->variables[$name] ?? false);
284
		}
285
286
		/**
287
		 * Get the variable list
288
		 */
289
290
		public function getVars() : array {
291
292
			return $this->variables;
293
		}
294
295
		/**
296
		 * Get the block contents
297
		 */
298
299
		public function getContents() : string {
300
301
			if (!$this->enabled) return '';
302
303
			# Lock the block
304
305
			$this->enabled = false;
306
307
			# Generate contents
308
309
			$contents = ((0 === $this->count) ? $this->buildContents() : parent::getContents());
310
311
			# Unlock the block
312
313
			$this->enabled = true;
314
315
			# ------------------------
316
317
			return $contents;
318
		}
319
320
		/**
321
		 * Disable the block
322
		 *
323
		 * @return the current block object
324
		 */
325
326
		public function disable() : Block {
327
328
			$this->enabled = false;
329
330
			return $this;
331
		}
332
333
		/**
334
		 * Enable the block
335
		 *
336
		 * @return the current block object
337
		 */
338
339
		public function enable() : Block {
340
341
			$this->enabled = true;
342
343
			return $this;
344
		}
345
346
		/**
347
		 * Check if the block is enabled
348
		 */
349
350
		public function isEnabled() : bool {
351
352
			return $this->enabled;
353
		}
354
355
		/**
356
		 * An alias for the set method
357
		 */
358
359
		public function __set(string $name, $value) : Block {
360
361
			return $this->set($name, $value);
362
		}
363
364
		/**
365
		 * An alias for the get method
366
		 */
367
368
		public function __get(string $name) {
369
370
			return $this->get($name);
371
		}
372
373
		/**
374
		 * Check if a component exists
375
		 */
376
377
		public function __isset(string $name) : bool {
378
379
			return (isset($this->blocks[$name]) || isset($this->loops[$name]) || isset($this->variables[$name]));
380
		}
381
	}
382
}
383