Completed
Push — master ( 9caa90...8321d8 )
by Tom
02:40
created

Sheet   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 23
c 1
b 0
f 0
lcom 1
cbo 3
dl 0
loc 104
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A parse() 0 18 4
A CssToRule() 0 5 1
A writeRule() 0 9 2
A processingInstructions() 0 17 4
A import() 0 4 1
A sortRules() 0 6 4
A stripComments() 0 9 2
A getProperties() 0 15 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\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 $baseDir;
12
	private $prefix;
13
	private $valueParser;
14
15
	public function __construct($tss, $baseDir, Value $valueParser, $prefix = '') {
16
		$this->tss = $this->stripComments($tss);
17
		$this->baseDir = $baseDir;
18
		$this->prefix = $prefix;
19
		$this->valueParser = $valueParser;
20
	}
21
22
	public function parse($pos = 0, $rules = []) {
23
		while ($next = strpos($this->tss, '{', $pos)) {
24
			if ($processing = $this->processingInstructions($this->tss, $pos, $next)) {
25
				$pos = $processing['endPos']+1;
26
				$rules = array_merge($processing['rules'], $rules);
27
			}
28
29
			$selector = trim(substr($this->tss, $pos, $next-$pos));
30
			$rule = $this->cssToRule($selector, count($rules));	
31
			$pos =  strpos($this->tss, '}', $next)+1;
32
			$rule->properties = $this->getProperties(trim(substr($this->tss, $next+1, $pos-2-$next)));	
1 ignored issue
show
Documentation introduced by
The property $properties is declared private in Transphporm\Rule. Since you implemented __set(), maybe consider adding a @property or @property-write annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
33
			$rules = $this->writeRule($rules, $selector, $rule);
34
		}
35
		//there may be processing instructions at the end
36
		if ($processing = $this->processingInstructions($this->tss, $pos, strlen($this->tss))) $rules = array_merge($processing['rules'], $rules);
37
		usort($rules, [$this, 'sortRules']);
38
		return $rules;
39
	}
40
41
	private function CssToRule($selector, $index) {
42
		$xPath = new CssToXpath($selector, $this->valueParser, $this->prefix);
43
		$rule = new \Transphporm\Rule($xPath->getXpath(), $xPath->getPseudo(), $xPath->getDepth(), $index++);
44
		return $rule;
45
	}
46
47
	private function writeRule($rules, $selector, $newRule) {
48
		if (isset($rules[$selector])) {
49
			$newRule->properties = array_merge($rules[$selector]->properties, $newRule->properties);
50
		}
51
52
		$rules[$selector] = $newRule;
53
		
54
		return $rules;
55
	}
56
57
	private function processingInstructions($tss, $pos, $next) {
58
		$rules = [];
59
		while (($atPos = strpos($tss, '@', $pos)) !== false) {
60
			if ($atPos  <= (int) $next) {
61
				$spacePos = strpos($tss, ' ', $atPos);
62
				$funcName = substr($tss, $atPos+1, $spacePos-$atPos-1);
63
				$pos = strpos($tss, ';', $spacePos);
64
				$args = substr($tss, $spacePos+1, $pos-$spacePos-1);
65
				$rules = array_merge($rules, $this->$funcName($args));
66
			}
67
			else {
68
				break;	
69
			} 
70
		}
71
72
		return empty($rules) ? false : ['endPos' => $pos, 'rules' => $rules];
73
	}
74
75
	private function import($args) {
76
		$sheet = new Sheet(file_get_contents($this->baseDir . trim($args, '\'" ')), $this->baseDir, $this->valueParser, $this->prefix);
77
		return $sheet->parse();
78
	}
79
80
	private function sortRules($a, $b) {
81
		//If they have the same depth, compare on index
82
		if ($a->depth === $b->depth) return $a->index < $b->index ? -1 : 1;
83
84
		return ($a->depth < $b->depth) ? -1 : 1;
85
	}
86
87
	private function stripComments($str) {
88
		$pos = 0;
89
		while (($pos = strpos($str, '/*', $pos)) !== false) {
90
			$end = strpos($str, '*/', $pos);
91
			$str = substr_replace($str, '', $pos, $end-$pos+2);
92
		}
93
94
		return $str;
95
	}
96
97
	private function getProperties($str) {
98
		$stringExtractor = new StringExtractor($str);
99
		$rules = explode(';', $stringExtractor);
100
		$return = [];
101
102
		foreach ($rules as $rule) {
103
			if (trim($rule) === '') continue;
104
			$parts = explode(':', $rule, 2);
105
106
			$parts[1] = $stringExtractor->rebuild($parts[1]);
107
			$return[trim($parts[0])] = isset($parts[1]) ? trim($parts[1]) : '';
108
		}
109
110
		return $return;
111
	}
112
}
113