ar_cssStyles   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 29
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 10
c 0
b 0
f 0
ccs 0
cts 22
cp 0
wmc 7
lcom 1
cbo 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A __toString() 0 15 5
A getVariable() 0 3 1
1
<?php
2
	ar_pinp::allow( 'ar_css' );
3
	ar_pinp::allow( 'ar_cssStyleSheet' );
4
	ar_pinp::allow( 'ar_cssSearch' );
5
	ar::load('html');
6
7
	class ar_css extends arBase {
8
9
		public static function stylesheet() {
10
			return new ar_cssStyleSheet( );
11
		}
12
13
	}
14
15
	class ar_cssStyleSheet extends ar_htmlElement {
16
		// FIXME: make the css content available as nodeValue of a child ar_htmlNode (or a list of nodes?)
17
		// create a ar_cssRule which implements or extends ar_htmlNode?
18
		private $cssText   = '';
19
		private $variables = array();
20
		public  $rules     = null;
21
22
		public function __construct($tagName = 'style', $attributes = array(), $childNodes = null, $parentNode = null) {
23
			$this->rules   = new ar_cssRules( $this );
24
			if ( !$attributes ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $attributes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
25
				$attributes = array();
26
			}
27
			if ( !$attributes['type'] ) {
28
				$attributes['type'] = 'text/css';
29
			}
30
			parent::__construct( $tagName, $attributes, null, $parentNode );
31
		}
32
33
		public function rule( $selector, $styles ) {
34
			$this->rules[$selector] = new ar_cssStyles( $this->rules, $styles );
35
			return $this;
36
		}
37
38
		public function find( $search ) {
39
			$found = new ar_cssRules( $this );
40
			foreach ( $this->rules as $rule => $styles ) {
41
				if ( preg_match( $search, $rule ) ) {
42
					$found[$rule] = $styles;
43
				}
44
			}
45
			return new ar_cssSearch( $this, $search, $found );
46
		}
47
48
		public function add( $selector, $styles ) {
49
			$this->rules[$selector] = new ar_cssStyles(
50
				$this->rules,
51
				array_merge(
52
					(array) $this->rules[$selector],
53
					(array) $styles
54
				)
55
			);
56
			return $this;
57
		}
58
59
		public function delete( $selector, $styles = null ) {
60
			if ( isset($styles) ) {
61
				foreach( $styles as $style ) {
62
					unset( $this->rules[$selector][$style] );
63
				}
64
			} else {
65
				unset( $this->rules[$selector] );
66
			}
67
			return $this;
68
		}
69
70
		public function copy( $selector, $newselector ) {
71
			$this->add( $newselector, $this->rules[$selector] );
72
		}
73
74
		public function import( $cssText ) {
75
			// ignore comments /* */ but keep them in
76
			$ruleRE  = '/([^{]*)\{(.*)\}/isU';
77
			$styleRE = '/([^:]+)\:(.+)(;|$)/isU';
78
			while ( preg_match( $ruleRE, $cssText, $matches ) ) {
79
				$rule       = $matches[1];
80
				$stylesText = $matches[2];
81
				$styles = array();
82
				while ( preg_match( $styleRE, $stylesText, $styleMatches ) ) {
83
					$styles[ $styleMatches[1] ] = $styleMatches[2];
84
					$stylesText = str_replace( $styleMatches[0], '', $stylesText );
85
				}
86
				$this->add( $rule, $styles );
87
				$cssText = str_replace( $matches[0], '', $cssText);
88
			}
89
			$this->cssText = $cssText;
90
			return $this;
91
		}
92
93
		public function rename( $selector, $newselector ) {
94
			$this->rules[$newselector] = $this->rules[$selector];
95
			unset( $this->rules[$selector] );
96
		}
97
98
		public function getVariable( $name ) {
99
			return $this->variables[$name] ? $this->variables[$name] : null;
100
		}
101
102
		public function bind( $variable, $value = null, $dummy = 'string' ) {
103
			if ( is_array($variable) ) {
104
				$this->variables = $variable + $this->variables;
105
			} else {
106
				$this->variables[$variable] = $value;
107
			}
108
			return $this;
109
		}
110
111
		public function __toString() {
112
			return (string) ar_html::tag( 'style', $this->attributes, (string) $this->rules );
113
		}
114
	}
