Fix bug in background-position with center keyword.
[htmlpurifier.git] / library / HTMLPurifier / AttrDef / CSS / BackgroundPosition.php
blobfae82eaec8093db4c2de72db706110c58f7cb97c
1 <?php
3 /* W3C says:
4 [ // adjective and number must be in correct order, even if
5 // you could switch them without introducing ambiguity.
6 // some browsers support that syntax
8 <percentage> | <length> | left | center | right
11 <percentage> | <length> | top | center | bottom
13 ] |
14 [ // this signifies that the vertical and horizontal adjectives
15 // can be arbitrarily ordered, however, there can only be two,
16 // one of each, or none at all
18 left | center | right
19 ] ||
21 top | center | bottom
24 top, left = 0%
25 center, (none) = 50%
26 bottom, right = 100%
29 /* QuirksMode says:
30 keyword + length/percentage must be ordered correctly, as per W3C
32 Internet Explorer and Opera, however, support arbitrary ordering. We
33 should fix it up.
35 Minor issue though, not strictly necessary.
38 // control freaks may appreciate the ability to convert these to
39 // percentages or something, but it's not necessary
41 /**
42 * Validates the value of background-position.
44 class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
47 protected $length;
48 protected $percentage;
50 public function __construct() {
51 $this->length = new HTMLPurifier_AttrDef_CSS_Length();
52 $this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage();
55 public function validate($string, $config, $context) {
56 $string = $this->parseCDATA($string);
57 $bits = explode(' ', $string);
59 $keywords = array();
60 $keywords['h'] = false; // left, right
61 $keywords['v'] = false; // top, bottom
62 $keywords['ch'] = false; // center (first word)
63 $keywords['cv'] = false; // center (second word)
64 $measures = array();
66 $i = 0;
68 $lookup = array(
69 'top' => 'v',
70 'bottom' => 'v',
71 'left' => 'h',
72 'right' => 'h',
73 'center' => 'c'
76 foreach ($bits as $bit) {
77 if ($bit === '') continue;
79 // test for keyword
80 $lbit = ctype_lower($bit) ? $bit : strtolower($bit);
81 if (isset($lookup[$lbit])) {
82 $status = $lookup[$lbit];
83 if ($status == 'c') {
84 if ($i == 0) {
85 $status = 'ch';
86 } else {
87 $status = 'cv';
90 $keywords[$status] = $lbit;
91 $i++;
94 // test for length
95 $r = $this->length->validate($bit, $config, $context);
96 if ($r !== false) {
97 $measures[] = $r;
98 $i++;
101 // test for percentage
102 $r = $this->percentage->validate($bit, $config, $context);
103 if ($r !== false) {
104 $measures[] = $r;
105 $i++;
110 if (!$i) return false; // no valid values were caught
112 $ret = array();
114 // first keyword
115 if ($keywords['h']) $ret[] = $keywords['h'];
116 elseif ($keywords['ch']) {
117 $ret[] = $keywords['ch'];
118 $keywords['cv'] = false; // prevent re-use: center = center center
120 elseif (count($measures)) $ret[] = array_shift($measures);
122 if ($keywords['v']) $ret[] = $keywords['v'];
123 elseif ($keywords['cv']) $ret[] = $keywords['cv'];
124 elseif (count($measures)) $ret[] = array_shift($measures);
126 if (empty($ret)) return false;
127 return implode(' ', $ret);
133 // vim: et sw=4 sts=4