1: <?php
2:
3: /**
4: * Definition for tables
5: */
6: class HTMLPurifier_ChildDef_Table extends HTMLPurifier_ChildDef
7: {
8: public $allow_empty = false;
9: public $type = 'table';
10: public $elements = array('tr' => true, 'tbody' => true, 'thead' => true,
11: 'tfoot' => true, 'caption' => true, 'colgroup' => true, 'col' => true);
12: public function __construct() {}
13: public function validateChildren($tokens_of_children, $config, $context) {
14: if (empty($tokens_of_children)) return false;
15:
16: // this ensures that the loop gets run one last time before closing
17: // up. It's a little bit of a hack, but it works! Just make sure you
18: // get rid of the token later.
19: $tokens_of_children[] = false;
20:
21: // only one of these elements is allowed in a table
22: $caption = false;
23: $thead = false;
24: $tfoot = false;
25:
26: // as many of these as you want
27: $cols = array();
28: $content = array();
29:
30: $nesting = 0; // current depth so we can determine nodes
31: $is_collecting = false; // are we globbing together tokens to package
32: // into one of the collectors?
33: $collection = array(); // collected nodes
34: $tag_index = 0; // the first node might be whitespace,
35: // so this tells us where the start tag is
36:
37: foreach ($tokens_of_children as $token) {
38: $is_child = ($nesting == 0);
39:
40: if ($token === false) {
41: // terminating sequence started
42: } elseif ($token instanceof HTMLPurifier_Token_Start) {
43: $nesting++;
44: } elseif ($token instanceof HTMLPurifier_Token_End) {
45: $nesting--;
46: }
47:
48: // handle node collection
49: if ($is_collecting) {
50: if ($is_child) {
51: // okay, let's stash the tokens away
52: // first token tells us the type of the collection
53: switch ($collection[$tag_index]->name) {
54: case 'tr':
55: case 'tbody':
56: $content[] = $collection;
57: break;
58: case 'caption':
59: if ($caption !== false) break;
60: $caption = $collection;
61: break;
62: case 'thead':
63: case 'tfoot':
64: // access the appropriate variable, $thead or $tfoot
65: $var = $collection[$tag_index]->name;
66: if ($$var === false) {
67: $$var = $collection;
68: } else {
69: // transmutate the first and less entries into
70: // tbody tags, and then put into content
71: $collection[$tag_index]->name = 'tbody';
72: $collection[count($collection)-1]->name = 'tbody';
73: $content[] = $collection;
74: }
75: break;
76: case 'colgroup':
77: $cols[] = $collection;
78: break;
79: }
80: $collection = array();
81: $is_collecting = false;
82: $tag_index = 0;
83: } else {
84: // add the node to the collection
85: $collection[] = $token;
86: }
87: }
88:
89: // terminate
90: if ($token === false) break;
91:
92: if ($is_child) {
93: // determine what we're dealing with
94: if ($token->name == 'col') {
95: // the only empty tag in the possie, we can handle it
96: // immediately
97: $cols[] = array_merge($collection, array($token));
98: $collection = array();
99: $tag_index = 0;
100: continue;
101: }
102: switch($token->name) {
103: case 'caption':
104: case 'colgroup':
105: case 'thead':
106: case 'tfoot':
107: case 'tbody':
108: case 'tr':
109: $is_collecting = true;
110: $collection[] = $token;
111: continue;
112: default:
113: if (!empty($token->is_whitespace)) {
114: $collection[] = $token;
115: $tag_index++;
116: }
117: continue;
118: }
119: }
120: }
121:
122: if (empty($content)) return false;
123:
124: $ret = array();
125: if ($caption !== false) $ret = array_merge($ret, $caption);
126: if ($cols !== false) foreach ($cols as $token_array) $ret = array_merge($ret, $token_array);
127: if ($thead !== false) $ret = array_merge($ret, $thead);
128: if ($tfoot !== false) $ret = array_merge($ret, $tfoot);
129: foreach ($content as $token_array) $ret = array_merge($ret, $token_array);
130: if (!empty($collection) && $is_collecting == false){
131: // grab the trailing space
132: $ret = array_merge($ret, $collection);
133: }
134:
135: array_pop($tokens_of_children); // remove phantom token
136:
137: return ($ret === $tokens_of_children) ? true : $ret;
138:
139: }
140: }
141:
142: // vim: et sw=4 sts=4
143: