Conversation
This was referenced Jun 17, 2026
sgiehl
added a commit
that referenced
this pull request
Jun 18, 2026
…24648) psr/log relocates its class files (Psr/Log -> src) between its v1 (Matomo 5) and v3 (Matomo 6). During a one-click update the running pre-update process replaces the install's files via installNewFiles() but keeps its already-initialised autoloader, which can then no longer resolve the relocated psr/log classes from their old paths - so rendering the rest of the update request fatals with 'Class Psr\Log\NullLogger not found' and the update aborts before the database migration runs. Preload the (small) psr/log package at the start of installNewFiles(), while the old files are still present, so those classes stay resolvable for the remainder of the request. This is only needed for the 5 -> 6 update and can be removed again in Matomo 6. The fix is validated end to end by the Matomo 6 dependency-upgrade PR (#24640), whose LatestStableInstall test fixture emulates exactly this preload on the downloaded stable install so the one-click update UI tests pass.
- Never emit an APPROVE review; post COMMENT for non-blocking outcomes since the verdict comes from an LLM reading the untrusted PR diff - Recompute highest_severity from finding counts instead of discarding the whole review on a trivial mismatch - Document the listFiles patch-truncation degradation for large PRs - Remove the unused codex job final_message output
Co-authored-by: aikido-pr-checks[bot] <169896070+aikido-pr-checks[bot]@users.noreply.github.com>
Without the secret, openai/codex-action skips starting its proxy but still tries to read the server-info file, crashing with a cryptic "Failed to read server info" error. Add an early guard so the cause is clear in the codex job log.
Update the minimum PHP version in the canonical locations: the early runtime guard (testMinimumPhpVersion.php), composer.json (require + platform) and the release checklist test, plus the README. The composer platform no longer needs to exceed the floor now that wikimedia/less.php is satisfied at 8.1.
Bump the lowest tested PHP version to 8.1 across the GitHub workflows, the DDEV config and PHPStan's target version. Raise the test-action generator's LATEST_PHP_VERSION to 8.4 so generated plugin matrices keep covering two PHP versions now that the minimum is 8.1.
Drop conditionals and workarounds that only applied below PHP 8.1: the argon2id <7.3 guard, the 8.0.x output-compression workaround branches (the still-reachable 8.1.4/8.1.5 branches remain), the PHP_VERSION_ID < 80100 reflection setAccessible blocks in tests, and the PHP 8.0 test-data branches. Dropping the Referrers testSuffix branch also makes its phpSerialized74 / phpSerialized expected files obsolete.
Refresh platform/platform-overrides to 8.1.0 and the content-hash so composer install resolves under the new floor. CI was failing because the lock still pinned the 7.2.9 build platform.
Targeting phpVersion 80100 reworded many already-baselined internal type errors under PHP 8.1 stubs; regenerate the baseline to match. Fix two issues in code instead of baselining them: preferredAlgorithm() returns string (not int) under 8.1, and drop the stale GdImage class.notFound ignore in CustomLogo (the class exists on 8.x).
Insights_initial and Notifications_loaded only differ in the order of tied rows/notifications (identical values), which changed because PHP 8.0 made sorting stable. UI tests now run on 8.1, so adopt the 8.x order. Refs #24638.
Pull in the regenerated min_php_ system-test expected files for PHP 8.1 (plugin-MarketingCampaignsReporting dev-17598).
UIIntegrationTest_ecommerce_overview and GoalsPages_ecommerce could capture the report title link in its :hover state (a 2px underline) because the screenshot was taken without resetting the mouse, so a leftover cursor position from an earlier test bled through. Move the cursor off-screen before capturing, matching the existing mouse.move(-10, -10) idiom. Refs #24638.
…cursor" This reverts commit 5a1555a.
Goals\Reports\Get sets title_edit_entity_url (making EnrichedHeadline render the report title as a link) when $idGoal > GoalManager::IDGOAL_ORDER (0). $idGoal is read as a string, so for ecommerce reports it is e.g. 'ecommerceOrder'. On PHP 7 "ecommerceOrder" > 0 was false (string cast to int 0); on PHP 8 it is true (int cast to string), so the ecommerce overview title was wrongly linked. Cast $idGoal to int to restore the intended behaviour on all PHP versions. Refs #24638.
Bump twig within major 3 to the latest release (3.11.3 -> 3.27.1). The Twig sandbox advisories previously ignored in composer.json (justified "blocked while Matomo supports PHP 7.2") are fixed in 3.27.1, so the 15 audit-ignore entries are removed - composer audit is clean. Also drops the now-unneeded symfony/polyfill-php81. Part of [Matomo 6] composer dependency upgrades. Refs #24638.
Twig 3.27 appends the template name and line to render-exception messages
("... in \"@Dashboard/index.twig\" at line 4."); rebaseline the screenshot
to match. Behaviour is unchanged (same safe error page) and no Matomo API
changed, so no CHANGELOG entry.
Minor bump within major 2 (lock only; constraint ~2.0 already allowed it). Part of [Matomo 6] composer dependency upgrades.
Latest within major 3 (constraint widened ~3.0.13 -> ^3.0). Part of [Matomo 6] composer dependency upgrades.
c-pchart 3.1 fixed its setAxisDisplay() param type (obsolete baseline entry removed) and returns GdImage on PHP 8.x, surfacing ImageGraph\StaticGraph::getRenderedImage()'s resource-vs-GdImage return type. Regenerated baseline; no Matomo API change.
Major bump (constraint ~2.0 -> ^3.0). The Matomo\Decompress\* API used by core/Unzip.php (DecompressInterface, Tar/Gzip/ZipArchive/PclZip extract()/errorInfo()/constructors) is unchanged, so no code changes are needed. Part of [Matomo 6] composer dependency upgrades.
Major bump (^6.0.0 -> ^7.0). php-di 7 dropped annotation support and typed its interfaces, so align Matomo's internal container code: - remove the defunct ContainerBuilder::useAnnotations(false) call (annotations are gone in 7; autowiring stays on, attributes default off - behaviour unchanged) - match the now-typed signatures: DefinitionSource::getDefinition(string): ?Definition and Container::get(string): mixed / make(string, array): mixed / injectOn(object): object Internal container only; plugin callers (strings/objects) are unaffected, so no CHANGELOG entry. Part of [Matomo 6] composer dependency upgrades.
Missed in the php-di 7 bump: this test DefinitionSource also implements DI\Definition\Source\DefinitionSource, so its getDefinition() needs the typed signature (string): ?Definition. It builds the TEST container, so the old untyped signature fataled across every suite. Test helper only.
… PHP 8.4+) php-di 7 uses NativeProxyFactory (PHP 8.4+ native lazy objects) instead of the ProxyManager-based ProxyFactory; both implement ProxyFactoryInterface. Matomo's Container::__construct typed the param as the concrete ?ProxyFactory, which rejected NativeProxyFactory on 8.4/8.5 (fataled across the whole 8.5 cell). Widen to ?ProxyFactoryInterface to match php-di 7's parent. Internal container; no CHANGELOG.
Major bump (^2.8 -> ^3.0). The geoip2 Reader + model/record API used by plugins/GeoIp2 (Reader, country/city/enterprise/isp/asn, isoCode/name/subdivisions/traits accessors) is compatible with v3 - PHPStan finds no issues. Part of [Matomo 6] composer dependency upgrades.
First of two majors (3 -> 4). The legacy lessc compatibility class (setImportDir/setFormatter/compile) used by StylesheetUIAssetMerger still exists in less.php 4, so no code change is needed. Part of [Matomo 6] composer dependency upgrades.
less.php 4 emits the shorter named CSS colors (white, red) instead of their hex equivalents (#ffffff, #ff0000) when compiling LESS. Output is functionally identical; update the AssetManagerTest expected fixture to match.
Second of two majors (4 -> 5). The legacy lessc compatibility class (setImportDir/setFormatter/compile) used by StylesheetUIAssetMerger still ships in less.php 5, so no code change is needed. Completes the less.php upgrade. Part of [Matomo 6] composer dependency upgrades.
Bumps symfony/console, event-dispatcher, monolog-bridge, process (+ dev var-dumper, yaml) from 5.4 to 6.4 LTS (the highest line installable under PHP 8.1; 7.x/8.x need 8.2/8.4). psr/container is pulled to 2.0 (compatible with php-di 7). Vendor-forced signature alignment on the ConsoleCommand base class: addArgument()/addOption() return ': static', getHelper() returns ': mixed'. handleSignal() now returns 'int|false' (Symfony 6.3+ deprecated returning nothing); it returns 0 to preserve the previous exit-after-handling behaviour. ConsoleFormatter::format() returns ': mixed' to match the monolog-bridge. The symfony/monolog-bridge ConsoleFormatter is @Final since 6.1 and its version-conditional CompatibilityFormatter trait resolves to the monolog 3 LogRecord signature under static analysis while monolog 1.x is installed; the file is excluded from PHPStan with a TODO to revisit during the monolog 3 upgrade. Part of [Matomo 6] composer dependency upgrades. No CHANGELOG entry: handleSignal() is final (plugins extend the unchanged handleSystemSignal hook), the other touched methods are disabled stubs, and ConsoleFormatter is internal.
Symfony 6.3+ terminates the process immediately after handleSignal() returns an int exit code. Matomo's signalable commands instead use signals to request a graceful shutdown (the scheduler and archiver finish the current unit of work, log the abort and stop the loop themselves), so the command must keep running after the signal is handled. Returning false preserves that behaviour, which matches Symfony 5.4 where handleSignal() did not auto-terminate. Fixes RunScheduledTasksProcessSignalTest and CoreArchiverProcessSignalTest. Verified locally: both signal test classes pass (2/20 and 16/219 assertions).
First of two coupled major steps for the logging cluster (monolog 1 -> 2, psr/log 1 -> 2). monolog 2 added return types to HandlerInterface (handle()/isHandling(): bool) and to the AbstractProcessingHandler/StreamHandler write(): void, so the custom handlers are aligned: DatabaseHandler, EchoHandler, FileHandler, WebNotificationHandler write() -> : void; FailureLogMessageDetector, LogCaptureHandler handle() -> : bool; WebNotificationHandler isHandling() -> : bool. monolog 2 keeps array records (LogRecord arrives in monolog 3) and its FormatterInterface/ProcessorInterface/ResettableInterface are still untyped, so formatters, processors and reset() are unchanged. Part of [Matomo 6] composer dependency upgrades. No CHANGELOG entry: the Monolog handlers are internal and not part of any plugin-facing API.
psr/log 2 removed the Psr\Log\Test\TestLogger helper that the test mock extended; reimplement it inline in tests/PHPUnit/Framework/Mock/TestLogger.php (same recording API the tests rely on) so it no longer depends on the dropped class. monolog 2 narrows the inherited isHandling() record type hint to the level only; add an @param phpdoc on WebNotificationHandler::isHandling() documenting that the full record (with context) is available at runtime, resolving the PHPStan error. No CHANGELOG entry: test-only mock plus an internal handler phpdoc.
monolog 2 changed the default LineFormatter date format to ISO 8601 with microseconds. The EchoHandler (used for the on-screen tracker debug output) relies on the default formatter, so override getDefaultFormatter() to keep the previous 'Y-m-d H:i:s' format and leave the user facing log output unchanged. Also add the monolog 2 write(): void return type to the anonymous handlers defined in ResetInvalidationsTest and InvalidateReportDataTest. Part of [Matomo 6] composer dependency upgrades. No CHANGELOG entry: internal handler behaviour preservation plus test-only signatures.
psr/log moves its class files (Psr/Log -> src) between major versions. During a one-click update the running (pre-update) process replaces the files but keeps its initialised autoloader, which can then no longer resolve the relocated classes, so rendering the updater result fatals with 'Class Psr\Log\NullLogger not found'. The proper fix has to ship in the Matomo version we update from (5.x): load the relocated psr/log classes before installNewFiles() swaps the files, keeping them in memory for the rest of that request. Patch the downloaded stable install in the LatestStableInstall fixture accordingly so the one-click update UI tests exercise (and prove) that upgrade path. Part of [Matomo 6] composer dependency upgrades. No CHANGELOG entry: test fixture only.
Loading Psr\Log\NullLogger transitively loads its parent AbstractLogger, the LoggerInterface it implements and the LoggerTrait it uses, which is what the updater needs to resolve the logger after the file swap. Avoids preloading the whole psr/log package.
Resolving the logger during the one-click update touches several psr/log classes (NullLogger and LogLevel at least), so preload the whole (tiny) package before installNewFiles() rather than a subset.
Final coupled major step for the logging cluster (monolog 2 -> 3, psr/log 2 -> 3). monolog 3 passes immutable Monolog\LogRecord objects instead of array records and gives its handler/processor/formatter methods LogRecord type hints. Updated the custom handlers (handle/isHandling/write), processors (__invoke) and formatters (format) to accept LogRecord; LogRecord still implements ArrayAccess so the existing field reads ($record['message'], ['extra'], ['level_name'], etc.) keep working. The processors that rewrite the message (Token, Sprintf, ExceptionToText) now use the immutable LogRecord::with() API. FailureLogMessageDetector::reset() gained the monolog 3 ': void' return type. psr/log 3 adds ': void' to the PSR-3 logger methods; Piwik\Log\Logger and NullLogger inherit it from their monolog/psr parents, so only the plugin-facing Piwik\Log\LoggerInterface contract is affected - documented under Breaking Changes in CHANGELOG.md. monolog 3 marks Monolog\Logger and the symfony/monolog-bridge ConsoleFormatter as @Final; Matomo's long-standing proxy/extension of those is intentional, so the two 'extends @Final class' notices are added to the PHPStan baseline and the temporary ConsoleFormatter PHPStan exclude is removed (its LogRecord signature now matches the bridge). Unit tests updated to build LogRecord inputs. Part of [Matomo 6] composer dependency upgrades.
psr/log 3 requires the ': void' return type on log(), and monolog 3's PsrLogMessageProcessor now consumes/returns a Monolog\LogRecord instead of an array record. Update the FakeLogger mock accordingly so it no longer fails to declare (which was breaking the unit and several integration test suites).
The anonymous AbstractProcessingHandler subclasses used to capture log output in InvalidateReportDataTest and ResetInvalidationsTest must declare write(LogRecord $record) under monolog 3; $record['formatted'] keeps working via LogRecord's ArrayAccess.
a009230 to
3841643
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds on the PHP 8.1 minimum-version bump (#24638) to upgrade Matomo's composer dependencies to the latest versions installable under PHP 8.1.
Done one package (or coupled group) at a time, one major at a time, so each breaking change is isolated to its own commit + CI run. Ordering is safe/minor bumps first, known-breaking majors last, to keep CI green as long as possible.
Scope: runtime
requiredeps;symfony/var-dumper+symfony/yamlmove with the Symfony stack. Dev tooling (phpunit/phpstan/phpdoc-parser) is a separate follow-up.Note: the PHP 8.1 floor caps Symfony at 6.4 LTS (7.x/8.x need PHP 8.2/8.4).
Progress
config.audit.ignore. Twig now appends the template source location to render errors → rebaselined theview_render_error_user_inputUI screenshot.phpstan-baseline.neon(getRenderedImage()now returnsGdImage; dropped an obsoletesetAxisDisplayentry). No production change.LocalTracker/AnonymousPiwikUsageMeasurementoverride signatures, fixture token handling and ~34assertTrue($t->doTrackXxx())sites. Too large/cross-cutting → split into its own follow-up PR; kept at 3.3.2 here.useAnnotations(false)call. Signature alignment only:Container::get/make/injectOnreturn types,proxyFactoryparam typedProxyFactoryInterface(php-di 7 usesNativeProxyFactoryon PHP 8.4+), andgetDefinition(): ?Definitionon the INI + testing definition sources.lessccompatibility class still ships → no production change. less.php 4 emits shorter named CSS colors (white/red) → updated theAssetManagerTestexpected fixture.psr/containerto 2.0. Signature alignment on theConsoleCommandbase (addArgument/addOption→: static,getHelper→: mixed);handleSignal→int|false, returnsfalseto keep signalable commands running for graceful shutdown (Symfony 6.3+ would otherwise terminate immediately).ConsoleFormatter::format→: mixed.handle/isHandling→: bool,write→: void); reimplemented the removedPsr\Log\Test\TestLoggermock; preserved the tracker debug date format viaEchoHandler::getDefaultFormatter()(monolog 2 changed the default to ISO8601). monolog 3: handlers/processors/formatters take immutableMonolog\LogRecord(itsArrayAccesskeeps field reads working; message-rewriting processors useLogRecord::with());FakeLogger/test capture handlers adapted;Monolog\Logger& the bridgeConsoleFormatterare now@final→ 2 PHPStan baseline entries. psr/log 3 adds: voidto the PSR-3 methods → documented as a Breaking Change forPiwik\Log\LoggerInterfaceimplementers inCHANGELOG.md.Upgrade-path note (psr/log)
psr/log relocated its class files (
Psr/Log/→src/) between v1 and v2/v3. During a one-click update the running (pre-update) process replaces the files but keeps its initialised autoloader, which then can't resolve the relocated classes —Class "Psr\Log\NullLogger" not found. The real fix belongs in the version updated from (5.x): preload the psr/log classes beforeUpdater::installNewFiles(). TheLatestStableInstalltest fixture emulates that fix so the one-click-update UI tests exercise and prove the 5→6 path; a matchingCoreUpdaterfix needs to ship in a Matomo 5.x release (separate PR).Checklist