Skip to content

Commit

Permalink
feat: PHP 8.1 support
Browse files Browse the repository at this point in the history
This patch provides PHP 8.1 support, via the following changes:

- Adds `~8.1.0` to the list of allowed PHP versions.
- Marks a conflict with symfony/console versions prior to 5.3.11 (first version supporting PHP 8.1)
- Replaces usage of `gmstrftime()` with a combination of casting timestamps to `DateTimeImmutable` objects with a GMT timezone, and using `IntlDateFormatter::formatObject()` with an equivalent date/time format to what was used with `gmstrftime()`.
- Adds `#[\ReturnTimeWillChange]` attributes to classes implementing `JsonSerialize` to ensure they remain both backwards and forwards compatible.

Signed-off-by: Matthew Weier O'Phinney <matthew@weierophinney.net>
  • Loading branch information
weierophinney committed Dec 1, 2021
1 parent 628721c commit 797dbcd
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 140 deletions.
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"extra": {
},
"require": {
"php": "^7.4 || ~8.0.0",
"php": "^7.4 || ~8.0.0 || ~8.1.0",
"composer/package-versions-deprecated": "^1.11",
"dflydev/fig-cookies": "^2.0.1 || ^3.0",
"laminas/laminas-cli": "^0.1.5 || ^1.0",
Expand All @@ -48,7 +48,7 @@
"filp/whoops": "^2.1",
"laminas/laminas-coding-standard": "~2.2.0",
"laminas/laminas-servicemanager": "^3.3",
"phpunit/phpunit": "^9.3.10",
"phpunit/phpunit": "^9.5.5",
"psalm/plugin-phpunit": "^0.13.0",
"swoole/ide-helper": "^4.5.5",
"vimeo/psalm": "^4.0"
Expand Down Expand Up @@ -79,7 +79,8 @@
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
},
"replace": {
"zendframework/zend-expressive-swoole": "^2.5.0"
"conflict": {
"symfony/console": "<5.3.11",
"zendframework/zend-expressive-swoole": "*"
}
}
204 changes: 106 additions & 98 deletions composer.lock

Large diffs are not rendered by default.

28 changes: 17 additions & 11 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" bootstrap="test/bootstrap.php" colors="true">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./src</directory>
</include>
</coverage>
<testsuites>
<testsuite name="mezzio-swoole">
<directory>./test</directory>
</testsuite>
</testsuites>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="test/bootstrap.php"
convertDeprecationsToExceptions="true"
colors="true">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./src</directory>
</include>
</coverage>

<testsuites>
<testsuite name="mezzio-swoole">
<directory>./test</directory>
</testsuite>
</testsuites>
</phpunit>
2 changes: 1 addition & 1 deletion psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.12.0@e42bc4a23f67acba28a23bb09c348e2ff38a1d87">
<files psalm-version="4.13.1@5cf660f63b548ccd4a56f62d916ee4d6028e01a3">
<file src="src/AbstractStaticResourceHandlerFactory.php">
<MixedArgument occurrences="3">
<code>$compressionLevel</code>
Expand Down
10 changes: 7 additions & 3 deletions src/StaticResourceHandler/LastModifiedMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
namespace Mezzio\Swoole\StaticResourceHandler;

use DateTimeImmutable;
use DateTimeZone;
use IntlDateFormatter;
use Swoole\Http\Request;

use function filemtime;
use function gmstrftime;
use function preg_match;
use function trim;

class LastModifiedMiddleware implements MiddlewareInterface
{
Expand Down Expand Up @@ -42,7 +42,11 @@ public function __invoke(Request $request, string $filename, callable $next): St
}

$lastModified = filemtime($filename) ?: 0;
$formattedLastModified = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModified = new DateTimeImmutable('@' . $lastModified, new DateTimeZone('GMT'));
$formattedLastModified = IntlDateFormatter::formatObject(
$lastModified,
'EEEE dd-MMM-yy HH:mm:ss z'
);

$response->addHeader('Last-Modified', $formattedLastModified);

Expand Down
3 changes: 3 additions & 0 deletions src/Task/ServiceBasedTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
namespace Mezzio\Swoole\Task;

use Psr\Container\ContainerInterface;
// phpcs:ignore SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse
use ReturnTypeWillChange;
use Webmozart\Assert\Assert;

