[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |