Skip to content

Commit 6b70577

Browse files
committed
[BUGFIX] Read project version from the DOM so "0.10" is not coerced to 0.1
A <project version="0.10"> in guides.xml was rendered as version 0.1 (title, objects.inv, every |version| substitution). XmlFileLoader parses guides.xml with XmlUtils::convertDomElementToArray(), which runs phpize() on every attribute value, coercing version-like strings into numbers: "0.10" becomes the float 0.1, "1.0" becomes 1, "13.0" becomes 13. Read the <project> attributes (all strings) straight from the DOM, and detach the element before the conversion so phpize never sees them. The version is now read correctly at the source instead of being coerced and patched up afterwards. This makes the previous "escaped version" workaround obsolete -- writing version="'3.0'" with single quotes to dodge phpize, with a beforeNormalization that stripped them again -- so it is removed; write the version directly, e.g. version="0.10". Reported on docs.typo3.org for netresearch/nr-vault and nr-llm (0.10 / 0.12). Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
1 parent 6d70127 commit 6b70577

3 files changed

Lines changed: 30 additions & 40 deletions

File tree

packages/guides-cli/src/Config/XmlFileLoader.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
namespace phpDocumentor\Guides\Cli\Config;
1515

16+
use DOMAttr;
17+
use DOMElement;
1618
use Symfony\Component\Config\Loader\FileLoader;
1719
use Symfony\Component\Config\Util\Exception\XmlParsingException;
1820
use Symfony\Component\Config\Util\XmlUtils;
@@ -36,9 +38,34 @@ public function load(mixed $resource, string|null $type = null): array
3638
throw new XmlParsingException(sprintf('The XML file "%s" is not valid.', $resource));
3739
}
3840

41+
// The <project> attributes (title, version, release, copyright) are all
42+
// strings and are read from the DOM directly. XmlUtils::convertDomElementToArray()
43+
// below runs phpize() on every attribute value, which coerces version-like
44+
// strings into numbers ("0.10" would become the float 0.1, "1.0" would
45+
// become 1). Reading them with getAttribute() and detaching <project>
46+
// beforehand keeps the version exactly as written.
47+
$projectConfig = null;
48+
$project = $element->getElementsByTagName('project')->item(0);
49+
if ($project instanceof DOMElement) {
50+
$projectConfig = [];
51+
foreach ($project->attributes as $attribute) {
52+
if (!($attribute instanceof DOMAttr)) {
53+
continue;
54+
}
55+
56+
$projectConfig[$attribute->name] = $attribute->value;
57+
}
58+
59+
$project->parentNode?->removeChild($project);
60+
}
61+
3962
$rootConfig = XmlUtils::convertDomElementToArray($element);
4063
assert(is_array($rootConfig));
4164

65+
if ($projectConfig !== null) {
66+
$rootConfig['project'] = $projectConfig;
67+
}
68+
4269
$configs = [];
4370
if (isset($rootConfig['import'])) {
4471
foreach ((array) $rootConfig['import'] as $import) {

packages/guides/src/DependencyInjection/GuidesExtension.php

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,8 @@
4343
use function assert;
4444
use function dirname;
4545
use function is_array;
46-
use function is_int;
4746
use function is_string;
4847
use function pathinfo;
49-
use function trim;
50-
use function var_export;
5148

5249
final class GuidesExtension extends Extension implements CompilerPassInterface, ConfigurationInterface, PrependExtensionInterface
5350
{
@@ -64,42 +61,8 @@ public function getConfigTreeBuilder(): TreeBuilder
6461
->arrayNode('project')
6562
->children()
6663
->scalarNode('title')->end()
67-
->scalarNode('version')
68-
->beforeNormalization()
69-
->always(
70-
// We need to revert the phpize call in XmlUtils. Version is always a string!
71-
static function ($value) {
72-
if (!is_int($value) && !is_string($value)) {
73-
return var_export($value, true);
74-
}
75-
76-
if (is_string($value)) {
77-
return trim($value, "'");
78-
}
79-
80-
return $value;
81-
},
82-
)
83-
->end()
84-
->end()
85-
->scalarNode('release')
86-
->beforeNormalization()
87-
->always(
88-
// We need to revert the phpize call in XmlUtils. Version is always a string!
89-
static function ($value) {
90-
if (!is_int($value) && !is_string($value)) {
91-
return var_export($value, true);
92-
}
93-
94-
if (is_string($value)) {
95-
return trim($value, "'");
96-
}
97-
98-
return $value;
99-
},
100-
)
101-
->end()
102-
->end()
64+
->scalarNode('version')->end()
65+
->scalarNode('release')->end()
10366
->scalarNode('copyright')->end()
10467
->end()
10568
->end()

tests/Integration/tests/meta/version-from-guides-xml/input/guides.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
>
77
<project
88
title="Render guides"
9-
version="'3.0'"
9+
version="3.0"
1010
release="3.0.0"
1111
/>
1212
</guides>

0 commit comments

Comments
 (0)