Add vim modelines to all files.
[htmlpurifier.git] / library / HTMLPurifier / AttrDef / CSS / Font.php
blob699ee0b7012a6d1a5d951d7598ab528247b579b8
1 <?php
3 /**
4 * Validates shorthand CSS property font.
5 */
6 class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
9 /**
10 * Local copy of component validators.
12 * @note If we moved specific CSS property definitions to their own
13 * classes instead of having them be assembled at run time by
14 * CSSDefinition, this wouldn't be necessary. We'd instantiate
15 * our own copies.
17 protected $info = array();
19 public function __construct($config) {
20 $def = $config->getCSSDefinition();
21 $this->info['font-style'] = $def->info['font-style'];
22 $this->info['font-variant'] = $def->info['font-variant'];
23 $this->info['font-weight'] = $def->info['font-weight'];
24 $this->info['font-size'] = $def->info['font-size'];
25 $this->info['line-height'] = $def->info['line-height'];
26 $this->info['font-family'] = $def->info['font-family'];
29 public function validate($string, $config, $context) {
31 static $system_fonts = array(
32 'caption' => true,
33 'icon' => true,
34 'menu' => true,
35 'message-box' => true,
36 'small-caption' => true,
37 'status-bar' => true
40 // regular pre-processing
41 $string = $this->parseCDATA($string);
42 if ($string === '') return false;
44 // check if it's one of the keywords
45 $lowercase_string = strtolower($string);
46 if (isset($system_fonts[$lowercase_string])) {
47 return $lowercase_string;
50 $bits = explode(' ', $string); // bits to process
51 $stage = 0; // this indicates what we're looking for
52 $caught = array(); // which stage 0 properties have we caught?
53 $stage_1 = array('font-style', 'font-variant', 'font-weight');
54 $final = ''; // output
56 for ($i = 0, $size = count($bits); $i < $size; $i++) {
57 if ($bits[$i] === '') continue;
58 switch ($stage) {
60 // attempting to catch font-style, font-variant or font-weight
61 case 0:
62 foreach ($stage_1 as $validator_name) {
63 if (isset($caught[$validator_name])) continue;
64 $r = $this->info[$validator_name]->validate(
65 $bits[$i], $config, $context);
66 if ($r !== false) {
67 $final .= $r . ' ';
68 $caught[$validator_name] = true;
69 break;
72 // all three caught, continue on
73 if (count($caught) >= 3) $stage = 1;
74 if ($r !== false) break;
76 // attempting to catch font-size and perhaps line-height
77 case 1:
78 $found_slash = false;
79 if (strpos($bits[$i], '/') !== false) {
80 list($font_size, $line_height) =
81 explode('/', $bits[$i]);
82 if ($line_height === '') {
83 // ooh, there's a space after the slash!
84 $line_height = false;
85 $found_slash = true;
87 } else {
88 $font_size = $bits[$i];
89 $line_height = false;
91 $r = $this->info['font-size']->validate(
92 $font_size, $config, $context);
93 if ($r !== false) {
94 $final .= $r;
95 // attempt to catch line-height
96 if ($line_height === false) {
97 // we need to scroll forward
98 for ($j = $i + 1; $j < $size; $j++) {
99 if ($bits[$j] === '') continue;
100 if ($bits[$j] === '/') {
101 if ($found_slash) {
102 return false;
103 } else {
104 $found_slash = true;
105 continue;
108 $line_height = $bits[$j];
109 break;
111 } else {
112 // slash already found
113 $found_slash = true;
114 $j = $i;
116 if ($found_slash) {
117 $i = $j;
118 $r = $this->info['line-height']->validate(
119 $line_height, $config, $context);
120 if ($r !== false) {
121 $final .= '/' . $r;
124 $final .= ' ';
125 $stage = 2;
126 break;
128 return false;
130 // attempting to catch font-family
131 case 2:
132 $font_family =
133 implode(' ', array_slice($bits, $i, $size - $i));
134 $r = $this->info['font-family']->validate(
135 $font_family, $config, $context);
136 if ($r !== false) {
137 $final .= $r . ' ';
138 // processing completed successfully
139 return rtrim($final);
141 return false;
144 return false;
149 // vim: et sw=4 sts=4