Skip to content

Add Related-entities title-bar navigation with open PHP/JS filter surface - #371

Merged
AllTerrainDeveloper merged 2 commits into
trunkfrom
add/related-entities-titlebar
Jul 20, 2026
Merged

Add Related-entities title-bar navigation with open PHP/JS filter surface#371
AllTerrainDeveloper merged 2 commits into
trunkfrom
add/related-entities-titlebar

Conversation

@AllTerrainDeveloper

@AllTerrainDeveloper AllTerrainDeveloper commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

What

A "Related" title-bar button (network icon, right of the ⋯ menu) on any window whose content identity carries navigation targets. Clicking it opens a grouped dropdown; picking an item opens that entity as its own desktop window.

Built-ins cover posts and pages:

  • Commentsedit-comments.php?p={id}, with the approved + pending count the opened screen actually lists
  • Categories / Tags → one item per assigned term → term.php?taxonomy=…&tag_ID=… (grouped per taxonomy, budgeted at 32 across taxonomies)
  • Media → one item per associated attachment (featured, attached, wp-image-{id} embeds, deduped, capped at 20) → upload.php?item={id}

Developer surface (the point of the PR)

Entity-agnostic, both ends open — e.g. a payments plugin can show "Order #77" and its line items on a payment-detail window with two filters:

  • PHPdesktop_mode_window_related_entities( $related, $identity, $screen ): runs in real admin context, after desktop_mode_window_content_identity and only when an identity resolved, so plugin-injected identities for custom screens get the pass too. Malformed entries are sanitized server-side, mirroring the JS engine's validation exactly — one bad item can never cost a window its whole identity.
  • JSdesktop-mode.related-entities.items (( items, { windowId, content } )): one resolver feeds both the button's visibility and the menu build, so they can't disagree. Filters receive shallow copies — the documented items.push(…); return items idiom can't corrupt the stored identity.

Items ride the existing desktop-mode-content-identity bridge payload as WindowContentRef.related (engine cap 64; built-ins can never reach it). Built-ins attach only while the filtered identity still refers to the detected post — rewriting a gated post's identity leaks nothing.

Supporting changes

  • edit-comments.php?p=N now announces a per-post identity rooted at the post → the comments window ties to its post window.
  • IDENTITY_PARAMS gains tag_ID + item so term/media deep links get their own windows. Generic id deliberately stays transient (plugin row actions must keep navigating lists in place). One-time migration note: saved geometry for term-edit / media-detail windows resets once, since their ids change.
  • Content Graph drops its own term-…/comment-…/media-… window-id suffixes — deriveWindowId now differentiates these itself, and the suffixes forked ids away from every other open path (duplicate windows for the same entity).
  • Menu panel reuses the ⋯ panel class (drag-tracker exclusion + positioning — a pointerdown on a menu item must not start a window drag), closes cleanly on repaint/content change, suppresses the post-pick double-click that would otherwise maximize the window, and supports full keyboard navigation (arrows / Home / End / Enter / Escape, focus returned to the trigger).
  • The Related menu deliberately does not consult native URL remaps: it exists for filtered deep links, which an id-based native open would drop.

Docs

hooks-reference.md, javascript-reference.md, bridge-protocol.md updated in the same change; new recipe docs/examples/related-entities.md (PHP CPT recipe + JS filter recipe), indexed in examples/README.md.

Testing

  • PHPUnit: new tests/phpunit/tests/relatedEntities.php (20 tests — builders, caps, sanitizer edge cases incl. whitespace/'0', filter ordering, identity-rewrite guard, pending-comment gating) — full suite green (1234).
  • Vitest: new tests/vitest/related-entities.test.ts (resolver, filter contracts, menu lifecycle, keyboard nav, repaint/stale-panel) + engine related normalization + deriveWindowId regressions — full suite green (2077).
  • A high-effort multi-agent code review ran over the diff; all confirmed findings were fixed or explicitly documented (the id identity-param idea was rejected for regressing row-action navigation).
  • Manually verified on the local dev stack: button visibility follows navigation, all three groups open their targets, ties draw to the opened windows.

🤖 Generated with Claude Code

Open WordPress Playground Preview

AllTerrainDeveloper and others added 2 commits July 19, 2026 12:39
…face

A "Related" title-bar button on any window whose content identity
carries navigation targets. Built-ins cover posts/pages: Comments
(edit-comments.php?p={id}, approved + pending count), one item per
assigned term (term.php), and one item per associated media
(upload.php?item={id}). Picking an item opens it as its own window.

Developer surface, both ends open and entity-agnostic:
- PHP: desktop_mode_window_related_entities( $related, $identity,
  $screen ) — runs in real admin context after the identity filter,
  only when an identity resolved; malformed entries sanitized
  server-side (mirroring the JS engine's trim validation exactly so
  one bad item can never cost a window its whole identity).
- JS: desktop-mode.related-entities.items — applied by a single
  resolver used for both button visibility and menu build; filters
  receive shallow copies so the documented push-and-return idiom
  can't corrupt the stored identity.

The related items ride the existing desktop-mode-content-identity
bridge payload as WindowContentRef.related (engine-capped at 64;
built-ins budgeted to never reach it). Built-ins attach only while
the filtered identity still refers to the detected post, so an
identity filter that rewrites a gated post leaks nothing.

Supporting changes:
- edit-comments.php?p=N now announces a per-post identity rooted at
  the post, so the comments window ties to its post window.
- IDENTITY_PARAMS gains tag_ID and item so term/media deep links get
  their own windows (one-time window-id migration for saved term/
  media window geometry; generic `id` deliberately stays transient —
  plugin row actions must keep navigating lists in place).
- content-graph no longer appends its own term/comment/media window
  id suffixes — deriveWindowId now differentiates those, and the
  suffix forked ids away from every other open path, producing
  duplicate windows for the same entity.
- Menu panel reuses the ⋯ menu-panel class (drag-tracker exclusion +
  positioning), closes on repaint/content change without leaking its
  document listeners, suppresses the post-pick double-click that
  would otherwise maximize the window, and supports full keyboard
  navigation (arrows/Home/End/Enter/Escape).

Docs: hooks-reference, javascript-reference, bridge-protocol, new
examples/related-entities.md. Tests: PHPUnit relatedEntities.php,
vitest related-entities.test.ts, plus engine/utils coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Introduced 'Linked posts' group in the related entities menu, allowing internal hyperlinks to resolve to other posts.
- Updated the REST API to recompute content identity, including related navigation items after block editor saves.
- Added tests to ensure linked posts are correctly identified and displayed in the related entities menu.
- Enhanced JavaScript to dynamically update the related menu without page reloads.
- Updated documentation to reflect new features and changes in related entities handling.
@AllTerrainDeveloper
AllTerrainDeveloper merged commit 262e08a into trunk Jul 20, 2026
5 checks passed
@AllTerrainDeveloper
AllTerrainDeveloper deleted the add/related-entities-titlebar branch July 20, 2026 14:43
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