diff --git a/.devcontainer/build.sh b/.devcontainer/build.sh
new file mode 100755
index 0000000..4648539
--- /dev/null
+++ b/.devcontainer/build.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+
+set -e
+
+FORMAT="${1:-xhtml}"
+
+case "$FORMAT" in
+ xhtml) DOCROOT="output/php-chunked-xhtml" ;;
+ php) DOCROOT="../web-php" ;;
+ *) echo "Usage: $0 [xhtml|php]" >&2; exit 1 ;;
+esac
+
+php ../doc-base/configure.php \
+ --disable-libxml-check \
+ --enable-xml-details \
+ --redirect-stderr-to-stdout \
+ --with-base-lang=extensions
+
+php -d memory_limit=512M ../phd/render.php \
+ --docbook ../doc-base/.manual.xml \
+ --output ./output \
+ --package PHP \
+ --format "$FORMAT"
+
+# Restart any existing server, then launch the new one in its own session so
+# Ctrl+C in the debug terminal only kills the log tail below. The server keeps
+# running until the next build replaces it (or the container shuts down).
+#
+# auto_prepend_file rewrites $_SERVER from the request's Host header so the PHP
+# format's $MYSITE-built URLs work behind Codespaces / other port forwarders.
+LOG="/tmp/php-server-${FORMAT}.log"
+pkill -f 'php -S 0.0.0.0:8080' 2>/dev/null || true
+PREPEND="$(cd "$(dirname "$0")" && pwd)/server-prepend.php"
+setsid nohup php -d "auto_prepend_file=$PREPEND" -S 0.0.0.0:8080 -t "$DOCROOT" \
+ >"$LOG" 2>&1 "Build XHTML & serve" (or "Build PHP web & serve")
+
+ View them: http://localhost:8080
+
+EOF
diff --git a/.devcontainer/server-prepend.php b/.devcontainer/server-prepend.php
new file mode 100644
index 0000000..658e6f3
--- /dev/null
+++ b/.devcontainer/server-prepend.php
@@ -0,0 +1,15 @@
+> /usr/local/etc/php/conf.d/local.ini
+
+ENV FORMAT=xhtml
+
+CMD ["sh", "-c", "\
+php doc-base/configure.php --with-base-lang=extensions && \
+exec php phd/render.php \
+ --docbook doc-base/.manual.xml \
+ --output=/var/www/extensions/output \
+ --package PHP \
+ --format ${FORMAT} \
+"]
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..02c4fef
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,12 @@
+; This file is for unifying the coding style for different editors and IDEs.
+; More information at https://editorconfig.org
+
+root = true
+
+[*.xml]
+charset = utf-8
+indent_size = 1
+indent_style = space
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dcc145f
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+*.xml linguist-detectable
+*.ent linguist-language=XML linguist-detectable
diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml
new file mode 100644
index 0000000..7fc8695
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug-report.yml
@@ -0,0 +1,43 @@
+name: "Bug Report"
+description: "Report an issue with the PHP documentation"
+labels: ["bug"]
+
+body:
+ - type: input
+ id: affected-page
+ attributes:
+ label: "Affected page"
+ description: "Provide the URL or file path of the affected documentation page."
+ placeholder: "e.g., https://www.php.net/manual/extensions/function.strlen.php"
+ validations:
+ required: true
+
+ - type: textarea
+ id: issue-description
+ attributes:
+ label: "Issue description"
+ description: "Describe the bug, including incorrect behavior, broken links, or missing content."
+ placeholder: "Describe what's wrong or missing on the page."
+ validations:
+ required: true
+
+ - type: textarea
+ id: steps-to-reproduce
+ attributes:
+ label: "Steps to reproduce"
+ description: "Explain how to reproduce the issue."
+ placeholder: |
+ 1. Go to the page
+ 2. Describe the actions
+ 3. Explain the expected behavior
+ validations:
+ required: false
+
+ - type: textarea
+ id: suggested-fix
+ attributes:
+ label: "Suggested fix"
+ description: "Provide corrections or relevant references if possible."
+ placeholder: "e.g., link to correct behavior or suggested text/code."
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/documentation-improvement.yml b/.github/ISSUE_TEMPLATE/documentation-improvement.yml
new file mode 100644
index 0000000..ddda53a
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/documentation-improvement.yml
@@ -0,0 +1,40 @@
+name: "Documentation Improvement"
+description: "Suggest an improvement for the PHP documentation"
+labels: ["enhancement"]
+
+body:
+ - type: input
+ id: affected-page
+ attributes:
+ label: "Affected page"
+ description: "Provide the URL or file path of the documentation to improve."
+ placeholder: "e.g., https://www.php.net/manual/extensions/function.strlen.php"
+ validations:
+ required: true
+
+ - type: textarea
+ id: current-issue
+ attributes:
+ label: "Current issue"
+ description: "Explain what is wrong or lacking, such as outdated info, missing examples, or unclear explanations."
+ placeholder: "Explain why the current documentation needs improvement."
+ validations:
+ required: true
+
+ - type: textarea
+ id: suggested-improvement
+ attributes:
+ label: "Suggested improvement"
+ description: "Provide updated content, better examples, or clarifications."
+ placeholder: "Share your proposed improvement."
+ validations:
+ required: true
+
+ - type: textarea
+ id: additional-context
+ attributes:
+ label: "Additional context (optional)"
+ description: "Provide references, links, or examples from official or relevant sources."
+ placeholder: "Optional references or further explanation."
+ validations:
+ required: false
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..3237fd1
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,10 @@
+version: 2
+updates:
+ - package-ecosystem: "devcontainers"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "monthly"
diff --git a/.github/workflows/docbook-cs.yaml b/.github/workflows/docbook-cs.yaml
new file mode 100644
index 0000000..6bf8f77
--- /dev/null
+++ b/.github/workflows/docbook-cs.yaml
@@ -0,0 +1,110 @@
+# https://docs.github.com/en/actions
+
+name: "DocBook Lint"
+
+on:
+ push:
+ branches:
+ - "main"
+ pull_request:
+ branches:
+ - "main"
+
+permissions:
+ contents: "read"
+
+concurrency:
+ group: "${{ github.workflow }}-${{ github.ref }}"
+ cancel-in-progress: true
+
+jobs:
+ docbook-cs:
+ name: "DocBook Style Check"
+ runs-on: "ubuntu-latest"
+
+ env:
+ # Base commit to diff against: PR base on pull_request, pre-push tip on push.
+ BASE_SHA: |-
+ ${{
+ case(
+ github.event_name == 'pull_request', github.event.pull_request.base.sha,
+ github.event_name == 'push', github.event.before,
+ 'INVALID'
+ )
+ }}
+
+ strategy:
+ matrix:
+ language:
+ - "extensions"
+
+ steps:
+ - name: "Checkout php/doc-${{ matrix.language }}"
+ uses: "actions/checkout@v7"
+ with:
+ ref: "${{ github.event.pull_request.head.sha }}"
+ path: "${{ matrix.language }}"
+ fetch-depth: 50
+
+ - name: "Checkout php/doc-base"
+ uses: "actions/checkout@v7"
+ with:
+ path: "doc-base"
+ repository: "php/doc-base"
+
+ - name: "Checkout php/docbook-cs"
+ uses: "actions/checkout@v7"
+ with:
+ path: "docbook-cs"
+ repository: "php/docbook-cs"
+
+ - name: "Fetch diff base"
+ working-directory: "${{ matrix.language }}"
+ run: |
+ git fetch origin "$BASE_SHA" --depth=50
+ # Deepen until the merge-base is reachable (long-lived branches)
+ for i in 1 2 3 4 5; do
+ git merge-base "$BASE_SHA" HEAD >/dev/null 2>&1 && break
+ git fetch --deepen=100 origin "$BASE_SHA"
+ done
+
+ - name: "Setup PHP"
+ uses: "shivammathur/setup-php@v2"
+ with:
+ php-version: "8.5"
+ extensions: "dom, libxml, simplexml"
+ tools: composer, cs2pr
+ env:
+ fail-fast: true
+
+ - name: "Build documentation"
+ run: |
+ php doc-base/configure.php \
+ --disable-libxml-check \
+ --enable-xml-details \
+ --redirect-stderr-to-stdout \
+ --with-base-lang=${{ matrix.language }}
+
+ - name: "Install docbook-cs"
+ working-directory: "docbook-cs"
+ run: composer install --no-interaction --no-progress
+
+ - name: "Run docbook-cs with diff"
+ working-directory: "${{ matrix.language }}"
+ run: |
+ set -o pipefail
+ git diff "$BASE_SHA"...HEAD | php ../docbook-cs/bin/docbook-cs \
+ --report=checkstyle \
+ --no-colors > docbook-report.xml
+
+ - name: "Upload report"
+ if: ${{ ! cancelled() }}
+ uses: "actions/upload-artifact@v7"
+ with:
+ name: "docbook-report"
+ path: "${{ matrix.language }}/docbook-report.xml"
+
+ - name: "Annotate PR with violations"
+ if: ${{ ! cancelled() }}
+ working-directory: "${{ matrix.language }}"
+ run: cs2pr docbook-report.xml --colorize --prepend-filename
diff --git a/.github/workflows/integrate.yaml b/.github/workflows/integrate.yaml
new file mode 100644
index 0000000..733ec28
--- /dev/null
+++ b/.github/workflows/integrate.yaml
@@ -0,0 +1,54 @@
+# https://docs.github.com/en/actions
+
+name: "Integrate"
+
+on:
+ pull_request: null
+ push:
+ branches:
+ - "main"
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ name: "Build"
+
+ runs-on: "ubuntu-latest"
+
+ strategy:
+ matrix:
+ language:
+ - "extensions"
+
+ steps:
+ - name: "Checkout php/doc-${{ matrix.language }}"
+ uses: "actions/checkout@v7"
+ with:
+ path: "${{ matrix.language }}"
+ repository: "php/doc-${{ matrix.language }}"
+
+ - name: "Checkout php/doc-base"
+ uses: "actions/checkout@v7"
+ with:
+ path: "doc-base"
+ repository: "php/doc-base"
+
+ - name: "Setup PHP"
+ uses: "shivammathur/setup-php@v2"
+ with:
+ php-version: "8.5"
+ extensions: "dom, libxml, simplexml"
+ env:
+ fail-fast: true
+
+ - name: "Build documentation for ${{ matrix.language }}"
+ run: "php doc-base/configure.php --disable-libxml-check --enable-xml-details --redirect-stderr-to-stdout --with-base-lang=${{ matrix.language }}"
+
+ - name: "Upload .manual.xml"
+ uses: actions/upload-artifact@v7
+ with:
+ name: .manual.xml
+ path: doc-base/.manual.xml
+ include-hidden-files: true
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3569f8c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+output/
+temp/
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..558b9e1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,34 @@
+.PHONY: *
+
+SHELL = /bin/sh
+
+CURRENT_UID := $(shell id -u)
+CURRENT_GID := $(shell id -g)
+
+#
+# If doc-base or phd exist as siblings to the current directory, add those as
+# volumes to our Docker runs.
+#
+
+PATHS := -v ${PWD}:/var/www/extensions
+ifneq ($(wildcard ../doc-base/LICENSE),)
+ PATHS += -v ${PWD}/../doc-base:/var/www/doc-base
+endif
+ifneq ($(wildcard ../phd/LICENSE),)
+ PATHS += -v ${PWD}/../phd:/var/www/phd
+endif
+
+xhtml: temp/.dockerbuilt
+ docker run --rm ${PATHS} -w /var/www -u ${CURRENT_UID}:${CURRENT_GID} php/doc-extensions
+
+php: temp/.dockerbuilt
+ docker run --rm ${PATHS} -w /var/www -u ${CURRENT_UID}:${CURRENT_GID} \
+ -e FORMAT=php php/doc-extensions
+
+build: temp/.dockerbuilt
+
+temp/.dockerbuilt: .docker/Dockerfile
+ docker build \
+ --build-arg UID=${CURRENT_UID} --build-arg GID=${CURRENT_GID} \
+ .docker -t php/doc-extensions
+ mkdir -p temp && touch temp/.dockerbuilt
diff --git a/bookinfo.xml b/bookinfo.xml
new file mode 100644
index 0000000..e32ce2f
--- /dev/null
+++ b/bookinfo.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ This manual documents third-party PHP extensions:
+ extensions that are maintained outside the
+ php-src repository, and are typically distributed
+ via PECL or PIE.
+
+
+ It complements the main PHP manual, which documents the language
+ itself and the extensions bundled with PHP, available at
+ &url.php.docs;.
+
+
+
+
+ Copyright
+
+ Copyright © 1997 - by the PHP Documentation Group.
+ This material may be distributed only subject to the terms and
+ conditions set forth in the Creative Commons Attribution 3.0
+ License or later. The latest version is presently available at
+ &url.cc.by;.
+
+
+
+
diff --git a/docbookcs.xml b/docbookcs.xml
new file mode 100644
index 0000000..8c56e5c
--- /dev/null
+++ b/docbookcs.xml
@@ -0,0 +1,39 @@
+
+
+
+
+ extensions
+ doc-base
+
+
+
+
+
+
+
+
+
+
+
+ .
+
+
+
+ language-defs.ent
+ language-snippets.ent
+ entities/
+ ../doc-base/entities/
+ ../doc-base/temp/manual.ent
+ ../doc-base/temp/entities.ent
+ ../doc-base/temp/file-entities.ent
+ ../doc-base/temp/file-entities
+
+
+
+ output/*
+
+
+
diff --git a/language-defs.ent b/language-defs.ent
new file mode 100644
index 0000000..adb277a
--- /dev/null
+++ b/language-defs.ent
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+&Changelog;'>
+Predefined Classes'>
+Class synopsis'>
+Enum synopsis'>
+Predefined Constants'>
+Constructor'>
+Description'>
+Encoding'>
+Examples'>
+Exceptions'>
+Errors/Exceptions'>
+&FAQ;'>
+Installation'>
+Introduction'>
+Indices'>
+Interface synopsis'>
+Methods'>
+MySQL Native Driver Only'>
+Notes'>
+Parameters'>
+Options'>
+Properties'>
+Requirements'>
+Resource Types'>
+Runtime Configuration'>
+Return Values'>
+See Also'>
+Installing/Configuring'>
+Unicode'>
+Usage'>
diff --git a/language-snippets.ent b/language-snippets.ent
new file mode 100644
index 0000000..6424e77
--- /dev/null
+++ b/language-snippets.ent
@@ -0,0 +1,3 @@
+
+
+
diff --git a/manual.xml b/manual.xml
new file mode 100644
index 0000000..a1ecb4b
--- /dev/null
+++ b/manual.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+%configure;
+
+%text-entities;
+
+%translation-defs;
+%translation-snippets;
+%translation-extensions;
+
+%language-defs;
+%language-snippets;
+%language-extensions;
+
+%base-entities;
+%file-entities;
+
+]>
+
+
+ &ThirdPartyManual;
+ &bookinfo;
+
+
+
+ &ThirdPartyExtensions;
+ &reference.example.book;
+
+
+
diff --git a/reference/example/book.xml b/reference/example/book.xml
new file mode 100644
index 0000000..20771e1
--- /dev/null
+++ b/reference/example/book.xml
@@ -0,0 +1,13 @@
+
+
+ Example
+ Example
+
+
+ &reftitle.intro;
+
+ Placeholder book serving as a template for third-party extension
+ documentation; it will be removed once real extensions are added.
+
+
+