Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

OptimizeChoose.php

Zuletzt modifiziert: 02.04.2025, 15:04 - Dateigröße: 6.08 KiB


001  <?php
002   
003  /**
004  * @package   s9e\TextFormatter
005  * @copyright Copyright (c) 2010-2022 The s9e authors
006  * @license   http://www.opensource.org/licenses/mit-license.php The MIT License
007  */
008  namespace s9e\TextFormatter\Configurator\TemplateNormalizations;
009   
010  use DOMElement;
011   
012  class OptimizeChoose extends AbstractChooseOptimization
013  {
014      /**
015      * Adopt the children of given element's only child
016      *
017      * @param  DOMElement $branch
018      * @return void
019      */
020      protected function adoptChildren(DOMElement $branch)
021      {
022          while ($branch->firstChild->firstChild)
023          {
024              $branch->appendChild($branch->firstChild->removeChild($branch->firstChild->firstChild));
025          }
026          $branch->removeChild($branch->firstChild);
027      }
028   
029      /**
030      * Test whether all branches of current xsl:choose element share a common firstChild/lastChild
031      *
032      * @param  string $childType Either firstChild or lastChild
033      * @return bool
034      */
035      protected function matchBranches($childType)
036      {
037          $branches = $this->getBranches();
038          if (!isset($branches[0]->$childType))
039          {
040              return false;
041          }
042   
043          $childNode = $branches[0]->$childType;
044          foreach ($branches as $branch)
045          {
046              if (!isset($branch->$childType) || !$this->isEqualNode($childNode, $branch->$childType))
047              {
048                  return false;
049              }
050          }
051   
052          return true;
053      }
054   
055      /**
056      * Test whether all branches of current xsl:choose element have a single child with the same start tag
057      *
058      * @return bool
059      */
060      protected function matchOnlyChild()
061      {
062          $branches = $this->getBranches();
063          if (!isset($branches[0]->firstChild))
064          {
065              return false;
066          }
067   
068          $firstChild = $branches[0]->firstChild;
069          if ($this->isXsl($firstChild, 'choose'))
070          {
071              // Abort on xsl:choose because we can't move it without moving its children
072              return false;
073          }
074   
075          foreach ($branches as $branch)
076          {
077              if ($branch->childNodes->length !== 1 || !($branch->firstChild instanceof DOMElement))
078              {
079                  return false;
080              }
081              if (!$this->isEqualTag($firstChild, $branch->firstChild))
082              {
083                  return false;
084              }
085          }
086   
087          return true;
088      }
089   
090      /**
091      * Move the firstChild of each branch before current xsl:choose
092      *
093      * @return void
094      */
095      protected function moveFirstChildBefore()
096      {
097          $branches = $this->getBranches();
098          $this->choose->parentNode->insertBefore(array_pop($branches)->firstChild, $this->choose);
099          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  }