Skip to content

Require PHP >=8.1 and migrate tooling from Psalm to PHPStan#43

Merged
loevgaard merged 6 commits into
1.xfrom
php-81-phpstan-migration
Jun 30, 2026
Merged

Require PHP >=8.1 and migrate tooling from Psalm to PHPStan#43
loevgaard merged 6 commits into
1.xfrom
php-81-phpstan-migration

Conversation

@loevgaard

@loevgaard loevgaard commented Jun 30, 2026

Copy link
Copy Markdown
Member

Closes #5

What

Modernises the package toolchain and makes the test suite self-contained:

  • PHP >=7.4>=8.1 (composer.json + CI matrix).
  • Psalm → PHPStan. Removes psalm.xml / psalm-baseline.xml, adds phpstan.neon.dist. composer analyse now runs phpstan analyse.
  • Inlines the dev tooling that the newest setono/code-quality-pack bundles directly into require-dev (PHPStan + extensions, PHPUnit 10, Rector, Infection, ECS via sylius-labs/coding-standard, shipmonk/composer-dependency-analyser).
  • Removes roave/security-advisories and setono/code-quality-pack from require-dev, and the stale extra.branch-alias.
  • Mocks the QuickPay client in tests so the suite no longer hits the live API (Closes Use mock client instead of live client in tests #5).

Offline test suite (Closes #5)

The action/model tests used to drive real payments against api.quickpay.net with shared test credentials, which made the unit-test jobs slow and flaky (async settlement timing + shared account state).

  • Adds tests/StubHttpClient.php — a Payum HttpClientInterface that returns pre-queued PSR-7 responses in FIFO order, so Api::doRequest() never reaches the network.
  • ApiTestTrait now builds the Api around the stub (and a minimal gateway sharing it, for NotifyAction's ConfirmPayment sub-request) and exposes helpers to queue canned QuickPay payment JSON.
  • The action tests and QuickpayModelTest queue the responses each flow expects; AuthorizeActionTest's token factory is a Prophecy double; the sleep() waits are gone.
  • The full suite now runs in ~50ms with no network access and is deterministic across runs (verified by proxying all traffic to a dead port).

PHPStan

  • Level 8, scoped to src/ — matching what the old Psalm config analysed. Level 9/max is impractical here because Payum's ArrayObject-based request model makes everything mixed at the API boundary.
  • All findings fixed at the root (iterable value types; the dynamic-property hydration in QuickPayModel now uses ReflectionProperty::setValue; QuickPayPayment::createFromResponse no longer has an implicit-nullable $url, which PHPStan flags on PHP 8.4+). No baseline, no ignores.

PHPUnit / test infrastructure

The suite couldn't even run on PHP 8.1 before (PHPUnit 7.5 fatals). On PHPUnit 10:

  • QuickPayGatewayFactoryTest no longer uses assertion helpers removed in PHPUnit 9 (assertAttributeInstanceOf, readAttribute, …).
  • Adds tests/GenericActionTestCase.php — a local copy of Payum's GenericActionTest (which payum/core export-ignores from its dist, so it is absent on a --prefer-dist install). Test doubles use Prophecy.

Dependencies / CI

  • guzzle 6 → 7 (php-http/guzzle7-adapter): guzzle 6 is EOL and excluded from resolution by Composer 2.10's advisory blocker, so it can no longer be installed. guzzle 7 resolves to a non-advisory version on its own — no advisory ignores needed. Adds php-http/message (legacy MessageFactory for Payum's discovery), guzzlehttp/psr7 ^2, and php-http/discovery (so the gateway builds across the lowest dependency set too).
  • ecs.php and phpunit.xml.dist ported to current config formats; adds rector.php and infection.json.dist.
  • CI runs on PHP 8.1–8.5 (lowest + highest) and swaps composer-require-checker / composer-unused for shipmonk/composer-dependency-analyser; coverage upload moved to codecov-action@v5.

Full gate is green on both lowest and highest: composer validate --strict, normalize, check-style, analyse, composer-dependency-analyser, and phpunit (138 tests, offline).

- Bump the PHP requirement from >=7.4 to >=8.1
- Replace Psalm with PHPStan (level 8, analysing src/ as the old Psalm
  config did); remove psalm.xml and psalm-baseline.xml
- Inline the dev tooling that setono/code-quality-pack used to bundle
  (PHPStan + extensions, PHPUnit 10, Rector, Infection, ECS via
  sylius-labs/coding-standard, shipmonk/composer-dependency-analyser)
  directly into require-dev, and drop roave/security-advisories and
  setono/code-quality-pack
- Add phpstan.neon.dist, rector.php and infection.json.dist; port ecs.php
  and phpunit.xml.dist to the current config formats
- Fix the type issues PHPStan surfaced in src/ (iterable value types,
  dynamic-property hydration in QuickPayModel)
- Make the test suite run on PHPUnit 10: replace the assertion helpers
  removed in PHPUnit 9 in QuickPayGatewayFactoryTest, and read the
  QuickPay error body from the response instead of the (now reformatted)
  HttpException message in CaptureActionTest
- Update CI to run on PHP 8.1-8.4 and swap composer-require-checker /
  composer-unused for shipmonk/composer-dependency-analyser
Two failures surfaced once CI ran on Composer 2.10 (which excludes
advisory-affected packages from resolution):

- guzzlehttp/guzzle ^6 + php-http/guzzle6-adapter can no longer be
  installed: every guzzle 6.x release is flagged by security advisories
  (and guzzle6-adapter is abandoned). Migrate the test HTTP client to
  guzzle 7 via php-http/guzzle7-adapter; guzzle 7 resolves to a
  non-advisory version on its own, so no advisory ignores are needed.
  Add php-http/message for the legacy MessageFactory that Payum's
  discovery still relies on, and bump guzzlehttp/psr7 to ^2.

- The action tests borrow Payum\Core\Tests\GenericActionTest, which is
  export-ignored from payum/core's dist archive, so a default
  --prefer-dist install (what CI does) doesn't ship it. Pin payum/core
  to a source install so the class is present.
…ource

Replaces the previous preferred-install=source workaround (which made CI
clone payum/core on every job and flaked on the network) with a local
copy of the base test class.

- Add tests/GenericActionTestCase.php: a trimmed copy of
  Payum\Core\Tests\GenericActionTest (which payum/core export-ignores
  from its dist, so it is absent on a --prefer-dist install). Test
  doubles use Prophecy (phpspec/prophecy-phpunit) instead of PHPUnit's
  mock builder; the abstract Generic in the data provider is an
  anonymous subclass since Prophecy cannot run inside a data provider.
- ActionTestAbstract now extends our GenericActionTestCase; drop the
  tests/bootstrap.php hack that aliased payum's test namespace and point
  phpunit at vendor/autoload.php.
- Fix QuickPayPayment::createFromResponse implicit-nullable $url
  (?string), which PHPStan flags as an error on PHP 8.4+.
- Remove the now-unused config.preferred-install and the stale
  extra.branch-alias (dev-master) block.
@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.00000% with 3 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (1.x@a0d6de8). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/Api.php 50.00% 1 Missing ⚠️
src/Model/QuickPayPayment.php 50.00% 1 Missing ⚠️
src/Model/QuickPayPaymentLink.php 0.00% 1 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff           @@
##             1.x      #43   +/-   ##
======================================
  Coverage       ?   89.50%           
  Complexity     ?      122           
======================================
  Files          ?       16           
  Lines          ?      362           
  Branches       ?        0           
======================================
  Hits           ?      324           
  Misses         ?       38           
  Partials       ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The action/model tests used to drive real payments against
api.quickpay.net with shared test credentials, which made the unit-test
jobs slow and flaky (async settlement timing + shared account state).

- Add tests/StubHttpClient.php: a Payum HttpClientInterface that returns
  pre-queued PSR-7 responses in FIFO order, so Api::doRequest() never
  reaches the network.
- ApiTestTrait now builds the Api around the stub (and a minimal gateway
  sharing it, for NotifyAction's ConfirmPayment sub-request), and exposes
  helpers to queue canned QuickPay payment JSON.
- Rewrite the action tests and QuickpayModelTest to queue the responses
  each flow expects; AuthorizeActionTest's token factory is now a Prophecy
  double. Drop the sleep() calls that waited on the real API.

The full suite now runs in ~50ms with no network access and is
deterministic across runs.
QuickPayGatewayFactoryTest builds a real gateway, and payum/core eagerly
resolves httplug.client via Http\Discovery\HttpClientDiscovery. With the
lowest dependency set, old payum/core does not pull php-http/discovery in,
so the discovery class is missing and gateway construction fails. Depend
on php-http/discovery directly (it already ships with the highest set) so
guzzle7-adapter is discoverable across all dependency ranges.
@loevgaard loevgaard merged commit c425531 into 1.x Jun 30, 2026
20 checks passed
@loevgaard loevgaard deleted the php-81-phpstan-migration branch June 30, 2026 12:00
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.

Use mock client instead of live client in tests

1 participant