Completed
Push — master ( f4ecf6...811ac1 )
by Tom
03:44
created

CssToXpath::processAttr()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 17
rs 8.8571
cc 5
eloc 12
nc 5
nop 2
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\Parser;
8
class CssToXpath {
9
	private $specialChars = [' ', '.', '>', '~', '#', ':', '[', ']'];
10
	private $translators = [];
11
	private $css;
12
	private $depth;
13
14
	public function __construct($css, Value $valueParser, $prefix = '') {
0 ignored issues
show
Unused Code introduced by
The parameter $valueParser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
15
		$this->css = str_replace([' >', '> '],['>', '>'], trim($css));
16
		$this->translators = [
17
			' ' => function($string) use ($prefix) { return '//' . $prefix . $string;	},
18
			'' => function($string) use ($prefix) { return '/' . $prefix . $string;	},
19
			'>' => function($string) use ($prefix) { return '/' . $prefix  . $string; },
20
			'#' => function($string) { return '[@id=\'' . $string . '\']'; },
21
			'.' => function($string) { return '[contains(concat(\' \', normalize-space(@class), \' \'), \' ' . $string . ' \')]'; }, 
22
			'[' => function($string, $xpath) { return '[' .'php:function(\'\Transphporm\Parser\CssToXpath::processAttr\', \'' . $string . '\', .)' . ']';	},
0 ignored issues
show
Unused Code introduced by
The parameter $xpath is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
23
			']' => function() {	return ''; }
24
		];
25
	}
26
27
	private function createSelector() {
28
		$selector = new \stdclass;
29
		$selector->type = '';
30
		$selector->string = '';
31
		return $selector;
32
	}
33
34
	//XPath only allows registering of static functions... this is a hacky workaround for that
35
	public static function processAttr($attr, $element) {
36
		$valueParser = new Value(\Transphporm\Hook\DataFunction::$latest);
37
38
		$comparators = ['!=', '='];
39
		foreach ($comparators as $comparator) {
40
			if (strpos($attr, $comparator) !== false) {
41
				$parts = explode($comparator, $attr);
42
				$parts = array_map(function($val) use ($valueParser, $element) {
43
					return $valueParser->parse($val, $element[0])[0];
44
				}, $parts);
45
				
46
				if ($comparator == '=') return $element[0]->getAttribute($parts[0]) == $parts[1];
47
				else if ($comparator == '!=') return $element[0]->getAttribute($parts[0]) != $parts[1];
48
			}
49
		}
50
		return $attr;
51
	}
52
53
	//split the css into indivudal functions
54
	private function split($css) {
55
		$selectors = [];
56
		$selector = $this->createSelector();
57
		$selectors[] = $selector;
58
59
		for ($i = 0; $i < strlen($css); $i++) {
60
			if (in_array($css[$i], $this->specialChars)) {
61
				$selector = $this->createSelector();
62
				$selector->type = $css[$i];
63
				$selectors[] = $selector;
64
			}
65
			else $selector->string .= $css[$i];			
66
		}
67
		return $selectors;
68
	}
69
70
	public function getXpath() {
71
		$css = explode(':', $this->css)[0];
72
		$selectors = $this->split($css);
73
		$this->depth = count($selectors);
74
		$xpath = '/';
75
		foreach ($selectors as $selector) {
76
			if (isset($this->translators[$selector->type])) $xpath .= $this->translators[$selector->type]($selector->string, $xpath);
77
		}
78
79
		$xpath = str_replace('/[', '/*[', $xpath);
80
81
		return $xpath;
82
	}
83
84
	public function getDepth() {
85
		return $this->depth;
86
	}
87
	
88
	public function getPseudo() {
89
		$parts = explode(':', $this->css);
90
		array_shift($parts);
91
		return $parts;
92
	}
93
}