Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

This is the Developer Changelog for Matomo PHP Tracker. All breaking changes or new features are listed below.

## Matomo PHP Tracker 4.0.1

### Fixed
- Loading `MatomoTracker.php` no longer emits a deprecation notice for the predefined `$http_response_header` variable on PHP 8.5. PHP reports it at compile time, so it was emitted on every include (#155).

## Matomo PHP Tracker 4.0.0

Attention: this is a major release with breaking changes.
Expand Down
10 changes: 8 additions & 2 deletions MatomoTracker.php
Original file line number Diff line number Diff line change
Expand Up @@ -2400,6 +2400,12 @@ protected function sendRequest(#[\SensitiveParameter] string $url, string $metho
$stream_options = $this->prepareStreamOptions($method, $data, $forcePostUrlEncoded);

$ctx = stream_context_create($stream_options);

// $http_response_header must be assigned before the fallback read below: PHP 8.5
// deprecated the predefined variable and reports it at compile time, so the read would
// otherwise emit a notice merely by loading this file. PHP still overwrites the value.
$http_response_header = [];

$response = @file_get_contents($url, false, $ctx);
if ($response === false && $this->exceptionsEnabled) {
// Only include the host (never the query string, which carries token_auth/PII) in the message.
Expand All @@ -2414,8 +2420,8 @@ protected function sendRequest(#[\SensitiveParameter] string $url, string $metho
$responseHeaders = $headers;
}
} elseif ($response !== false) {
// PHP populates $http_response_header in the local scope whenever an HTTP response
// was received; the $response !== false guard guarantees that is the case here.
// PHP < 8.5 has no http_get_last_response_headers() and populates the local
// variable instead, which it only does when a response was actually received.
$responseHeaders = $http_response_header;
}

Expand Down
23 changes: 23 additions & 0 deletions tests/Unit/MatomoTrackerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,29 @@ public function testStreamTransportFailSafeReturnsFalseWhenExceptionsDisabled():
$this->assertFalse($tracker->doTrackPageView('some title'));
}

/**
* Loading the tracker must not emit any notice, as tools that turn those into exceptions
* (e.g. Psalm) would abort while autoloading the class. This is what the `$http_response_header`
* assignment in `sendRequest()` guards, so that assignment must stay above the read following it.
*/
public function testLoadingTheTrackerEmitsNoDeprecationNotice(): void
{
// -n ignores the environment's php.ini, so that unrelated startup diagnostics (e.g. a
// dangling extension line) cannot fail this test
$command = escapeshellarg(PHP_BINARY)
. ' -n -d error_reporting=-1 -d display_errors=1 -d log_errors=0 -r '
. escapeshellarg('include ' . var_export(dirname(__DIR__, 2) . '/MatomoTracker.php', true) . '; echo \'loaded\';')
. ' 2>&1';

$output = [];
$exitCode = -1;
exec($command, $output, $exitCode);

// expecting the marker rather than just no output also catches a child that never ran
$this->assertSame('loaded', trim(implode("\n", $output)), 'Loading the tracker must not emit any notice');
$this->assertSame(0, $exitCode);
}

public function testGetUrlTrackCrash(): void
{
$tracker = $this->createTracker();
Expand Down
Loading