Commit 7e78b0f1d28 for php.net
commit 7e78b0f1d2855a927f1873012aba50cc1f22395b
Author: Máté Kocsis <kocsismate@woohoolabs.com>
Date: Thu Mar 5 13:42:36 2026 +0100
Add support for generating the namespace for the manual (#21313)
[skip ci]
diff --git a/build/gen_stub.php b/build/gen_stub.php
index 57424ac33aa..75f4b12f957 100755
--- a/build/gen_stub.php
+++ b/build/gen_stub.php
@@ -2525,15 +2525,17 @@ protected function getTypeCode(string $variableLikeName, string &$code): string
}
/** @param array<string, ConstInfo> $allConstInfos */
- public function getFieldSynopsisElement(DOMDocument $doc, array $allConstInfos): DOMElement
+ public function getFieldSynopsisElement(DOMDocument $doc, array $allConstInfos, int $indentationLevel): DOMElement
{
+ $indentation = str_repeat(" ", $indentationLevel);
+
$fieldsynopsisElement = $doc->createElement("fieldsynopsis");
- $this->addModifiersToFieldSynopsis($doc, $fieldsynopsisElement);
+ $this->addModifiersToFieldSynopsis($doc, $fieldsynopsisElement, $indentationLevel + 1);
$type = $this->phpDocType ?? $this->type;
if ($type) {
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation "));
$fieldsynopsisElement->appendChild($type->getTypeForDoc($doc));
}
@@ -2544,31 +2546,33 @@ public function getFieldSynopsisElement(DOMDocument $doc, array $allConstInfos):
$varnameElement->setAttribute("linkend", $this->getFieldSynopsisDefaultLinkend());
}
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation "));
$fieldsynopsisElement->appendChild($varnameElement);
$valueString = $this->getFieldSynopsisValueString($allConstInfos);
if ($valueString) {
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation "));
$initializerElement = $doc->createElement("initializer", $valueString);
$fieldsynopsisElement->appendChild($initializerElement);
}
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation"));
return $fieldsynopsisElement;
}
- protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement): void
+ protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement, int $indentationLevel): void
{
+ $indentation = str_repeat(" ", $indentationLevel);
+
if ($this->flags & Modifiers::PUBLIC) {
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation"));
$fieldsynopsisElement->appendChild($doc->createElement("modifier", "public"));
} elseif ($this->flags & Modifiers::PROTECTED) {
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation"));
$fieldsynopsisElement->appendChild($doc->createElement("modifier", "protected"));
} elseif ($this->flags & Modifiers::PRIVATE) {
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation"));
$fieldsynopsisElement->appendChild($doc->createElement("modifier", "private"));
}
}
@@ -2912,16 +2916,18 @@ protected function getFlagsByPhpVersion(): VersionFlags
return $flags;
}
- protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement): void
+ protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement, int $indentationLevel): void
{
- parent::addModifiersToFieldSynopsis($doc, $fieldsynopsisElement);
+ parent::addModifiersToFieldSynopsis($doc, $fieldsynopsisElement, $indentationLevel);
+
+ $indentation = str_repeat(" ", $indentationLevel);
if ($this->flags & Modifiers::FINAL) {
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation"));
$fieldsynopsisElement->appendChild($doc->createElement("modifier", "final"));
}
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation"));
$fieldsynopsisElement->appendChild($doc->createElement("modifier", "const"));
}
}
@@ -3256,22 +3262,24 @@ protected function getFlagsByPhpVersion(): VersionFlags
return $flags;
}
- protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement): void
+ protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement, int $indentationLevel): void
{
- parent::addModifiersToFieldSynopsis($doc, $fieldsynopsisElement);
+ parent::addModifiersToFieldSynopsis($doc, $fieldsynopsisElement, $indentationLevel);
+
+ $indentation = str_repeat(" ", $indentationLevel);
if ($this->flags & Modifiers::STATIC) {
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation"));
$fieldsynopsisElement->appendChild($doc->createElement("modifier", "static"));
}
if ($this->flags & Modifiers::FINAL) {
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation"));
$fieldsynopsisElement->appendChild($doc->createElement("modifier", "final"));
}
if ($this->flags & Modifiers::READONLY || $this->isDocReadonly) {
- $fieldsynopsisElement->appendChild(new DOMText("\n "));
+ $fieldsynopsisElement->appendChild(new DOMText("\n$indentation"));
$fieldsynopsisElement->appendChild($doc->createElement("modifier", "readonly"));
}
}
@@ -3743,12 +3751,30 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
$classSynopsis = $doc->createElement("classsynopsis");
$classSynopsis->setAttribute("class", $this->type === "interface" ? "interface" : "class");
+ $namespace = $this->getNamespace();
+ if ($namespace) {
+ $classSynopsisIndentationLevel = 4;
+ $classSynopsisIndentation = str_repeat(" ", $classSynopsisIndentationLevel);
+ $packageSynopsis = $doc->createElement("packagesynopsis");
+ $packageSynopsis->appendChild(new DOMText("\n$classSynopsisIndentation"));
+ $package = $doc->createElement("package", $namespace);
+ $packageSynopsis->appendChild($package);
+ $packageSynopsis->appendChild(new DOMText("\n\n$classSynopsisIndentation"));
+ $packageSynopsis->appendChild($classSynopsis);
+ $packageSynopsis->appendChild(new DOMText("\n "));
+ $root = $packageSynopsis;
+ } else {
+ $root = $classSynopsis;
+ $classSynopsisIndentationLevel = 3;
+ $classSynopsisIndentation = str_repeat(" ", $classSynopsisIndentationLevel);
+ }
+
$exceptionOverride = $this->type === "class" && $this->isException($classMap) ? "exception" : null;
- $ooElement = self::createOoElement($doc, $this, $exceptionOverride, true, null, 4);
+ $ooElement = self::createOoElement($doc, $this, $exceptionOverride, true, null, $classSynopsisIndentationLevel + 1);
if (!$ooElement) {
return null;
}
- $classSynopsis->appendChild(new DOMText("\n "));
+ $classSynopsis->appendChild(new DOMText("\n$classSynopsisIndentation "));
$classSynopsis->appendChild($ooElement);
foreach ($this->extends as $k => $parent) {
@@ -3763,13 +3789,13 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
null,
false,
$k === 0 ? "extends" : null,
- 4
+ $classSynopsisIndentationLevel + 1
);
if (!$ooElement) {
return null;
}
- $classSynopsis->appendChild(new DOMText("\n\n "));
+ $classSynopsis->appendChild(new DOMText("\n\n$classSynopsisIndentation "));
$classSynopsis->appendChild($ooElement);
}
@@ -3779,11 +3805,11 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
throw new Exception("Missing implemented interface " . $interface->toString());
}
- $ooElement = self::createOoElement($doc, $interfaceInfo, null, false, $k === 0 ? "implements" : null, 4);
+ $ooElement = self::createOoElement($doc, $interfaceInfo, null, false, $k === 0 ? "implements" : null, $classSynopsisIndentationLevel + 1);
if (!$ooElement) {
return null;
}
- $classSynopsis->appendChild(new DOMText("\n\n "));
+ $classSynopsis->appendChild(new DOMText("\n\n$classSynopsisIndentation "));
$classSynopsis->appendChild($ooElement);
}
@@ -3807,31 +3833,32 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
$classSynopsis,
$parentsWithInheritedConstants,
"&Constants;",
- "&InheritedConstants;"
+ "&InheritedConstants;",
+ $classSynopsisIndentationLevel + 1
);
if (!empty($this->constInfos)) {
- $classSynopsis->appendChild(new DOMText("\n\n "));
+ $classSynopsis->appendChild(new DOMText("\n\n$classSynopsisIndentation "));
$classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Constants;");
$classSynopsisInfo->setAttribute("role", "comment");
$classSynopsis->appendChild($classSynopsisInfo);
foreach ($this->constInfos as $constInfo) {
- $classSynopsis->appendChild(new DOMText("\n "));
- $fieldSynopsisElement = $constInfo->getFieldSynopsisElement($doc, $allConstInfos);
+ $classSynopsis->appendChild(new DOMText("\n$classSynopsisIndentation "));
+ $fieldSynopsisElement = $constInfo->getFieldSynopsisElement($doc, $allConstInfos, $classSynopsisIndentationLevel + 1);
$classSynopsis->appendChild($fieldSynopsisElement);
}
}
if (!empty($this->propertyInfos)) {
- $classSynopsis->appendChild(new DOMText("\n\n "));
+ $classSynopsis->appendChild(new DOMText("\n\n$classSynopsisIndentation "));
$classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Properties;");
$classSynopsisInfo->setAttribute("role", "comment");
$classSynopsis->appendChild($classSynopsisInfo);
foreach ($this->propertyInfos as $propertyInfo) {
- $classSynopsis->appendChild(new DOMText("\n "));
- $fieldSynopsisElement = $propertyInfo->getFieldSynopsisElement($doc, $allConstInfos);
+ $classSynopsis->appendChild(new DOMText("\n$classSynopsisIndentation "));
+ $fieldSynopsisElement = $propertyInfo->getFieldSynopsisElement($doc, $allConstInfos, $classSynopsisIndentationLevel + 1);
$classSynopsis->appendChild($fieldSynopsisElement);
}
}
@@ -3841,11 +3868,12 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
$classSynopsis,
$parentsWithInheritedProperties,
"&Properties;",
- "&InheritedProperties;"
+ "&InheritedProperties;",
+ $classSynopsisIndentationLevel + 1
);
if (!empty($this->funcInfos)) {
- $classSynopsis->appendChild(new DOMText("\n\n "));
+ $classSynopsis->appendChild(new DOMText("\n\n$classSynopsisIndentation "));
$classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&Methods;");
$classSynopsisInfo->setAttribute("role", "comment");
$classSynopsis->appendChild($classSynopsisInfo);
@@ -3854,35 +3882,38 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
$escapedName = addslashes($this->name->__toString());
if ($this->hasConstructor()) {
- $classSynopsis->appendChild(new DOMText("\n "));
+ $classSynopsis->appendChild(new DOMText("\n$classSynopsisIndentation "));
$includeElement = $this->createIncludeElement(
$doc,
- "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:constructorsynopsis[@role='$escapedName'])"
+ "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:constructorsynopsis[@role='$escapedName'])",
+ $classSynopsisIndentationLevel + 1
);
$classSynopsis->appendChild($includeElement);
}
if ($this->hasMethods()) {
- $classSynopsis->appendChild(new DOMText("\n "));
+ $classSynopsis->appendChild(new DOMText("\n$classSynopsisIndentation "));
$includeElement = $this->createIncludeElement(
$doc,
- "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[@role='$escapedName'])"
+ "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[@role='$escapedName'])",
+ $classSynopsisIndentationLevel + 1
);
$classSynopsis->appendChild($includeElement);
}
if ($this->hasDestructor()) {
- $classSynopsis->appendChild(new DOMText("\n "));
+ $classSynopsis->appendChild(new DOMText("\n$classSynopsisIndentation "));
$includeElement = $this->createIncludeElement(
$doc,
- "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:destructorsynopsis[@role='$escapedName'])"
+ "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$classReference')/db:refentry/db:refsect1[@role='description']/descendant::db:destructorsynopsis[@role='$escapedName'])",
+ $classSynopsisIndentationLevel + 1
);
$classSynopsis->appendChild($includeElement);
}
}
if (!empty($parentsWithInheritedMethods)) {
- $classSynopsis->appendChild(new DOMText("\n\n "));
+ $classSynopsis->appendChild(new DOMText("\n\n$classSynopsisIndentation "));
$classSynopsisInfo = $doc->createElement("classsynopsisinfo", "&InheritedMethods;");
$classSynopsisInfo->setAttribute("role", "comment");
$classSynopsis->appendChild($classSynopsisInfo);
@@ -3895,10 +3926,11 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
$escapedParentName = addslashes($parentName->__toString());
foreach ($parentMethodsynopsisTypes as $parentMethodsynopsisType) {
- $classSynopsis->appendChild(new DOMText("\n "));
+ $classSynopsis->appendChild(new DOMText("\n$classSynopsisIndentation "));
$includeElement = $this->createIncludeElement(
$doc,
- "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$parentReference')/db:refentry/db:refsect1[@role='description']/descendant::db:{$parentMethodsynopsisType}[@role='$escapedParentName'])"
+ "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$parentReference')/db:refentry/db:refsect1[@role='description']/descendant::db:{$parentMethodsynopsisType}[@role='$escapedParentName'])",
+ $classSynopsisIndentationLevel + 1
);
$classSynopsis->appendChild($includeElement);
@@ -3906,16 +3938,16 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
}
}
- $classSynopsis->appendChild(new DOMText("\n "));
+ $classSynopsis->appendChild(new DOMText("\n$classSynopsisIndentation"));
- return $classSynopsis;
+ return $root;
}
private static function createOoElement(
DOMDocument $doc,
ClassInfo $classInfo,
?string $typeOverride,
- bool $withModifiers,
+ bool $isMainClass,
?string $modifierOverride,
int $indentationLevel
): ?DOMElement {
@@ -3933,7 +3965,7 @@ private static function createOoElement(
if ($modifierOverride !== null) {
$ooElement->appendChild($doc->createElement('modifier', $modifierOverride));
$ooElement->appendChild(new DOMText("\n$indentation "));
- } elseif ($withModifiers) {
+ } elseif ($isMainClass) {
foreach ($classInfo->attributes as $attribute) {
$modifier = $doc->createElement("modifier", "#[\\" . $attribute->class . "]");
$modifier->setAttribute("role", "attribute");
@@ -3955,7 +3987,7 @@ private static function createOoElement(
}
}
- $nameElement = $doc->createElement("{$type}name", $classInfo->name->toString());
+ $nameElement = $doc->createElement("{$type}name", $isMainClass ? $classInfo->getClassName() : $classInfo->name->toString());
$ooElement->appendChild($nameElement);
$ooElement->appendChild(new DOMText("\n$indentation"));
@@ -4124,16 +4156,30 @@ private function hasMethods(): bool
return false;
}
- private function createIncludeElement(DOMDocument $doc, string $query): DOMElement
+ public function getNamespace(): ?string {
+ if ($this->name->isQualified()) {
+ return $this->name->slice(0, -1)->toString();
+ }
+
+ return null;
+ }
+
+ public function getClassName(): string {
+ return $this->name->getLast();
+ }
+
+ private function createIncludeElement(DOMDocument $doc, string $query, int $indentationLevel): DOMElement
{
+ $indentation = str_repeat(" ", $indentationLevel);
+
$includeElement = $doc->createElement("xi:include");
$attr = $doc->createAttribute("xpointer");
$attr->value = $query;
$includeElement->appendChild($attr);
$fallbackElement = $doc->createElement("xi:fallback");
- $includeElement->appendChild(new DOMText("\n "));
+ $includeElement->appendChild(new DOMText("\n$indentation "));
$includeElement->appendChild($fallbackElement);
- $includeElement->appendChild(new DOMText("\n "));
+ $includeElement->appendChild(new DOMText("\n$indentation"));
return $includeElement;
}
@@ -4156,24 +4202,27 @@ public function __clone()
/**
* @param Name[] $parents
*/
- private function appendInheritedMemberSectionToClassSynopsis(DOMDocument $doc, DOMElement $classSynopsis, array $parents, string $label, string $inheritedLabel): void
+ private function appendInheritedMemberSectionToClassSynopsis(DOMDocument $doc, DOMElement $classSynopsis, array $parents, string $label, string $inheritedLabel, int $indentationLevel): void
{
if (empty($parents)) {
return;
}
- $classSynopsis->appendChild(new DOMText("\n\n "));
+ $indentation = str_repeat(" ", $indentationLevel);
+
+ $classSynopsis->appendChild(new DOMText("\n\n$indentation"));
$classSynopsisInfo = $doc->createElement("classsynopsisinfo", "$inheritedLabel");
$classSynopsisInfo->setAttribute("role", "comment");
$classSynopsis->appendChild($classSynopsisInfo);
foreach ($parents as $parent) {
- $classSynopsis->appendChild(new DOMText("\n "));
+ $classSynopsis->appendChild(new DOMText("\n$indentation"));
$parentReference = self::getClassSynopsisReference($parent);
$includeElement = $this->createIncludeElement(
$doc,
- "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$parentReference')/db:partintro/db:section/db:classsynopsis/db:fieldsynopsis[preceding-sibling::db:classsynopsisinfo[1][@role='comment' and text()='$label']]))"
+ "xmlns(db=http://docbook.org/ns/docbook) xpointer(id('$parentReference')/db:partintro/db:section/db:classsynopsis/db:fieldsynopsis[preceding-sibling::db:classsynopsisinfo[1][@role='comment' and text()='$label']]))",
+ $indentationLevel
);
$classSynopsis->appendChild($includeElement);
}