diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index fe594210..a2033873 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -1,10 +1,11 @@
name: 'CI'
on:
+ workflow_dispatch: ~
push:
branches:
- master
- pull_request:
+ pull_request: ~
jobs:
@@ -54,7 +55,9 @@ jobs:
- name: 'PHP CS Fixer'
if: always() && steps.deps.outcome == 'success'
- run: vendor/bin/php-cs-fixer fix --dry-run --diff
+ run: |
+ make php-cs-fixer.phar
+ ./php-cs-fixer.phar fix --dry-run --diff
- name: 'PhpStan'
if: always() && steps.deps.outcome == 'success'
@@ -76,7 +79,38 @@ jobs:
strategy:
fail-fast: false # don't cancel other matrix jobs on failure
matrix:
- php: [ '7.4', '8.0' ]
+ include:
+ # Previous Symfony versions
+ - name: 'Test Symfony 5.3 [Linux, PHP 8.0]'
+ os: 'ubuntu-latest'
+ php: '8.0'
+ symfony: '5.3.*'
+
+ # Previous PHP versions
+ - name: 'Test Symfony 5.4 [Linux, PHP 7.4]'
+ os: 'ubuntu-latest'
+ php: '7.4'
+ symfony: '5.4.*@dev'
+ allow-unstable: true
+
+ # Most recent versions
+ - name: 'Test Symfony 5.4 [Linux, PHP 8.1]'
+ os: 'ubuntu-latest'
+ php: '8.1'
+ symfony: '5.4.*@dev'
+ allow-unstable: true
+
+ - name: 'Test Symfony 5.4 [Windows, PHP 8.0]'
+ os: 'windows-latest'
+ php: '8.0'
+ symfony: '5.4.*@dev'
+ allow-unstable: true
+
+ - name: 'Test Symfony 6.0 [Linux, PHP 8.1]'
+ os: 'ubuntu-latest'
+ php: '8.1'
+ symfony: '6.0.*@dev'
+ allow-unstable: true
steps:
- name: 'Checkout'
@@ -84,39 +118,40 @@ jobs:
- name: 'Setup PHP'
uses: shivammathur/setup-php@v2
+
with:
- coverage: "none"
- extensions: "json"
- ini-values: "memory_limit=-1"
- php-version: "${{ matrix.php }}"
+ php-version: ${{ matrix.php }}
+ coverage: none
+ extensions: json
+ ini-values: 'memory_limit=-1'
+ tools: 'composer:v2,flex'
- - name: 'Determine composer cache directory'
+ - name: 'Get composer cache directory'
id: composer-cache
- run: echo "::set-output name=directory::$(composer config cache-dir)"
+ run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- - name: 'Cache composer dependencies'
+ - name: 'Cache dependencies'
uses: actions/cache@v2
with:
- path: ${{ steps.composer-cache.outputs.directory }}
- key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
- restore-keys: ${{ matrix.php }}-composer-
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-php-${{ matrix.php }}-symfony-${{ matrix.symfony }}-${{ hashFiles('**/composer.json') }}-flags-${{ matrix.composer-flags }}
+ restore-keys: ${{ runner.os }}-composer-
- - name: 'Fixup Composer'
- if: matrix.php == 8.0
- run: |
- echo "::group::Fixup Composer platform config for third-parties deps not PHP 8 ready yet"
- composer config platform.php 7.4.99
- echo "::endgroup::"
+ - name: 'Allow unstable packages'
+ run: composer config minimum-stability dev
+ if: ${{ matrix.allow-unstable }}
- name: 'Install dependencies'
run: |
echo "::group::composer update"
- composer update --no-progress --ansi
+ composer update --prefer-dist --no-progress ${{ matrix.composer-flags }} --ansi
echo "::endgroup::"
echo "::group::install phpunit"
vendor/bin/simple-phpunit install
echo "::endgroup::"
+ env:
+ SYMFONY_REQUIRE: "${{ matrix.symfony }}"
- name: 'Run tests'
run: vendor/bin/simple-phpunit --testdox
@@ -126,9 +161,6 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
- strategy:
- fail-fast: false # don't cancel other matrix jobs on failure
-
steps:
- name: 'Checkout'
uses: actions/checkout@v2
diff --git a/.gitignore b/.gitignore
index 868b1c50..26067f75 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
/vendor
/composer.lock
-/.php_cs.cache
+/.php-cs-fixer.cache
/.phpunit.result.cache
/node_modules
+/php-cs-fixer.phar
diff --git a/.php_cs b/.php-cs-fixer.php
similarity index 86%
rename from .php_cs
rename to .php-cs-fixer.php
index 2eaddb54..27bae6fb 100644
--- a/.php_cs
+++ b/.php-cs-fixer.php
@@ -13,27 +13,29 @@
->exclude('tests/fixtures/app/build')
;
-return PhpCsFixer\Config::create()
+return (new PhpCsFixer\Config)
->setUsingCache(true)
->setRiskyAllowed(true)
->setFinder($finder)
->setRules([
'@Symfony' => true,
- 'php_unit_namespaced' => true,
- 'psr0' => false,
+ 'array_syntax' => ['syntax' => 'short'],
'concat_space' => ['spacing' => 'one'],
- 'phpdoc_summary' => false,
+ 'header_comment' => ['header' => $header],
+ 'native_function_invocation' => ['include' => ['@compiler_optimized']],
+ 'ordered_imports' => true,
+ 'php_unit_namespaced' => true,
+ 'php_unit_method_casing' => false,
'phpdoc_annotation_without_dot' => false,
+ 'phpdoc_summary' => false,
'phpdoc_order' => true,
- 'array_syntax' => ['syntax' => 'short'],
- 'ordered_imports' => true,
+ 'phpdoc_trim_consecutive_blank_line_separation' => true,
+ 'psr_autoloading' => true,
+ 'single_line_throw' => false,
'simplified_null_return' => false,
- 'header_comment' => ['header' => $header],
- 'yoda_style' => [],
- 'no_superfluous_phpdoc_tags' => true,
- 'native_function_invocation' => ['include' => ['@compiler_optimized']],
'void_return' => true,
- 'single_line_throw' => false,
+ 'yoda_style' => [],
+
// @see https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues/5495
'binary_operator_spaces' => ['operators' => ['|' => null]]
])
diff --git a/Makefile b/Makefile
index a0d638f1..60fb421c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,7 @@
.PHONY: dist
+PHP_CS_FIXER_VERSION=v3.3.2
+
##########
# Colors #
##########
@@ -25,8 +27,30 @@ php8:
# Install #
###########
+setup:
+ composer global require --no-progress --no-scripts --no-plugins symfony/flex
+
+install: setup
install:
+ rm -f composer.lock
+ composer config minimum-stability --unset
+ composer update --prefer-dist
+
+install-54: setup
+install-54: export SYMFONY_REQUIRE = 5.4.*@dev
+install-54:
+ rm -f composer.lock
+ composer config minimum-stability dev
+ composer update
+ composer config minimum-stability --unset
+
+install-60: setup
+install-60: export SYMFONY_REQUIRE = 6.0.*@dev
+install-60:
+ rm -f composer.lock
+ composer config minimum-stability dev
composer update
+ composer config minimum-stability --unset
########
# Lint #
@@ -34,16 +58,26 @@ install:
lint: lint-phpcsfixer lint-phpstan lint-twig lint-yaml lint-composer
-fix-phpcsfixer: php8
-fix-phpcsfixer:
- vendor/bin/php-cs-fixer fix
-
lint-composer:
composer validate --strict
+php-cs-fixer.phar:
+ wget --no-verbose https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/${PHP_CS_FIXER_VERSION}/php-cs-fixer.phar
+ chmod +x php-cs-fixer.phar
+
+update-php-cs-fixer.phar:
+ rm -f php-cs-fixer.phar
+ make php-cs-fixer.phar
+
lint-phpcsfixer: php8
+lint-phpcsfixer: php-cs-fixer.phar
lint-phpcsfixer:
- vendor/bin/php-cs-fixer fix --dry-run --diff
+ ./php-cs-fixer.phar fix --dry-run --diff
+
+fix-phpcsfixer: php8
+fix-phpcsfixer: php-cs-fixer.phar
+fix-phpcsfixer:
+ ./php-cs-fixer.phar fix
lint-phpstan:
vendor/bin/phpstan analyse --memory-limit=-1
diff --git a/composer.json b/composer.json
index f575a7df..08245173 100644
--- a/composer.json
+++ b/composer.json
@@ -32,43 +32,44 @@
}
},
"prefer-stable": true,
- "minimum-stability": "dev",
"require": {
"php": ">=7.4",
"ext-dom": "*",
"erusev/parsedown": "^1.7.4",
- "symfony/asset": "^5.1",
- "symfony/config": "^5.1",
- "symfony/console": "^5.1",
- "symfony/css-selector": "^5.1",
- "symfony/dependency-injection": "^5.1",
- "symfony/dom-crawler": "^5.1",
- "symfony/event-dispatcher": "^5.1",
- "symfony/filesystem": "^5.1",
- "symfony/finder": "^5.1",
- "symfony/http-foundation": "^5.1",
- "symfony/http-kernel": "^5.1",
- "symfony/mime": "^5.1",
- "symfony/process": "^5.1",
- "symfony/property-access": "^5.1",
- "symfony/routing": "^5.1",
- "symfony/serializer": "^5.1",
- "symfony/string": "^5.1",
- "symfony/yaml": "^5.1",
+ "symfony/asset": "^5.1|^6.0",
+ "symfony/config": "^5.1|^6.0",
+ "symfony/console": "^5.1|^6.0",
+ "symfony/css-selector": "^5.1|^6.0",
+ "symfony/dependency-injection": "^5.1|^6.0",
+ "symfony/dom-crawler": "^5.1|^6.0",
+ "symfony/event-dispatcher": "^5.1|^6.0",
+ "symfony/filesystem": "^5.1|^6.0",
+ "symfony/finder": "^5.1|^6.0",
+ "symfony/http-foundation": "^5.1|^6.0",
+ "symfony/http-kernel": "^5.1|^6.0",
+ "symfony/mime": "^5.1|^6.0",
+ "symfony/process": "^5.1|^6.0",
+ "symfony/property-access": "^5.1|^6.0",
+ "symfony/routing": "^5.1|^6.0",
+ "symfony/serializer": "^5.1|^6.0",
+ "symfony/string": "^5.1|^6.0",
+ "symfony/yaml": "^5.1|^6.0",
"twig/twig": "^2.12|^3.0"
},
"require-dev": {
+ "doctrine/annotations": "^1.9",
"ekino/phpstan-banned-code": "^0.4",
- "friendsofphp/php-cs-fixer": "^2.16",
"phpspec/prophecy-phpunit": "^2.0",
"phpstan/phpstan": "^0.12.32",
- "symfony/browser-kit": "^5.1",
- "symfony/expression-language": "^5.1",
- "symfony/framework-bundle": "^5.1",
+ "psr/log": "^1",
+ "symfony/browser-kit": "^5.1|^6.0",
+ "symfony/expression-language": "^5.1|^6.0",
+ "symfony/framework-bundle": "^5.1|^6.0",
"symfony/monolog-bundle": "^3.7",
- "symfony/phpunit-bridge": "^5.1",
- "symfony/twig-bridge": "^5.1",
- "symfony/twig-bundle": "^5.1"
+ "symfony/phpunit-bridge": "^5.3|^6.0",
+ "symfony/stopwatch": "^5.1|^6.0",
+ "symfony/twig-bridge": "^5.1|^6.0",
+ "symfony/twig-bundle": "^5.1|^6.0"
},
"extra": {
"branch-alias": {
@@ -76,6 +77,9 @@
}
},
"config": {
+ "preferred-install": {
+ "*": "dist"
+ },
"sort-packages": true
}
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index e4e48938..5fd906ef 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -13,9 +13,9 @@
-
-
+
+
diff --git a/src/Builder/Sitemap.php b/src/Builder/Sitemap.php
index 6a2f4674..e6f7d17e 100644
--- a/src/Builder/Sitemap.php
+++ b/src/Builder/Sitemap.php
@@ -9,7 +9,8 @@
namespace Stenope\Bundle\Builder;
/**
- * Sitemap
+ * @phpstan-implements \Iterator
+ * @final
*/
class Sitemap implements \Iterator, \Countable
{
@@ -21,8 +22,6 @@ class Sitemap implements \Iterator, \Countable
private $urls = [];
/**
- * Position
- *
* @var int
*/
private $position = 0;
@@ -30,10 +29,10 @@ class Sitemap implements \Iterator, \Countable
/**
* Add location
*
- * @param string $location The URL
- * @param DateTime $lastModified Date of last modification
- * @param int $priority Location priority
- * @param string $frequency
+ * @param string $location The URL
+ * @param \DateTime $lastModified Date of last modification
+ * @param int $priority Location priority
+ * @param string $frequency
*/
public function add(string $location, \DateTime $lastModified = null, int $priority = null, string $frequency = null): void
{
@@ -68,7 +67,10 @@ public function rewind(): void
/**
* {@inheritdoc}
+ *
+ * @return mixed
*/
+ #[\ReturnTypeWillChange]
public function current()
{
return $this->urls[array_keys($this->urls)[$this->position]];
@@ -76,7 +78,10 @@ public function current()
/**
* {@inheritdoc}
+ *
+ * @return mixed
*/
+ #[\ReturnTypeWillChange]
public function key()
{
return array_keys($this->urls)[$this->position];
@@ -93,7 +98,7 @@ public function next(): void
/**
* {@inheritdoc}
*/
- public function valid()
+ public function valid(): bool
{
return isset(array_keys($this->urls)[$this->position]);
}
@@ -101,7 +106,7 @@ public function valid()
/**
* {@inheritdoc}
*/
- public function count()
+ public function count(): int
{
return \count($this->urls);
}
diff --git a/src/Command/DebugCommand.php b/src/Command/DebugCommand.php
index 0b139d36..9b71d02b 100644
--- a/src/Command/DebugCommand.php
+++ b/src/Command/DebugCommand.php
@@ -190,11 +190,11 @@ private function getOrders(array $rawOrders): array
{
$orders = [];
foreach ($rawOrders ?? [] as $field) {
- if (\str_starts_with($field, 'desc:')) {
+ if (str_starts_with($field, 'desc:')) {
$orders[substr($field, 5)] = false;
continue;
}
- if (\str_starts_with($field, '-')) {
+ if (str_starts_with($field, '-')) {
$orders[substr($field, 1)] = false;
continue;
}
diff --git a/src/Command/StopwatchHelperTrait.php b/src/Command/StopwatchHelperTrait.php
index 4df07286..a57a45fa 100644
--- a/src/Command/StopwatchHelperTrait.php
+++ b/src/Command/StopwatchHelperTrait.php
@@ -11,15 +11,18 @@
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Stopwatch\StopwatchEvent;
+/**
+ * @internal
+ */
trait StopwatchHelperTrait
{
private static function formatEvent(StopwatchEvent $event): string
{
return sprintf(
'Start time: %s — End time: %s — Duration: %s — Memory used: %s',
- date('H:i:s', ($event->getOrigin() + $event->getStartTime()) / 1000),
- date('H:i:s', ($event->getOrigin() + $event->getEndTime()) / 1000),
- static::formatTimePrecision($event->getDuration() / 1000),
+ date('H:i:s', (int) (($event->getOrigin() + $event->getStartTime()) / 1000)),
+ date('H:i:s', (int) (($event->getOrigin() + $event->getEndTime()) / 1000)),
+ static::formatTimePrecision((int) $event->getDuration() / 1000),
Helper::formatMemory($event->getMemory())
);
}
diff --git a/src/ContentManager.php b/src/ContentManager.php
index 2ee57689..7881d364 100644
--- a/src/ContentManager.php
+++ b/src/ContentManager.php
@@ -122,13 +122,13 @@ private function filterBy(array &$contents, $filterBy = null): void
private function sortBy(array &$contents, $sortBy = null): void
{
if ($sorter = $this->getSortFunction($sortBy)) {
- \set_error_handler(static function (int $severity, string $message, ?string $file, ?int $line): void {
+ set_error_handler(static function (int $severity, string $message, ?string $file, ?int $line): void {
throw new \ErrorException($message, $severity, $severity, $file, $line);
});
uasort($contents, $sorter);
- \restore_error_handler();
+ restore_error_handler();
}
}
diff --git a/src/Decoder/HtmlDecoder.php b/src/Decoder/HtmlDecoder.php
index 7f788ff1..d604b8e6 100644
--- a/src/Decoder/HtmlDecoder.php
+++ b/src/Decoder/HtmlDecoder.php
@@ -13,6 +13,8 @@
/**
* Parse Html data
+ *
+ * @final
*/
class HtmlDecoder implements DecoderInterface
{
@@ -24,7 +26,7 @@ class HtmlDecoder implements DecoderInterface
/**
* {@inheritdoc}
*/
- public function decode($data, $format, array $context = [])
+ public function decode($data, $format, array $context = []): array
{
$crawler = new Crawler($data);
@@ -46,7 +48,7 @@ public function decode($data, $format, array $context = [])
/**
* {@inheritdoc}
*/
- public function supportsDecoding($format)
+ public function supportsDecoding($format): bool
{
return self::FORMAT === $format;
}
diff --git a/src/Decoder/MarkdownDecoder.php b/src/Decoder/MarkdownDecoder.php
index 2e7bb446..7a09685f 100644
--- a/src/Decoder/MarkdownDecoder.php
+++ b/src/Decoder/MarkdownDecoder.php
@@ -14,6 +14,8 @@
/**
* Parse Markdown data
+ *
+ * @final
*/
class MarkdownDecoder implements DecoderInterface
{
@@ -36,7 +38,7 @@ public function __construct(Parsedown $parser)
/**
* {@inheritdoc}
*/
- public function decode($data, $format, array $context = [])
+ public function decode($data, $format, array $context = []): array
{
$content = trim($data);
$separator = static::HEAD_SEPARATOR;
@@ -57,7 +59,7 @@ public function decode($data, $format, array $context = [])
/**
* {@inheritdoc}
*/
- public function supportsDecoding($format)
+ public function supportsDecoding($format): bool
{
return self::FORMAT === $format;
}
diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php
index 06c97c80..21e6ef94 100644
--- a/src/DependencyInjection/Configuration.php
+++ b/src/DependencyInjection/Configuration.php
@@ -13,13 +13,16 @@
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
+/**
+ * @final
+ */
class Configuration implements ConfigurationInterface
{
private const NATIVE_PROVIDERS_TYPES = [
LocalFilesystemProviderFactory::TYPE,
];
- public function getConfigTreeBuilder()
+ public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('stenope');
$rootNode = method_exists(TreeBuilder::class, 'getRootNode') ? $treeBuilder->getRootNode() : $treeBuilder->root('stenope');
diff --git a/src/DependencyInjection/StenopeExtension.php b/src/DependencyInjection/StenopeExtension.php
index 3a58449d..aeac4d22 100644
--- a/src/DependencyInjection/StenopeExtension.php
+++ b/src/DependencyInjection/StenopeExtension.php
@@ -26,6 +26,9 @@
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
+/**
+ * @final
+ */
class StenopeExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container): void
@@ -60,12 +63,12 @@ public function load(array $configs, ContainerBuilder $container): void
}
}
- public function getNamespace()
+ public function getNamespace(): string
{
return 'http://stenope.com/schema/dic/stenope';
}
- public function getXsdValidationBasePath()
+ public function getXsdValidationBasePath(): string
{
return __DIR__ . '/../../config/schema';
}
diff --git a/src/EventListener/Informator.php b/src/EventListener/Informator.php
index b1caed57..6fd89eaa 100644
--- a/src/EventListener/Informator.php
+++ b/src/EventListener/Informator.php
@@ -15,11 +15,12 @@
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Twig\Environment;
+/**
+ * @final
+ */
class Informator implements EventSubscriberInterface
{
/**
- * Url Generator
- *
* @var UrlGeneratorInterface
*/
private $urlGenerator;
@@ -31,9 +32,6 @@ class Informator implements EventSubscriberInterface
*/
private $twig;
- /**
- * Injecting dependencies
- */
public function __construct(UrlGeneratorInterface $urlGenerator, Environment $twig)
{
$this->urlGenerator = $urlGenerator;
@@ -43,14 +41,11 @@ public function __construct(UrlGeneratorInterface $urlGenerator, Environment $tw
/**
* {@inheritdoc}
*/
- public static function getSubscribedEvents()
+ public static function getSubscribedEvents(): array
{
return [KernelEvents::REQUEST => 'onRequest'];
}
- /**
- * Before request
- */
public function onRequest(RequestEvent $event): void
{
$request = $event->getRequest();
@@ -66,12 +61,7 @@ public function onRequest(RequestEvent $event): void
}
}
- /**
- * Get canonical URL
- *
- * @return string
- */
- private function getCanonicalUrl(Request $request)
+ private function getCanonicalUrl(Request $request): string
{
if (!$request->attributes->get('_route')) {
return '';
@@ -84,12 +74,7 @@ private function getCanonicalUrl(Request $request)
);
}
- /**
- * Get root URL
- *
- * @return string
- */
- private function getRootUrl(Request $request)
+ private function getRootUrl(Request $request): string
{
return sprintf('%s://%s', $request->getScheme(), $request->getHost());
}
diff --git a/src/EventListener/SitemapListener.php b/src/EventListener/SitemapListener.php
index 51ff64c4..8d1a7baa 100644
--- a/src/EventListener/SitemapListener.php
+++ b/src/EventListener/SitemapListener.php
@@ -16,6 +16,8 @@
/**
* Map all routes into a Sitemap
+ *
+ * @final
*/
class SitemapListener implements EventSubscriberInterface
{
@@ -42,7 +44,7 @@ public function onKernelResponse(ResponseEvent $event): void
if ($route && $route->isMapped() && $request->attributes->get('_canonical')) {
$this->sitemap->add(
$request->attributes->get('_canonical'),
- new \DateTime($response->headers->get('Last-Modified'))
+ new \DateTime($response->headers->get('Last-Modified') ?? 'now')
);
}
}
@@ -50,7 +52,7 @@ public function onKernelResponse(ResponseEvent $event): void
/**
* {@inheritdoc}
*/
- public static function getSubscribedEvents()
+ public static function getSubscribedEvents(): array
{
return [KernelEvents::RESPONSE => 'onKernelResponse'];
}
diff --git a/src/ExpressionLanguage/ExpressionLanguageProvider.php b/src/ExpressionLanguage/ExpressionLanguageProvider.php
index f5de43ab..690446f8 100644
--- a/src/ExpressionLanguage/ExpressionLanguageProvider.php
+++ b/src/ExpressionLanguage/ExpressionLanguageProvider.php
@@ -24,7 +24,7 @@ public function __construct(iterable $providers = [])
$this->providers = $providers;
}
- public function getFunctions()
+ public function getFunctions(): iterable
{
// prepend the default functions to let users override these easily:
yield from [
diff --git a/src/HttpKernel/Controller/ArgumentResolver/ContentArgumentResolver.php b/src/HttpKernel/Controller/ArgumentResolver/ContentArgumentResolver.php
index 12e92231..aec9ec76 100644
--- a/src/HttpKernel/Controller/ArgumentResolver/ContentArgumentResolver.php
+++ b/src/HttpKernel/Controller/ArgumentResolver/ContentArgumentResolver.php
@@ -13,6 +13,9 @@
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
+/**
+ * @final
+ */
class ContentArgumentResolver implements ArgumentValueResolverInterface
{
private ContentManagerInterface $contentManager;
@@ -22,7 +25,7 @@ public function __construct(ContentManagerInterface $contentManager)
$this->contentManager = $contentManager;
}
- public function resolve(Request $request, ArgumentMetadata $argument)
+ public function resolve(Request $request, ArgumentMetadata $argument): iterable
{
$slug = $request->attributes->get($argument->getName());
@@ -33,7 +36,7 @@ public function resolve(Request $request, ArgumentMetadata $argument)
yield $this->contentManager->getContent($argument->getType(), $slug);
}
- public function supports(Request $request, ArgumentMetadata $argument)
+ public function supports(Request $request, ArgumentMetadata $argument): bool
{
if (null === $argument->getType() || !$this->contentManager->supports($argument->getType())) {
return false;
diff --git a/src/Processor/HtmlIdProcessor.php b/src/Processor/HtmlIdProcessor.php
index facfbbf3..4fd0c0d1 100644
--- a/src/Processor/HtmlIdProcessor.php
+++ b/src/Processor/HtmlIdProcessor.php
@@ -77,7 +77,7 @@ private function setIdFromHashedContent(\DOMElement $element): void
private function setIdForImage(\DOMElement $element): void
{
if (!$id = $element->getAttribute('id')) {
- $name = $element->getAttribute('alt') ?: \basename($element->getAttribute('src'));
+ $name = $element->getAttribute('alt') ?: basename($element->getAttribute('src'));
$element->setAttribute('id', $this->slugify($name));
}
}
diff --git a/src/Routing/RouteInfoCollection.php b/src/Routing/RouteInfoCollection.php
index 9bbf3182..f8a96bfc 100644
--- a/src/Routing/RouteInfoCollection.php
+++ b/src/Routing/RouteInfoCollection.php
@@ -11,7 +11,8 @@
use Symfony\Component\Routing\RouterInterface;
/**
- * @phpstan-implements IteratorAggregate
+ * @phpstan-implements \IteratorAggregate
+ * @final
*/
class RouteInfoCollection implements \IteratorAggregate, \ArrayAccess, \Countable
{
@@ -37,20 +38,17 @@ private function getInfos(): array
return $this->routeInfos;
}
- public function getIterator()
+ public function getIterator(): \Traversable
{
return new \ArrayIterator($this->getInfos());
}
- public function offsetExists($offset)
+ public function offsetExists($offset): bool
{
return isset($this->getInfos()[$offset]);
}
- /**
- * @return RouteInfo|null
- */
- public function offsetGet($offset)
+ public function offsetGet($offset): ?RouteInfo
{
return $this->getInfos()[$offset] ?? null;
}
@@ -65,7 +63,7 @@ public function offsetUnset($offset): void
throw new \BadMethodCallException(sprintf('Unexpected call to "%s()"', __METHOD__));
}
- public function count()
+ public function count(): int
{
return \count($this->getInfos());
}
diff --git a/src/Routing/UrlGenerator.php b/src/Routing/UrlGenerator.php
index e5742682..9de874cc 100644
--- a/src/Routing/UrlGenerator.php
+++ b/src/Routing/UrlGenerator.php
@@ -14,6 +14,8 @@
/**
* A wrapper for UrlGenerator that register every generated url in the PageList.
+ *
+ * @final
*/
class UrlGenerator implements UrlGeneratorInterface
{
@@ -28,7 +30,7 @@ public function __construct(RouteInfoCollection $routesInfo, UrlGeneratorInterfa
$this->routesInfo = $routesInfo;
}
- public function generate($name, $parameters = [], $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
+ public function generate($name, $parameters = [], $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): string
{
if (($routeInfo = $this->routesInfo[$name] ?? null) && !$routeInfo->isIgnored()) {
$this->pageList->add(
@@ -44,7 +46,7 @@ public function setContext(RequestContext $context): void
$this->urlGenerator->setContext($context);
}
- public function getContext()
+ public function getContext(): RequestContext
{
return $this->urlGenerator->getContext();
}
diff --git a/src/Serializer/Normalizer/SkippingInstantiatedObjectDenormalizer.php b/src/Serializer/Normalizer/SkippingInstantiatedObjectDenormalizer.php
index 3b3c8526..0c1a0eca 100644
--- a/src/Serializer/Normalizer/SkippingInstantiatedObjectDenormalizer.php
+++ b/src/Serializer/Normalizer/SkippingInstantiatedObjectDenormalizer.php
@@ -12,12 +12,14 @@
/**
* Avoiding double-denormalization for already instantiated objects inside $data.
+ *
+ * @final
*/
class SkippingInstantiatedObjectDenormalizer implements ContextAwareDenormalizerInterface
{
public const SKIP = 'skip_instantiated_object';
- public function denormalize($data, string $type, string $format = null, array $context = [])
+ public function denormalize($data, string $type, string $format = null, array $context = []): object
{
return $data;
}
diff --git a/src/StenopeBundle.php b/src/StenopeBundle.php
index 457ab392..c53bb067 100644
--- a/src/StenopeBundle.php
+++ b/src/StenopeBundle.php
@@ -12,6 +12,9 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
+/**
+ * @final
+ */
class StenopeBundle extends Bundle
{
public function build(ContainerBuilder $container): void
@@ -21,7 +24,7 @@ public function build(ContainerBuilder $container): void
$container->addCompilerPass(new TwigExtensionFixerCompilerPass());
}
- public function getPath()
+ public function getPath(): string
{
return \dirname(__DIR__);
}
diff --git a/src/Twig/ContentExtension.php b/src/Twig/ContentExtension.php
index 9d0e7e79..b7a71864 100644
--- a/src/Twig/ContentExtension.php
+++ b/src/Twig/ContentExtension.php
@@ -11,9 +11,12 @@
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
+/**
+ * @final
+ */
class ContentExtension extends AbstractExtension
{
- public function getFunctions()
+ public function getFunctions(): array
{
return [
new TwigFunction('content_get', [ContentRuntime::class, 'getContent']),
diff --git a/tests/Integration/BuildTest.php b/tests/Integration/BuildTest.php
index 1d6e5aed..0c4fc741 100644
--- a/tests/Integration/BuildTest.php
+++ b/tests/Integration/BuildTest.php
@@ -64,7 +64,7 @@ public function testBuildApp(): void
$this->assertStringContainsString('[OK] Built 17 pages.', $output);
/** @var TestLogger $logger */
- $logger = static::$container->get('logger');
+ $logger = static::getContainer()->get('logger');
$logger->hasWarningThatContains('Url "http://localhost/without-noindex" contains a "x-robots-tag: noindex" header that will be lost by going static.');
}
diff --git a/tests/Unit/DependencyInjection/StenopeExtensionTest.php b/tests/Unit/DependencyInjection/StenopeExtensionTest.php
index 667da95d..b8f2df92 100644
--- a/tests/Unit/DependencyInjection/StenopeExtensionTest.php
+++ b/tests/Unit/DependencyInjection/StenopeExtensionTest.php
@@ -19,7 +19,7 @@
abstract class StenopeExtensionTest extends TestCase
{
- const FIXTURES_PATH = __DIR__ . '/../../fixtures/Unit/DependencyInjection/StenopeExtension';
+ public const FIXTURES_PATH = __DIR__ . '/../../fixtures/Unit/DependencyInjection/StenopeExtension';
public function testDefaults(): void
{
diff --git a/tests/Unit/Service/Git/LastModifiedFetcherTest.php b/tests/Unit/Service/Git/LastModifiedFetcherTest.php
index 14eac68a..6dfa2073 100644
--- a/tests/Unit/Service/Git/LastModifiedFetcherTest.php
+++ b/tests/Unit/Service/Git/LastModifiedFetcherTest.php
@@ -44,13 +44,12 @@ public function testUnavailable(): void
self::assertCount(1, $logger->records);
self::assertNull($fetcher->__invoke('some-fake-path'));
- self::assertCount(1, $logger->records, 'Do not attempt to check git avaiulability twice');
+ self::assertCount(1, $logger->records, 'Do not attempt to check git availability twice');
}
public function testSuccess(): void
{
- $logger = new TestLogger();
- $fetcher = new LastModifiedFetcher(self::$executable, $logger);
+ $fetcher = new LastModifiedFetcher(self::$executable);
$fetcher->reset();
self::assertInstanceOf(\DateTimeImmutable::class, $date = $fetcher->__invoke('some-fake-path'));
@@ -59,8 +58,7 @@ public function testSuccess(): void
public function testEmpty(): void
{
- $logger = new TestLogger();
- $fetcher = new LastModifiedFetcher(self::$executable, $logger);
+ $fetcher = new LastModifiedFetcher(self::$executable);
$fetcher->reset();
self::assertNull($fetcher->__invoke('empty'));
@@ -68,8 +66,7 @@ public function testEmpty(): void
public function testFailure(): void
{
- $logger = new TestLogger();
- $fetcher = new LastModifiedFetcher(self::$executable, $logger);
+ $fetcher = new LastModifiedFetcher(self::$executable);
$fetcher->reset();
$this->expectException(ProcessFailedException::class);
diff --git a/tests/Unit/TableOfContent/CrawlerTableOfContentGeneratorTest.php b/tests/Unit/TableOfContent/CrawlerTableOfContentGeneratorTest.php
index efb9b9d7..ad7a5c7d 100644
--- a/tests/Unit/TableOfContent/CrawlerTableOfContentGeneratorTest.php
+++ b/tests/Unit/TableOfContent/CrawlerTableOfContentGeneratorTest.php
@@ -6,7 +6,7 @@
* @author Thomas Jarrand
*/
-namespace Stenope\Bundle\Tests\Unit\Service;
+namespace Stenope\Bundle\Tests\Unit\TableOfContent;
use PHPUnit\Framework\TestCase;
use Stenope\Bundle\TableOfContent\CrawlerTableOfContentGenerator;
diff --git a/tests/fixtures/app/src/Controller/AuthorsController.php b/tests/fixtures/app/src/Controller/AuthorsController.php
index 4bcc17a8..6deb15b4 100644
--- a/tests/fixtures/app/src/Controller/AuthorsController.php
+++ b/tests/fixtures/app/src/Controller/AuthorsController.php
@@ -13,12 +13,12 @@
use Symfony\Component\Routing\Annotation\Route;
/**
- * @Route("/authors")
+ * @Route(path="/authors")
*/
class AuthorsController extends AbstractController
{
/**
- * @Route("/{author<[\w.]+>}.json", name="author_json", options={
+ * @Route(path="/{author<[\w.]+>}.json", name="author_json", options={
* "stenope": {
* "sitemap": false,
* },
@@ -36,7 +36,7 @@ public function showAsJson(Author $author)
}
/**
- * @Route("/{author}", name="author")
+ * @Route(path="/{author}", name="author")
*/
public function show(Author $author)
{
diff --git a/tests/fixtures/app/src/Controller/DefaultController.php b/tests/fixtures/app/src/Controller/DefaultController.php
index a95836b7..90ae9564 100644
--- a/tests/fixtures/app/src/Controller/DefaultController.php
+++ b/tests/fixtures/app/src/Controller/DefaultController.php
@@ -15,7 +15,7 @@
class DefaultController extends AbstractController
{
/**
- * @Route("/", name="homepage")
+ * @Route(path="/", name="homepage")
*/
public function index()
{
@@ -27,7 +27,7 @@ public function index()
}
/**
- * @Route("/foo.html", name="foo_html")
+ * @Route(path="/foo.html", name="foo_html")
*/
public function foo()
{
diff --git a/tests/fixtures/app/src/Controller/NoIndexController.php b/tests/fixtures/app/src/Controller/NoIndexController.php
index 016da506..f18f0175 100644
--- a/tests/fixtures/app/src/Controller/NoIndexController.php
+++ b/tests/fixtures/app/src/Controller/NoIndexController.php
@@ -14,7 +14,7 @@
class NoIndexController extends AbstractController
{
/**
- * @Route("/with-noindex", name="with_noindex")
+ * @Route(path="/with-noindex", name="with_noindex")
*/
public function withNoIndex()
{
@@ -26,7 +26,7 @@ public function withNoIndex()
}
/**
- * @Route("/without-noindex", name="without_noindex")
+ * @Route(path="/without-noindex", name="without_noindex")
*/
public function withoutNoIndex()
{
diff --git a/tests/fixtures/app/src/Controller/RecipesController.php b/tests/fixtures/app/src/Controller/RecipesController.php
index 44ff03e0..e2c63942 100644
--- a/tests/fixtures/app/src/Controller/RecipesController.php
+++ b/tests/fixtures/app/src/Controller/RecipesController.php
@@ -16,7 +16,7 @@
use Symfony\Component\Routing\Annotation\Route;
/**
- * @Route("/recipes")
+ * @Route(path="/recipes")
*/
class RecipesController extends AbstractController
{
@@ -28,7 +28,7 @@ public function __construct(ContentManager $manager)
}
/**
- * @Route("/", name="recipes")
+ * @Route(path="/", name="recipes")
*/
public function index()
{
@@ -43,7 +43,7 @@ public function index()
/**
* Ensure {@link ContentArgumentResolver} handles nullable arguments properly.
*
- * @Route("/optional-recipe", name="optional-recipe", options={
+ * @Route(path="/optional-recipe", name="optional-recipe", options={
* "stenope": {
* "ignore": true,
* },
@@ -55,7 +55,7 @@ public function optionalRecipe(?Recipe $recipe)
}
/**
- * @Route("/{recipe}.pdf", name="recipe_pdf", options={
+ * @Route(path="/{recipe}.pdf", name="recipe_pdf", options={
* "stenope": {
* "sitemap": false,
* },
@@ -71,7 +71,7 @@ public function downloadAsPdf(Recipe $recipe)
}
/**
- * @Route("/{recipe}", name="recipe")
+ * @Route(path="/{recipe}", name="recipe")
*/
public function show(Recipe $recipe)
{
diff --git a/tests/fixtures/app/src/Kernel.php b/tests/fixtures/app/src/Kernel.php
index a731ac61..f52cc247 100644
--- a/tests/fixtures/app/src/Kernel.php
+++ b/tests/fixtures/app/src/Kernel.php
@@ -13,11 +13,14 @@
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
+/**
+ * @final
+ */
class Kernel extends BaseKernel
{
use MicroKernelTrait;
- public function getProjectDir()
+ public function getProjectDir(): string
{
return __DIR__ . '/..';
}