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; |
||
0 ignored issues
–
show
|
|||
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
|
|||
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
|
|||
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 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: