Completed
Push — update/wordads-shortcode-name ( 7e5709...86de40 )
by
unknown
11:35
created

csstidy_print::size()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 4
nop 1
dl 0
loc 11
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * CSSTidy - CSS Parser and Optimiser
5
 *
6
 * CSS Printing class
7
 * This class prints CSS data generated by csstidy.
8
 *
9
 * Copyright 2005, 2006, 2007 Florian Schmitz
10
 *
11
 * This file is part of CSSTidy.
12
 *
13
 *   CSSTidy is free software; you can redistribute it and/or modify
14
 *   it under the terms of the GNU Lesser General Public License as published by
15
 *   the Free Software Foundation; either version 2.1 of the License, or
16
 *   (at your option) any later version.
17
 *
18
 *   CSSTidy is distributed in the hope that it will be useful,
19
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 *   GNU Lesser General Public License for more details.
22
 *
23
 *   You should have received a copy of the GNU Lesser General Public License
24
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
25
 *
26
 * @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
27
 * @package csstidy
28
 * @author Florian Schmitz (floele at gmail dot com) 2005-2007
29
 * @author Brett Zamir (brettz9 at yahoo dot com) 2007
30
 * @author Cedric Morin (cedric at yterium dot com) 2010
31
 */
32
33
/**
34
 * CSS Printing class
35
 *
36
 * This class prints CSS data generated by csstidy.
37
 *
38
 * @package csstidy
39
 * @author Florian Schmitz (floele at gmail dot com) 2005-2006
40
 * @version 1.0.1
41
 */
