HTMLPurifier 4.4.0
|
00001 <?php 00002 00006 class HTMLPurifier_ChildDef_List extends HTMLPurifier_ChildDef 00007 { 00008 public $type = 'list'; 00009 // lying a little bit, so that we can handle ul and ol ourselves 00010 // XXX: This whole business with 'wrap' is all a bit unsatisfactory 00011 public $elements = array('li' => true, 'ul' => true, 'ol' => true); 00012 public function validateChildren($tokens_of_children, $config, $context) { 00013 // Flag for subclasses 00014 $this->whitespace = false; 00015 00016 // if there are no tokens, delete parent node 00017 if (empty($tokens_of_children)) return false; 00018 00019 // the new set of children 00020 $result = array(); 00021 00022 // current depth into the nest 00023 $nesting = 0; 00024 00025 // a little sanity check to make sure it's not ALL whitespace 00026 $all_whitespace = true; 00027 00028 $seen_li = false; 00029 $need_close_li = false; 00030 00031 foreach ($tokens_of_children as $token) { 00032 if (!empty($token->is_whitespace)) { 00033 $result[] = $token; 00034 continue; 00035 } 00036 $all_whitespace = false; // phew, we're not talking about whitespace 00037 00038 if ($nesting == 1 && $need_close_li) { 00039 $result[] = new HTMLPurifier_Token_End('li'); 00040 $nesting--; 00041 $need_close_li = false; 00042 } 00043 00044 $is_child = ($nesting == 0); 00045 00046 if ($token instanceof HTMLPurifier_Token_Start) { 00047 $nesting++; 00048 } elseif ($token instanceof HTMLPurifier_Token_End) { 00049 $nesting--; 00050 } 00051 00052 if ($is_child) { 00053 if ($token->name === 'li') { 00054 // good 00055 $seen_li = true; 00056 } elseif ($token->name === 'ul' || $token->name === 'ol') { 00057 // we want to tuck this into the previous li 00058 $need_close_li = true; 00059 $nesting++; 00060 if (!$seen_li) { 00061 // create a new li element 00062 $result[] = new HTMLPurifier_Token_Start('li'); 00063 } else { 00064 // backtrack until </li> found 00065 while(true) { 00066 $t = array_pop($result); 00067 if ($t instanceof HTMLPurifier_Token_End) { 00068 // XXX actually, these invariants could very plausibly be violated 00069 // if we are doing silly things with modifying the set of allowed elements. 00070 // FORTUNATELY, it doesn't make a difference, since the allowed 00071 // elements are hard-coded here! 00072 if ($t->name !== 'li') { 00073 trigger_error("Only li present invariant violated in List ChildDef", E_USER_ERROR); 00074 return false; 00075 } 00076 break; 00077 } elseif ($t instanceof HTMLPurifier_Token_Empty) { // bleagh 00078 if ($t->name !== 'li') { 00079 trigger_error("Only li present invariant violated in List ChildDef", E_USER_ERROR); 00080 return false; 00081 } 00082 // XXX this should have a helper for it... 00083 $result[] = new HTMLPurifier_Token_Start('li', $t->attr, $t->line, $t->col, $t->armor); 00084 break; 00085 } else { 00086 if (!$t->is_whitespace) { 00087 trigger_error("Only whitespace present invariant violated in List ChildDef", E_USER_ERROR); 00088 return false; 00089 } 00090 } 00091 } 00092 } 00093 } else { 00094 // start wrapping (this doesn't precisely mimic 00095 // browser behavior, but what browsers do is kind of 00096 // hard to mimic in a standards compliant way 00097 // XXX Actually, this has no impact in practice, 00098 // because this gets handled earlier. Arguably, 00099 // we should rip out all of that processing 00100 $result[] = new HTMLPurifier_Token_Start('li'); 00101 $nesting++; 00102 $seen_li = true; 00103 $need_close_li = true; 00104 } 00105 } 00106 $result[] = $token; 00107 } 00108 if ($need_close_li) { 00109 $result[] = new HTMLPurifier_Token_End('li'); 00110 } 00111 if (empty($result)) return false; 00112 if ($all_whitespace) { 00113 return false; 00114 } 00115 if ($tokens_of_children == $result) return true; 00116 return $result; 00117 } 00118 } 00119 00120 // vim: et sw=4 sts=4