Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   1  <?php
   2  
   3  class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector
   4  {
   5      /**
   6       * @type HTMLPurifier_Context
   7       */
   8      private $context;
   9  
  10      /**
  11       * @type HTMLPurifier_Config
  12       */
  13      private $config;
  14  
  15      /**
  16       * @type HTMLPurifier_AttrValidator
  17       */
  18      private $attrValidator;
  19  
  20      /**
  21       * @type bool
  22       */
  23      private $removeNbsp;
  24  
  25      /**
  26       * @type bool
  27       */
  28      private $removeNbspExceptions;
  29  
  30      /**
  31       * Cached contents of %AutoFormat.RemoveEmpty.Predicate
  32       * @type array
  33       */
  34      private $exclude;
  35  
  36      /**
  37       * @param HTMLPurifier_Config $config
  38       * @param HTMLPurifier_Context $context
  39       * @return void
  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                  // HACK, see HTMLPurifier/Printer/ConfigForm.php
  52                  $this->exclude[$key] = explode(';', $attrs);
  53              }
  54          }
  55          $this->attrValidator = new HTMLPurifier_AttrValidator();
  56      }
  57  
  58      /**
  59       * @param HTMLPurifier_Token $token
  60       */
  61      public function handleElement(&$token)
  62      {
  63          if (!$token instanceof HTMLPurifier_Token_Start) {
  64              return;
  65          }
  66          $next = false;
  67          $deleted = 1; // the current tag
  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              // This is safe because we removed the token that triggered this.
 106              $this->rewindOffset($b+$deleted);
 107              return;
 108          }
 109      }
 110  }
 111  
 112  // vim: et sw=4 sts=4