Skip to content

IBX-8074: Made SiteAccessService react to CONFIG_SCOPE_CHANGE/RESTORE - #806

Open
Steveb-p wants to merge 4 commits into
4.6from
IBX-12204-siteaccessservice-scope-stack-4.6
Open

IBX-8074: Made SiteAccessService react to CONFIG_SCOPE_CHANGE/RESTORE#806
Steveb-p wants to merge 4 commits into
4.6from
IBX-12204-siteaccessservice-scope-stack-4.6

Conversation

@Steveb-p

@Steveb-p Steveb-p commented Aug 12, 2026

Copy link
Copy Markdown
Contributor
🎫 Issue IBX-8074

Related PRs:

Description:

Same fix as #805, backported one branch further. SiteAccessService::getCurrent() only ever returned whatever was set once via the (shared, singleton) SiteAccessAware::setSiteAccess() call. ContentPreviewHelper::changeConfigScope()/restoreConfigScope() and ConsoleCommandListener::onConsoleCommand() build a new SiteAccess and only dispatch it as a ScopeChangeEvent under MVCEvents::CONFIG_SCOPE_CHANGE/CONFIG_SCOPE_RESTORE — they never touch that shared object. So during content preview or a --siteaccess CLI run, getCurrent() kept returning the outer/main siteaccess instead of the one that's actually active.

SiteAccessService now implements EventSubscriberInterface and reacts to those two events directly, keeping a small stack: push on CONFIG_SCOPE_CHANGE, pop on CONFIG_SCOPE_RESTORE (never below the base entry, so an unbalanced restore can't null out the current siteaccess). setSiteAccess() still seeds the base of that stack, so the existing DI wiring in routing.yml and the SiteAccessAware contract are untouched.

Deliberately not the full IBX-12204/#798 rework — no changeSiteAccess()/restoreSiteAccess() API, no SiteAccessAware deprecation, no migrating ContentPreviewHelper/ConsoleCommandListener/etc. off it, no MVCEvents::SITEACCESS/FINISH_REQUEST sub-request handling. Just the reactive fix, since ContentPreviewHelper and ConsoleCommandListener already dispatch the events we need — zero changes required on their end.

For QA:

Unit coverage is in SiteAccessServiceTest (change/restore, the never-drop-base guard, nested change/restore round-tripping). To see it manually:

  1. Publish some content, then open it in Preview for a siteaccess other than the one you're currently browsing.
  2. In the preview sub-request, dump $container->get(SiteAccessServiceInterface::class)->getCurrent()->name (e.g. from a debug template block, or a breakpoint in ContentPreviewHelper::changeConfigScope() right after the call) — it should be the previewed siteaccess, not the one you started from.
  3. Leave preview — getCurrent() should be back to the original siteaccess.

Same idea for CLI: run any command with --siteaccess=<other> and confirm SiteAccessServiceInterface::getCurrent()->name reflects it instead of the default.

getCurrent() only ever reflected the value set once via the shared
SiteAccessAware::setSiteAccess() singleton, so it never picked up a scope
change dispatched by ContentPreviewHelper or ConsoleCommandListener. It now
keeps a small stack, pushing on CONFIG_SCOPE_CHANGE and popping on
CONFIG_SCOPE_RESTORE.

@konradoboza konradoboza left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one! +1 as long as CI + regressions agree.

Comment on lines +66 to +68
if (count($this->siteAccessStack) > 1) {
array_pop($this->siteAccessStack);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Early return.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd argue that this is one of the rare cases where early return makes it harder to read, because the original code does not contain a logical "negation", and the primary purpose of the code is to execute this logic check.

Changed anyway.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Makes SiteAccessService track configuration scope changes so getCurrent() reflects preview and CLI SiteAccess contexts.

Changes:

  • Adds event subscriptions and SiteAccess stack handling.
  • Registers the service as an event subscriber.
  • Adds unit coverage for stack behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/lib/MVC/Symfony/SiteAccess/SiteAccessService.php Implements scope-aware SiteAccess tracking.
src/bundle/Core/Resources/config/routing.yml Registers the event subscriber.
tests/lib/MVC/Symfony/SiteAccess/SiteAccessServiceTest.php Tests change, restore, and nesting behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/lib/MVC/Symfony/SiteAccess/SiteAccessService.php
private SiteAccessProviderInterface $provider;

private ?SiteAccess $siteAccess = null;
/** @var \Ibexa\Core\MVC\Symfony\SiteAccess[] */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** @var \Ibexa\Core\MVC\Symfony\SiteAccess[] */
/** @var list<SiteAccess> */

*/
public function onConfigScopeChange(ScopeChangeEvent $event): void
{
$this->siteAccessStack[] = $event->getSiteAccess();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If $event->getSiteAccess() returns array, shouldn't its name be plural?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Event returns a single SiteAccess.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how I connected [] on the left of the assignment with the returned array on the right 😅
I was still before morning coffee then 🫣

Comment on lines +84 to +85
$this->createMock(SiteAccessProviderInterface::class),
$this->createMock(ConfigResolverInterface::class)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These could be mocks I guess, as long as we don't put expectation one them 😉

here, and in other added test cases

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something isn't working Ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants