Skip to content

[TMP] IBX-12046: Removed Symfony 8 deprecated code usage - #822

Open
ViniTou wants to merge 10 commits into
6.0from
ibx-12046-symfony-deprecations
Open

[TMP] IBX-12046: Removed Symfony 8 deprecated code usage#822
ViniTou wants to merge 10 commits into
6.0from
ibx-12046-symfony-deprecations

Conversation

@ViniTou

@ViniTou ViniTou commented Sep 9, 2026

Copy link
Copy Markdown
Contributor
🎫 Issue IBX-12046

Related PRs:

Description:

First step of the Symfony 8 upgrade, done on Symfony 7.4: every direct Symfony deprecation the core unit and integration suites reported with SYMFONY_DEPRECATIONS_HELPER=max[direct]=0 is gone (59 → 0), and the code paths Symfony 8.0 removes outright are replaced while still running on 7.4.

Structural change — DefaultRouter becomes a decorator

  • Symfony\Bundle\FrameworkBundle\Routing\Router is @final and becomes final in 8.0, so Ibexa\Bundle\Core\Routing\DefaultRouter no longer extends it.
  • DefaultRouter is now a final decorator of router.default — service ibexa.routing.default_router, decorates: router.default — implementing RouterInterface, RequestMatcherInterface, WarmableInterface and SiteAccessAware.
  • Behaviour is unchanged: same semanticPathinfo matching, same SiteAccess-aware generate() logic.
  • The SiteAccess router, the non-SiteAccess-aware route prefixes and the logger are now constructor arguments; setSiteAccess() stays for SiteAccessAware.
  • RouterPass (which swapped the class of router.default) is removed; ChainRoutingPass only tags router.default for the chain.
  • setConfigResolver() is dropped — nothing read it.

Contract alignment

  • symfony/templating (frozen at 6.4) is dropped: Controller::render() renders through twig, getTemplateEngine()getTwig().
  • User::getSalt() is removed and eraseCredentials() is marked #[\Deprecated], as Symfony 7.3 asks.
  • UserChecker::checkPostAuth() and the two voters take the new nullable TokenInterface / Vote argument.
  • UniqueIdentifier and LocationIsContainerContentType get #[HasNamedArguments] constructors.
  • The options-array path is removed outright from the UniqueIdentifier contract — 6.0 is a major, and Symfony 8 drops it from Constraint anyway. The three subclasses in the org (discounts, segmentation) are final, and their YAML mappings and attributes already resolve to named arguments through Symfony's loaders, so only test call sites change.
  • Request::get() and nested OptionsResolver::setDefault() closures use the 7.4 replacements; symfony/options-resolver is now an explicit requirement, since core calls it directly.
  • Serializer\Annotation\IgnoreSerializer\Attribute\Ignore.

Merge order

  1. This PR.
  2. ibexa/rest — it defines its templated URI router as a DefaultRouter service inheriting the FrameworkBundle Router definition, which breaks once DefaultRouter is a decorator; the rest PR wraps an inner templated router instead.
  3. ibexa/discounts and ibexa/segmentation — test call sites for the named-arguments constraints.

For QA:

Routing is the sensitive area:

  • URL generation and matching across URI-, host- and port-based SiteAccesses, including links carrying the siteaccess route parameter.
  • nonSiteAccessAwareRoutes such as _wdt / _profiler.
  • cache:warmup and debug:router.
  • Login / logout and password-expiry checks.

Documentation:

  • Ibexa\Bundle\Core\Routing\DefaultRouter is final and no longer extends Symfony\Bundle\FrameworkBundle\Routing\Router; the SiteAccess-aware router is the router.default decorator ibexa.routing.default_router.
  • Ibexa\Core\MVC\Symfony\Controller\Controller::getTemplateEngine() is replaced by getTwig().
  • Constraints extending Ibexa\Contracts\Core\Validation\Constraint\UniqueIdentifier must be instantiated with named (or positional) arguments: new MyConstraint(identifierPath: 'identifier', existingIdPath: 'id'). The options-array form is no longer accepted.

Replaced DefaultRouter's inheritance from the @Final FrameworkBundle Router with a decorator of router.default,
dropped symfony/templating from the base Controller, and aligned Security, Validator, HttpFoundation and
OptionsResolver usages with the Symfony 7.4 contracts so the unit and integration suites report no direct
Symfony deprecations.
Missing-type ignores no longer match now typed methods, tripping reportUnmatchedIgnoredErrors.
@ViniTou ViniTou changed the title IBX-12046: Removed Symfony 8 deprecated code usage [TMP] IBX-12046: Removed Symfony 8 deprecated code usage Sep 9, 2026
@ViniTou
ViniTou force-pushed the ibx-12046-symfony-deprecations branch from d189346 to 6f649b0 Compare September 9, 2026 11:14
@ViniTou
ViniTou force-pushed the ibx-12046-symfony-deprecations branch from 38dfb70 to b3b24cd Compare September 9, 2026 13:13
…tifier

