Completed
Push — master ( f8e36b...235894 )
by Tom
02:30
created

PseudoMatcher::betweenBrackets()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
rs 9.6667
cc 3
eloc 6
nc 2
nop 4
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\Hook;
8
/** Determines whether $element matches the pseudo rule such as nth-child() or [attribute="value"] */
9
class PseudoMatcher {
10
	private $pseudo;
11
	private $dataFunction;
12
13
	public function __construct($pseudo, DataFunction $dataFunction) {
14
		$this->pseudo = $pseudo;
15
		$this->dataFunction = $dataFunction;
16
	}
17
18
	public function matches($element) {
19
		$matches = true;
20
21
		foreach ($this->pseudo as $pseudo) {			
22
			$matches = $matches && $this->attribute($pseudo, $element) && $this->nth($pseudo, $element);			
23
		}		
24
		return $matches;
25
	}
26
27
	private function betweenBrackets($string, $openChr, $closingChr, $start = 0) {
28
		$open = strpos($string, $openChr, $start);
29
		$close = strpos($string, $closingChr, $open);
30
31
		$cPos = $open+1;
32
		while (($cPos = strpos($string, $openChr, $cPos+1)) !== false && $cPos < $close) $close = strpos($string, $closingChr, $close+1);
33
34
		return substr($string, $open+1, $close-$open-1);
35
	}
36
	
37
	private function attribute($pseudo, $element) {
38
		if (strpos($pseudo, '=') === false) return true;
39
40
		$pos = strpos($pseudo, '[');
41
		if ($pos === false) return true;
42
		
43
		$name = substr($pseudo, 0, $pos);
44
		$criteria = $this->betweenBrackets($pseudo, '[', ']');
45
		
46
		list ($field, $value) = explode('=', $criteria);
47
48
		$operator = $this->getOperator($field);
49
50
		$field = trim($field, $operator);		
51
		$value = $this->parseValue(trim($value, '"'));
52
53
		$lookupValue = $this->dataFunction->$name([$field], $element);
54
		$matched = $lookupValue == $value;
55
		return $operator === '!' ? !$matched : $matched;		
56
	}
57
58
	private function parseValue($value) {
59
		if ($value == 'true') return true;
60
		else if ($value == 'false') return false;
61
		else return $value;
62
	}
63
64
	private function getOperator($field) {
65
		if ($field[strlen($field)-1] == '!') {
66
			return '!';
67
		}
68
		else return '';
69
	}
70
71
	private function nth($pseudo, $element) {
72
		if (strpos($pseudo, 'nth-child') === 0) {	
73
			$criteria = $this->getBetween($pseudo, '(', ')');
74
			$num = $this->getBetween($element->getNodePath(), '[', ']');
75
			
76
			if (is_callable([$this, $criteria])) return $this->$criteria($num);
77
			else return $num == $criteria;
78
			
79
		}
80
		return true;
81
	}
82
83
	public function attr() {
84
		foreach ($this->pseudo as $pseudo) {
85
			if (strpos($pseudo, 'attr') === 0) {
86
				$criteria = trim($this->getBetween($pseudo, '(', ')'));
87
				return $criteria;
88
			}
89
		}
90
91
		return false;
92
	}
93
94
	public function header($element)  {
95
		if ($this->matches($element)) {
96
			foreach ($this->pseudo as $pseudo) {
97
				if (strpos($pseudo, 'header') === 0) return $this->getBetween($pseudo, '[', ']');
98
			}
99
		}
100
	}
101
102
	private function odd($num) {
103
		return $num % 2 === 1;
104
	}
105
106
	private function even($num) {
107
		return $num % 2 === 0;
108
	}
109
110
	private function getBetween($string, $start, $end) {
111
		$open = strpos($string, $start);
112
		if ($open === false) return false;
113
		$close = strpos($string, $end, $open);
114
		return substr($string, $open+1, $close-$open-1);
115
	}
116
117
	public function getPseudo() {
118
		return $this->pseudo;
119
	}
120
}