| 1: | <?php
|
| 2: |
|
| 3: | class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector
|
| 4: | {
|
| 5: | |
| 6: | |
| 7: |
|
| 8: | private $context;
|
| 9: |
|
| 10: | |
| 11: | |
| 12: |
|
| 13: | private $config;
|
| 14: |
|
| 15: | |
| 16: | |
| 17: |
|
| 18: | private $attrValidator;
|
| 19: |
|
| 20: | |
| 21: | |
| 22: |
|
| 23: | private $removeNbsp;
|
| 24: |
|
| 25: | |
| 26: | |
| 27: |
|
| 28: | private $removeNbspExceptions;
|
| 29: |
|
| 30: | |
| 31: | |
| 32: | |
| 33: |
|
| 34: | private $exclude;
|
| 35: |
|
| 36: | |
| 37: | |
| 38: | |
| 39: | |
| 40: |
|
| 41: | public function prepare($config, $context)
|
| 42: | {
|
| 43: | parent::prepare($config, $context);
|
| 44: | $this->config = $config;
|
| 45: | $this->context = $context;
|
| 46: | $this->removeNbsp = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp');
|
| 47: | $this->removeNbspExceptions = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions');
|
| 48: | $this->exclude = $config->get('AutoFormat.RemoveEmpty.Predicate');
|
| 49: | foreach ($this->exclude as $key => $attrs) {
|
| 50: | if (!is_array($attrs)) {
|
| 51: |
|
| 52: | $this->exclude[$key] = explode(';', $attrs);
|
| 53: | }
|
| 54: | }
|
| 55: | $this->attrValidator = new HTMLPurifier_AttrValidator();
|
| 56: | }
|
| 57: |
|
| 58: | |
| 59: | |
| 60: |
|
| 61: | public function handleElement(&$token)
|
| 62: | {
|
| 63: | if (!$token instanceof HTMLPurifier_Token_Start) {
|
| 64: | return;
|
| 65: | }
|
| 66: | $next = false;
|
| 67: | $deleted = 1;
|
| 68: | for ($i = count($this->inputZipper->back) - 1; $i >= 0; $i--, $deleted++) {
|
| 69: | $next = $this->inputZipper->back[$i];
|
| 70: | if ($next instanceof HTMLPurifier_Token_Text) {
|
| 71: | if ($next->is_whitespace) {
|
| 72: | continue;
|
| 73: | }
|
| 74: | if ($this->removeNbsp && !isset($this->removeNbspExceptions[$token->name])) {
|
| 75: | $plain = str_replace("\xC2\xA0", "", $next->data);
|
| 76: | $isWsOrNbsp = $plain === '' || ctype_space($plain);
|
| 77: | if ($isWsOrNbsp) {
|
| 78: | continue;
|
| 79: | }
|
| 80: | }
|
| 81: | }
|
| 82: | break;
|
| 83: | }
|
| 84: | if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) {
|
| 85: | $this->attrValidator->validateToken($token, $this->config, $this->context);
|
| 86: | $token->armor['ValidateAttributes'] = true;
|
| 87: | if (isset($this->exclude[$token->name])) {
|
| 88: | $r = true;
|
| 89: | foreach ($this->exclude[$token->name] as $elem) {
|
| 90: | if (!isset($token->attr[$elem])) $r = false;
|
| 91: | }
|
| 92: | if ($r) return;
|
| 93: | }
|
| 94: | if (isset($token->attr['id']) || isset($token->attr['name'])) {
|
| 95: | return;
|
| 96: | }
|
| 97: | $token = $deleted + 1;
|
| 98: | for ($b = 0, $c = count($this->inputZipper->front); $b < $c; $b++) {
|
| 99: | $prev = $this->inputZipper->front[$b];
|
| 100: | if ($prev instanceof HTMLPurifier_Token_Text && $prev->is_whitespace) {
|
| 101: | continue;
|
| 102: | }
|
| 103: | break;
|
| 104: | }
|
| 105: |
|
| 106: | $this->rewindOffset($b+$deleted);
|
| 107: | return;
|
| 108: | }
|
| 109: | }
|
| 110: | }
|
| 111: |
|
| 112: |
|
| 113: | |