Change matching method in ShopContextSubscriber#39837
Conversation
|
Hi @djbuch, [Edit] |
|
Hello, I made the change you said, let's wait and see the check results. [Edit] |
Okay, even though I tested it quickly locally and it works, let's wait for the tests to be sure/safe |
|
Yes the PHPStan tests failed Error: Call to an undefined method Symfony\Component\Routing\RouterInterface::matchRequest(). Line src/PrestaShopBundle/EventListener/Admin/Context/ShopContextSubscriber.php 365 Call to an undefined method |
|
@djbuch You could try it this way: PrestaShop/app/config/admin/services.yml Line 61 in 8ab6eb7 you can replace PrestaShopBundle\EventListener\Admin\Context\ShopContextSubscriber: ~ with:
PrestaShopBundle\EventListener\Admin\Context\ShopContextSubscriber:
autowire: true
autoconfigure: true
arguments:
$router: '@router'Let's check if it doesn't throw an error anymore, and then we'll ask the others for confirmation too. |
Updated ShopContextSubscriber to enable autowiring and autoconfiguration.
|
Hello I checked the problem, and the code below helped: Could you guys check? |
|
@kpodemski where should this code go ? |
|
I haven't tested other bugs that were reported by @Codencode, I've only tested sending emails :) If that works, then it also requires removing RouterInterface and adapting tests if needed |
|
But the problem here is in the matching of the route. Because of "request.isXmlHttpRequest()" in the route definition. |
|
@djbuch I'm not sure about that, to me the problem was a mismatch in the route. After applying the changes I don't have any errors mentioned by @Codencode |
@kpodemski this solution works, I tested it for the cases that were causing issues and it's ok. |
|
@kpodemski yes but the missmatch is because of But the route exists, it is defined so it should be found. You can see that if you remove the condition [EDIT] : Did you try it in multishop context ? |
| private readonly ShopConfigurationInterface $configuration, | ||
| private readonly MultistoreFeature $multistoreFeature, | ||
| private readonly RouterInterface $router, | ||
| private readonly Router $router, |
There was a problem hiding this comment.
I think you should be able to replace this with RequestMatcherInterface the interface that implements the method you need. And the @router service correctly implements it
As much as possible we should favor using interfaces instead of explicit classes
There was a problem hiding this comment.
Hello I already tried that : 4228f42 but the check failed
There was a problem hiding this comment.
Ok tried again and with forcing the argument this time, let's see
| PrestaShopBundle\EventListener\Admin\Context\ShopContextSubscriber: | ||
| autowire: true | ||
| autoconfigure: true | ||
| arguments: | ||
| $router: '@router' |
There was a problem hiding this comment.
The autowire and autoconfigure are already set as default values on this file (at the top of the file), so in theory you don't need to change this service definition
The autowiring should also be able to automatically inject the @router service (also check my other comment about using the appropriate interface) If by lack of chance the DI doesn't inject the service you expect to you can at most limit this modifications to only the arguments part
There was a problem hiding this comment.
@jolelievre
Hi Jonathan,
If we don't pass the $router: '@router' parameter to the service, we get this error:
Cannot autowire service "PrestaShopBundle\EventListener\Admin\Context\ShopContextSubscriber": argument
"$router" of method "__construct()" references class "Symfony\Component\Routing\Router" but no such service exists.
Try changing the type-hint to one of its parents: interface "Symfony\Component\Routing\RouterInterface", interface
"Symfony\Component\Routing\RequestContextAwareInterface", interface "Symfony\Component\Routing\Generator\UrlGeneratorInterface",
or interface "Symfony\Component\Routing\Matcher\UrlMatcherInterface".
So apparently, the system can't inject Symfony\Component\Routing\Router, which is why I suggested modifying the service definition.
You're absolutely right that we can avoid re-adding autowire and autoconfigure - I was the one who led @djbuch to make that mistake.
There was a problem hiding this comment.
Hello, tried without, and I need the arguments part. But as it is written for some other Services forcing arguments in the file I think I should keep
autowire: true
autoconfigure: true
There was a problem hiding this comment.
ok my bad, let's go with then
|
Hi guys, the fix seems legit I didn't go in depth into the router matchRequest method but I understand the idea behind it and it does make sense that the full request will give better matching for advanced routing configuration that just passing the path I just commented on how this could be done in a cleaner way by using |
Added autowiring and arguments for ShopContextSubscriber.
| { | ||
| try { | ||
| $routeInfo = $this->router->match($request->getPathInfo()); | ||
| $routeInfo = $this->router->matchRequest($request); |
There was a problem hiding this comment.
We discussed about this with @kpodemski and his approach is also interesting:
$controller = $request->attributes->get('_controller');because this way of retrieving the controller is faster BUT it requires the RouterListener to have been executed as it's the one that will set this attribute. The trick thing here is that this subscriber is executed twice:
- once before the router
- once after the router
So we thought maybe both solutions could be mixed, to combine both performance and stability, something like:
// Try to get the controller already set on the request (if RouterListener was executed)
$controller = $request->attributes->get('_controller');
if (empty($controller)) {
// If the attribute is not present yet we handle the matching ourselves and get the controller via routing info
$routeInfo = $this->router->matchRequest($request);
$controller = $routeInfo['_controller'];
}There was a problem hiding this comment.
OK with that, I added these lines
| PrestaShopBundle\EventListener\Admin\Context\ShopContextSubscriber: | ||
| autowire: true | ||
| autoconfigure: true | ||
| arguments: | ||
| $router: '@router' |
There was a problem hiding this comment.
ok my bad, let's go with then
| } | ||
|
|
||
| private function mockRouter(): RouterInterface|MockObject | ||
| private function mockRouter(): Router|MockObject |
There was a problem hiding this comment.
Can you try using the interface please as well? It should work
There was a problem hiding this comment.
OK I did the change, seems to work
jolelievre
left a comment
There was a problem hiding this comment.
Thanks @djbuch and @kpodemski
| PrestaShopBundle\EventListener\Admin\Context\ShopContextSubscriber: | ||
| autowire: true | ||
| autoconfigure: true | ||
| arguments: | ||
| $router: '@router' |
There was a problem hiding this comment.
@jolelievre
Hi Jonathan,
If we don't pass the $router: '@router' parameter to the service, we get this error:
Cannot autowire service "PrestaShopBundle\EventListener\Admin\Context\ShopContextSubscriber": argument
"$router" of method "__construct()" references class "Symfony\Component\Routing\Router" but no such service exists.
Try changing the type-hint to one of its parents: interface "Symfony\Component\Routing\RouterInterface", interface
"Symfony\Component\Routing\RequestContextAwareInterface", interface "Symfony\Component\Routing\Generator\UrlGeneratorInterface",
or interface "Symfony\Component\Routing\Matcher\UrlMatcherInterface".
So apparently, the system can't inject Symfony\Component\Routing\Router, which is why I suggested modifying the service definition.
You're absolutely right that we can avoid re-adding autowire and autoconfigure - I was the one who led @djbuch to make that mistake.
|
Hello @djbuch Could you rebase on |


match()instead ofmatchRequest()caused the full Request object not to be passed to the router. This resulted inSymfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTraitgenerating a "pseudo" request without headers, breaking route conditions that rely on request properties (e.g.,request.isXmlHttpRequest()on theadmin_emails_send_testroute).2. Try to send a test email using the AJAX request
3. Verify that the request is properly handled and the
isXmlHttpRequest()condition is correctly evaluated4. Check that routes with request-based conditions (like header checks) work as expected