diff --git a/.github/workflows/ci-docs.yaml b/.github/workflows/ci-docs.yaml index 28b41ed11..cbe7618a5 100644 --- a/.github/workflows/ci-docs.yaml +++ b/.github/workflows/ci-docs.yaml @@ -20,7 +20,7 @@ jobs: steps: - name: "Checkout" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: "Create cache dir" run: mkdir .cache @@ -30,12 +30,12 @@ jobs: id: extract_base_branch - name: "Cache DOCtor-RST" - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: .cache key: ${{ runner.os }}-doctor-rst-${{ steps.extract_base_branch.outputs.branch }} - name: "Run DOCtor-RST" - uses: docker://oskarstark/doctor-rst:1.61.1 + uses: docker://oskarstark/doctor-rst:1.64.0 with: args: --short --error-format=github --cache-file=/github/workspace/.cache/doctor-rst.cache diff --git a/.github/workflows/ci-linux.yaml b/.github/workflows/ci-linux.yaml index 2de12c996..9f9c8b2a7 100644 --- a/.github/workflows/ci-linux.yaml +++ b/.github/workflows/ci-linux.yaml @@ -70,17 +70,17 @@ jobs: run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - name: Composer install - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: dependency-versions: "${{ matrix.dependency-versions }}" - name: Composer install php-cs-fixer - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: composer-options: "--no-scripts --working-dir=tools/php-cs-fixer" - name: Composer install twigcs - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: composer-options: "--no-scripts --working-dir=tools/twigcs" diff --git a/.github/workflows/ci-static-analysis.yaml b/.github/workflows/ci-static-analysis.yaml index cd338a584..a0681f3c3 100644 --- a/.github/workflows/ci-static-analysis.yaml +++ b/.github/workflows/ci-static-analysis.yaml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout code - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" - name: Install PHP @@ -35,13 +35,13 @@ jobs: - name: Composer install - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: composer-options: "--no-scripts" - name: Composer install php-cs-fixer - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: composer-options: "--no-scripts --working-dir=tools/php-cs-fixer" @@ -64,17 +64,17 @@ jobs: php-version: 8.2 - name: Install Composer Dependencies - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: composer-options: "--no-scripts" - name: Install PHPStan - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: composer-options: "--no-scripts --working-dir=tools/phpstan" - name: Install Optional Dependencies - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: composer-options: "--no-scripts --working-dir=tools/phpstan/includes" diff --git a/.github/workflows/ci-windows.yaml b/.github/workflows/ci-windows.yaml index e99e6c559..44a059f0d 100644 --- a/.github/workflows/ci-windows.yaml +++ b/.github/workflows/ci-windows.yaml @@ -46,17 +46,17 @@ jobs: extensions: pdo, pdo_sqlite - name: Composer Install - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: dependency-versions: "${{ matrix.dependency-versions }}" - name: Composer install php-cs-fixer - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: composer-options: "--no-scripts --working-dir=tools/php-cs-fixer" - name: Composer install twigcs - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: composer-options: "--no-scripts --working-dir=tools/twigcs" diff --git a/composer.json b/composer.json index df1c451ba..3b9010d17 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,6 @@ "php": ">=8.1", "doctrine/inflector": "^2.0", "nikic/php-parser": "^4.18|^5.0", - "php-cs-fixer/shim": "^v3.64", "symfony/config": "^6.4|^7.0", "symfony/console": "^6.4|^7.0", "symfony/dependency-injection": "^6.4|^7.0", diff --git a/config/services.xml b/config/services.xml index 8f0b2a209..5fbc0439b 100644 --- a/config/services.xml +++ b/config/services.xml @@ -41,7 +41,6 @@ - %env(default::string:MAKER_PHP_CS_FIXER_BINARY_PATH)% %env(default::string:MAKER_PHP_CS_FIXER_CONFIG_PATH)% diff --git a/src/Maker/MakeTwigComponent.php b/src/Maker/MakeTwigComponent.php index 4bf55ee8d..e72da5096 100644 --- a/src/Maker/MakeTwigComponent.php +++ b/src/Maker/MakeTwigComponent.php @@ -71,7 +71,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $factory = $generator->createClassNameDetails( $name, - $this->namespace, + str_replace($generator->getRootNamespace().'\\', '', $this->namespace), ); $templatePath = str_replace('\\', '/', $factory->getRelativeNameWithoutSuffix()); @@ -111,7 +111,7 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma try { $value = Yaml::parse($this->fileManager->getFileContents($path)); - $this->namespace = substr(array_key_first($value['twig_component']['defaults']), 4); + $this->namespace = array_key_first($value['twig_component']['defaults']); } catch (\Throwable $throwable) { throw new RuntimeCommandException(message: 'Unable to parse twig_component.yaml', previous: $throwable); } diff --git a/src/Resources/bin/php-cs-fixer-v3.49.0.phar b/src/Resources/bin/php-cs-fixer-v3.49.0.phar new file mode 100755 index 000000000..cbbbe5834 Binary files /dev/null and b/src/Resources/bin/php-cs-fixer-v3.49.0.phar differ diff --git a/src/Util/TemplateLinter.php b/src/Util/TemplateLinter.php index 19907938d..9a298625d 100644 --- a/src/Util/TemplateLinter.php +++ b/src/Util/TemplateLinter.php @@ -12,7 +12,6 @@ namespace Symfony\Bundle\MakerBundle\Util; use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException; -use Symfony\Bundle\MakerBundle\FileManager; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\ExecutableFinder; use Symfony\Component\Process\Process; @@ -26,12 +25,14 @@ */ final class TemplateLinter { + // Version must match bundled version file name. e.g. php-cs-fixer-v3.49.9.phar + public const BUNDLED_PHP_CS_FIXER_VERSION = '3.49.0'; + private bool $usingBundledPhpCsFixer = true; private bool $usingBundledPhpCsFixerConfig = true; private bool $needsPhpCmdPrefix = true; public function __construct( - private FileManager $fileManager, private ?string $phpCsFixerBinaryPath = null, private ?string $phpCsFixerConfigPath = null, ) { @@ -97,15 +98,9 @@ public function writeLinterMessage(OutputInterface $output): void private function setBinary(): void { - // Use Bundled (shim) PHP-CS-Fixer + // Use Bundled PHP-CS-Fixer if (null === $this->phpCsFixerBinaryPath) { - $shimLocation = \sprintf('%s/vendor/bin/php-cs-fixer', \dirname(__DIR__, 2)); - - if (is_file($shimLocation)) { - $this->phpCsFixerBinaryPath = $shimLocation; - - return; - } + $this->phpCsFixerBinaryPath = \sprintf('%s/Resources/bin/php-cs-fixer-v%s.phar', \dirname(__DIR__), self::BUNDLED_PHP_CS_FIXER_VERSION); return; } @@ -134,8 +129,7 @@ private function setBinary(): void private function setConfig(): void { // No config provided, but there is a dist config file in the project dir - $defaultConfigPath = \sprintf('%s/.php-cs-fixer.dist.php', $this->fileManager->getRootDirectory()); - if (null === $this->phpCsFixerConfigPath && file_exists($defaultConfigPath)) { + if (null === $this->phpCsFixerConfigPath && file_exists($defaultConfigPath = '.php-cs-fixer.dist.php')) { $this->phpCsFixerConfigPath = $defaultConfigPath; $this->usingBundledPhpCsFixerConfig = false; diff --git a/templates/authenticator/EmptyAuthenticator.tpl.php b/templates/authenticator/EmptyAuthenticator.tpl.php index bfa1e7fc1..66c124490 100644 --- a/templates/authenticator/EmptyAuthenticator.tpl.php +++ b/templates/authenticator/EmptyAuthenticator.tpl.php @@ -26,7 +26,7 @@ public function onAuthenticationFailure(Request $request, AuthenticationExceptio // TODO: Implement onAuthenticationFailure() method. } -// public function start(Request $request, AuthenticationException $authException = null): Response +// public function start(Request $request, ?AuthenticationException $authException = null): Response // { // /* // * If you would like this class to control what happens when an anonymous user accesses a diff --git a/templates/security/custom/Authenticator.tpl.php b/templates/security/custom/Authenticator.tpl.php index dacec9b52..9aaa46235 100644 --- a/templates/security/custom/Authenticator.tpl.php +++ b/templates/security/custom/Authenticator.tpl.php @@ -54,7 +54,7 @@ public function onAuthenticationFailure(Request $request, AuthenticationExceptio return new JsonResponse($data, Response::HTTP_UNAUTHORIZED); } - // public function start(Request $request, AuthenticationException $authException = null): Response + // public function start(Request $request, ?AuthenticationException $authException = null): Response // { // /* // * If you would like this class to control what happens when an anonymous user accesses a diff --git a/templates/serializer/Normalizer.tpl.php b/templates/serializer/Normalizer.tpl.php index 8fdeee82b..504d7efb6 100644 --- a/templates/serializer/Normalizer.tpl.php +++ b/templates/serializer/Normalizer.tpl.php @@ -12,7 +12,7 @@ public function __construct( ) { } - public function normalize($object, string $format = null, array $context = []): array + public function normalize($object, ?string $format = null, array $context = []): array { $data = $this->normalizer->normalize($object, $format, $context); @@ -21,7 +21,7 @@ public function normalize($object, string $format = null, array $context = []): return $data; } - public function supportsNormalization($data, string $format = null, array $context = []): bool + public function supportsNormalization($data, ?string $format = null, array $context = []): bool { return $data instanceof ; diff --git a/tests/Command/MakerCommandTest.php b/tests/Command/MakerCommandTest.php index d52b2d723..06aa9823d 100644 --- a/tests/Command/MakerCommandTest.php +++ b/tests/Command/MakerCommandTest.php @@ -40,7 +40,7 @@ public function testExceptionOnMissingDependencies(): void $fileManager = $this->createMock(FileManager::class); - $command = new MakerCommand($maker, $fileManager, new Generator($fileManager, 'App'), new TemplateLinter($fileManager)); + $command = new MakerCommand($maker, $fileManager, new Generator($fileManager, 'App'), new TemplateLinter()); // needed because it's normally set by the Application $command->setName('make:foo'); $tester = new CommandTester($command); @@ -53,7 +53,7 @@ public function testExceptionOnUnknownRootNamespace(): void $fileManager = $this->createMock(FileManager::class); - $command = new MakerCommand($maker, $fileManager, new Generator($fileManager, 'Unknown'), new TemplateLinter($fileManager)); + $command = new MakerCommand($maker, $fileManager, new Generator($fileManager, 'Unknown'), new TemplateLinter()); // needed because it's normally set by the Application $command->setName('make:foo'); $tester = new CommandTester($command); diff --git a/tests/Maker/TemplateLinterTest.php b/tests/Maker/TemplateLinterTest.php index 2747bb033..cf14850ab 100644 --- a/tests/Maker/TemplateLinterTest.php +++ b/tests/Maker/TemplateLinterTest.php @@ -33,6 +33,7 @@ protected function getMakerClass(): string public function getTestDetails(): \Generator { yield 'lints_templates_with_custom_php_cs_fixer_and_config' => [$this->createMakerTest() + ->addExtraDependencies('php-cs-fixer/shim') ->run(function (MakerTestRunner $runner) { $runner->copy('template-linter/php-cs-fixer.test.php', 'php-cs-fixer.test.php'); @@ -52,12 +53,13 @@ public function getTestDetails(): \Generator self::assertStringContainsString('Linted by custom php-cs-config', $generatedTemplate); - $expectedOutput = 'System PHP-CS-Fixer (bin/php-cs-fixer) & System PHP-CS-Fixer Configuration'; + $expectedOutput = 'System PHP-CS-Fixer (bin/php-cs-fixer) & System PHP-CS-Fixer Configuration (php-cs-fixer.test.php)'; self::assertStringContainsString($expectedOutput, $output); }), ]; yield 'lints_templates_with_flex_generated_config_file' => [$this->createMakerTest() + ->addExtraDependencies('php-cs-fixer/shim') ->run(function (MakerTestRunner $runner) { $runner->replaceInFile( '.php-cs-fixer.dist.php', @@ -77,14 +79,13 @@ public function getTestDetails(): \Generator self::assertStringContainsString('Linted with stock php-cs-config', $generatedTemplate); - $expectedOutput = 'Bundled PHP-CS-Fixer & System PHP-CS-Fixer Configuration'; + $expectedOutput = 'Bundled PHP-CS-Fixer & System PHP-CS-Fixer Configuration (.php-cs-fixer.dist.php)'; self::assertStringContainsString($expectedOutput, $output); }), ]; yield 'lints_templates_with_bundled_php_cs_fixer' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { - $runner->deleteFile('.php-cs-fixer.dist.php'); // Voter class name $output = $runner->runMaker(['FooBar']); diff --git a/tests/Util/TemplateLinterTest.php b/tests/Util/TemplateLinterTest.php index f5086b6e7..aca250c4f 100644 --- a/tests/Util/TemplateLinterTest.php +++ b/tests/Util/TemplateLinterTest.php @@ -11,9 +11,7 @@ namespace Symfony\Bundle\MakerBundle\Tests\Util; -use Composer\InstalledVersions; use PHPUnit\Framework\TestCase; -use Symfony\Bundle\MakerBundle\FileManager; use Symfony\Bundle\MakerBundle\Util\TemplateLinter; use Symfony\Component\Process\Process; @@ -30,30 +28,27 @@ public function testExceptionBinaryPathDoesntExist(): void { $this->expectExceptionMessage('The MAKER_PHP_CS_FIXER_BINARY_PATH provided: /some/bad/path does not exist.'); - new TemplateLinter($this->createMock(FileManager::class), phpCsFixerBinaryPath: '/some/bad/path'); + new TemplateLinter(phpCsFixerBinaryPath: '/some/bad/path'); } public function testExceptionThrownIfConfigPathDoesntExist(): void { $this->expectExceptionMessage('The MAKER_PHP_CS_FIXER_CONFIG_PATH provided: /bad/config/path does not exist.'); - new TemplateLinter($this->createMock(FileManager::class), phpCsFixerConfigPath: '/bad/config/path'); + new TemplateLinter(phpCsFixerConfigPath: '/bad/config/path'); } public function testPhpCsFixerVersion(): void { $this->markTestSkippedOnWindows(); - $fixerPath = \sprintf('%s/vendor/php-cs-fixer/shim/php-cs-fixer', \dirname(__DIR__, 2)); - - // Get the installed version and remove the preceding "v" - $expectedVersion = ltrim(InstalledVersions::getPrettyVersion('php-cs-fixer/shim'), 'v'); + $fixerPath = \sprintf('%s/src/Resources/bin/php-cs-fixer-v%s.phar', \dirname(__DIR__, 2), TemplateLinter::BUNDLED_PHP_CS_FIXER_VERSION); $process = Process::fromShellCommandline(\sprintf('%s -V', $fixerPath)); $process->run(); - self::assertStringContainsString($expectedVersion, $process->getOutput()); + self::assertStringContainsString(TemplateLinter::BUNDLED_PHP_CS_FIXER_VERSION, $process->getOutput()); } private function markTestSkippedOnWindows(): void diff --git a/tests/fixtures/make-entity/regenerate-embedded/attributes/src/Entity/Money.php b/tests/fixtures/make-entity/regenerate-embedded/attributes/src/Entity/Money.php index f5e46a29a..87f226377 100644 --- a/tests/fixtures/make-entity/regenerate-embedded/attributes/src/Entity/Money.php +++ b/tests/fixtures/make-entity/regenerate-embedded/attributes/src/Entity/Money.php @@ -16,7 +16,7 @@ class Money #[ORM\Column(name: 'amount')] private ?int $amount; - public function __construct($amount = null, Currency $currency = null) + public function __construct($amount = null, ?Currency $currency = null) { $this->amount = $amount; $this->currency = $currency ?? new Currency(); diff --git a/tests/fixtures/make-serializer-normalizer/EntityFixtureNormalizer.php b/tests/fixtures/make-serializer-normalizer/EntityFixtureNormalizer.php index 4316e3b27..848110fab 100644 --- a/tests/fixtures/make-serializer-normalizer/EntityFixtureNormalizer.php +++ b/tests/fixtures/make-serializer-normalizer/EntityFixtureNormalizer.php @@ -10,7 +10,7 @@ class EntityFixtureNormalizer implements NormalizerInterface { public function __construct( #[Autowire(service: 'serializer.normalizer.object')] - private NormalizerInterface $normalizer, + private NormalizerInterface $normalizer ) { } diff --git a/tests/fixtures/make-serializer-normalizer/FooBarNormalizer.php b/tests/fixtures/make-serializer-normalizer/FooBarNormalizer.php index 8a8c50aaf..3f253fdbd 100644 --- a/tests/fixtures/make-serializer-normalizer/FooBarNormalizer.php +++ b/tests/fixtures/make-serializer-normalizer/FooBarNormalizer.php @@ -9,7 +9,7 @@ class FooBarNormalizer implements NormalizerInterface { public function __construct( #[Autowire(service: 'serializer.normalizer.object')] - private NormalizerInterface $normalizer, + private NormalizerInterface $normalizer ) { } diff --git a/tests/fixtures/make-validator/expected/FooBar.php b/tests/fixtures/make-validator/expected/FooBar.php index 239fd8bf1..40bbd5087 100644 --- a/tests/fixtures/make-validator/expected/FooBar.php +++ b/tests/fixtures/make-validator/expected/FooBar.php @@ -14,7 +14,7 @@ final class FooBar extends Constraint public function __construct( public string $mode = 'strict', ?array $groups = null, - mixed $payload = null, + mixed $payload = null ) { parent::__construct([], $groups, $payload); } diff --git a/tests/fixtures/make-voter/expected/FooBarVoter.php b/tests/fixtures/make-voter/expected/FooBarVoter.php index 2a2cf060c..2cfc1ee22 100644 --- a/tests/fixtures/make-voter/expected/FooBarVoter.php +++ b/tests/fixtures/make-voter/expected/FooBarVoter.php @@ -22,6 +22,7 @@ protected function supports(string $attribute, mixed $subject): bool protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool { $user = $token->getUser(); + // if the user is anonymous, do not grant access if (!$user instanceof UserInterface) { return false; @@ -33,6 +34,7 @@ protected function voteOnAttribute(string $attribute, mixed $subject, TokenInter // logic to determine if the user can EDIT // return true or false break; + case self::VIEW: // logic to determine if the user can VIEW // return true or false diff --git a/tests/fixtures/make-voter/expected/not_final_FooBarVoter.php b/tests/fixtures/make-voter/expected/not_final_FooBarVoter.php index f67500726..e38fb4ad2 100644 --- a/tests/fixtures/make-voter/expected/not_final_FooBarVoter.php +++ b/tests/fixtures/make-voter/expected/not_final_FooBarVoter.php @@ -22,6 +22,7 @@ protected function supports(string $attribute, mixed $subject): bool protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool { $user = $token->getUser(); + // if the user is anonymous, do not grant access if (!$user instanceof UserInterface) { return false; @@ -33,6 +34,7 @@ protected function voteOnAttribute(string $attribute, mixed $subject, TokenInter // logic to determine if the user can EDIT // return true or false break; + case self::VIEW: // logic to determine if the user can VIEW // return true or false diff --git a/tests/fixtures/security/make-custom-authenticator/expected/FixtureAuthenticator.php b/tests/fixtures/security/make-custom-authenticator/expected/FixtureAuthenticator.php index c9edf8402..b6126fdff 100644 --- a/tests/fixtures/security/make-custom-authenticator/expected/FixtureAuthenticator.php +++ b/tests/fixtures/security/make-custom-authenticator/expected/FixtureAuthenticator.php @@ -63,7 +63,7 @@ public function onAuthenticationFailure(Request $request, AuthenticationExceptio return new JsonResponse($data, Response::HTTP_UNAUTHORIZED); } - // public function start(Request $request, AuthenticationException $authException = null): Response + // public function start(Request $request, ?AuthenticationException $authException = null): Response // { // /* // * If you would like this class to control what happens when an anonymous user accesses a