From 3987b63be4c49c505a0e09897f5eda70fc527b2a Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Tue, 23 May 2023 18:24:52 +1000 Subject: [PATCH] Use XPath instead of getElementsByTagName Bug: T336917 --- src/Model/Svg/SvgFile.php | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/Model/Svg/SvgFile.php b/src/Model/Svg/SvgFile.php index 02252e2e..bac275e2 100644 --- a/src/Model/Svg/SvgFile.php +++ b/src/Model/Svg/SvgFile.php @@ -15,6 +15,7 @@ use DOMDocument; use DOMElement; use DOMNode; +use DOMNodeList; use DOMXpath; use Krinkle\Intuition\Intuition; use Psr\Log\LoggerAwareTrait; @@ -158,7 +159,7 @@ protected function makeTranslationReady(): void } // Check that there is something to translate. - $texts = $this->document->getElementsByTagName('text'); + $texts = $this->getElementsByTagName('text'); $textLength = $texts->length; if (0 === $textLength) { // Nothing to translate. Given special handling in TranslateController. @@ -166,7 +167,7 @@ protected function makeTranslationReady(): void return; } - $styles = $this->document->getElementsByTagName('style'); + $styles = $this->getElementsByTagName('style'); $styleLength = $styles->length; for ($i = 0; $i < $styleLength; $i++) { $style = $styles->item($i); @@ -187,7 +188,7 @@ protected function makeTranslationReady(): void } // tref tags are not supported. - $trefs = $this->document->getElementsByTagName('tref'); + $trefs = $this->getElementsByTagName('tref'); if (0 !== $trefs->length) { throw new SvgStructureException('structure-error-contains-tref', $trefs->item(0)); } @@ -195,8 +196,8 @@ protected function makeTranslationReady(): void // Strip empty tspans, texts, fill $idsInUse $idsInUse = [ 0 ]; $translatableNodes = []; - $tspans = $this->document->getElementsByTagName('tspan'); - $texts = $this->document->getElementsByTagName('text'); + $tspans = $this->getElementsByTagName('tspan'); + $texts = $this->getElementsByTagName('text'); foreach ($tspans as $tspan) { if ($tspan->childNodes->length > 1 || ( 1 == $tspan->childNodes->length && XML_TEXT_NODE !== $tspan->childNodes->item(0)->nodeType ) @@ -256,8 +257,8 @@ protected function makeTranslationReady(): void // Reset $translatableNodes $translatableNodes = []; - $tspans = $this->document->getElementsByTagName('tspan'); - $texts = $this->document->getElementsByTagName('text'); + $tspans = $this->getElementsByTagName('tspan'); + $texts = $this->getElementsByTagName('text'); foreach ($tspans as $tspan) { array_push($translatableNodes, $tspan); } @@ -274,7 +275,7 @@ protected function makeTranslationReady(): void } } - $texts = $this->document->getElementsByTagName('text'); + $texts = $this->getElementsByTagName('text'); $textLength = $texts->length; for ($i = 0; $i < $textLength; $i++) { /** @var DOMElement $text */ @@ -322,9 +323,9 @@ protected function makeTranslationReady(): void } } - $switchLength = $this->document->getElementsByTagName('switch')->length; + $switchLength = $this->getElementsByTagName('switch')->length; for ($i = 0; $i < $switchLength; $i++) { - $switch = $this->document->getElementsByTagName('switch')->item($i); + $switch = $this->getElementsByTagName('switch')->item($i); $siblings = $switch->childNodes; $existingLangs = []; foreach ($siblings as $sibling) { @@ -396,7 +397,7 @@ protected function makeTranslationReady(): void */ protected function analyse(): void { - $switches = $this->document->getElementsByTagName('switch'); + $switches = $this->getElementsByTagName('switch'); $number = $switches->length; $translations = []; $this->filteredTextNodes = []; // Reset @@ -470,6 +471,17 @@ protected function analyse(): void $this->savedLanguages = array_unique($this->savedLanguages); } + /** + * Workaround for O(N^2) performance of DOMDocument::getElementsByTagName() T336917 + * + * @param string $name + * @return DOMNodeList + */ + private function getElementsByTagName(string $name): DOMNodeList + { + return $this->xpath->query("//*[local-name()=\"$name\"]"); + } + /** * Returns a list of translations present in the loaded file, in the following format: * @@ -561,7 +573,7 @@ public function switchToTranslationSet(array $translations): array $currentLanguages = $this->getSavedLanguages(); $expanded = $started = []; - $switches = $this->document->getElementsByTagName('switch'); + $switches = $this->getElementsByTagName('switch'); $number = $switches->length; for ($i = 0; $i < $number; $i++) { $switch = $switches->item($i);