| 1: | <?php | 
| 2: |  | 
| 3: |  | 
| 4: |  | 
| 5: |  | 
| 6: |  | 
| 7: |  | 
| 8: |  | 
| 9: | class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector | 
| 10: | { | 
| 11: |  | 
| 12: |  | 
| 13: |  | 
| 14: | public $name = 'AutoParagraph'; | 
| 15: |  | 
| 16: |  | 
| 17: |  | 
| 18: |  | 
| 19: | public $needed = array('p'); | 
| 20: |  | 
| 21: |  | 
| 22: |  | 
| 23: |  | 
| 24: | private function _pStart() | 
| 25: | { | 
| 26: | $par = new HTMLPurifier_Token_Start('p'); | 
| 27: | $par->armor['MakeWellFormed_TagClosedError'] = true; | 
| 28: | return $par; | 
| 29: | } | 
| 30: |  | 
| 31: |  | 
| 32: |  | 
| 33: |  | 
| 34: | public function handleText(&$token) | 
| 35: | { | 
| 36: | $text = $token->data; | 
| 37: |  | 
| 38: | if ($this->allowsElement('p')) { | 
| 39: | if (empty($this->currentNesting) || strpos($text, "\n\n") !== false) { | 
| 40: |  | 
| 41: |  | 
| 42: |  | 
| 43: |  | 
| 44: |  | 
| 45: | $i = $nesting = null; | 
| 46: | if (!$this->forwardUntilEndToken($i, $current, $nesting) && $token->is_whitespace) { | 
| 47: |  | 
| 48: |  | 
| 49: |  | 
| 50: | } else { | 
| 51: | if (!$token->is_whitespace || $this->_isInline($current)) { | 
| 52: |  | 
| 53: |  | 
| 54: |  | 
| 55: |  | 
| 56: |  | 
| 57: |  | 
| 58: |  | 
| 59: |  | 
| 60: | $token = array($this->_pStart()); | 
| 61: | $this->_splitText($text, $token); | 
| 62: | } else { | 
| 63: |  | 
| 64: |  | 
| 65: | } | 
| 66: | } | 
| 67: | } else { | 
| 68: |  | 
| 69: |  | 
| 70: |  | 
| 71: |  | 
| 72: |  | 
| 73: | if ($this->_pLookAhead()) { | 
| 74: |  | 
| 75: |  | 
| 76: |  | 
| 77: |  | 
| 78: |  | 
| 79: |  | 
| 80: | $token = array($this->_pStart(), $token); | 
| 81: | } else { | 
| 82: |  | 
| 83: |  | 
| 84: |  | 
| 85: |  | 
| 86: |  | 
| 87: | } | 
| 88: | } | 
| 89: |  | 
| 90: | } elseif (!empty($this->currentNesting) && | 
| 91: | $this->currentNesting[count($this->currentNesting) - 1]->name == 'p') { | 
| 92: |  | 
| 93: |  | 
| 94: |  | 
| 95: |  | 
| 96: |  | 
| 97: | $token = array(); | 
| 98: | $this->_splitText($text, $token); | 
| 99: |  | 
| 100: | } else { | 
| 101: |  | 
| 102: |  | 
| 103: |  | 
| 104: |  | 
| 105: |  | 
| 106: | } | 
| 107: | } | 
| 108: |  | 
| 109: |  | 
| 110: |  | 
| 111: |  | 
| 112: | public function handleElement(&$token) | 
| 113: | { | 
| 114: |  | 
| 115: |  | 
| 116: | if ($this->allowsElement('p')) { | 
| 117: | if (!empty($this->currentNesting)) { | 
| 118: | if ($this->_isInline($token)) { | 
| 119: |  | 
| 120: |  | 
| 121: |  | 
| 122: |  | 
| 123: | $i = null; | 
| 124: | $this->backward($i, $prev); | 
| 125: |  | 
| 126: | if (!$prev instanceof HTMLPurifier_Token_Start) { | 
| 127: |  | 
| 128: | if ($prev instanceof HTMLPurifier_Token_Text && | 
| 129: | substr($prev->data, -2) === "\n\n" | 
| 130: | ) { | 
| 131: |  | 
| 132: |  | 
| 133: |  | 
| 134: | $token = array($this->_pStart(), $token); | 
| 135: | } else { | 
| 136: |  | 
| 137: |  | 
| 138: |  | 
| 139: |  | 
| 140: |  | 
| 141: |  | 
| 142: | } | 
| 143: | } else { | 
| 144: |  | 
| 145: |  | 
| 146: |  | 
| 147: | if ($this->_pLookAhead()) { | 
| 148: |  | 
| 149: |  | 
| 150: | $token = array($this->_pStart(), $token); | 
| 151: | } else { | 
| 152: |  | 
| 153: |  | 
| 154: |  | 
| 155: |  | 
| 156: |  | 
| 157: | } | 
| 158: | } | 
| 159: | } else { | 
| 160: |  | 
| 161: |  | 
| 162: | } | 
| 163: | } else { | 
| 164: | if ($this->_isInline($token)) { | 
| 165: |  | 
| 166: |  | 
| 167: |  | 
| 168: |  | 
| 169: | $token = array($this->_pStart(), $token); | 
| 170: | } else { | 
| 171: |  | 
| 172: |  | 
| 173: | } | 
| 174: |  | 
| 175: | $i = null; | 
| 176: | if ($this->backward($i, $prev)) { | 
| 177: | if (!$prev instanceof HTMLPurifier_Token_Text) { | 
| 178: |  | 
| 179: |  | 
| 180: |  | 
| 181: |  | 
| 182: | if (!is_array($token)) { | 
| 183: | $token = array($token); | 
| 184: | } | 
| 185: | array_unshift($token, new HTMLPurifier_Token_Text("\n\n")); | 
| 186: | } else { | 
| 187: |  | 
| 188: |  | 
| 189: |  | 
| 190: |  | 
| 191: |  | 
| 192: |  | 
| 193: | } | 
| 194: | } | 
| 195: | } | 
| 196: | } else { | 
| 197: |  | 
| 198: |  | 
| 199: |  | 
| 200: |  | 
| 201: | } | 
| 202: | } | 
| 203: |  | 
| 204: |  | 
| 205: |  | 
| 206: |  | 
| 207: |  | 
| 208: |  | 
| 209: |  | 
| 210: |  | 
| 211: |  | 
| 212: | private function _splitText($data, &$result) | 
| 213: | { | 
| 214: | $raw_paragraphs = explode("\n\n", $data); | 
| 215: | $paragraphs = array(); | 
| 216: | $needs_start = false; | 
| 217: | $needs_end = false; | 
| 218: |  | 
| 219: | $c = count($raw_paragraphs); | 
| 220: | if ($c == 1) { | 
| 221: |  | 
| 222: |  | 
| 223: | $result[] = new HTMLPurifier_Token_Text($data); | 
| 224: | return; | 
| 225: | } | 
| 226: | for ($i = 0; $i < $c; $i++) { | 
| 227: | $par = $raw_paragraphs[$i]; | 
| 228: | if (trim($par) !== '') { | 
| 229: | $paragraphs[] = $par; | 
| 230: | } else { | 
| 231: | if ($i == 0) { | 
| 232: |  | 
| 233: | if (empty($result)) { | 
| 234: |  | 
| 235: |  | 
| 236: |  | 
| 237: |  | 
| 238: | $result[] = new HTMLPurifier_Token_End('p'); | 
| 239: | $result[] = new HTMLPurifier_Token_Text("\n\n"); | 
| 240: |  | 
| 241: |  | 
| 242: |  | 
| 243: |  | 
| 244: |  | 
| 245: | $needs_start = true; | 
| 246: | } else { | 
| 247: |  | 
| 248: |  | 
| 249: |  | 
| 250: | array_unshift($result, new HTMLPurifier_Token_Text("\n\n")); | 
| 251: | } | 
| 252: | } elseif ($i + 1 == $c) { | 
| 253: |  | 
| 254: |  | 
| 255: | $needs_end = true; | 
| 256: | } | 
| 257: | } | 
| 258: | } | 
| 259: |  | 
| 260: |  | 
| 261: |  | 
| 262: | if (empty($paragraphs)) { | 
| 263: | return; | 
| 264: | } | 
| 265: |  | 
| 266: |  | 
| 267: | if ($needs_start) { | 
| 268: | $result[] = $this->_pStart(); | 
| 269: | } | 
| 270: |  | 
| 271: |  | 
| 272: | foreach ($paragraphs as $par) { | 
| 273: | $result[] = new HTMLPurifier_Token_Text($par); | 
| 274: | $result[] = new HTMLPurifier_Token_End('p'); | 
| 275: | $result[] = new HTMLPurifier_Token_Text("\n\n"); | 
| 276: | $result[] = $this->_pStart(); | 
| 277: | } | 
| 278: |  | 
| 279: |  | 
| 280: |  | 
| 281: |  | 
| 282: | array_pop($result); | 
| 283: |  | 
| 284: |  | 
| 285: |  | 
| 286: | if (!$needs_end) { | 
| 287: | array_pop($result); | 
| 288: | array_pop($result); | 
| 289: | } | 
| 290: | } | 
| 291: |  | 
| 292: |  | 
| 293: |  | 
| 294: |  | 
| 295: |  | 
| 296: |  | 
| 297: |  | 
| 298: | private function _isInline($token) | 
| 299: | { | 
| 300: | return isset($this->htmlDefinition->info['p']->child->elements[$token->name]); | 
| 301: | } | 
| 302: |  | 
| 303: |  | 
| 304: |  | 
| 305: |  | 
| 306: |  | 
| 307: |  | 
| 308: | private function _pLookAhead() | 
| 309: | { | 
| 310: | if ($this->currentToken instanceof HTMLPurifier_Token_Start) { | 
| 311: | $nesting = 1; | 
| 312: | } else { | 
| 313: | $nesting = 0; | 
| 314: | } | 
| 315: | $ok = false; | 
| 316: | $i = null; | 
| 317: | while ($this->forwardUntilEndToken($i, $current, $nesting)) { | 
| 318: | $result = $this->_checkNeedsP($current); | 
| 319: | if ($result !== null) { | 
| 320: | $ok = $result; | 
| 321: | break; | 
| 322: | } | 
| 323: | } | 
| 324: | return $ok; | 
| 325: | } | 
| 326: |  | 
| 327: |  | 
| 328: |  | 
| 329: |  | 
| 330: |  | 
| 331: |  | 
| 332: |  | 
| 333: | private function _checkNeedsP($current) | 
| 334: | { | 
| 335: | if ($current instanceof HTMLPurifier_Token_Start) { | 
| 336: | if (!$this->_isInline($current)) { | 
| 337: |  | 
| 338: |  | 
| 339: |  | 
| 340: | return false; | 
| 341: | } | 
| 342: | } elseif ($current instanceof HTMLPurifier_Token_Text) { | 
| 343: | if (strpos($current->data, "\n\n") !== false) { | 
| 344: |  | 
| 345: |  | 
| 346: | return true; | 
| 347: | } else { | 
| 348: |  | 
| 349: |  | 
| 350: | } | 
| 351: | } | 
| 352: | return null; | 
| 353: | } | 
| 354: | } | 
| 355: |  | 
| 356: |  | 
| 357: |  |