diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a213879 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,12 @@ +/.github/ export-ignore +/features/ export-ignore +/tests/ export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/composer-require-checker.json export-ignore +/infection.json export-ignore +/phpcs.xml export-ignore +/phpstan.neon export-ignore +/phpstan-baseline.neon export-ignore +/phpunit.xml export-ignore +/psalm.xml export-ignore diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 7557cfb..c8431c4 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -1,13 +1,20 @@ name: Check Build -on: [push, pull_request] +on: [pull_request] jobs: build: + strategy: + matrix: + php: ["7.4", "8.0"] + include: + - php: "8.0" + composer_args: "--ignore-platform-reqs" + runs-on: ubuntu-latest container: - image: eventjet/checks-7.4:latest + image: eventjet/checks-${{ matrix.php }}:latest steps: - name: Checkout @@ -17,23 +24,24 @@ jobs: run: | mkdir -p /root/.ssh ssh-keyscan -t rsa github.com >> /root/.ssh/known_hosts + echo "COMPOSER_CACHE=$(composer config cache-dir)" >> $GITHUB_ENV - name: Composer Cache - uses: actions/cache@v1 + uses: actions/cache@v2 with: - path: $(composer config cache-files-dir) - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: | - ${{ runner.os }}-composer- + path: | + ${{ env.COMPOSER_CACHE }} + vendor + key: ${{ runner.os }}-composer - name: Install dependencies run: | - composer install --no-progress --no-suggest --no-interaction > /dev/null + composer update --no-progress --no-interaction ${{ matrix.composer_args }} > /dev/null - name: Static analysis run: | composer check-deps - composer cs-check + composer cs-check -- --runtime-set php_version 70400 composer phpstan -- --no-progress composer psalm @@ -42,11 +50,19 @@ jobs: vendor/bin/phpunit --coverage-clover=coverage.xml --stop-on-failure composer run --timeout=0 infection + - name: Save Infection result + uses: actions/upload-artifact@v2 + if: always() + with: + name: infection-log.txt + path: infection-log.txt + - name: Monitor coverage if: github.event_name == 'pull_request' - uses: slavcodev/coverage-monitor-action@1.0.1 + uses: slavcodev/coverage-monitor-action@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} clover_file: "coverage.xml" - threshold_alert: 90 - threshold_warning: 95 + comment_context: PHP ${{ matrix.php }} + threshold_alert: 100 + threshold_warning: 100 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f2a290b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 0.1.3 - TBD + +### Added + +- [#8](https://github.com/eventjet/eventjet-asset-manager/pull/8) adds support for PHP 8 + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..eac2a73 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,16 @@ +MIT License + +Copyright (c) 2021 Eventjet + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/composer.json b/composer.json index 641ccdd..8242632 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "fig/http-message-util": "^1.1", "laminas/laminas-diactoros": "^2.3", "narrowspark/mimetypes": "^1.6", - "psr/container": "^1.0", + "psr/container": "^1.1 || ^2.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0", "psr/http-server-handler": "^1.0", @@ -18,17 +18,16 @@ "thecodingmachine/safe": "^1.1" }, "require-dev": { - "eventjet/coding-standard": "^3.1", - "infection/infection": "^0.16", - "maglnet/composer-require-checker": "^2.0", + "eventjet/coding-standard": "^3.7", + "infection/infection": "^0.25", + "maglnet/composer-require-checker": "^3.3", "nette/php-generator": "^3.3", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^0.12.5", "phpstan/phpstan-phpunit": "^0.12.6", "phpstan/phpstan-strict-rules": "^0.12.1", - "phpunit/phpunit": "^9.0", - "thecodingmachine/phpstan-safe-rule": "^1.0", - "vimeo/psalm": "^3.8" + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.10" }, "config": { "sort-packages": true @@ -63,7 +62,7 @@ "check-deps": "vendor/bin/composer-require-checker", "cs-check": "vendor/bin/phpcs", "cs-fix": "vendor/bin/phpcbf", - "infection": "vendor/bin/infection --threads=4 --min-msi=100 --min-covered-msi=100", + "infection": "vendor/bin/infection --threads=4", "infection-xdebug": "@composer run --timeout=0 infection -- --initial-tests-php-options='-d zend_extension=xdebug.so'", "phpstan": "vendor/bin/phpstan analyse", "phpunit": "vendor/bin/phpunit", diff --git a/infection.json b/infection.json index e2ebb44..da0a1a5 100644 --- a/infection.json +++ b/infection.json @@ -7,5 +7,7 @@ }, "logs": { "text": "infection-log.txt" - } + }, + "minMsi": 100, + "minCoveredMsi": 100 } diff --git a/phpcs.xml b/phpcs.xml index f0f4129..335a9a3 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -1,6 +1,9 @@ + + + src tests diff --git a/phpunit.xml b/phpunit.xml index 4e1dbb4..011c1c4 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -2,6 +2,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" + beStrictAboutChangesToGlobalState="true" + beStrictAboutOutputDuringTests="true" + verbose="true" + convertDeprecationsToExceptions="true" > @@ -11,9 +15,9 @@ tests/functional - - + + src - - + + diff --git a/psalm.xml b/psalm.xml index 57035c5..52f542b 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Asset/FileAsset.php b/src/Asset/FileAsset.php index 35686b8..f411cec 100644 --- a/src/Asset/FileAsset.php +++ b/src/Asset/FileAsset.php @@ -7,6 +7,8 @@ use Narrowspark\MimeType\MimeTypeExtensionGuesser; use SplFileInfo; +use function strlen; + final class FileAsset implements AssetInterface { private ?string $content; diff --git a/src/Resolver/PathMappingResolver.php b/src/Resolver/PathMappingResolver.php index 6f3a8cb..b0f646d 100644 --- a/src/Resolver/PathMappingResolver.php +++ b/src/Resolver/PathMappingResolver.php @@ -7,14 +7,16 @@ use Eventjet\AssetManager\Asset\AssetFactoryInterface; use Eventjet\AssetManager\Asset\AssetInterface; +use function file_exists; + final class PathMappingResolver implements ResolverInterface { - /** @var string[] */ + /** @var array */ private array $pathMapping; private AssetFactoryInterface $factory; /** - * @param string[] $pathMapping + * @param array $pathMapping */ public function __construct(array $pathMapping, AssetFactoryInterface $factory) { diff --git a/src/Resolver/PathMappingResolverFactory.php b/src/Resolver/PathMappingResolverFactory.php index bfa1d2f..382faf6 100644 --- a/src/Resolver/PathMappingResolverFactory.php +++ b/src/Resolver/PathMappingResolverFactory.php @@ -18,7 +18,7 @@ public function __invoke(ContainerInterface $container): PathMappingResolver } /** - * @return array + * @return array */ private function paths(ContainerInterface $container): array { diff --git a/src/Service/AssetManager.php b/src/Service/AssetManager.php index f2fae21..3c25819 100644 --- a/src/Service/AssetManager.php +++ b/src/Service/AssetManager.php @@ -4,6 +4,7 @@ namespace Eventjet\AssetManager\Service; +use DateTimeImmutable; use DateTimeZone; use Eventjet\AssetManager\Resolver\ResolverInterface; use Fig\Http\Message\StatusCodeInterface; @@ -13,8 +14,6 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamFactoryInterface; use RuntimeException; -use Safe\DateTimeImmutable; -use Safe\Exceptions\DatetimeException; use function gmdate; use function is_string; @@ -49,17 +48,21 @@ public function buildAssetResponse(ServerRequestInterface $request): ResponseInt $etagFile = \Safe\md5_file($asset->getPath()); $serverParams = $request->getServerParams(); + /** @var string|null $ifModifiedSince */ $ifModifiedSince = $serverParams['HTTP_IF_MODIFIED_SINCE'] ?? null; + /** @var string|null $etagHeader */ $etagHeader = $serverParams['HTTP_IF_NONE_MATCH'] ?? null; if (is_string($ifModifiedSince)) { - try { - $ifModifiedSince = DateTimeImmutable::createFromFormat( - DATE_RFC7231, - $ifModifiedSince, - new DateTimeZone('UTC') - )->getTimestamp(); - } catch (DatetimeException $exception) { + $modifiedDate = DateTimeImmutable::createFromFormat( + DATE_RFC7231, + $ifModifiedSince, + new DateTimeZone('UTC') + ); + + if ($modifiedDate instanceof DateTimeImmutable) { + $ifModifiedSince = $modifiedDate->getTimestamp(); + } else { $ifModifiedSince = null; } } diff --git a/tests/unit/ObjectFactory.php b/tests/unit/ObjectFactory.php index 7e706b7..f081996 100644 --- a/tests/unit/ObjectFactory.php +++ b/tests/unit/ObjectFactory.php @@ -18,6 +18,8 @@ use function str_replace; use function stream_get_meta_data; +use const DIRECTORY_SEPARATOR; + final class ObjectFactory { public static function tmpFileName(): string diff --git a/tests/unit/Service/AssetManagerTest.php b/tests/unit/Service/AssetManagerTest.php index 5e7dfb7..e79c80e 100644 --- a/tests/unit/Service/AssetManagerTest.php +++ b/tests/unit/Service/AssetManagerTest.php @@ -15,6 +15,8 @@ use function gmdate; +use const DATE_RFC7231; + class AssetManagerTest extends TestCase { private ResolverStub $resolver; diff --git a/tests/unit/TestDouble/ContainerStub.php b/tests/unit/TestDouble/ContainerStub.php index ecca89a..a0ecc40 100644 --- a/tests/unit/TestDouble/ContainerStub.php +++ b/tests/unit/TestDouble/ContainerStub.php @@ -22,18 +22,14 @@ public function __construct(array $map) } /** - * @param mixed $id * @return mixed */ - public function get($id) + public function get(string $id) { return $this->map[$id] ?? null; } - /** - * @param mixed $id - */ - public function has($id): bool + public function has(string $id): bool { return array_key_exists($id, $this->map); }