Skip to content

Fix all PHPStan errors and empty the baseline#126

Open
pierredup wants to merge 2 commits into
mainfrom
empty-phpstan-baseline
Open

Fix all PHPStan errors and empty the baseline#126
pierredup wants to merge 2 commits into
mainfrom
empty-phpstan-baseline

Conversation

@pierredup

Copy link
Copy Markdown
Member

Summary

Resolves every PHPStan (level max) error across the Platform, Saas, Ui and Rector tooling so that phpstan-baseline.neon no longer ignores anything — the baseline is now empty (ignoreErrors: []).

Previously the baseline suppressed 244 entries (406 underlying errors across 46 files). All of them are now fixed at the source.

Approach

Fixes address root causes only — no @phpstan-ignore comments, no baseline entries, no assert()/inline @var overrides, no silencing casts, and no type widening:

  • External LemonSqueezy payloads (integration, webhook consumer, payload converter): added runtime-validating accessor helpers (is_string/is_array guards that throw on shape mismatch) and split union-typed handling into per-type methods, instead of accessing offsets on mixed.
  • Symfony config arrays: precise array{...}-shape PHPDoc reflecting the Configuration tree, with genuine guards where values are dynamic.
  • Doctrine repositories: @extends ServiceEntityRepository<Entity> generics and narrowing of mixed query results to typed entities/lists; extended PlanFeatureRepositoryInterface where a missing method was the real cause.
  • Return types & dead code: corrected string|null → guaranteed-string via guards, removed never-null/unused union members, and eliminated always-true/false instanceof/match branches.
  • Rector rules: class_exists/interface_exists guards to narrow stringclass-string before new ReflectionClass(...), plus generics and int|false handling.
  • Test files (incl. the 143-error SchemaGeneratorTest): added small section()/arrayAt() helpers that navigate dynamic nested arrays using real PHPUnit assertArrayHasKey/assertIsArray (genuine runtime validation, not type suppression).

Verification

  • vendor/bin/phpstan[OK] No errors (--generate-baseline confirms nothing left to baseline)
  • vendor/bin/ecs check --fix → clean
  • vendor/bin/phpunit → 280 tests, 938 assertions, all passing

Resolve every PHPStan (level max) error across the Platform, Saas, Ui
and Rector tooling so phpstan-baseline.neon no longer ignores anything.

Fixes address root causes only - no @PHPStan-Ignore, no baseline
entries, no assert()/inline @var overrides, no silencing casts, and no
type widening:
- validate external LemonSqueezy payloads via runtime-checked accessors
- give Symfony config arrays precise array-shape PHPDoc
- add generics to Doctrine repositories and narrow query results
- correct return types and remove dead instanceof/match branches
- narrow dynamic test data with real PHPUnit assertions
Copilot AI review requested due to automatic review settings June 18, 2026 19:02
@coveralls

coveralls commented Jun 18, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 27784202711

Warning

No base build found for commit f5afe3a on main.
Coverage changes can't be calculated without a base build.
If a base build is processing, this comment will update automatically when it completes.

Coverage: 19.432%

Details

  • Patch coverage: 298 uncovered changes across 27 files (28 of 326 lines covered, 8.59%).

Uncovered Changes

Top 10 Files by Coverage Impact Changed Covered %
src/Bundle/Saas/Integration/LemonSqueezy.php 62 0 0.0%
src/Bundle/Saas/Webhook/Converter/LemonSqueezyPayloadConverter.php 40 0 0.0%
src/Bundle/Saas/RemoteEvent/LemonSqueezyWebhookConsumer.php 38 2 5.26%
src/Bundle/Platform/Kernel.php 28 0 0.0%
src/Bundle/Saas/Repository/PlanRepository.php 15 0 0.0%
src/Tools/Rector/Rules/AddGenericTemplateExtendsRector.php 14 0 0.0%
src/Bundle/Saas/Console/Command/SubscriptionListCommand.php 13 0 0.0%
src/Bundle/Platform/DependencyInjection/CompilerPass/AuthenticationCompilerPass.php 11 0 0.0%
src/Bundle/Platform/Security/TwoFactor/Traits/UserTwoFactor.php 10 0 0.0%
src/Bundle/Platform/Repository/UserRepository.php 9 0 0.0%
Total (29 files) 326 28 8.59%

Coverage Regressions

Requires a base build to compare against. How to fix this →


Coverage Stats

Coverage Status
Relevant Lines: 3453
Covered Lines: 671
Line Coverage: 19.43%
Coverage Strength: 2.29 hits per line

💛 - Coveralls

Copilot AI 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.

Pull request overview

This PR eliminates all PHPStan (level max) findings across the Platform, Saas, Ui bundles and Rector tooling, resulting in an empty phpstan-baseline.neon (ignoreErrors: []). The changes primarily tighten runtime validation for dynamic arrays/payloads and improve type precision in repositories, config builders, and tests.

Changes:

  • Add runtime-validated accessors / array-navigation helpers to safely handle mixed payload/config shapes (notably LemonSqueezy + config builder tests).
  • Tighten types across repositories, bundles, kernel/config processing, and cache usage to satisfy PHPStan max without baselines/ignores.
  • Update Rector rules to use reflection guards and correct return/regex handling, plus remove the baseline content.

Reviewed changes

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

Show a summary per file
File Description
tests/Bundle/Ui/Config/Builder/UiConfigBuilderTest.php Adds section() helper to safely assert/navigate nested config arrays.
tests/Bundle/Saas/RemoteEvent/LemonSqueezyWebhookConsumerTest.php Updates data provider param PHPDoc to match new event base types.
tests/Bundle/Saas/Feature/PlanFeatureManagerTest.php Adjusts repository stub return shape + adds no-op save/remove for interface parity.
tests/Bundle/Saas/Config/Builder/SaasConfigBuilderTest.php Adds arrayAt() helper and extra runtime assertions when navigating built config.
tests/Bundle/PlatformBundle/Response/RedirectResponseTest.php Switches to runtime instance check instead of is_a() class-string assertion.
tests/Bundle/PlatformBundle/Config/SchemaGeneratorTest.php Adds section() helper to safely assert/navigate generated schema arrays.
tests/Bundle/PlatformBundle/Config/Builder/PlatformConfigBuilderTest.php Adds section() helper to safely assert/navigate built config arrays.
src/Tools/Rector/Rules/EnforcePlatformEntityRepositoryRector.php Adds class_exists/interface_exists guard; updates docblock manipulation logic (contains issues noted in review).
src/Tools/Rector/Rules/AddGenericTemplateExtendsRector.php Adds reflection guards, handles preg_match_all() false, and tightens arg handling.
src/Test/Traits/UsesFixturesTrait.php Ensures decoded fixture JSON is an array and normalizes keys to strings.
src/Bundle/Ui/SolidWorxPlatformUiBundle.php Makes createContainerExtension() non-nullable.
src/Bundle/Saas/Webhook/Converter/LemonSqueezyPayloadConverter.php Validates payload shape via arrayValue/stringValue before converting to RemoteEvent types.
src/Bundle/Saas/Subscription/SubscriptionManager.php Simplifies plan id string extraction via match (true) with proper narrowing.
src/Bundle/Saas/SolidWorxPlatformSaasBundle.php Makes createContainerExtension() non-nullable.
src/Bundle/Saas/Repository/PlanRepository.php Tightens find() signature and normalizes query results to Plan lists.
src/Bundle/Saas/Repository/PlanFeatureRepositoryInterface.php Adds save/remove operations to align with actual usage.
src/Bundle/Saas/RemoteEvent/SubscriptionRemoteEvent.php Adds payload array PHPDoc for constructor.
src/Bundle/Saas/RemoteEvent/SubscriptionPaymentRemoteEvent.php Adds payload array PHPDoc for constructor.
src/Bundle/Saas/RemoteEvent/LemonSqueezyWebhookConsumer.php Splits subscription vs payment event creation and validates gateway event id extraction.
src/Bundle/Saas/Integration/Options.php Adds typed options array PHPDoc and toArray() return type detail.
src/Bundle/Saas/Integration/LemonSqueezy.php Adds runtime-validated accessors for LemonSqueezy response shapes.
src/Bundle/Saas/Feature/PlanFeatureManager.php Requires cache to be both Contracts cache + Adapter (so clear() is available); updates return doc to list<Plan>.
src/Bundle/Saas/EventSubscriber/SubscriptionEventSubscriber.php Improves invalid-status exception message context.
src/Bundle/Saas/Event/TrialStartedEvent.php Uses nullsafe access for nullable subscription DTO.
src/Bundle/Saas/Entity/Plan.php Adds generic type PHPDoc for subscriptions collection.
src/Bundle/Saas/Dto/LemonSqueezy/Meta.php Adds typed PHPDoc for customData.
src/Bundle/Saas/Doctrine/EventSubscriber/PlanIdSubscriber.php Uses slug()->lower()->toString() instead of strtolower() on unicode string.
src/Bundle/Saas/Console/Command/SubscriptionListCommand.php Hardens CLI option parsing and subscriber id formatting (proxy-safe class resolution).
src/Bundle/Saas/Config/SaasConfiguration.php Adds is_string guards in config validation closures.
src/Bundle/Saas/Config/Builder/SaasConfigBuilder.php Builds doctrine section via local accumulator to avoid mixed offset access.
src/Bundle/Platform/Twig/Components/Security/TwoFactor.php Validates form data shape before reading secret.
src/Bundle/Platform/SolidWorxPlatformBundle.php Makes createContainerExtension() non-nullable and asserts it implements ExtensionInterface.
src/Bundle/Platform/Security/TwoFactor/Traits/UserTwoFactor.php Adds list type for backup codes, null-guards for email-based identifiers, and stable reindexing.
src/Bundle/Platform/Routing/LoginPageRouteLoader.php Adds precise iterable array-shape PHPDoc and removes unnecessary string casts.
src/Bundle/Platform/Repository/UserRepository.php Fixes generics doc, removes optional class override, and hardens refresh/load behaviors.
src/Bundle/Platform/Model/User.php Throws if email is unset when resolving user identifier.
src/Bundle/Platform/Menu/Provider.php Updates SplPriorityQueue generic priority type annotation to match stable ordering priority arrays.
src/Bundle/Platform/Menu/Options.php Expands options array-shape to include extras and fixes malformed docblock opener.
src/Bundle/Platform/Kernel.php Normalizes raw config to string-keyed arrays and hardens bundle registration + 2FA enablement detection.
src/Bundle/Platform/Form/Type/Security/TwoFactorVerifyType.php Adds options array-shape PHPDoc and removes unsafe cast for secret.
src/Bundle/Platform/Form/Type/Security/LoginType.php Adds options array-shape PHPDoc for configurable field names.
src/Bundle/Platform/Feature/FeatureValue.php Safely stringifies array values by filtering to scalar/Stringable elements.
src/Bundle/Platform/DependencyInjection/SolidWorxPlatformExtension.php Updates autoconfiguration callback signature to accept Reflector and guards method-only behavior.
src/Bundle/Platform/DependencyInjection/Extension/TwoFactorExtension.php Removes incompatible default config value from method signature.
src/Bundle/Platform/DependencyInjection/CompilerPass/MenuCompilerPass.php Adds runtime guard ensuring tag attributes are arrays before offset access.
src/Bundle/Platform/DependencyInjection/CompilerPass/AuthenticationCompilerPass.php Adds runtime guards for firewalls/options argument shapes before array ops.
phpstan-baseline.neon Clears baseline to ignoreErrors: [].
Comments suppressed due to low confidence (1)

src/Tools/Rector/Rules/EnforcePlatformEntityRepositoryRector.php:192

  • while ($reflection = $reflection->getParentClass()) uses a non-boolean condition (ReflectionClass|false), which is exactly what PHPStan flags under strict rules (while.condNotBoolean). Since this PR aims to keep the baseline empty, rewrite the loop to use an explicit boolean condition and advance the parent reflection inside the loop.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

continue;
}

$typeName = $value->type->type->name;
Resolve the strict-rules, deprecation, symfony and phpunit extension
errors that surface in CI (and were previously hidden by a stale local
result cache), so the empty baseline holds under the full ruleset:

- keep override params contravariant (PlanRepository::find,
  LemonSqueezyPayloadConverter::convert, Rector refactor() rules,
  LoginType/TwoFactorVerifyType::buildForm) and narrow via guards
- add generics to form types (@extends AbstractType<mixed>) and the
  2FA component (FormInterface<mixed>)
- type Kernel::registerBundles via the non-deprecated Bundle class
- replace short ternary, mixed/int|false booleans and a useless cast
- rename getBackUpCodes() to match the interface; use getFile()
- replace always-true assertInstanceOf checks with real assertions
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.

3 participants