Skip to content

fix: resolve container bindings without a leading backslash - #710

Merged
ViewFromTheBox merged 1 commit into
release/1.6from
bugfix/692-entity-search-controller-container-binding-backslash
Aug 7, 2026
Merged

ViewFromTheBox merged 1 commit into
release/1.6from
bugfix/692-entity-search-controller-container-binding-backslash

Conversation

@ViewFromTheBox

Copy link
Copy Markdown
Member

Description

Laravel's container does not normalise FQCN keys, so '\Foo\Bar' and Foo\Bar::class are two distinct entries. EntitySearchController::searchCmsFrameworkEntities() built the template / template-part resolver class strings with a leading backslash, so app( $resolverClass ) missed any host- or test-registered binding and silently constructed a fresh resolver instead. class_exists() behaves identically either way, which is why the guard above it hid the problem — the code "worked", just never with the override the host asked for.

This drops the leading backslash there, and sweeps the rest of the package for the same pattern.

Closes: #692

Type of Change

  • Bug fix (fixes an issue)
  • New feature (adds new functionality)
  • Enhancement (improves existing functionality)
  • Refactoring (code improvement, no behavior change)
  • Documentation update
  • Performance improvement
  • Security fix
  • Breaking change (breaks backward compatibility)

Related Issue

Issue: #692

Motivation and Context

Host apps and test suites can't decorate or stub the site-editor resolvers behind the entity-search endpoint — their binding is registered under the canonical key and the controller looks up a different one. The failure is silent: results still come back, just from the wrong (freshly-constructed) instance.

Pre-existing; not introduced by #688. Found during review of #689 while fixing the identical bug in TemplatePartInliner — that one surfaced only because a new test tried to inject a stub resolver and quietly got the real one instead. It was left out of #689 to keep that diff scoped.

Changes Made

  • EntitySearchController — dropped the leading \ from both resolver class strings, with a comment explaining why the canonical key matters.
  • Swept the package for the same pattern and corrected every site whose class string is resolved through the container:
    • VisualEditorServiceProvider::registerQueryResolverBinding() — QueryRuntime (via $app->make())
    • SnippetBlock::renderTree() — BlockRenderer
    • DynamicLoopBlock — BlockRenderer
    • VisibilityEvaluator::resolveRoles() — RoleManager
    • MenuLocationsController — ThemeManager (plus the sibling MenuLocationAssignment string in the same statement, for consistency)
  • Deliberately left alone the sites whose class strings only feed class_exists() or static Eloquent calls, where the leading backslash is inert: PatternInliner::PATTERN_MODEL, CustomFieldSource's $cmsField, and MenuLocationsController::cmsFrameworkAvailable(). Changing those would widen the diff without fixing anything.

How Has This Been Tested?

Testing Environment:

  • Operating System: macOS (Darwin 27.0.0)
  • Browser (if applicable): n/a — server-side
  • PHP Version: 8.4.3
  • Project Version: 1.5.5 (branched off release/1.6)

Tests Performed:

  1. Full package suite: composer test — 1741 passed, 1 skipped, 4570 assertions.
  2. Verified the new tests are genuine regression guards: temporarily restored the leading backslash in EntitySearchController and confirmed the template override test fails, then confirmed it passes with the fix.
  3. Manual verification in the dev app — the link-control menu picker still populates Template / Template Part results against a real cms-framework install; smoke-checked the dynamic loop / snippet block rendering and the menu-locations endpoint, since those share the fix.

Accessibility Tests Run

  • Keyboard navigation tested
  • Screen reader tested
  • Color contrast verified
  • ARIA labels checked

Details: Not applicable — this is a server-side container-resolution fix with no rendered output or markup changes. The picker's UI is unchanged.

Tests Added

  • Unit tests added/updated
  • Integration tests added/updated
  • All tests passing

Test details: Two regression tests in tests/Feature/VisualEditor/EntitySearchControllerTest.php bind stand-in TemplateResolver / TemplatePartResolver instances under the canonical key and assert the controller uses them. The template test also pins the alphabetical sort; the template-part test exercises the q= needle filter. Both fail against the old string.

The two pre-existing "cms-framework is not installed" tests were renamed to "when no theme resolves" — cms-framework is present in the Testbench environment, so the empty result comes from there being no active theme, not from a missing package. The file's header comment was corrected to match.

Documentation

  • Inline code documentation added
  • README updated
  • Wiki updated
  • API documentation updated

Documentation details: Added an inline comment at the fix site explaining the container's lack of FQCN normalisation, so the missing backslash reads as deliberate rather than as a typo waiting to be "fixed" back. No public API changed, so no README/wiki updates are needed.

Screenshots

n/a — no visual change.

Pre-Submission Checklist

  • Followed contributing guidelines
  • Checked for other open PRs for same update
  • Code passes all tests
  • Code has been linted — this package ships no lint tooling (composer.json has only a test script); style was matched by hand against the surrounding code.
  • Accessibility tests completed — n/a, see above
  • Code follows project style guide
  • Self-review completed
  • Comments added for complex code
  • No new warnings generated

Laravel's container does not normalise FQCN keys, so `'\Foo\Bar'` and
`Foo\Bar::class` are distinct entries. `EntitySearchController` built
the template / template-part resolver class strings with a leading
backslash, so `app()` missed any host- or test-registered binding and
silently constructed a fresh resolver instead. `class_exists()` behaves
identically either way, which hid the problem.

Swept the package for the same pattern and corrected every site whose
class string is resolved through the container: the query-runtime
binding in the service provider, the Blade `BlockRenderer` lookups in
SnippetBlock and DynamicLoopBlock, the RoleManager lookup in
VisibilityEvaluator, and the ThemeManager lookup in
MenuLocationsController. Sites that only feed `class_exists()` or static
Eloquent calls are left alone — the backslash is inert there.

Adds two regression tests that bind stand-in resolvers under the
canonical key and assert the controller uses them; both fail against the
old string.

Closes #692

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@ViewFromTheBox, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 33 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c387eee7-ea19-48be-b55d-a7c8d5bf5c81

📥 Commits

Reviewing files that changed from the base of the PR and between feb20d8 and ddef5fb.

📒 Files selected for processing (7)
  • src/Blocks/DynamicContent/DynamicLoopBlock.php
  • src/Blocks/DynamicContent/SnippetBlock.php
  • src/Http/Controllers/EntitySearchController.php
  • src/Http/Controllers/MenuLocationsController.php
  • src/Visibility/VisibilityEvaluator.php
  • src/VisualEditorServiceProvider.php
  • tests/Feature/VisualEditor/EntitySearchControllerTest.php

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ViewFromTheBox ViewFromTheBox moved this from Backlog to In Review in ArtisanPack UI Overview Aug 7, 2026
@ViewFromTheBox
ViewFromTheBox marked this pull request as ready for review August 7, 2026 16:17
@ViewFromTheBox
ViewFromTheBox merged commit 5dba03c into release/1.6 Aug 7, 2026
6 checks passed
@github-project-automation github-project-automation Bot moved this from In Review to Done in ArtisanPack UI Overview Aug 7, 2026
@ViewFromTheBox
ViewFromTheBox deleted the bugfix/692-entity-search-controller-container-binding-backslash branch August 7, 2026 16:18
@ViewFromTheBox ViewFromTheBox mentioned this pull request Aug 8, 2026
13 of 28 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant