From f397062cb495bd39b67ccc9dd3ed515f7473990e Mon Sep 17 00:00:00 2001 From: John Rayes Date: Wed, 15 Apr 2026 17:27:04 -0700 Subject: [PATCH 01/14] make it final --- Sources/PackageManager/XmlArray.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index f153871373..b3e8b10bbc 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -22,7 +22,7 @@ * Class XmlArray * Represents an XML array */ -class XmlArray +final class XmlArray { /******************* * Public properties From 8269ef617a464c6bf3929b922c24835aff7c92b0 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Wed, 15 Apr 2026 17:30:49 -0700 Subject: [PATCH 02/14] requesting a different memory limit is costly in hot code paths --- Sources/PackageManager/XmlArray.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index b3e8b10bbc..ba9c1c8df2 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -61,9 +61,6 @@ final class XmlArray */ public function __construct(string|array $data, bool $auto_trim = false, ?int $level = null, bool $is_clone = false) { - // If we're using this try to get some more memory. - Sapi::setMemoryLimit('32M'); - // Set the debug level. $this->debug_level = $level !== null ? $level : error_reporting(); $this->trim = $auto_trim; From 59159b65cacf0614464343971487da9aa7533ef7 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Wed, 15 Apr 2026 17:37:36 -0700 Subject: [PATCH 03/14] reuse local string offsets --- Sources/PackageManager/XmlArray.php | 51 ++++++++++++++++++----------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index ba9c1c8df2..3c3fcbbb4e 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -157,13 +157,15 @@ public function path(string $path, bool $return_full = false): XmlArray|string|f // For each element in the path. foreach ($path as $el) { + $pos = strpos($el, '['); + // Deal with sets.... - if (str_contains($el, '[')) { - $lvl = (int) substr($el, strpos($el, '[') + 1); - $el = substr($el, 0, strpos($el, '[')); + if ($pos !== false) { + $lvl = (int) substr($el, $pos + 1); + $el = substr($el, 0, $pos); } // Find an attribute. - elseif (str_starts_with($el, '@')) { + elseif ($el[0] === '@') { // It simplifies things if the attribute is already there ;). if (isset($array[$el])) { return $array[$el]; @@ -221,13 +223,15 @@ public function exists(string $path): bool // For each element in the path. foreach ($path as $el) { + $pos = strpos($el, '['); + // Deal with sets.... - if (str_contains($el, '[')) { - $lvl = (int) substr($el, strpos($el, '[') + 1); - $el = substr($el, 0, strpos($el, '[')); + if ($pos !== false) { + $lvl = (int) substr($el, $pos + 1); + $el = substr($el, 0, $pos); } // Find an attribute. - elseif (str_starts_with($el, '@')) { + elseif ($el[0] === '@') { return isset($array[$el]); } else { $lvl = null; @@ -431,8 +435,10 @@ protected function _parse(string $data): array // Didn't find a tag? Keep looping.... if (!isset($match[1]) || $match[1] == '') { + $pos = strpos($data, '<'); + // If there's no <, the rest is data. - if (!str_contains($data, '<')) { + if ($pos === false) { $text_value = $this->_from_cdata($data); $data = ''; @@ -444,9 +450,9 @@ protected function _parse(string $data): array } } // If the < isn't immediately next to the current position... more data. - elseif (strpos($data, '<') > 0) { - $text_value = $this->_from_cdata(substr($data, 0, strpos($data, '<'))); - $data = substr($data, strpos($data, '<')); + elseif ($pos > 0) { + $text_value = $this->_from_cdata(substr($data, 0, $pos)); + $data = substr($data, $pos); if ($text_value != '') { $current[] = [ @@ -456,10 +462,12 @@ protected function _parse(string $data): array } } // If we're looking at a with no start, kill it. - elseif (str_contains($data, '<') && strpos($data, '<') == 0) { - if (strpos($data, '<', 1) !== false) { - $text_value = $this->_from_cdata(substr($data, 0, strpos($data, '<', 1))); - $data = substr($data, strpos($data, '<', 1)); + elseif ($pos === 0) { + $pos1 = strpos($data, '<', 1); + + if ($pos1 !== false) { + $text_value = $this->_from_cdata(substr($data, 0, $pos1)); + $data = substr($data, $pos1); if ($text_value != '') { $current[] = [ @@ -490,8 +498,11 @@ protected function _parse(string $data): array // If this ISN'T empty, remove the close tag and parse the inner data. if ((!isset($match[3]) || trim($match[3]) != '/') && (!isset($match[2]) || trim($match[2]) != '/')) { + $tag_start = '<' . $match[1]; + $tag_end = ''; + // Because PHP 5.2.0+ seems to croak using regex, we'll have to do this the less fun way. - $last_tag_end = strpos($data, ''); + $last_tag_end = strpos($data, $tag_end); if ($last_tag_end === false) { continue; @@ -501,7 +512,7 @@ protected function _parse(string $data): array while (1 == 1) { // Where is the next start tag? - $next_tag_start = strpos($data, '<' . $match[1], $offset); + $next_tag_start = strpos($data, $tag_start, $offset); // If the next start tag is after the last end tag then we've found the right close. if ($next_tag_start === false || $next_tag_start > $last_tag_end) { @@ -509,7 +520,7 @@ protected function _parse(string $data): array } // If not then find the next ending tag. - $next_tag_end = strpos($data, '', $offset); + $next_tag_end = strpos($data, $tag_end, $offset); // Didn't find one? Then just use the last and sod it. if ($next_tag_end === false) { @@ -522,7 +533,7 @@ protected function _parse(string $data): array // Parse the insides. $inner_match = substr($data, 0, $last_tag_end); // Data now starts from where this section ends. - $data = substr($data, $last_tag_end + \strlen('')); + $data = substr($data, $last_tag_end + \strlen($tag_end)); if (!empty($inner_match)) { // Parse the inner data. From 1a8a1dadbd70a3b0182561b6e1ffb5e87bd4bcaa Mon Sep 17 00:00:00 2001 From: John Rayes Date: Wed, 15 Apr 2026 17:41:13 -0700 Subject: [PATCH 04/14] always great to modernise old php 4 code --- Sources/PackageManager/XmlArray.php | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index 3c3fcbbb4e..68fcaabd18 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -198,11 +198,8 @@ public function path(string $path, bool $return_full = false): XmlArray|string|f $array = ['name' => $el . '[]', $array]; } - // Create the right type of class... - $newClass = \get_class($this); - // Return a new XmlArray for the result. - return $array === false ? false : new $newClass($array, $this->trim, $this->debug_level, true); + return $array === false ? false : new self($array, $this->trim, $this->debug_level, true); } /** @@ -296,11 +293,8 @@ public function set(string $path): array continue; } - // Create the right type of class... - $newClass = \get_class($this); - // Create a new XmlArray and stick it in the array. - $array[] = new $newClass($val, $this->trim, $this->debug_level, true); + $array[] = new self($val, $this->trim, $this->debug_level, true); } return $array; @@ -664,20 +658,9 @@ protected function _array(array $array): string|array */ protected function _from_cdata(string $data): string { - // Get the HTML translation table and reverse it. - $trans_tbl = array_flip(get_html_translation_table(HTML_ENTITIES, ENT_QUOTES)); - - // Translate all the entities out. - $data = strtr( - preg_replace_callback( - '~&#(\d{1,4});~', - function ($m) { - return \chr("{$m[1]}"); - }, - $data, - ), - $trans_tbl, - ); + if (str_contains($data, '&')) { + $data = html_entity_decode($data, ENT_QUOTES | ENT_XML1, 'UTF-8'); + } return $this->trim ? trim($data) : $data; } From 01f0348b4de179e053975ee5e856a96dd4dde951 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Wed, 15 Apr 2026 17:43:08 -0700 Subject: [PATCH 05/14] formatting --- Sources/PackageManager/XmlArray.php | 38 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index 68fcaabd18..48485e46c4 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -367,29 +367,34 @@ public function to_array(?string $path = null): array */ public function _to_cdata(string $data): string { - $inCdata = $inComment = false; + // Quickly check for either comments or CDATA tags. + if (strpos($data, '|)~', $data, -1, PREG_SPLIT_DELIM_CAPTURE); foreach ($parts as $part) { // Handle XML comments. - if (!$inCdata && $part === '') { - $inComment = false; - } elseif ($inComment) { + if ($in_comment && $part === '-->') { + $in_comment = false; + } elseif ($in_comment) { continue; } - // Handle Cdata blocks. - elseif (!$inComment && $part === '') { - $inCdata = false; - } elseif ($inCdata) { + // Handle CDATA blocks. + elseif (!$in_comment && $part === '') { + $in_cdata = false; + } elseif ($in_cdata) { $output .= htmlentities($part, ENT_QUOTES); } @@ -415,8 +420,7 @@ public function _to_cdata(string $data): string protected function _parse(string $data): array { // Start with an 'empty' array with no data. - $current = [ - ]; + $current = []; // Loop until we're out of data. while ($data !== '') { @@ -504,7 +508,7 @@ protected function _parse(string $data): array $offset = 0; - while (1 == 1) { + while (true) { // Where is the next start tag? $next_tag_start = strpos($data, $tag_start, $offset); @@ -586,7 +590,7 @@ protected function _xml(array $array, ?int $indent): string } // This is just text! - if ($array['name'] == '!') { + if ($array['name'] === '!') { return $indentation . ''; } @@ -636,7 +640,7 @@ protected function _array(array $array): string|array continue; } - if ($value['name'] == '!') { + if ($value['name'] === '!') { $text .= $value['value']; } else { $return[$value['name']] = $this->_array($value); From 4f4e889ae5b75e62c2c6f6facb24f7d0cad9de69 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Wed, 15 Apr 2026 17:47:31 -0700 Subject: [PATCH 06/14] regex is admittedly really cool, but it's not needed here and slows us down --- Sources/PackageManager/XmlArray.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index 48485e46c4..533139e060 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -428,7 +428,7 @@ protected function _parse(string $data): array preg_match('/\A<([\w\-:]+)((?:\s+[\s\S]+?)?)([\s]?\/)?' . '>/', $data, $match); if (isset($match[0])) { - $data = preg_replace('/' . preg_quote($match[0], '/') . '/s', '', $data, 1); + $data = substr($data, \strlen($match[0])); } // Didn't find a tag? Keep looping.... From cb5025a1a9e825c6bbb8e2c92ef41ff8fae1681b Mon Sep 17 00:00:00 2001 From: John Rayes Date: Wed, 15 Apr 2026 17:49:09 -0700 Subject: [PATCH 07/14] statically cache indentation --- Sources/PackageManager/XmlArray.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index 533139e060..e47c2034bf 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -575,8 +575,12 @@ protected function _parse(string $data): array */ protected function _xml(array $array, ?int $indent): string { - $indentation = $indent !== null ? ' -' . str_repeat(' ', $indent) : ''; + static $indentation_cache; + + $indentation_cache ??= $indent !== null + ? "\n" . str_repeat("\t", $indent) + : ''; + $indentation = $indentation_cache; // This is a set of elements, with no name... if (\is_array($array) && !isset($array['name'])) { From d13017569eafb590fd285f4128412913e7a98887 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Wed, 15 Apr 2026 17:50:43 -0700 Subject: [PATCH 08/14] quicker to use a hash map here --- Sources/PackageManager/XmlArray.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index e47c2034bf..bce47551b0 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -731,7 +731,8 @@ protected function _path(array $array, string $path, ?int $level, bool $no_error $paths = explode('|', $path); // A * means all elements of any name. - $show_all = \in_array('*', $paths); + $pathMap = array_flip($paths); + $show_all = isset($pathMap['*']); $results = []; @@ -741,7 +742,7 @@ protected function _path(array $array, string $path, ?int $level, bool $no_error continue; } - if ($show_all || \in_array($value['name'], $paths)) { + if ($show_all || isset($pathMap[$value['name']])) { // Skip elements before "the one". if ($level !== null && $level > 0) { $level--; From 84a1ecd2eb5f5f111deb06c69b62d34989940261 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Wed, 15 Apr 2026 17:52:16 -0700 Subject: [PATCH 09/14] much tighter debug guarding --- Sources/PackageManager/XmlArray.php | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index bce47551b0..ce0986f1aa 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -171,16 +171,16 @@ public function path(string $path, bool $return_full = false): XmlArray|string|f return $array[$el]; } - $trace = debug_backtrace(); - $i = 0; + if ($this->debug_level & E_NOTICE) { + $trace = debug_backtrace(); + $i = 0; - while ($i < \count($trace) && isset($trace[$i]['class']) && $trace[$i]['class'] == \get_class($this)) { - $i++; - } - $debug = ' (from ' . $trace[$i - 1]['file'] . ' on line ' . $trace[$i - 1]['line'] . ')'; + while ($i < \count($trace) && isset($trace[$i]['class']) && $trace[$i]['class'] == self::class) { + $i++; + } + $debug = ' (from ' . $trace[$i - 1]['file'] . ' on line ' . $trace[$i - 1]['line'] . ')'; - // Cause an error. - if ($this->debug_level & E_NOTICE) { + // Cause an error. trigger_error(Lang::getTxt('undefined_xml_attribute', [substr($el, 1) . $debug], file: 'Errors'), E_USER_NOTICE); } @@ -622,7 +622,7 @@ protected function _xml(array $array, ?int $indent): string if ($inside_elements) { $output .= '>' . $output_el . $indentation . ''; } else { - $output .= ' />'; + $output .= ' />'; } return $output; @@ -753,19 +753,17 @@ protected function _path(array $array, string $path, ?int $level, bool $no_error } // No results found... - if (empty($results)) { + if (empty($results) && $this->debug_level & E_NOTICE && !$no_error) { $trace = debug_backtrace(); $i = 0; - while ($i < \count($trace) && isset($trace[$i]['class']) && $trace[$i]['class'] == \get_class($this)) { + while ($i < \count($trace) && isset($trace[$i]['class']) && $trace[$i]['class'] == self::class) { $i++; } $debug = ' from ' . $trace[$i - 1]['file'] . ' on line ' . $trace[$i - 1]['line']; // Cause an error. - if ($this->debug_level & E_NOTICE && !$no_error) { - trigger_error(Lang::getTxt('undefined_xml_element', [$path . $debug], file: 'Errors'), E_USER_NOTICE); - } + trigger_error(Lang::getTxt('undefined_xml_element', [$path . $debug], file: 'Errors'), E_USER_NOTICE); return false; } From 285d48750ccf37df8766d777c6bd8a864c5957a8 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Wed, 15 Apr 2026 19:03:40 -0700 Subject: [PATCH 10/14] Parse based on offsets --- Sources/PackageManager/XmlArray.php | 52 +++++++++++++++-------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index ce0986f1aa..40381cb570 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -422,23 +422,24 @@ protected function _parse(string $data): array // Start with an 'empty' array with no data. $current = []; - // Loop until we're out of data. - while ($data !== '') { - // Find and remove the next tag. - preg_match('/\A<([\w\-:]+)((?:\s+[\s\S]+?)?)([\s]?\/)?' . '>/', $data, $match); + $len = \strlen($data); + $offset = 0; + + while ($offset < $len) { + preg_match('/\G<([\w\-:]+)((?:\s+[\s\S]+?)?)([\s]?\/)?>/', $data, $match, 0, $offset); if (isset($match[0])) { - $data = substr($data, \strlen($match[0])); + $offset += \strlen($match[0]); } // Didn't find a tag? Keep looping.... if (!isset($match[1]) || $match[1] == '') { - $pos = strpos($data, '<'); + $pos = strpos($data, '<', $offset); // If there's no <, the rest is data. if ($pos === false) { - $text_value = $this->_from_cdata($data); - $data = ''; + $text_value = $this->_from_cdata(substr($data, $offset)); + $offset = $len; if ($text_value != '') { $current[] = [ @@ -448,9 +449,9 @@ protected function _parse(string $data): array } } // If the < isn't immediately next to the current position... more data. - elseif ($pos > 0) { - $text_value = $this->_from_cdata(substr($data, 0, $pos)); - $data = substr($data, $pos); + elseif ($pos > $offset) { + $text_value = $this->_from_cdata(substr($data, $offset, $pos - $offset)); + $offset = $pos; if ($text_value != '') { $current[] = [ @@ -460,12 +461,12 @@ protected function _parse(string $data): array } } // If we're looking at a with no start, kill it. - elseif ($pos === 0) { - $pos1 = strpos($data, '<', 1); + elseif ($pos === $offset) { + $pos1 = strpos($data, '<', $offset + 1); if ($pos1 !== false) { - $text_value = $this->_from_cdata(substr($data, 0, $pos1)); - $data = substr($data, $pos1); + $text_value = $this->_from_cdata(substr($data, $offset, $pos1 - $offset)); + $offset = $pos1; if ($text_value != '') { $current[] = [ @@ -474,8 +475,8 @@ protected function _parse(string $data): array ]; } } else { - $text_value = $this->_from_cdata($data); - $data = ''; + $text_value = $this->_from_cdata(substr($data, $offset)); + $offset = $len; if ($text_value != '') { $current[] = [ @@ -499,18 +500,17 @@ protected function _parse(string $data): array $tag_start = '<' . $match[1]; $tag_end = ''; - // Because PHP 5.2.0+ seems to croak using regex, we'll have to do this the less fun way. - $last_tag_end = strpos($data, $tag_end); + $last_tag_end = strpos($data, $tag_end, $offset); if ($last_tag_end === false) { continue; } - $offset = 0; + $inner_offset = $offset; while (true) { // Where is the next start tag? - $next_tag_start = strpos($data, $tag_start, $offset); + $next_tag_start = strpos($data, $tag_start, $inner_offset); // If the next start tag is after the last end tag then we've found the right close. if ($next_tag_start === false || $next_tag_start > $last_tag_end) { @@ -518,7 +518,7 @@ protected function _parse(string $data): array } // If not then find the next ending tag. - $next_tag_end = strpos($data, $tag_end, $offset); + $next_tag_end = strpos($data, $tag_end, $inner_offset); // Didn't find one? Then just use the last and sod it. if ($next_tag_end === false) { @@ -526,12 +526,14 @@ protected function _parse(string $data): array } $last_tag_end = $next_tag_end; - $offset = $next_tag_start + 1; + $inner_offset = $next_tag_start + 1; } + // Parse the insides. - $inner_match = substr($data, 0, $last_tag_end); + $inner_match = substr($data, $offset, $last_tag_end - $offset); + // Data now starts from where this section ends. - $data = substr($data, $last_tag_end + \strlen($tag_end)); + $offset = $last_tag_end + \strlen($tag_end); if (!empty($inner_match)) { // Parse the inner data. From b769345c048a4a8e35b8f1e660f4d7ede82ee5b3 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Thu, 16 Apr 2026 16:45:14 -0700 Subject: [PATCH 11/14] unused import --- Sources/PackageManager/XmlArray.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index 40381cb570..f72ff739a8 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -16,7 +16,6 @@ namespace SMF\PackageManager; use SMF\Lang; -use SMF\Sapi; /** * Class XmlArray From 7a92ea5b6d1f3354e071e807e8fab9731f7c2967 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Thu, 16 Apr 2026 16:46:11 -0700 Subject: [PATCH 12/14] styling --- Sources/PackageManager/XmlArray.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index f72ff739a8..1052ed3e9a 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -16,6 +16,7 @@ namespace SMF\PackageManager; use SMF\Lang; +use SMF\Sapi; /** * Class XmlArray @@ -623,7 +624,7 @@ protected function _xml(array $array, ?int $indent): string if ($inside_elements) { $output .= '>' . $output_el . $indentation . ''; } else { - $output .= ' />'; + $output .= ' />'; } return $output; @@ -732,8 +733,8 @@ protected function _path(array $array, string $path, ?int $level, bool $no_error $paths = explode('|', $path); // A * means all elements of any name. - $pathMap = array_flip($paths); - $show_all = isset($pathMap['*']); + $path_map = array_flip($paths); + $show_all = isset($path_map['*']); $results = []; @@ -743,7 +744,7 @@ protected function _path(array $array, string $path, ?int $level, bool $no_error continue; } - if ($show_all || isset($pathMap[$value['name']])) { + if ($show_all || isset($path_map[$value['name']])) { // Skip elements before "the one". if ($level !== null && $level > 0) { $level--; From a0037ffea6b1637d0db8878a10db83523fe29e72 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Thu, 16 Apr 2026 16:45:14 -0700 Subject: [PATCH 13/14] unused import --- Sources/PackageManager/XmlArray.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index 1052ed3e9a..d68bff0d68 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -16,7 +16,6 @@ namespace SMF\PackageManager; use SMF\Lang; -use SMF\Sapi; /** * Class XmlArray From 6feb116d00944373df925308543afa0e846a6002 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Sun, 19 Apr 2026 19:51:08 -0700 Subject: [PATCH 14/14] static cache here probably not worth the effort --- Sources/PackageManager/XmlArray.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Sources/PackageManager/XmlArray.php b/Sources/PackageManager/XmlArray.php index d68bff0d68..59c4032bf4 100644 --- a/Sources/PackageManager/XmlArray.php +++ b/Sources/PackageManager/XmlArray.php @@ -576,12 +576,8 @@ protected function _parse(string $data): array */ protected function _xml(array $array, ?int $indent): string { - static $indentation_cache; - - $indentation_cache ??= $indent !== null - ? "\n" . str_repeat("\t", $indent) - : ''; - $indentation = $indentation_cache; + $indentation = $indent !== null ? ' +' . str_repeat(' ', $indent) : ''; // This is a set of elements, with no name... if (\is_array($array) && !isset($array['name'])) {