[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/s9e/text-formatter/src/Configurator/TemplateNormalizations/ -> OptimizeChoose.php (source)

   1  <?php
   2  
   3  /**
   4  * @package   s9e\TextFormatter
   5  * @copyright Copyright (c) 2010-2022 The s9e authors
   6  * @license   http://www.opensource.org/licenses/mit-license.php The MIT License
   7  */
   8  namespace s9e\TextFormatter\Configurator\TemplateNormalizations;
   9  
  10  use DOMElement;
  11  
  12  class OptimizeChoose extends AbstractChooseOptimization
  13  {
  14      /**
  15      * Adopt the children of given element's only child
  16      *
  17      * @param  DOMElement $branch
  18      * @return void
  19      */
  20  	protected function adoptChildren(DOMElement $branch)
  21      {
  22          while ($branch->firstChild->firstChild)
  23          {
  24              $branch->appendChild($branch->firstChild->removeChild($branch->firstChild->firstChild));
  25          }
  26          $branch->removeChild($branch->firstChild);
  27      }
  28  
  29      /**
  30      * Test whether all branches of current xsl:choose element share a common firstChild/lastChild
  31      *
  32      * @param  string $childType Either firstChild or lastChild
  33      * @return bool
  34      */
  35  	protected function matchBranches($childType)
  36      {
  37          $branches = $this->getBranches();
  38          if (!isset($branches[0]->$childType))
  39          {
  40              return false;
  41          }
  42  
  43          $childNode = $branches[0]->$childType;
  44          foreach ($branches as $branch)
  45          {
  46              if (!isset($branch->$childType) || !$this->isEqualNode($childNode, $branch->$childType))
  47              {
  48                  return false;
  49              }
  50          }
  51  
  52          return true;
  53      }
  54  
  55      /**
  56      * Test whether all branches of current xsl:choose element have a single child with the same start tag
  57      *
  58      * @return bool
  59      */
  60  	protected function matchOnlyChild()
  61      {
  62          $branches = $this->getBranches();
  63          if (!isset($branches[0]->firstChild))
  64          {
  65              return false;
  66          }
  67  
  68          $firstChild = $branches[0]->firstChild;
  69          if ($this->isXsl($firstChild, 'choose'))
  70          {
  71              // Abort on xsl:choose because we can't move it without moving its children
  72              return false;
  73          }
  74  
  75          foreach ($branches as $branch)
  76          {
  77              if ($branch->childNodes->length !== 1 || !($branch->firstChild instanceof DOMElement))
  78              {
  79                  return false;
  80              }
  81              if (!$this->isEqualTag($firstChild, $branch->firstChild))
  82              {
  83                  return false;
  84              }
  85          }
  86  
  87          return true;
  88      }
  89  
  90      /**
  91      * Move the firstChild of each branch before current xsl:choose
  92      *
  93      * @return void
  94      */
  95  	protected function moveFirstChildBefore()
  96      {
  97          $branches = $this->getBranches();
  98          $this->choose->parentNode->insertBefore(array_pop($branches)->firstChild, $this->choose);
  99          foreach ($branches as $branch)
 100          {
 101              $branch->removeChild($branch->firstChild);
 102          }
 103      }
 104  
 105      /**
 106      * Move the lastChild of each branch after current xsl:choose
 107      *
 108      * @return void
 109      */
 110  	protected function moveLastChildAfter()
 111      {
 112          $branches = $this->getBranches();
 113          $node     = array_pop($branches)->lastChild;
 114          if (isset($this->choose->nextSibling))
 115          {
 116              $this->choose->parentNode->insertBefore($node, $this->choose->nextSibling);
 117          }
 118          else
 119          {
 120              $this->choose->parentNode->appendChild($node);
 121          }
 122          foreach ($branches as $branch)
 123          {
 124              $branch->removeChild($branch->lastChild);
 125          }
 126      }
 127  
 128      /**
 129      * {@inheritdoc}
 130      */
 131  	protected function optimizeChoose()
 132      {
 133          if ($this->hasOtherwise())
 134          {
 135              $this->optimizeCommonFirstChild();
 136              $this->optimizeCommonLastChild();
 137              $this->optimizeCommonOnlyChild();
 138              $this->optimizeEmptyBranch();
 139              $this->optimizeEmptyOtherwise();
 140          }
 141          if ($this->isEmpty())
 142          {
 143              $this->choose->parentNode->removeChild($this->choose);
 144          }
 145          else
 146          {
 147              $this->optimizeSingleBranch();
 148          }
 149      }
 150  
 151      /**
 152      * Optimize current xsl:choose by moving out the first child of each branch if they match
 153      *
 154      * @return void
 155      */
 156  	protected function optimizeCommonFirstChild()
 157      {
 158          while ($this->matchBranches('firstChild'))
 159          {
 160              $this->moveFirstChildBefore();
 161          }
 162      }
 163  
 164      /**
 165      * Optimize current xsl:choose by moving out the last child of each branch if they match
 166      *
 167      * @return void
 168      */
 169  	protected function optimizeCommonLastChild()
 170      {
 171          while ($this->matchBranches('lastChild'))
 172          {
 173              $this->moveLastChildAfter();
 174          }
 175      }
 176  
 177      /**
 178      * Optimize current xsl:choose by moving out only child of each branch if they match
 179      *
 180      * This will reorder xsl:choose/xsl:when/div into div/xsl:choose/xsl:when if every branch has
 181      * the same only child (excluding the child's own descendants)
 182      *
 183      * @return void
 184      */
 185  	protected function optimizeCommonOnlyChild()
 186      {
 187          while ($this->matchOnlyChild())
 188          {
 189              $this->reparentChild();
 190          }
 191      }
 192  
 193      /**
 194      * Switch the logic of an xsl:otherwise if the only other branch is empty
 195      *
 196      * @return void
 197      */
 198  	protected function optimizeEmptyBranch()
 199      {
 200          $query = 'count(xsl:when) = 1 and count(xsl:when/node()) = 0 and xsl:otherwise';
 201          if (!$this->xpath->evaluate($query, $this->choose))
 202          {
 203              return;
 204          }
 205  
 206          // test="@foo" becomes test="not(@foo)"
 207          $when = $this->xpath('xsl:when', $this->choose)[0];
 208          $when->setAttribute('test', 'not(' . $when->getAttribute('test') . ')');
 209  
 210          $otherwise = $this->xpath('xsl:otherwise', $this->choose)[0];
 211          while ($otherwise->firstChild)
 212          {
 213              $when->appendChild($otherwise->removeChild($otherwise->firstChild));
 214          }
 215      }
 216  
 217      /**
 218      * Optimize away the xsl:otherwise child of current xsl:choose if it's empty
 219      *
 220      * @return void
 221      */
 222  	protected function optimizeEmptyOtherwise()
 223      {
 224          $query = 'xsl:otherwise[count(node()) = 0]';
 225          foreach ($this->xpath($query, $this->choose) as $otherwise)
 226          {
 227              $this->choose->removeChild($otherwise);
 228          }
 229      }
 230  
 231      /**
 232      * Replace current xsl:choose with xsl:if if it has only one branch
 233      *
 234      * @return void
 235      */
 236  	protected function optimizeSingleBranch()
 237      {
 238          $query = 'count(xsl:when) = 1 and not(xsl:otherwise)';
 239          if (!$this->xpath->evaluate($query, $this->choose))
 240          {
 241              return;
 242          }
 243          $when = $this->xpath('xsl:when', $this->choose)[0];
 244          $if   = $this->createElement('xsl:if');
 245          $if->setAttribute('test', $when->getAttribute('test'));
 246          while ($when->firstChild)
 247          {
 248              $if->appendChild($when->removeChild($when->firstChild));
 249          }
 250  
 251          $this->choose->parentNode->replaceChild($if, $this->choose);
 252      }
 253  
 254      /**
 255      * Reorder the current xsl:choose tree to make it a child of the first child of its first branch
 256      *
 257      * This will reorder xsl:choose/xsl:when/div into div/xsl:choose/xsl:when
 258      *
 259      * @return void
 260      */
 261  	protected function reparentChild()
 262      {
 263          $branches  = $this->getBranches();
 264          $childNode = $branches[0]->firstChild->cloneNode();
 265          $childNode->appendChild($this->choose->parentNode->replaceChild($childNode, $this->choose));
 266  
 267          foreach ($branches as $branch)
 268          {
 269              $this->adoptChildren($branch);
 270          }
 271      }
 272  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1