/**
Expand Down Expand Up @@ -59,6 +61,7 @@ public function __invoke(ContainerInterface $container)
*
* @return array
*/
#[ReturnTypeWillChange]
public function jsonSerialize()
{
return [
Expand Down
3 changes: 3 additions & 0 deletions src/Task/Task.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
namespace Mezzio\Swoole\Task;

use Psr\Container\ContainerInterface;
// phpcs:ignore SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse
use ReturnTypeWillChange;
use Webmozart\Assert\Assert;

use function array_shift;
Expand Down Expand Up @@ -63,6 +65,7 @@ public function __invoke(ContainerInterface $container)
*
* @return array
*/
#[ReturnTypeWillChange]
public function jsonSerialize()
{
return [
Expand Down
21 changes: 21 additions & 0 deletions test/FormatTimestampTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace MezzioTest\Swoole;

use DateTimeImmutable;
use DateTimeZone;
use IntlDateFormatter;

trait FormatTimestampTrait
{
public function formatTimestamp(int $timestamp): string
{
$dateTime = new DateTimeImmutable('@' . $timestamp, new DateTimeZone('GMT'));
return IntlDateFormatter::formatObject(
$dateTime,
'EEEE dd-MMM-yy HH:mm:ss z'
);
}
}
21 changes: 11 additions & 10 deletions test/StaticResourceHandler/IntegrationMappedTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,24 @@
use Mezzio\Swoole\StaticResourceHandler\MethodNotAllowedMiddleware;
use Mezzio\Swoole\StaticResourceHandler\OptionsMiddleware;
use Mezzio\Swoole\StaticResourceHandler\StaticResourceResponse;
use MezzioTest\Swoole\FormatTimestampTrait;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Swoole\Http\Request as SwooleHttpRequest;
use Swoole\Http\Response as SwooleHttpResponse;

use function filemtime;
use function filesize;
use function gmstrftime;
use function md5_file;
use function sprintf;
use function trim;

/**
* Integraiton tests for StaticMappedResourceHandler
*/
class IntegrationMappedTest extends TestCase
{
use FormatTimestampTrait;

/**
* @var FileLocationRepositoryInterface|MockObject
* @psalm-var MockObject&FileLocationRepositoryInterface
Expand Down Expand Up @@ -148,7 +149,7 @@ public function testSendStaticResourceEmitsContentAndHeadersMatchingDirectivesFo
$this->mockFileLocRepo->method('findFile')->with('/content.txt')->willReturn($file);

$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$etag = sprintf('W/"%x-%x"', $lastModified, filesize($file));

$request = $this->createMock(SwooleHttpRequest::class);
Expand Down Expand Up @@ -200,7 +201,7 @@ public function testSendStaticResourceEmitsHeadersOnlyWhenMatchingDirectivesForH
$this->mockFileLocRepo->method('findFile')->with('/content.txt')->willReturn($file);

$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$etag = sprintf('W/"%x-%x"', $lastModified, filesize($file));

$request = $this->createMock(SwooleHttpRequest::class);
Expand Down Expand Up @@ -254,7 +255,7 @@ public function testSendStaticResourceEmitsAllowHeaderWithHeadersAndNoBodyWhenMa
$this->mockFileLocRepo->method('findFile')->with('/content.txt')->willReturn($file);

$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$etag = sprintf('W/"%x-%x"', $lastModified, filesize($file));

$request = $this->createMock(SwooleHttpRequest::class);
Expand Down Expand Up @@ -309,7 +310,7 @@ public function testSendStaticResourceViaGetSkipsClientSideCacheMatchingIfNoETag
$this->mockFileLocRepo->method('findFile')->with('/content.txt')->willReturn($file);

$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$etag = sprintf('W/"%x-%x"', $lastModified, filesize($file));

$request = $this->createMock(SwooleHttpRequest::class);
Expand Down Expand Up @@ -362,7 +363,7 @@ public function testSendStaticResourceViaHeadSkipsClientSideCacheMatchingIfNoETa
$this->mockFileLocRepo->method('findFile')->with('/content.txt')->willReturn($file);

$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$etag = sprintf('W/"%x-%x"', $lastModified, filesize($file));

$request = $this->createMock(SwooleHttpRequest::class);
Expand Down Expand Up @@ -565,7 +566,7 @@ public function testSendStaticResourceViaGetHitsClientSideCacheMatchingIfLastMod
$this->mockFileLocRepo->method('findFile')->with('/content.txt')->willReturn($file);

$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);

$request = $this->createMock(SwooleHttpRequest::class);
$request->header = [
Expand Down Expand Up @@ -613,9 +614,9 @@ public function testGetDoesNotHitClientSideCacheMatchingIfLastModifiedDoesNotMat
$this->mockFileLocRepo->method('findFile')->with('/content.txt')->willReturn($file);

$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$ifModifiedSince = $lastModified - 3600;
$ifModifiedSinceFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $ifModifiedSince));
$ifModifiedSinceFormatted = $this->formatTimestamp($ifModifiedSince);

$request = $this->createMock(SwooleHttpRequest::class);
$request->header = [
Expand Down
21 changes: 11 additions & 10 deletions test/StaticResourceHandler/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,20 @@

use Mezzio\Swoole\StaticResourceHandler;
use Mezzio\Swoole\StaticResourceHandler\StaticResourceResponse;
use MezzioTest\Swoole\FormatTimestampTrait;
use PHPUnit\Framework\TestCase;
use Swoole\Http\Request as SwooleHttpRequest;
use Swoole\Http\Response as SwooleHttpResponse;

use function filemtime;
use function filesize;
use function gmstrftime;
use function md5_file;
use function sprintf;
use function trim;

class IntegrationTest extends TestCase
{
use FormatTimestampTrait;

/**
* @var string
* @psalm-var non-empty-string
Expand Down Expand Up @@ -117,7 +118,7 @@ public function testSendStaticResourceEmitsContentAndHeadersMatchingDirectivesFo
{
$file = $this->docRoot . '/content.txt';
$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$etag = sprintf('W/"%x-%x"', $lastModified, filesize($file));

$request = $this->createMock(SwooleHttpRequest::class);
Expand Down Expand Up @@ -164,7 +165,7 @@ public function testSendStaticResourceEmitsHeadersOnlyWhenMatchingDirectivesForH
{
$file = $this->docRoot . '/content.txt';
$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$etag = sprintf('W/"%x-%x"', $lastModified, filesize($file));

$request = $this->createMock(SwooleHttpRequest::class);
Expand Down Expand Up @@ -213,7 +214,7 @@ public function testSendStaticResourceEmitsAllowHeaderWithHeadersAndNoBodyWhenMa
{
$file = $this->docRoot . '/content.txt';
$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$etag = sprintf('W/"%x-%x"', $lastModified, filesize($file));

$request = $this->createMock(SwooleHttpRequest::class);
Expand Down Expand Up @@ -263,7 +264,7 @@ public function testSendStaticResourceViaGetSkipsClientSideCacheMatchingIfNoETag
{
$file = $this->docRoot . '/content.txt';
$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$etag = sprintf('W/"%x-%x"', $lastModified, filesize($file));

$request = $this->createMock(SwooleHttpRequest::class);
Expand Down Expand Up @@ -311,7 +312,7 @@ public function testSendStaticResourceViaHeadSkipsClientSideCacheMatchingIfNoETa
{
$file = $this->docRoot . '/content.txt';
$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$etag = sprintf('W/"%x-%x"', $lastModified, filesize($file));

$request = $this->createMock(SwooleHttpRequest::class);
Expand Down Expand Up @@ -494,7 +495,7 @@ public function testSendStaticResourceViaGetHitsClientSideCacheMatchingIfLastMod
{
$file = $this->docRoot . '/content.txt';
$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);

$request = $this->createMock(SwooleHttpRequest::class);
$request->header = [
Expand Down Expand Up @@ -537,9 +538,9 @@ public function testGetDoesNotHitClientSideCacheMatchingIfLastModifiedDoesNotMat
{
$file = $this->docRoot . '/content.txt';
$lastModified = filemtime($file);
$lastModifiedFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $lastModified));
$lastModifiedFormatted = $this->formatTimestamp($lastModified);
$ifModifiedSince = $lastModified - 3600;
$ifModifiedSinceFormatted = trim(gmstrftime('%A %d-%b-%y %T %Z', $ifModifiedSince));
$ifModifiedSinceFormatted = $this->formatTimestamp($ifModifiedSince);

$request = $this->createMock(SwooleHttpRequest::class);
$request->header = [
Expand Down
6 changes: 3 additions & 3 deletions test/StaticResourceHandler/LastModifiedMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@
use Mezzio\Swoole\StaticResourceHandler\LastModifiedMiddleware;
use Mezzio\Swoole\StaticResourceHandler\StaticResourceResponse;
use MezzioTest\Swoole\AssertResponseTrait;
use MezzioTest\Swoole\FormatTimestampTrait;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Swoole\Http\Request;

use function gmstrftime;
use function time;
use function trim;

class LastModifiedMiddlewareTest extends TestCase
{
use AssertResponseTrait;
use FormatTimestampTrait;

/** @var callable */
private $next;
Expand Down Expand Up @@ -82,7 +82,7 @@ public function testMiddlewareCreatesLastModifiedHeaderWhenPathMatchesARegex():
public function testMiddlewareDisablesContentWhenLastModifiedIsGreaterThanClientExpectation(): void
{
$ifModifiedSince = time() + 3600;
$ifModifiedSince = trim(gmstrftime('%A %d-%b-%y %T %Z', $ifModifiedSince));
$ifModifiedSince = $this->formatTimestamp($ifModifiedSince);

$this->request->server = [
'request_uri' => '/images/image.png',
Expand Down

0 comments on commit 797dbcd

Please sign in to comment.