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. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
MergeIdenticalConditionalBranches.php
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 use DOMNode;
012 use s9e\TextFormatter\Configurator\Helpers\XPathHelper;
013
014 /**
015 * Merge xsl:when branches if they have identical content
016 *
017 * NOTE: may fail if branches have identical equality expressions, e.g. "@a=1" and "@a=1"
018 */
019 class MergeIdenticalConditionalBranches extends AbstractNormalization
020 {
021 /**
022 * {@inheritdoc}
023 */
024 protected $queries = ['//xsl:choose'];
025
026 /**
027 * Collect consecutive xsl:when elements that share the same kind of equality tests
028 *
029 * Will return xsl:when elements that test a constant part (e.g. a literal) against the same
030 * variable part (e.g. the same attribute)
031 *
032 * @param DOMNode $node First node to inspect
033 * @return DOMElement[]
034 */
035 protected function collectCompatibleBranches(DOMNode $node)
036 {
037 $nodes = [];
038 $key = null;
039 $values = [];
040
041 while ($node && $this->isXsl($node, 'when'))
042 {
043 $branch = XPathHelper::parseEqualityExpr($node->getAttribute('test'));
044
045 if ($branch === false || count($branch) !== 1)
046 {
047 // The expression is not entirely composed of equalities, or they have a different
048 // variable part
049 break;
050 }
051
052 if (isset($key) && key($branch) !== $key)
053 {
054 // Not the same variable as our branches
055 break;
056 }
057
058 if (array_intersect($values, end($branch)))
059 {
060 // Duplicate values across branches, e.g. ".=1 or .=2" and ".=2 or .=3"
061 break;
062 }
063
064 $key = key($branch);
065 $values = array_merge($values, end($branch));
066
067 // Record this node then move on to the next sibling
068 $nodes[] = $node;
069 $node = $node->nextSibling;
070 }
071
072 return $nodes;
073 }
074
075 /**
076 * Merge identical xsl:when elements from a list
077 *
078 * @param DOMElement[] $nodes
079 * @return void
080 */
081 protected function mergeBranches(array $nodes)
082 {
083 $sortedNodes = [];
084 foreach ($nodes as $node)
085 {
086 $outerXML = $node->ownerDocument->saveXML($node);
087 $innerXML = preg_replace('([^>]+>(.*)<[^<]+)s', '$1', $outerXML);
088
089 $sortedNodes[$innerXML][] = $node;
090 }
091
092 foreach ($sortedNodes as $identicalNodes)
093 {
094 if (count($identicalNodes) < 2)
095 {
096 continue;
097 }
098
099 $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 }