source: trunk/include/smarty/libs/sysplugins/smarty_internal_compilebase.php @ 23384

Last change on this file since 23384 was 23384, checked in by rvelices, 12 years ago

smarty 3 - first pass for tests

File size: 6.3 KB
Line 
1<?php
2/**
3 * Smarty Internal Plugin CompileBase
4 *
5 * @package Smarty
6 * @subpackage Compiler
7 * @author Uwe Tews
8 */
9
10/**
11 * This class does extend all internal compile plugins
12 *
13 * @package Smarty
14 * @subpackage Compiler
15 */
16abstract class Smarty_Internal_CompileBase {
17
18    /**
19     * Array of names of required attribute required by tag
20     *
21     * @var array
22     */
23    public $required_attributes = array();
24    /**
25     * Array of names of optional attribute required by tag
26     * use array('_any') if there is no restriction of attributes names
27     *
28     * @var array
29     */
30    public $optional_attributes = array();
31    /**
32     * Shorttag attribute order defined by its names
33     *
34     * @var array
35     */
36    public $shorttag_order = array();
37    /**
38     * Array of names of valid option flags
39     *
40     * @var array
41     */
42    public $option_flags = array('nocache');
43
44    /**
45     * This function checks if the attributes passed are valid
46     *
47     * The attributes passed for the tag to compile are checked against the list of required and
48     * optional attributes. Required attributes must be present. Optional attributes are check against
49     * the corresponding list. The keyword '_any' specifies that any attribute will be accepted
50     * as valid
51     *
52     * @param object $compiler   compiler object
53     * @param array  $attributes attributes applied to the tag
54     * @return array of mapped attributes for further processing
55     */
56    public function getAttributes($compiler, $attributes)
57    {
58        $_indexed_attr = array();
59        // loop over attributes
60        foreach ($attributes as $key => $mixed) {
61            // shorthand ?
62            if (!is_array($mixed)) {
63                // option flag ?
64                if (in_array(trim($mixed, '\'"'), $this->option_flags)) {
65                    $_indexed_attr[trim($mixed, '\'"')] = true;
66                    // shorthand attribute ?
67                } else if (isset($this->shorttag_order[$key])) {
68                    $_indexed_attr[$this->shorttag_order[$key]] = $mixed;
69                } else {
70                    // too many shorthands
71                    $compiler->trigger_template_error('too many shorthand attributes', $compiler->lex->taglineno);
72                }
73                // named attribute
74            } else {
75                $kv = each($mixed);
76                // option flag?
77                if (in_array($kv['key'], $this->option_flags)) {
78                    if (is_bool($kv['value'])) {
79                        $_indexed_attr[$kv['key']] = $kv['value'];
80                    } else if (is_string($kv['value']) && in_array(trim($kv['value'], '\'"'), array('true', 'false'))) {
81                        if (trim($kv['value']) == 'true') {
82                            $_indexed_attr[$kv['key']] = true;
83                        } else {
84                            $_indexed_attr[$kv['key']] = false;
85                        }
86                    } else if (is_numeric($kv['value']) && in_array($kv['value'], array(0, 1))) {
87                        if ($kv['value'] == 1) {
88                            $_indexed_attr[$kv['key']] = true;
89                        } else {
90                            $_indexed_attr[$kv['key']] = false;
91                        }
92                    } else {
93                        $compiler->trigger_template_error("illegal value of option flag \"{$kv['key']}\"", $compiler->lex->taglineno);
94                    }
95                    // must be named attribute
96                } else {
97                    reset($mixed);
98                    $_indexed_attr[key($mixed)] = $mixed[key($mixed)];
99                }
100            }
101        }
102        // check if all required attributes present
103        foreach ($this->required_attributes as $attr) {
104            if (!array_key_exists($attr, $_indexed_attr)) {
105                $compiler->trigger_template_error("missing \"" . $attr . "\" attribute", $compiler->lex->taglineno);
106            }
107        }
108        // check for unallowed attributes
109        if ($this->optional_attributes != array('_any')) {
110            $tmp_array = array_merge($this->required_attributes, $this->optional_attributes, $this->option_flags);
111            foreach ($_indexed_attr as $key => $dummy) {
112                if (!in_array($key, $tmp_array) && $key !== 0) {
113                    $compiler->trigger_template_error("unexpected \"" . $key . "\" attribute", $compiler->lex->taglineno);
114                }
115            }
116        }
117        // default 'false' for all option flags not set
118        foreach ($this->option_flags as $flag) {
119            if (!isset($_indexed_attr[$flag])) {
120                $_indexed_attr[$flag] = false;
121            }
122        }
123
124        return $_indexed_attr;
125    }
126
127    /**
128     * Push opening tag name on stack
129     *
130     * Optionally additional data can be saved on stack
131     *
132     * @param object    $compiler   compiler object
133     * @param string    $openTag    the opening tag's name
134     * @param mixed     $data       optional data saved
135     */
136    public function openTag($compiler, $openTag, $data = null)
137    {
138        array_push($compiler->_tag_stack, array($openTag, $data));
139    }
140
141    /**
142     * Pop closing tag
143     *
144     * Raise an error if this stack-top doesn't match with expected opening tags
145     *
146     * @param object       $compiler    compiler object
147     * @param array|string $expectedTag the expected opening tag names
148     * @return mixed any type the opening tag's name or saved data
149     */
150    public function closeTag($compiler, $expectedTag)
151    {
152        if (count($compiler->_tag_stack) > 0) {
153            // get stacked info
154            list($_openTag, $_data) = array_pop($compiler->_tag_stack);
155            // open tag must match with the expected ones
156            if (in_array($_openTag, (array) $expectedTag)) {
157                if (is_null($_data)) {
158                    // return opening tag
159                    return $_openTag;
160                } else {
161                    // return restored data
162                    return $_data;
163                }
164            }
165            // wrong nesting of tags
166            $compiler->trigger_template_error("unclosed {" . $_openTag . "} tag");
167            return;
168        }
169        // wrong nesting of tags
170        $compiler->trigger_template_error("unexpected closing tag", $compiler->lex->taglineno);
171        return;
172    }
173
174}
175
176?>
Note: See TracBrowser for help on using the repository browser.