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