Table.php 5.4 KB

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