6.0 is a major and Symfony 8 removes options-array support from Constraint itself, so the contract now only
accepts named/positional arguments. The three subclasses in the org (discounts, segmentation) are final and
their production usages go through mapping loaders or attributes, which already pass named arguments; only
test call sites changed (ibexa/discounts#361, ibexa/segmentation#225).
It is an implementation detail of generate(); the reusable logic lives in the internal RequestContextFactory, which has its own test, and nothing in the organization calls the router method.
@ViniTou
ViniTou force-pushed the ibx-12046-symfony-deprecations branch from a2a18b0 to 6d52b84 Compare September 10, 2026 09:02
Both query controllers receive the page number as a query-string parameter (main-request content view,
or the fragment's own URI); request attributes and the POST body were only consulted because Request::get()
did so generically. InputBag::getInt() also turns garbage values into a 400 instead of a Pagerfanta exception.
@ViniTou
ViniTou requested a review from a team September 10, 2026 09:30
@ibexa-workflow-automation-1
ibexa-workflow-automation-1 Bot requested review from Steveb-p, alongosz, bnowak, ciastektk and mikadamczyk and removed request for a team September 10, 2026 09:31
ViniTou added a commit to ibexa/rest that referenced this pull request Sep 10, 2026
ViniTou added a commit to ibexa/rest that referenced this pull request Sep 10, 2026
The pin lives in the workflow step rather than composer.json: an inline alias is only honoured in a root
composer.json, so pinning inside the package conflicts with the ibexa/oss root requirement when the
functional job builds the full project (that job takes the branch from dependencies.json instead).
public function eraseCredentials(): void
{
$this->wrappedUser->eraseCredentials();
$wrappedUserReflection = new \ReflectionObject($this->wrappedUser);

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.

❤️
Since the method is now deprecated, Symfony 7.3+ no longer calls it, so the only remaining caller is manual application code. The ReflectionObject, hasMethod(), isPublic() and invoke() sequence is a lot of for that path, and isPublic() can never be false for an interface method. Could we drop the forwarding, or reduce it to if (method_exists($this->wrappedUser, 'eraseCredentials')) { $this->wrappedUser->eraseCredentials(); }?

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 want to drop this in actual bump to symfony 8, as I am not sure that this method was not called anywhere in sf7 stack.

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.

Dropped the isPublic() check, unreachable for an interface method: 01af398

Comment on lines +123 to 141
// Now putting back SiteAccess URI if needed.
if ($isSiteAccessAware && $siteAccess !== null && $siteAccess->matcher instanceof URILexer) {
if ($referenceType === self::ABSOLUTE_URL || $referenceType === self::NETWORK_PATH) {
$scheme = $context->getScheme();
$port = '';
if ($scheme === 'http' && $context->getHttpPort() !== 80) {
$port = ':' . $context->getHttpPort();
} elseif ($scheme === 'https' && $context->getHttpsPort() !== 443) {
$port = ':' . $context->getHttpsPort();
}

$base = $context->getHost() . $port . $context->getBaseUrl();
} else {
$base = $context->getBaseUrl();
}

$base = $context->getHost() . $port . $context->getBaseUrl();
} else {
$base = $context->getBaseUrl();
$linkUri = $base ? substr($url, strpos($url, $base) + strlen($base)) : $url;
$url = str_replace($linkUri, $siteAccess->matcher->analyseLink($linkUri), $url);
}

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.

It looks like it is a self-contained block that would read better as a private helper, like

    if ($isSiteAccessAware && $siteAccess !== null && $siteAccess->matcher instanceof URILexer) {
        $url = $this->prependSiteAccessUri($url, $context, $referenceType, $siteAccess->matcher);
    }

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.

probably, I keeped it this was to match how it look like in current version, but I dont see a reason to refactor this if changes are being made anyway.

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.

Extracted into DefaultRouter::prependSiteAccessUri(): f1f7466

Comment on lines +52 to +55
public function getInnerRouter(): RouterInterface&RequestMatcherInterface
{
return $this->innerRouter;
}

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.

This public getter exists only for DownloadControllerRequestFlowTest. The decorated service is already reachable in tests by the router.default.inner id (or the container.decorator tag). It may be worth dropping it to avoid widening the public API for a test assertion.

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.

Dropped getInnerRouter(), test fetches ibexa.routing.default_router.inner from the container instead: bd4286a

@sonarqubecloud

Copy link
Copy Markdown

@ViniTou
ViniTou requested a review from mikadamczyk September 10, 2026 12:45
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.

2 participants