115
116
	class ar_cssSearch extends arBase {
117
		private $styleSheet = null;
118
		private $search     = null;
119
		private $rules      = null;
120
121
		public function __construct( $styleSheet, $search, $rules ) {
122
			$this->styleSheet = $styleSheet;
123
			$this->search     = $search;
124
			$this->rules      = new ar_cssRules($styleSheet, $rules);
125
		}
126
127
		public function __toString() {
128
			$this->apply();
129
			return $this->styleSheet->__toString();
130
		}
131
132
		public function rule( $newstyles ) {
133
			foreach ( $this->rules as $rule => $styles ) {
134
				$this->rules[$rule] = new ar_cssStyles( $this->rules, $newstyles);
135
			}
136
			return $this;
137
		}
138
139
		public function delete( $oldstyles = null ) {
140
			foreach ( $this->rules as $rule => $styles ) {
141
				if (isset($oldstyles)) {
142
					foreach ( $oldstyles as $style ) {
143
						$this->rules[$rule][$style] = null;
144
					}
145
				} else {
146
					$this->rules[$rule] = null;
147
				}
148
			}
149
			return $this;
150
		}
151
152
		public function add( $newstyles ) {
153
			foreach ( $this->rules as $rule => $styles ) {
154
				$this->rules[$rule] = new ar_cssStyles( $this->rules, array_merge( (array) $styles, (array) $newstyles ) );
155
			}
156
			return $this;
157
		}
158
159
		public function rename( $newselector ) {
160
			foreach ( $this->rules as $rule => $styles ) {
161
				$newrule = preg_replace( $rule, $this->search, $newselector );
162
				$this->rules[$newrule] = $styles;
163
				$this->rules[$rule]    = null;
164
			}
165
			return $this;
166
		}
167
168
		public function apply() {
169
			foreach ( $this->rules as $rule => $styles ) {
170
				if ( isset($styles) ) {
171
					$this->styleSheet->rule( $rule, $styles );
172
				} else {
173
					$this->styleSheet->delete( $rule );
174
				}
175
			}
176
			return $this->styleSheet;
177
		}
178
	}
179
180
	interface ar_cssRulesInterface {
181
	}
182
183
	class ar_cssRules extends ArrayObject implements ar_cssRulesInterface {
184
		private $styleSheet = null;
185
186
		public function __construct( $styleSheet, $rules = array() ) {
187
			$this->styleSheet = $styleSheet;
188
			parent::__construct( (array) $rules );
189
		}
190
191
		public function __toString() {
192
			$result = '';
193
			foreach( $this as $rule => $style ) {
194
				$result .= "\n" . trim($rule) . " {\n" . $style . "}\n";
195
			}
196
			return $result;
197
		}
198
199
		public function getVariable( $name ) {
200
			return $this->styleSheet->getVariable( $name );
201
		}
202
	}
203
204
	interface ar_cssStylesInterface {
205
	}
206
207
	class ar_cssStyles extends ArrayObject implements ar_cssStylesInterface {
208
209
		private $rules = null;
210
211
		public function __construct( $rules, $styles = array() ) {
212
			$this->rules = $rules;
213
			parent::__construct( (array) $styles );
214
		}
215
216
		public function __toString() {
217
			$result = '';
218
			foreach ($this as $style => $value ) {
219
				if ( $value ) {
220
					while ( preg_match('/\b(var\((.*)\))/', $value, $matches) ) {
221
						$var   = $this->getVariable( $matches[2] );
222
						if ( isset($var) ) {
223
							$value = str_replace( $matches[1], $var, $value );
224
						}
225
					}
226
					$result .= "\t" . trim($style) . ": " . trim($value) . ";\n";
227
				}
228
			}
229
			return $result;
230
		}
231
232
		protected function getVariable( $name ) {
233
			return $this->rules->getVariable( $name );
234
		}
235
	}
236