Completed
Push — master ( 02c8a1...58faf5 )
by Tom
02:14
created

src/Parser/Sheet.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/* @description     Transformation Style Sheets - Revolutionising PHP templating    *
3
 * @author          Tom Butler [email protected]                                             *
4
 * @copyright       2017 Tom Butler <[email protected]> | https://r.je/                      *
5
 * @license         http://www.opensource.org/licenses/bsd-license.php  BSD License *
6
 * @version         1.2                                                             */
7
namespace Transphporm\Parser;
8
/** Parses a .tss file into individual rules, each rule has a query e,g, `ul li` and a set of rules e.g. `display: none; bind: iteration(id);` */
9
class Sheet {
10
	private $tss;
11
	private $xPath;
12
	private $valueParser;
13
	private $sheetLoader;
14
	private $file;
15
	private $rules;
16
17
	public function __construct($tss, CssToXpath $xPath, Value $valueParser, \Transphporm\FilePath $filePath, \Transphporm\SheetLoader\SheetLoader $sheetLoader, $file = null) {
18
		$this->xPath = $xPath;
19
		$this->valueParser = $valueParser;
20
		$this->filePath = $filePath;
21
		$this->sheetLoader = $sheetLoader;
22
		$this->file = $file;
23
		$this->tss = (new Tokenizer($tss))->getTokens();
24
	}
25
26
	public function parse($indexStart = 0) {
27
		if (!empty($this->rules)) return $this->rules['rules'];
28
		$rules = $this->parseTokens($indexStart);
29
		$this->checkError($rules);
30
		return $rules;
31
	}
32
33
	private function parseTokens($indexStart) {
34
		$this->rules = [];
35
		foreach (new TokenFilterIterator($this->tss, [Tokenizer::WHITESPACE]) as $token) {
36
			if ($processing = $this->processingInstructions($token, count($this->rules)+$indexStart)) {
37
				$this->rules = array_merge($this->rules, $processing);
38
			}
39
			else if (!in_array($token['type'], [Tokenizer::NEW_LINE, Tokenizer::AT_SIGN])) $this->addRules($token, $indexStart++);
40
		}
41
42
		return $this->rules;
43
	}
44
45
	private function addRules($token, $indexStart) {
46
		$selector = $this->tss->from($token['type'], true)->to(Tokenizer::OPEN_BRACE);
47
48
		$this->tss->skip(count($selector));
49
		if (count($selector) === 0) return;
50
		$newRules = $this->cssToRules($selector, count($this->rules)+$indexStart, $this->getProperties($this->tss->current()['value']), $token['line']);
51
		$this->rules = $this->writeRule($this->rules, $newRules);
52
	}
53
54
	private function checkError($rules) {
55
		if (empty($rules) && count($this->tss) > 0) throw new \Exception('No TSS rules parsed');
56
	}
57
58
	private function CssToRules($selector, $index, $properties, $line) {
59
		$parts = $selector->trim()->splitOnToken(Tokenizer::ARG);
60
		$rules = [];
61
		foreach ($parts as $part) {
62
			$serialized = serialize($part->removeLine());
63
			$rules[$serialized] = new \Transphporm\Rule($this->xPath->getXpath($part), $this->xPath->getPseudo($part), $this->xPath->getDepth($part), $index, $this->file, $line);
64
			$rules[$serialized]->properties = $properties;
65
		}
66
		return $rules;
67
	}
68
69
	private function writeRule($rules, $newRules) {
70
		foreach ($newRules as $selector => $newRule) {
71
			if (isset($rules[$selector])) {
72
				$newRule->properties = array_merge($rules[$selector]->properties, $newRule->properties);
73
				$newRule->index = $rules[$selector]->index;
74
			}
75
			$rules[$selector] = $newRule;
76
		}
77
78
		return $rules;
79
	}
80
81
	private function processingInstructions($token, $indexStart) {
82
		if ($token['type'] !== Tokenizer::AT_SIGN) return false;
83
		$tokens = $this->tss->from(Tokenizer::AT_SIGN, false)->to(Tokenizer::SEMI_COLON, false);
84
		$funcName = $tokens->from(Tokenizer::NAME, true)->read();
85
		$funcToks = $tokens->from(Tokenizer::NAME);
86
		$args = $this->valueParser->parseTokens($funcToks);
87
		$rules = $this->$funcName($args, $indexStart, $funcToks);
88
		$this->tss->skip(count($tokens)+2);
89
90
		return $rules;
91
	}
92
93
	private function import($args, $indexStart, $tokens) {
0 ignored issues
show
The parameter $tokens 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...
94
		$fileName = $this->filePath->getFilePath($args[0]);
95
		$this->sheetLoader->addImport($fileName);
96
97
		$tssFile = new \Transphporm\SheetLoader\TSSString(file_get_contents($fileName), $this->filePath);
98
		return $tssFile->getRules($this->xPath, $this->valueParser, $this->sheetLoader, $indexStart);
99
	}
100
101
	private function cacheKey($args, $indexStart, $tokens) {
0 ignored issues
show
The parameter $args 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...
The parameter $indexStart 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...
102
		$this->sheetLoader->setCacheKey($tokens);
103
	}
104
105
	private function getProperties($tokens) {
106
        $rules = $tokens->splitOnToken(Tokenizer::SEMI_COLON);
107
108
        $return = [];
109
        foreach ($rules as $rule) {
110
            $name = $rule->from(Tokenizer::NAME, true)->to(Tokenizer::COLON)->read();
111
            $return[$name] = $rule->from(Tokenizer::COLON)->trim();
112
        }
113
114
        return $return;
115
    }
116
}
117