42
class csstidy_print {
43
44
	/**
45
	 * Saves the input CSS string
46
	 * @var string
47
	 * @access private
48
	 */
49
	public $input_css = '';
50
	/**
51
	 * Saves the formatted CSS string
52
	 * @var string
53
	 * @access public
54
	 */
55
	public $output_css = '';
56
	/**
57
	 * Saves the formatted CSS string (plain text)
58
	 * @var string
59
	 * @access public
60
	 */
61
	public $output_css_plain = '';
62
63
	/**
64
	 * Constructor
65
	 * @param array $css contains the class csstidy
66
	 * @access private
67
	 * @version 1.0
68
	 */
69
	function __construct(&$css) {
70
		$this->parser = & $css;
0 ignored issues
show
Bug introduced by
The property parser does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
71
		$this->css = & $css->css;
0 ignored issues
show
Bug introduced by
The property css does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
72
		$this->template = & $css->template;
0 ignored issues
show
Bug introduced by
The property template does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
73
		$this->tokens = & $css->tokens;
0 ignored issues
show
Bug introduced by
The property tokens does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
74
		$this->charset = & $css->charset;
0 ignored issues
show
Bug introduced by
The property charset does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
75
		$this->import = & $css->import;
0 ignored issues
show
Bug introduced by
The property import does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
76
		$this->namespace = & $css->namespace;
0 ignored issues
show
Bug introduced by
The property namespace does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
77
	}
78
79
	function csstidy_print(&$css) {
80
		$this->__construct($css);
81
	}
82
83
	/**
84
	 * Resets output_css and output_css_plain (new css code)
85
	 * @access private
86
	 * @version 1.0
87
	 */
88
	function _reset() {
89
		$this->output_css = '';
90
		$this->output_css_plain = '';
91
	}
92
93
	/**
94
	 * Returns the CSS code as plain text
95
	 * @param string $default_media default @media to add to selectors without any @media
96
	 * @return string
97
	 * @access public
98
	 * @version 1.0
99
	 */
100
	function plain($default_media='') {
101
		$this->_print(true, $default_media);
102
		return $this->output_css_plain;
103
	}
104
105
	/**
106
	 * Returns the formatted CSS code
107
	 * @param string $default_media default @media to add to selectors without any @media
108
	 * @return string
109
	 * @access public
110
	 * @version 1.0
111
	 */
112
	function formatted($default_media='') {
113
		$this->_print(false, $default_media);
114
		return $this->output_css;
115
	}
116
117
	/**
118
	 * Returns the formatted CSS code to make a complete webpage
119
	 * @param string $doctype shorthand for the document type
120
	 * @param bool $externalcss indicates whether styles to be attached internally or as an external stylesheet
121
	 * @param string $title title to be added in the head of the document
122
	 * @param string $lang two-letter language code to be added to the output
123
	 * @return string
124
	 * @access public
125
	 * @version 1.4
126
	 */
127
	function formatted_page($doctype='xhtml1.1', $externalcss=true, $title='', $lang='en') {
128
		switch ($doctype) {
129
			case 'xhtml1.0strict':
130
				$doctype_output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
131
			"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
132
				break;
133
			case 'xhtml1.1':
134
			default:
135
				$doctype_output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
136
				"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
137
				break;
138
		}
139
140
		$output = $cssparsed = '';
0 ignored issues
show
Unused Code introduced by
$cssparsed is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
141
		$this->output_css_plain = & $output;
142
143
		$output .= $doctype_output . "\n" . '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="' . $lang . '"';
144
		$output .= ( $doctype === 'xhtml1.1') ? '>' : ' lang="' . $lang . '">';
145
		$output .= "\n<head>\n    <title>$title</title>";
146
147
		if ($externalcss) {
148
			$output .= "\n    <style type=\"text/css\">\n";
149
			$cssparsed = file_get_contents('cssparsed.css');
150
			$output .= $cssparsed; // Adds an invisible BOM or something, but not in css_optimised.php
151
			$output .= "\n</style>";
152
		} else {
153
			$output .= "\n" . '    <link rel="stylesheet" type="text/css" href="cssparsed.css" />';
154
//			}
155
		}
156
		$output .= "\n</head>\n<body><code id=\"copytext\">";
157
		$output .= $this->formatted();
158
		$output .= '</code>' . "\n" . '</body></html>';
159
		return $this->output_css_plain;
160
	}
161
162
	/**
163
	 * Returns the formatted CSS Code and saves it into $this->output_css and $this->output_css_plain
164
	 * @param bool $plain plain text or not
165
	 * @param string $default_media default @media to add to selectors without any @media
166
	 * @access private
167
	 * @version 2.0
168
	 */
169
	function _print($plain = false, $default_media='') {
170
		if ($this->output_css && $this->output_css_plain) {
171
			return;
172
		}
173
174
		$output = '';
175
		if (!$this->parser->get_cfg('preserve_css')) {
176
			$this->_convert_raw_css($default_media);
177
		}
178
179
		$template = & $this->template;
180
181
		if ($plain) {
182
			$template = array_map('strip_tags', $template);
183
		}
184
185
		if ($this->parser->get_cfg('timestamp')) {
186
			array_unshift($this->tokens, array(COMMENT, ' CSSTidy ' . $this->parser->version . ': ' . date('r') . ' '));
187
		}
188
189
		if (!empty($this->charset)) {
190
			$output .= $template[0] . '@charset ' . $template[5] . $this->charset . $template[6];
191
		}
192
193
		if (!empty($this->import)) {
194
			for ($i = 0, $size = count($this->import); $i < $size; $i++) {
195
				$import_components = explode(' ', $this->import[$i]);
196
				if (substr($import_components[0], 0, 4) === 'url(' && substr($import_components[0], -1, 1) === ')') {
197
					$import_components[0] = '\'' . trim(substr($import_components[0], 4, -1), "'\"") . '\'';
198
					$this->import[$i] = implode(' ', $import_components);
199
					$this->parser->log('Optimised @import : Removed "url("', 'Information');
200
				}
201
				$output .= $template[0] . '@import ' . $template[5] . $this->import[$i] . $template[6];
202
			}
203
		}
204
205
		if (!empty($this->namespace)) {
206
			if (substr($this->namespace, 0, 4) === 'url(' && substr($this->namespace, -1, 1) === ')') {
207
				$this->namespace = '\'' . substr($this->namespace, 4, -1) . '\'';
208
				$this->parser->log('Optimised @namespace : Removed "url("', 'Information');
209
			}
210
			$output .= $template[0] . '@namespace ' . $template[5] . $this->namespace . $template[6];
211
		}
212
213
		$output .= $template[13];
214
		$in_at_out = '';
215
		$out = & $output;
216
217
		foreach ($this->tokens as $key => $token) {
218
			switch ($token[0]) {
219
				case AT_START:
220
					$out .= $template[0] . $this->_htmlsp($token[1], $plain) . $template[1];
221
					$out = & $in_at_out;
222
					break;
223
224
				case SEL_START:
225
					if ($this->parser->get_cfg('lowercase_s'))
226
						$token[1] = strtolower($token[1]);
227
					$out .= ( $token[1]{0} !== '@') ? $template[2] . $this->_htmlsp($token[1], $plain) : $template[0] . $this->_htmlsp($token[1], $plain);
228
					$out .= $template[3];
229
					break;
230
231
				case PROPERTY:
232
					if ($this->parser->get_cfg('case_properties') === 2) {
233
						$token[1] = strtoupper($token[1]);
234
					} elseif ($this->parser->get_cfg('case_properties') === 1) {
235
						$token[1] = strtolower($token[1]);
236
					}
237
					$out .= $template[4] . $this->_htmlsp($token[1], $plain) . ':' . $template[5];
238
					break;
239
240
				case VALUE:
241
					$out .= $this->_htmlsp($token[1], $plain);
242
					if ($this->_seeknocomment($key, 1) == SEL_END && $this->parser->get_cfg('remove_last_;')) {
243
						$out .= str_replace(';', '', $template[6]);
244
					} else {
245
						$out .= $template[6];
246
					}
247
					break;
248
249
				case SEL_END:
250
					$out .= $template[7];
251
					if ($this->_seeknocomment($key, 1) != AT_END)
252
						$out .= $template[8];
253
					break;
254
255
				case AT_END:
256
					$out = & $output;
257
					$out .= $template[10] . str_replace("\n", "\n" . $template[10], $in_at_out);
258
					$in_at_out = '';
259
					$out .= $template[9];
260
					break;
261
262
				case COMMENT:
263
					$out .= $template[11] . '/*' . $this->_htmlsp($token[1], $plain) . '*/' . $template[12];
264
					break;
265
			}
266
		}
267
268
		$output = trim($output);
269
270
		if (!$plain) {
271
			$this->output_css = $output;
272
			$this->_print(true);
273
		} else {
274
			// If using spaces in the template, don't want these to appear in the plain output
275
			$this->output_css_plain = str_replace('&#160;', '', $output);
276
		}
277
	}
278
279
	/**
280
	 * Gets the next token type which is $move away from $key, excluding comments
281
	 * @param integer $key current position
282
	 * @param integer $move move this far
283
	 * @return mixed a token type
284
	 * @access private
285
	 * @version 1.0
286
	 */
287
	function _seeknocomment($key, $move) {
288
		$go = ($move > 0) ? 1 : -1;
289
		for ($i = $key + 1; abs($key - $i) - 1 < abs($move); $i += $go) {
290
			if (!isset($this->tokens[$i])) {
291
				return;
292
			}
293
			if ($this->tokens[$i][0] == COMMENT) {
294
				$move += 1;
295
				continue;
296
			}
297
			return $this->tokens[$i][0];
298
		}
299
	}
300
301
	/**
302
	 * Converts $this->css array to a raw array ($this->tokens)
303
	 * @param string $default_media default @media to add to selectors without any @media
304
	 * @access private
305
	 * @version 1.0
306
	 */
307
	function _convert_raw_css($default_media='') {
308
		$this->tokens = array();
309
310
		foreach ($this->css as $medium => $val) {
311
			if ($this->parser->get_cfg('sort_selectors'))
312
				ksort($val);
313 View Code Duplication
			if (intval($medium) < DEFAULT_AT) {
314
				$this->parser->_add_token(AT_START, $medium, true);
315
			}
316
			elseif ($default_media) {
317
				$this->parser->_add_token(AT_START, $default_media, true);
318
			}
319
320
			foreach ($val as $selector => $vali) {
321
				if ($this->parser->get_cfg('sort_properties'))
322
					ksort($vali);
323
				$this->parser->_add_token(SEL_START, $selector, true);
324
325
				foreach ($vali as $property => $valj) {
326
					$this->parser->_add_token(PROPERTY, $property, true);
327
					$this->parser->_add_token(VALUE, $valj, true);
328
				}
329
330
				$this->parser->_add_token(SEL_END, $selector, true);
331
			}
332
333 View Code Duplication
			if (intval($medium) < DEFAULT_AT) {
334
				$this->parser->_add_token(AT_END, $medium, true);
335
			}
336
			elseif ($default_media) {
337
				$this->parser->_add_token(AT_END, $default_media, true);
338
			}
339
		}
340
	}
341
342
	/**
343
	 * Same as htmlspecialchars, only that chars are not replaced if $plain !== true. This makes  print_code() cleaner.
344
	 * @param string $string
345
	 * @param bool $plain
346
	 * @return string
347
	 * @see csstidy_print::_print()
348
	 * @access private
349
	 * @version 1.0
350
	 */
351
	function _htmlsp($string, $plain) {
352
		if (!$plain) {
353
			return htmlspecialchars($string, ENT_QUOTES, 'utf-8');
354
		}
355
		return $string;
356
	}
357
358
	/**
359
	 * Get compression ratio
360
	 * @access public
361
	 * @return float
362
	 * @version 1.2
363
	 */
364
	function get_ratio() {
365
		if (!$this->output_css_plain) {
366
			$this->formatted();
367
		}
368
		return round((strlen($this->input_css) - strlen($this->output_css_plain)) / strlen($this->input_css), 3) * 100;
369
	}
370
371
	/**
372
	 * Get difference between the old and new code in bytes and prints the code if necessary.
373
	 * @access public
374
	 * @return string
375
	 * @version 1.1
376
	 */
377
	function get_diff() {
378
		if (!$this->output_css_plain) {
379
			$this->formatted();
380
		}
381
382
		$diff = strlen($this->output_css_plain) - strlen($this->input_css);
383
384
		if ($diff > 0) {
385
			return '+' . $diff;
386
		} elseif ($diff == 0) {
387
			return '+-' . $diff;
388
		}
389
390
		return $diff;
391
	}
392
393
	/**
394
	 * Get the size of either input or output CSS in KB
395
	 * @param string $loc default is "output"
396
	 * @access public
397
	 * @return integer
398
	 * @version 1.0
399
	 */
400
	function size($loc = 'output') {
401
		if ($loc === 'output' && !$this->output_css) {
402
			$this->formatted();
403
		}
404
405
		if ($loc === 'input') {
406
			return (strlen($this->input_css) / 1000);
407
		} else {
408
			return (strlen($this->output_css_plain) / 1000);
409
		}
410
	}
411
412
}
413