Handle Symfony 8+ strip region in RequestHeaderBasedLocaleContext by marekrzytki · Pull Request #18935 · Sylius/Sylius
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/Sylius/Bundle/CoreBundle/Telemetry/EventListener/TelemetryListener.php (1)
21-21: 🛠️ Refactor suggestion | 🟠 MajorClass should be declared
final.Per coding guidelines, all PHP classes should be
finalexcept entities and repositories.TelemetryListeneris a service class and should be marked as final.Proposed fix
/** `@internal` */ -class TelemetryListener +final class TelemetryListener {As per coding guidelines: "Use
finalfor all PHP classes, except entities and repositories".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Sylius/Bundle/CoreBundle/Telemetry/EventListener/TelemetryListener.php` at line 21, The TelemetryListener class should be declared final per coding guidelines; update the class declaration for TelemetryListener by adding the final keyword (change "class TelemetryListener" to "final class TelemetryListener") so the service class is immutable and conforms to the rule that non-entity/repository classes are final.
🧹 Nitpick comments (6)
src/Sylius/Bundle/LocaleBundle/tests/Context/RequestHeaderBasedLocaleContextTest.php (1)
100-145: Good coverage of macro-region locale scenarios.The test cases cover the key scenarios for the Symfony 8+ behavior change, including
en_150andes_419macro-region locales.Consider adding a test case for multiple Accept-Language entries where the first language has no match but a subsequent one does, to verify the fallback iteration:
📝 Suggested additional test case
yield 'first locale by language prefix when multiple macro region locales available' => [ 'acceptLanguage' => 'en', 'default' => 'en_001', 'availableLocales' => ['en_001', 'en_150'], 'expected' => 'en_001', ]; + yield 'fallback to second preferred language' => [ + 'acceptLanguage' => 'fr,en;q=0.9', + 'default' => 'en_150', + 'availableLocales' => ['en_150', 'de_DE'], + 'expected' => 'en_150', + ]; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Sylius/Bundle/LocaleBundle/tests/Context/RequestHeaderBasedLocaleContextTest.php` around lines 100 - 145, Add a test case to provideResolvingCases() that verifies fallback across multiple Accept-Language entries: provide an acceptLanguage string containing multiple comma-separated languages where the first has no match (e.g. "fr, en" or "fr;q=0.9, en;q=0.8"), set default and availableLocales so only the later language matches (e.g. availableLocales contains 'en_150' but not any 'fr' locale), and assert expected resolves to the later matching locale (e.g. 'en_150') so RequestHeaderBasedLocaleContext::provideResolvingCases covers the iteration/fallback behavior.src/Sylius/Bundle/CoreBundle/tests/DependencyInjection/ConfigurationTest.php (1)
276-277: Consider adding a test for the minimum constraint validation.The tests verify the default value, but there's no test asserting that values below 1000 are rejected. Following the pattern of other validation tests in this file (e.g.,
it_throws_an_exception_if_value_of_batch_size_is_lower_then_1), consider adding:#[Test] public function it_throws_an_exception_if_query_timeout_is_below_minimum(): void { $this->assertConfigurationIsInvalid( [['telemetry' => ['query_timeout' => 999]]], '/Should be greater than or equal to 1000/', true, ); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Sylius/Bundle/CoreBundle/tests/DependencyInjection/ConfigurationTest.php` around lines 276 - 277, Add a new unit test method named it_throws_an_exception_if_query_timeout_is_below_minimum to src/Sylius/Bundle/CoreBundle/tests/DependencyInjection/ConfigurationTest.php that calls assertConfigurationIsInvalid with a configuration array containing ['telemetry' => ['query_timeout' => 999]], expects the validation message '/Should be greater than or equal to 1000/', and sets the third argument to true (following the pattern of it_throws_an_exception_if_value_of_batch_size_is_lower_then_1); this ensures the telemetry -> query_timeout minimum constraint is asserted.src/Sylius/Bundle/CoreBundle/Tests/Telemetry/Query/TimeoutRunnerTest.php (1)
154-168: Consider adding a test for query parameters passthrough.All current tests pass empty arrays
[]for parameters. Consider adding a test case that verifies non-empty parameters are correctly forwarded to the underlying connection methods.Example test case
public function test_parameters_are_passed_through(): void { $connection = $this->createMock(Connection::class); $connection->method('getDatabasePlatform')->willReturn($this->createMock(AbstractMySQLPlatform::class)); $connection->expects(self::once()) ->method('fetchAllAssociative') ->with( self::matchesRegularExpression('/MAX_EXECUTION_TIME/'), ['status' => 'completed'], ) ->willReturn([]); $runner = new TimeoutRunner(5000); $runner->fetchAllAssociative($connection, 'SELECT * FROM orders WHERE status = :status', ['status' => 'completed']); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Sylius/Bundle/CoreBundle/Tests/Telemetry/Query/TimeoutRunnerTest.php` around lines 154 - 168, Add a new test in TimeoutRunnerTest that verifies non-empty query parameters are forwarded: create a Connection mock, stub getDatabasePlatform() to return an AbstractMySQLPlatform (or MariaDBPlatform variant as appropriate), set an expectation on the Connection::fetchAllAssociative call to assert the SQL has the injected timeout clause (use self::matchesRegularExpression('/MAX_EXECUTION_TIME|SET STATEMENT/') to be flexible) and that the second argument equals the provided params array (e.g. ['status' => 'completed']), then instantiate TimeoutRunner and call fetchAllAssociative($connection, 'SELECT ... WHERE status = :status', ['status' => 'completed']) to satisfy the expectation.UPGRADE-2.1.md (1)
1-3: Heading level should increment by one.Line 3 uses
###(h3) directly after#(h1), skipping h2. This violates the markdown heading hierarchy rule (MD001). Consider using##for "Telemetry improvements" or adding an intermediate h2 section.# UPGRADE FROM `2.1.12` TO `2.1.13` -### Telemetry improvements +## Telemetry improvements🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@UPGRADE-2.1.md` around lines 1 - 3, The markdown skips an H2 level by using "### Telemetry improvements" directly under "# UPGRADE FROM `2.1.12` TO `2.1.13`"; update the heading hierarchy by changing "### Telemetry improvements" to "## Telemetry improvements" (or insert an intermediate H2 before it) so the headings increment correctly and satisfy MD001; locate the "Telemetry improvements" heading in UPGRADE-2.1.md and make the edit.src/Sylius/Bundle/CoreBundle/Resources/config/services/telemetry/telemetry.xml (1)
210-214: Consider extracting HttpClient as a named service.The inline
HttpClient::create()factory works correctly, but extracting it as a named service would improve testability and allow easier customization (e.g., adding proxy settings or custom options).<service id="sylius.telemetry.http_client" class="Symfony\Contracts\HttpClient\HttpClientInterface"> <factory class="Symfony\Component\HttpClient\HttpClient" method="create" /> </service>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Sylius/Bundle/CoreBundle/Resources/config/services/telemetry/telemetry.xml` around lines 210 - 214, Extract the inline HttpClient factory into a named service so tests and configuration can override it: define a service id "sylius.telemetry.http_client" using Symfony\Component\HttpClient\HttpClient::create (service class Symfony\Contracts\HttpClient\HttpClientInterface with factory Symfony\Component\HttpClient\HttpClient::create) and then replace the inline <service>...</service> argument block that currently calls HttpClient::create with a reference to "sylius.telemetry.http_client"; ensure any places using the inline factory (the argument passed where HttpClient is injected) now reference the new service id so proxy/custom options can be configured in one place.src/Sylius/Bundle/CoreBundle/Telemetry/Query/TimeoutRunner.php (1)
46-51: Add explicit return type declaration.The
fetchAssociativemethod has a PHPDoc return type but lacks the actual PHP return type declaration. Per coding guidelines, all methods should have type declarations.- public function fetchAssociative(Connection $connection, string $sql, array $params = []) + public function fetchAssociative(Connection $connection, string $sql, array $params = []): array|false🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Sylius/Bundle/CoreBundle/Telemetry/Query/TimeoutRunner.php` around lines 46 - 51, The fetchAssociative method in TimeoutRunner lacks an explicit PHP return type; update the method signature of fetchAssociative (which calls applyTimeout and executeInTimeoutContext and invokes $connection->fetchAssociative) to include the correct return type declared in the PHPDoc (e.g., ?array or array|false as appropriate) so the signature explicitly matches the documented return type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/Sylius/Bundle/CoreBundle/Telemetry/Provider/Business/OrdersBusinessDataProvider.php`:
- Around line 29-32: The constructor-promoted properties in
OrdersBusinessDataProvider::__construct (the Connection $connection and
TimeoutRunner $queryTimeoutRunner) should be declared readonly to reflect
immutability; update the promoted params to readonly Connection $connection and
readonly TimeoutRunner $queryTimeoutRunner so the class-level properties are
readonly and cannot be mutated after construction.
In `@src/Sylius/Component/Core/Telemetry/Cache/TelemetryCache.php`:
- Around line 96-99: The current separate methods wasRecentlyTriggered() and
markAsRecentlyTriggered() create a race where two processes can both think the
trigger is absent; replace them with a single atomic operation (e.g.,
acquireTrigger() or tryAcquireTrigger()) that performs a check-and-set in one
step using the cache provider's atomic primitives (or wrap the check/set in a
lock) so only the caller that successfully sets the key proceeds to send
telemetry; update callers to use the new acquire method and remove the separate
check/set usage in wasRecentlyTriggered() and markAsRecentlyTriggered().
---
Outside diff comments:
In `@src/Sylius/Bundle/CoreBundle/Telemetry/EventListener/TelemetryListener.php`:
- Line 21: The TelemetryListener class should be declared final per coding
guidelines; update the class declaration for TelemetryListener by adding the
final keyword (change "class TelemetryListener" to "final class
TelemetryListener") so the service class is immutable and conforms to the rule
that non-entity/repository classes are final.
---
Nitpick comments:
In
`@src/Sylius/Bundle/CoreBundle/Resources/config/services/telemetry/telemetry.xml`:
- Around line 210-214: Extract the inline HttpClient factory into a named
service so tests and configuration can override it: define a service id
"sylius.telemetry.http_client" using
Symfony\Component\HttpClient\HttpClient::create (service class
Symfony\Contracts\HttpClient\HttpClientInterface with factory
Symfony\Component\HttpClient\HttpClient::create) and then replace the inline
<service>...</service> argument block that currently calls HttpClient::create
with a reference to "sylius.telemetry.http_client"; ensure any places using the
inline factory (the argument passed where HttpClient is injected) now reference
the new service id so proxy/custom options can be configured in one place.
In `@src/Sylius/Bundle/CoreBundle/Telemetry/Query/TimeoutRunner.php`:
- Around line 46-51: The fetchAssociative method in TimeoutRunner lacks an
explicit PHP return type; update the method signature of fetchAssociative (which
calls applyTimeout and executeInTimeoutContext and invokes
$connection->fetchAssociative) to include the correct return type declared in
the PHPDoc (e.g., ?array or array|false as appropriate) so the signature
explicitly matches the documented return type.
In
`@src/Sylius/Bundle/CoreBundle/tests/DependencyInjection/ConfigurationTest.php`:
- Around line 276-277: Add a new unit test method named
it_throws_an_exception_if_query_timeout_is_below_minimum to
src/Sylius/Bundle/CoreBundle/tests/DependencyInjection/ConfigurationTest.php
that calls assertConfigurationIsInvalid with a configuration array containing
['telemetry' => ['query_timeout' => 999]], expects the validation message
'/Should be greater than or equal to 1000/', and sets the third argument to true
(following the pattern of
it_throws_an_exception_if_value_of_batch_size_is_lower_then_1); this ensures the
telemetry -> query_timeout minimum constraint is asserted.
In `@src/Sylius/Bundle/CoreBundle/Tests/Telemetry/Query/TimeoutRunnerTest.php`:
- Around line 154-168: Add a new test in TimeoutRunnerTest that verifies
non-empty query parameters are forwarded: create a Connection mock, stub
getDatabasePlatform() to return an AbstractMySQLPlatform (or MariaDBPlatform
variant as appropriate), set an expectation on the
Connection::fetchAllAssociative call to assert the SQL has the injected timeout
clause (use self::matchesRegularExpression('/MAX_EXECUTION_TIME|SET STATEMENT/')
to be flexible) and that the second argument equals the provided params array
(e.g. ['status' => 'completed']), then instantiate TimeoutRunner and call
fetchAllAssociative($connection, 'SELECT ... WHERE status = :status', ['status'
=> 'completed']) to satisfy the expectation.
In
`@src/Sylius/Bundle/LocaleBundle/tests/Context/RequestHeaderBasedLocaleContextTest.php`:
- Around line 100-145: Add a test case to provideResolvingCases() that verifies
fallback across multiple Accept-Language entries: provide an acceptLanguage
string containing multiple comma-separated languages where the first has no
match (e.g. "fr, en" or "fr;q=0.9, en;q=0.8"), set default and availableLocales
so only the later language matches (e.g. availableLocales contains 'en_150' but
not any 'fr' locale), and assert expected resolves to the later matching locale
(e.g. 'en_150') so RequestHeaderBasedLocaleContext::provideResolvingCases covers
the iteration/fallback behavior.
In `@UPGRADE-2.1.md`:
- Around line 1-3: The markdown skips an H2 level by using "### Telemetry
improvements" directly under "# UPGRADE FROM `2.1.12` TO `2.1.13`"; update the
heading hierarchy by changing "### Telemetry improvements" to "## Telemetry
improvements" (or insert an intermediate H2 before it) so the headings increment
correctly and satisfy MD001; locate the "Telemetry improvements" heading in
UPGRADE-2.1.md and make the edit.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 07c8438d-1a1c-469b-b7cb-369179b1fc23
📒 Files selected for processing (30)
CHANGELOG-2.2.mdUPGRADE-2.1.mdcomposer.jsonsrc/Sylius/Bundle/CoreBundle/DependencyInjection/Configuration.phpsrc/Sylius/Bundle/CoreBundle/DependencyInjection/SyliusCoreExtension.phpsrc/Sylius/Bundle/CoreBundle/Resources/config/services/telemetry/telemetry.xmlsrc/Sylius/Bundle/CoreBundle/SyliusCoreBundle.phpsrc/Sylius/Bundle/CoreBundle/Telemetry/EventListener/TelemetryListener.phpsrc/Sylius/Bundle/CoreBundle/Telemetry/Provider/Business/CountriesDataProvider.phpsrc/Sylius/Bundle/CoreBundle/Telemetry/Provider/Business/CurrenciesDataProvider.phpsrc/Sylius/Bundle/CoreBundle/Telemetry/Provider/Business/LocalesDataProvider.phpsrc/Sylius/Bundle/CoreBundle/Telemetry/Provider/Business/MetricsCountsDataProvider.phpsrc/Sylius/Bundle/CoreBundle/Telemetry/Provider/Business/OrdersBusinessDataProvider.phpsrc/Sylius/Bundle/CoreBundle/Telemetry/Provider/Business/PaymentMethodsDataProvider.phpsrc/Sylius/Bundle/CoreBundle/Telemetry/Provider/Business/ShippingMethodsDataProvider.phpsrc/Sylius/Bundle/CoreBundle/Telemetry/Query/TimeoutRunner.phpsrc/Sylius/Bundle/CoreBundle/Tests/Telemetry/Query/TimeoutRunnerTest.phpsrc/Sylius/Bundle/CoreBundle/tests/DependencyInjection/ConfigurationTest.phpsrc/Sylius/Bundle/CoreBundle/tests/Telemetry/EventListener/TelemetryListenerTest.phpsrc/Sylius/Bundle/CoreBundle/tests/Telemetry/Provider/Business/CountriesDataProviderTest.phpsrc/Sylius/Bundle/CoreBundle/tests/Telemetry/Provider/Business/CurrenciesDataProviderTest.phpsrc/Sylius/Bundle/CoreBundle/tests/Telemetry/Provider/Business/LocalesDataProviderTest.phpsrc/Sylius/Bundle/CoreBundle/tests/Telemetry/Provider/Business/MetricsCountsDataProviderTest.phpsrc/Sylius/Bundle/CoreBundle/tests/Telemetry/Provider/Business/OrdersBusinessDataProviderTest.phpsrc/Sylius/Bundle/CoreBundle/tests/Telemetry/Provider/Business/PaymentMethodsDataProviderTest.phpsrc/Sylius/Bundle/CoreBundle/tests/Telemetry/Provider/Business/ShippingMethodsDataProviderTest.phpsrc/Sylius/Bundle/LocaleBundle/Context/RequestHeaderBasedLocaleContext.phpsrc/Sylius/Bundle/LocaleBundle/tests/Context/RequestHeaderBasedLocaleContextTest.phpsrc/Sylius/Component/Core/Telemetry/Cache/TelemetryCache.phpsrc/Sylius/Component/Core/Telemetry/Cache/TelemetryCacheInterface.php