[ Index ]

PHP Cross Reference of phpBB-3.3.2-deutsch

title

Body

[close]

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

   1  <?php
   2  
   3  /**
   4  * @package   s9e\TextFormatter
   5  * @copyright Copyright (c) 2010-2020 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  use DOMNode;
  12  use s9e\TextFormatter\Configurator\Helpers\XPathHelper;
  13  
  14  /**
  15  * Merge xsl:when branches if they have identical content
  16  *
  17  * NOTE: may fail if branches have identical equality expressions, e.g. "@a=1" and "@a=1"
  18  */
  19  class MergeIdenticalConditionalBranches extends AbstractNormalization
  20  {
  21      /**
  22      * {@inheritdoc}
  23      */
  24      protected $queries = ['//xsl:choose'];
  25  
  26      /**
  27      * Collect consecutive xsl:when elements that share the same kind of equality tests
  28      *
  29      * Will return xsl:when elements that test a constant part (e.g. a literal) against the same
  30      * variable part (e.g. the same attribute)
  31      *
  32      * @param  DOMNode      $node First node to inspect
  33      * @return DOMElement[]
  34      */
  35  	protected function collectCompatibleBranches(DOMNode $node)
  36      {
  37          $nodes  = [];
  38          $key    = null;
  39          $values = [];
  40  
  41          while ($node && $this->isXsl($node, 'when'))
  42          {
  43              $branch = XPathHelper::parseEqualityExpr($node->getAttribute('test'));
  44  
  45              if ($branch === false || count($branch) !== 1)
  46              {
  47                  // The expression is not entirely composed of equalities, or they have a different
  48                  // variable part
  49                  break;
  50              }
  51  
  52              if (isset($key) && key($branch) !== $key)
  53              {
  54                  // Not the same variable as our branches
  55                  break;
  56              }
  57  
  58              if (array_intersect($values, end($branch)))
  59              {
  60                  // Duplicate values across branches, e.g. ".=1 or .=2" and ".=2 or .=3"
  61                  break;
  62              }
  63  
  64              $key    = key($branch);
  65              $values = array_merge($values, end($branch));
  66  
  67              // Record this node then move on to the next sibling
  68              $nodes[] = $node;
  69              $node    = $node->nextSibling;
  70          }
  71  
  72          return $nodes;
  73      }
  74  
  75      /**
  76      * Merge identical xsl:when elements from a list
  77      *
  78      * @param  DOMElement[] $nodes
  79      * @return void
  80      */
  81  	protected function mergeBranches(array $nodes)
  82      {
  83          $sortedNodes = [];
  84          foreach ($nodes as $node)
  85          {
  86              $outerXML = $node->ownerDocument->saveXML($node);
  87              $innerXML = preg_replace('([^>]+>(.*)<[^<]+)s', '$1', $outerXML);
  88  
  89              $sortedNodes[$innerXML][] = $node;
  90          }
  91  
  92          foreach ($sortedNodes as $identicalNodes)
  93          {
  94              if (count($identicalNodes) < 2)
  95              {
  96                  continue;
  97              }
  98  
  99              $expr = [];
 100              foreach ($identicalNodes as $i => $node)
 101              {
 102                  $expr[] = $node->getAttribute('test');
 103  
 104                  if ($i > 0)
 105                  {
 106                      $node->parentNode->removeChild($node);
 107                  }
 108              }
 109  
 110              $identicalNodes[0]->setAttribute('test', implode(' or ', $expr));
 111          }
 112      }
 113  
 114      /**
 115      * Inspect the branches of an xsl:choose element and merge branches if their content is identical
 116      * and their order does not matter
 117      *
 118      * @param  DOMElement $choose xsl:choose element
 119      * @return void
 120      */
 121  	protected function mergeCompatibleBranches(DOMElement $choose)
 122      {
 123          $node = $choose->firstChild;
 124          while ($node)
 125          {
 126              $nodes = $this->collectCompatibleBranches($node);
 127  
 128              if (count($nodes) > 1)
 129              {
 130                  $node = end($nodes)->nextSibling;
 131  
 132                  // Try to merge branches if there's more than one of them
 133                  $this->mergeBranches($nodes);
 134              }
 135              else
 136              {
 137                  $node = $node->nextSibling;
 138              }
 139          }
 140      }
 141  
 142      /**
 143      * Inspect the branches of an xsl:choose element and merge consecutive branches if their content
 144      * is identical
 145      *
 146      * @param  DOMElement $choose xsl:choose element
 147      * @return void
 148      */
 149  	protected function mergeConsecutiveBranches(DOMElement $choose)
 150      {
 151          // Try to merge consecutive branches even if their test conditions are not compatible,
 152          // e.g. "@a=1" and "@b=2"
 153          $nodes = [];
 154          foreach ($choose->childNodes as $node)
 155          {
 156              if ($this->isXsl($node, 'when'))
 157              {
 158                  $nodes[] = $node;
 159              }
 160          }
 161  
 162          $i = count($nodes);
 163          while (--$i > 0)
 164          {
 165              $this->mergeBranches([$nodes[$i - 1], $nodes[$i]]);
 166          }
 167      }
 168  
 169      /**
 170      * {@inheritdoc}
 171      */
 172  	protected function normalizeElement(DOMElement $element)
 173      {
 174          $this->mergeCompatibleBranches($element);
 175          $this->mergeConsecutiveBranches($element);
 176      }
 177  }


Generated: Wed Nov 11 20:28:18 2020 Cross-referenced by PHPXref 0.7.1