See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]
1 <?php 2 3 /** 4 * Abstract class for a set of proprietary modules that clean up (tidy) 5 * poorly written HTML. 6 * @todo Figure out how to protect some of these methods/properties 7 */ 8 class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule 9 { 10 /** 11 * List of supported levels. 12 * Index zero is a special case "no fixes" level. 13 * @type array 14 */ 15 public $levels = array(0 => 'none', 'light', 'medium', 'heavy'); 16 17 /** 18 * Default level to place all fixes in. 19 * Disabled by default. 20 * @type string 21 */ 22 public $defaultLevel = null; 23 24 /** 25 * Lists of fixes used by getFixesForLevel(). 26 * Format is: 27 * HTMLModule_Tidy->fixesForLevel[$level] = array('fix-1', 'fix-2'); 28 * @type array 29 */ 30 public $fixesForLevel = array( 31 'light' => array(), 32 'medium' => array(), 33 'heavy' => array() 34 ); 35 36 /** 37 * Lazy load constructs the module by determining the necessary 38 * fixes to create and then delegating to the populate() function. 39 * @param HTMLPurifier_Config $config 40 * @todo Wildcard matching and error reporting when an added or 41 * subtracted fix has no effect. 42 */ 43 public function setup($config) 44 { 45 // create fixes, initialize fixesForLevel 46 $fixes = $this->makeFixes(); 47 $this->makeFixesForLevel($fixes); 48 49 // figure out which fixes to use 50 $level = $config->get('HTML.TidyLevel'); 51 $fixes_lookup = $this->getFixesForLevel($level); 52 53 // get custom fix declarations: these need namespace processing 54 $add_fixes = $config->get('HTML.TidyAdd'); 55 $remove_fixes = $config->get('HTML.TidyRemove'); 56 57 foreach ($fixes as $name => $fix) { 58 // needs to be refactored a little to implement globbing 59 if (isset($remove_fixes[$name]) || 60 (!isset($add_fixes[$name]) && !isset($fixes_lookup[$name]))) { 61 unset($fixes[$name]); 62 } 63 } 64 65 // populate this module with necessary fixes 66 $this->populate($fixes); 67 } 68 69 /** 70 * Retrieves all fixes per a level, returning fixes for that specific 71 * level as well as all levels below it. 72 * @param string $level level identifier, see $levels for valid values 73 * @return array Lookup up table of fixes 74 */ 75 public function getFixesForLevel($level) 76 { 77 if ($level == $this->levels[0]) { 78 return array(); 79 } 80 $activated_levels = array(); 81 for ($i = 1, $c = count($this->levels); $i < $c; $i++) { 82 $activated_levels[] = $this->levels[$i]; 83 if ($this->levels[$i] == $level) { 84 break; 85 } 86 } 87 if ($i == $c) { 88 trigger_error( 89 'Tidy level ' . htmlspecialchars($level) . ' not recognized', 90 E_USER_WARNING 91 ); 92 return array(); 93 } 94 $ret = array(); 95 foreach ($activated_levels as $level) { 96 foreach ($this->fixesForLevel[$level] as $fix) { 97 $ret[$fix] = true; 98 } 99 } 100 return $ret; 101 } 102 103 /** 104 * Dynamically populates the $fixesForLevel member variable using 105 * the fixes array. It may be custom overloaded, used in conjunction 106 * with $defaultLevel, or not used at all. 107 * @param array $fixes 108 */ 109 public function makeFixesForLevel($fixes) 110 { 111 if (!isset($this->defaultLevel)) { 112 return; 113 } 114 if (!isset($this->fixesForLevel[$this->defaultLevel])) { 115 trigger_error( 116 'Default level ' . $this->defaultLevel . ' does not exist', 117 E_USER_ERROR 118 ); 119 return; 120 } 121 $this->fixesForLevel[$this->defaultLevel] = array_keys($fixes); 122 } 123 124 /** 125 * Populates the module with transforms and other special-case code 126 * based on a list of fixes passed to it 127 * @param array $fixes Lookup table of fixes to activate 128 */ 129 public function populate($fixes) 130 { 131 foreach ($fixes as $name => $fix) { 132 // determine what the fix is for 133 list($type, $params) = $this->getFixType($name); 134 switch ($type) { 135 case 'attr_transform_pre': 136 case 'attr_transform_post': 137 $attr = $params['attr']; 138 if (isset($params['element'])) { 139 $element = $params['element']; 140 if (empty($this->info[$element])) { 141 $e = $this->addBlankElement($element); 142 } else { 143 $e = $this->info[$element]; 144 } 145 } else { 146 $type = "info_$type"; 147 $e = $this; 148 } 149 $e->{$type}[$attr] = $fix; 150 break; 151 case 'tag_transform': 152 $this->info_tag_transform[$params['element']] = $fix; 153 break; 154 case 'child': 155 case 'content_model_type': 156 $element = $params['element']; 157 if (empty($this->info[$element])) { 158 $e = $this->addBlankElement($element); 159 } else { 160 $e = $this->info[$element]; 161 } 162 $e->$type = $fix; 163 break; 164 default: 165 trigger_error("Fix type $type not supported", E_USER_ERROR); 166 break; 167 } 168 } 169 } 170 171 /** 172 * Parses a fix name and determines what kind of fix it is, as well 173 * as other information defined by the fix 174 * @param $name String name of fix 175 * @return array(string $fix_type, array $fix_parameters) 176 * @note $fix_parameters is type dependant, see populate() for usage 177 * of these parameters 178 */ 179 public function getFixType($name) 180 { 181 // parse it 182 $property = $attr = null; 183 if (strpos($name, '#') !== false) { 184 list($name, $property) = explode('#', $name); 185 } 186 if (strpos($name, '@') !== false) { 187 list($name, $attr) = explode('@', $name); 188 } 189 190 // figure out the parameters 191 $params = array(); 192 if ($name !== '') { 193 $params['element'] = $name; 194 } 195 if (!is_null($attr)) { 196 $params['attr'] = $attr; 197 } 198 199 // special case: attribute transform 200 if (!is_null($attr)) { 201 if (is_null($property)) { 202 $property = 'pre'; 203 } 204 $type = 'attr_transform_' . $property; 205 return array($type, $params); 206 } 207 208 // special case: tag transform 209 if (is_null($property)) { 210 return array('tag_transform', $params); 211 } 212 213 return array($property, $params); 214 215 } 216 217 /** 218 * Defines all fixes the module will perform in a compact 219 * associative array of fix name to fix implementation. 220 * @return array 221 */ 222 public function makeFixes() 223 { 224 } 225 } 226 227 // vim: et sw=4 sts=4
title
Description
Body
title
Description
Body
title
Description
Body
title
Body