Skip to content

[TASK] Migrate HyperLinkNode/ReferenceNode constructor calls to array children form#1244

Closed
CybotTM wants to merge 3 commits into
TYPO3-Documentation:mainfrom
CybotTM:feature/modernize-inline-node-ctors
Closed

[TASK] Migrate HyperLinkNode/ReferenceNode constructor calls to array children form#1244
CybotTM wants to merge 3 commits into
TYPO3-Documentation:mainfrom
CybotTM:feature/modernize-inline-node-ctors

Conversation

@CybotTM
Copy link
Copy Markdown
Contributor

@CybotTM CybotTM commented May 9, 2026

Summary

Upstream phpDocumentor/guides#1161 deprecated the string-form first argument of HyperLinkNode::__construct() and the string-form second argument of ReferenceNode::__construct() in favor of an array of InlineNodeInterface instances. The BC bridge still works but emits a Doctrine\Deprecations trigger on every call. Pre-existing tech debt — not introduced by any recent bump.

This PR removes every deprecated call site (constructor + BCInlineNodeBehavior::getValue()) in the theme, then carries the upstream data model (children as list<InlineNodeInterface>) through the local code so private helpers and node ctors stop passing flat strings around. Independent of #1243 — branched from origin/main.

Commits

  1. 665aa4b6 Mechanical migration to array-form constructors. Each call site passes either [] or [new PlainTextInlineNode($value)] — mirroring the BC bridge's internal wrapping. Behavior-preserving.

  2. 233d9004 Adopt upstream style + getChildren() passthrough.

    • TextRoles: switch to upstream's compact truthy form $x ? [new PlainTextInlineNode($x)] : [] (as in upstream ReferenceTextRole, ApiClassTextRole, ReferenceRule, Markdown LinkParser). Where the source has a guaranteed-non-empty fallback, the ternary is dropped entirely.
    • NodeTransformers: stop calling deprecated BCInlineNodeBehavior::getValue() to flatten an inline tree just to rewrap it. Pass $node->getChildren() through directly. Bit-identical for plain-text content (entire TYPO3 corpus); preserves inline structure (emphasis, code, nested refs) for any future content. Removes the last remaining BCInlineNodeBehavior::getValue() call sites in the codebase.
  3. b4f2ba88 Push the children-array form through private helpers and FileInlineNode's parent ctor.

    • Three TextRoles (ViewhelperTextRole, ViewhelperArgumentTextRole, FileTextRole) had private createNodeWithInterlink helpers that still took string|null $referenceName and did the wrap-as-PlainTextInlineNode dance internally. Wrap once at the upstream-imposed createNode boundary instead, so the private helpers operate on the upstream data model directly (array $children typed list<InlineNodeInterface> for the two Viewhelper roles; non-nullable string $fileLabel for FileTextRole, since FileInlineNode's public surface is intentionally out of scope).
    • FileInlineNode::__construct silenced a hidden [TASK]: Bump friendsofphp/php-cs-fixer from 3.93.0 to 3.93.1 #1161 deprecation trigger: it called the 4-arg BC form parent::__construct(type, ref, string, array) — the BC bridge sees a string as 3rd positional and fires the deprecation regardless of the array as 4th positional. Switch to the 3-arg form (type, ref, array).

Test plan

All run locally with PHP_BIN=php on host PHP 8.5 after each commit:

  • make phpstan[OK] No errors
  • make test-unitOK (83 tests, 183 assertions)
  • make test-integrationTests: 113, Assertions: 1131, Deprecations: 3, Skipped: 2 (the 3 deprecations are pre-existing PHP 8.5 curl_close warnings in vendor code, identical to origin/main)
  • make test-rendertest → completed, no fixture diffs (53 + 35 + 4 + 4 SINGLEPAGE files)
  • make test-docs → completed (14 SINGLEPAGE files)

No expected-fixture HTML changed across any of the three commits, confirming the migration is behavior-preserving.

… children form

Upstream phpDocumentor/guides deprecated the string-form first/second argument
of HyperLinkNode and ReferenceNode constructors in favor of an array of
InlineNodeInterface instances (see phpDocumentor/guides#1161). The BC bridge
still works but emits a Doctrine\Deprecations trigger on every call.

This migrates all local theme call sites mechanically: each site now passes
either an empty array (when the children value is the empty string) or
[new PlainTextInlineNode($value)] (otherwise) — exactly mirroring the BC
bridge's internal wrapping. No behavior change.

Test fixtures unchanged. PHPStan clean. Unit/integration/rendertest pass.

Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
@CybotTM CybotTM marked this pull request as draft May 9, 2026 11:23
CybotTM added 2 commits May 9, 2026 13:45
Refines the inline-node constructor migration from the previous commit:

- TextRoles: switch from the verbose strict-equality wrap
  (`$x === '' ? [] : [new PlainTextInlineNode($x)]`) to the truthy-compact
  form (`$x ? [new PlainTextInlineNode($x)] : []`) used throughout upstream
  (ReferenceTextRole, ApiClassTextRole, ReferenceRule, Markdown LinkParser).
  Removes intermediate `$label` temp variables. For sites with a guaranteed
  non-empty fallback (`?? 'Forge'`, `?? sprintf(...)`, `?? 'EXT:' . $extKey`)
  the ternary is dropped entirely as the empty branch is unreachable.

- NodeTransformers: stop calling the deprecated
  `BCInlineNodeBehavior::getValue()` to flatten an inline tree to a string
  just to rewrap that string as a single PlainTextInlineNode. Pass
  `\$node->getChildren()` through directly. Bit-identical for plain-text
  content (the entire TYPO3 corpus); preserves inline structure (emphasis,
  code, nested refs) for any future content that has it. In
  ReplacePermalinksNodeTransformer the conditional label-reset (when the
  visible label equals the URL) now uses `\$node->toString()` for the
  comparison instead of the deprecated `getValue()`. Removes the only
  remaining call sites of the deprecated `getValue()` in this codebase.

Same upstream issue: phpDocumentor/guides#1161.

Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
…eNode parent ctor

Three TextRoles have private `createNodeWithInterlink` helpers that took
`string|null $referenceName` and did the wrap-as-PlainTextInlineNode dance
internally. Push the wrap up to the upstream-imposed `createNode` boundary
instead, so the private helpers operate on the upstream data model
(`list<InlineNodeInterface>`) directly:

- `ViewhelperTextRole`: helper now takes `array $children`. Wrap once in
  createNode, both branches of the interlink-regex switch pass the same
  children array.
- `ViewhelperArgumentTextRole`: same pattern.
- `FileTextRole`: helper signature changes from `string|null $referenceName`
  to `string $fileLabel` (non-null). The `?? $referenceTarget` fallback
  moves to createNode. FileInlineNode's own constructor surface is
  intentionally left unchanged — that's a separate concern.

Plus one drive-by silence-fix in `FileInlineNode::__construct`: it called
the 4-arg BC form of `AbstractLinkInlineNode::__construct(type, ref,
string, array)`, which triggers the same TYPO3-Documentation#1161 deprecation we're cleaning
up everywhere else (the BC bridge sees a string as 3rd positional and
fires the deprecation regardless of the array as 4th positional). Switch
to the 3-arg form `(type, ref, array)` — no BC bridge, no trigger.

Refs phpDocumentor/guides#1161.

Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
@CybotTM
Copy link
Copy Markdown
Contributor Author

CybotTM commented May 9, 2026

Closing this voluntarily — on reflection, this PR is preparatory cleanup with no user-facing benefit at this point in time:

  • Doctrine\Deprecations is not configured to trigger errors in this project (no Deprecation::enableWithTriggerError() call, no failOnDeprecation in phpunit.xml.dist). The [TASK]: Bump friendsofphp/php-cs-fixer from 3.93.0 to 3.93.1 #1161 deprecation triggers fire silently into a counter — there is no observable symptom in CI, logs, or runtime today.
  • Upstream's migration is visibly mid-stream: the AbstractReferenceTextRole vs. CustomLinkTextRole family split forces the wrap to happen at different architectural levels in our two TextRole families, and ResolvedInventoryLink is still @internal. A more cohesive migration path may emerge from upstream later (e.g., Rector recipe, unified API, or a firm BC-bridge removal timeline).
  • Maintainer review bandwidth is real cost; submitting a no-benefit PR for review trades that without compensation.

The branch is preserved on my fork (CybotTM/render-guides:feature/modernize-inline-node-ctors) and can be re-submitted as a fresh PR when upstream's direction is clearer or a BC-removal date is announced.

The companion PR #1243 — which actually fixes the rendering bug from #1236 — stays open and is unaffected by this closure. The two were always independent (different branches, both based on origin/main).

Sorry for the noise.

@CybotTM CybotTM closed this May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant