1<?php
2
3/**
4 * Transforms FONT tags to the proper form (SPAN with CSS styling)
5 *
6 * This transformation takes the three proprietary attributes of FONT and
7 * transforms them into their corresponding CSS attributes.  These are color,
8 * face, and size.
9 *
10 * @note Size is an interesting case because it doesn't map cleanly to CSS.
11 *       Thanks to
12 *       http://style.cleverchimp.com/font_size_intervals/altintervals.html
13 *       for reasonable mappings.
14 * @warning This doesn't work completely correctly; specifically, this
15 *          TagTransform operates before well-formedness is enforced, so
16 *          the "active formatting elements" algorithm doesn't get applied.
17 */
18class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform
19{
20    /**
21     * @type string
22     */
23    public $transform_to = 'span';
24
25    /**
26     * @type array
27     */
28    protected $_size_lookup = array(
29        '0' => 'xx-small',
30        '1' => 'xx-small',
31        '2' => 'small',
32        '3' => 'medium',
33        '4' => 'large',
34        '5' => 'x-large',
35        '6' => 'xx-large',
36        '7' => '300%',
37        '-1' => 'smaller',
38        '-2' => '60%',
39        '+1' => 'larger',
40        '+2' => '150%',
41        '+3' => '200%',
42        '+4' => '300%'
43    );
44
45    /**
46     * @param HTMLPurifier_Token_Tag $tag
47     * @param HTMLPurifier_Config $config
48     * @param HTMLPurifier_Context $context
49     * @return HTMLPurifier_Token_End|string
50     */
51    public function transform($tag, $config, $context)
52    {
53        if ($tag instanceof HTMLPurifier_Token_End) {
54            $new_tag = clone $tag;
55            $new_tag->name = $this->transform_to;
56            return $new_tag;
57        }
58
59        $attr = $tag->attr;
60        $prepend_style = '';
61
62        // handle color transform
63        if (isset($attr['color'])) {
64            $prepend_style .= 'color:' . $attr['color'] . ';';
65            unset($attr['color']);
66        }
67
68        // handle face transform
69        if (isset($attr['face'])) {
70            $prepend_style .= 'font-family:' . $attr['face'] . ';';
71            unset($attr['face']);
72        }
73
74        // handle size transform
75        if (isset($attr['size'])) {
76            // normalize large numbers
77            if ($attr['size'] !== '') {
78                if ($attr['size'][0] == '+' || $attr['size'][0] == '-') {
79                    $size = (int)$attr['size'];
80                    if ($size < -2) {
81                        $attr['size'] = '-2';
82                    }
83                    if ($size > 4) {
84                        $attr['size'] = '+4';
85                    }
86                } else {
87                    $size = (int)$attr['size'];
88                    if ($size > 7) {
89                        $attr['size'] = '7';
90                    }
91                }
92            }
93            if (isset($this->_size_lookup[$attr['size']])) {
94                $prepend_style .= 'font-size:' .
95                    $this->_size_lookup[$attr['size']] . ';';
96            }
97            unset($attr['size']);
98        }
99
100        if ($prepend_style) {
101            $attr['style'] = isset($attr['style']) ?
102                $prepend_style . $attr['style'] :
103                $prepend_style;
104        }
105
106        $new_tag = clone $tag;
107        $new_tag->name = $this->transform_to;
108        $new_tag->attr = $attr;
109
110        return $new_tag;
111    }
112}
113
114// vim: et sw=4 sts=4
115