Completed
Push — master ( 211030...0ada29 )
by Tom
03:22
created

Repeat::run()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 18
rs 9.2
cc 4
eloc 12
nc 3
nop 5
1
<?php
2
/* @description     Transformation Style Sheets - Revolutionising PHP templating    *
3
 * @author          Tom Butler [email protected]                                             *
4
 * @copyright       2015 Tom Butler <[email protected]> | https://r.je/                      *
5
 * @license         http://www.opensource.org/licenses/bsd-license.php  BSD License *
6
 * @version         1.0                                                             */
7
namespace Transphporm\Property;
8
class Repeat implements \Transphporm\Property {
9
	private $functionSet;
10
	private $elementData;
11
	private $baseDir;
12
13
	public function __construct(\Transphporm\FunctionSet $functionSet, \Transphporm\Hook\ElementData $elementData, &$baseDir) {
14
		$this->functionSet = $functionSet;
15
		$this->elementData = $elementData;
16
		$this->baseDir = &$baseDir;
17
	}
18
19
	public function run(array $values, \DomElement $element, array $rules, \Transphporm\Hook\PseudoMatcher $pseudoMatcher, array $properties = []) {
20
		$values = $this->fixEmpty($values);
21
		if ($element->getAttribute('transphporm') === 'added') return $element->parentNode->removeChild($element);
22
		$max = $this->getMax($values);
23
		$count = 0;
24
25
		foreach ($values[0] as $key => $iteration) {
26
			if ($count+1 > $max) break;
27
			$clone = $this->cloneElement($element, $iteration, $key, $count++);
28
			//Re-run the hook on the new element, but use the iterated data
29
			//Don't run repeat on the clones element or it will loop forever
30
			unset($rules['repeat']);
31
			$this->createHook($rules, $pseudoMatcher, $properties)->run($clone);
32
		}
33
		//Remove the original element
34
		$element->parentNode->removeChild($element);
35
		return false;
36
	}
37
38
	private function fixEmpty($value) {
39
		if (empty($value[0])) $value[0] = [];
40
		return $value;
41
	}
42
43
	private function cloneElement($element, $iteration, $key, $count) {
44
		$clone = $element->cloneNode(true);
45
		$this->tagElement($clone, $count);
46
47
		$this->elementData->bind($clone, $iteration, 'iteration');
48
		$this->elementData->bind($clone, $key, 'key');
49
		$element->parentNode->insertBefore($clone, $element);
50
		return $clone;
51
	}
52
53
	private function tagElement($element, $count) {
54
		//Mark all but one of the nodes as having been added by transphporm, when the hook is run again, these are removed
55
		if ($count > 0) $element->setAttribute('transphporm', 'added');
56
	}
57
58
	private function getMax($values) {
59
		return isset($values[1]) ? $values[1] : PHP_INT_MAX;
60
	}
61
62
	private function createHook($newRules, $pseudoMatcher, $properties) {
63
		$hook = new \Transphporm\Hook\PropertyHook($newRules, $this->baseDir, $this->baseDir, $pseudoMatcher, new \Transphporm\Parser\Value($this->functionSet), $this->functionSet);
64
		foreach ($properties as $name => $property) $hook->registerProperty($name, $property);
65
		return $hook;
66
	}
67
}
68