From 88148d0cb13abb970b804bb5e437483cd9a43e78 Mon Sep 17 00:00:00 2001 From: Jesse Rushlow Date: Tue, 24 May 2022 14:48:23 -0400 Subject: [PATCH] improve PHP 8 support w/ rector, removes legacy code, deprecates unused methods --- src/Command/MakerCommand.php | 4 -- src/Console/MigrationDiffFilteredOutput.php | 19 +++-- src/ConsoleStyle.php | 10 ++- src/DependencyBuilder.php | 18 ++--- src/DependencyInjection/Configuration.php | 7 +- src/Docker/DockerDatabaseServices.php | 16 ++--- src/Doctrine/DoctrineHelper.php | 4 +- src/Doctrine/EntityDetails.php | 4 +- src/Doctrine/EntityRegenerator.php | 22 +++--- src/Event/ConsoleErrorSubscriber.php | 2 +- src/EventRegistry.php | 13 ++-- src/FileManager.php | 69 ++++++------------- src/Generator.php | 35 +++++----- src/GeneratorTwigHelper.php | 10 ++- src/InputConfiguration.php | 2 +- src/Maker/AbstractMaker.php | 8 ++- src/Maker/MakeAuthenticator.php | 2 +- src/Maker/MakeCommand.php | 2 +- src/Maker/MakeDockerDatabase.php | 20 ++---- src/Maker/MakeEntity.php | 61 +++++++--------- src/Maker/MakeForm.php | 2 +- src/Maker/MakeMessage.php | 6 +- src/Maker/MakeMigration.php | 4 +- src/Maker/MakeRegistrationForm.php | 3 +- src/Maker/MakeResetPassword.php | 6 +- src/Maker/MakeSerializerNormalizer.php | 2 +- src/Maker/MakeStimulusController.php | 4 +- src/Maker/MakeUser.php | 20 +++--- src/Renderer/FormTypeRenderer.php | 8 +-- src/Resources/config/services.xml | 3 +- src/Security/SecurityControllerBuilder.php | 6 -- src/Security/UserClassBuilder.php | 4 +- src/Security/UserClassConfiguration.php | 17 ----- src/Str.php | 6 +- src/Test/MakerTestRunner.php | 1 - src/Util/AutoloaderUtil.php | 10 +-- src/Util/ClassDetails.php | 2 +- src/Util/ClassNameValue.php | 4 +- src/Util/ComposerAutoloaderFinder.php | 12 ++-- src/Util/MakerFileLinkFormatter.php | 13 +--- src/Validator.php | 15 ++-- tests/Command/MakerCommandTest.php | 9 +-- tests/Doctrine/EntityRegeneratorTest.php | 4 +- tests/GeneratorTest.php | 5 +- tests/Maker/MakeAuthenticatorTest.php | 2 - tests/Maker/MakeRegistrationFormTest.php | 1 - tests/Maker/MakeUserTest.php | 2 - .../SecurityControllerBuilderTest.php | 10 +-- tests/Util/ClassSourceManipulatorTest.php | 10 +-- ...pVersionTest.php => PhpCompatUtilTest.php} | 48 +------------ 50 files changed, 195 insertions(+), 372 deletions(-) rename tests/Util/{PhpVersionTest.php => PhpCompatUtilTest.php} (59%) diff --git a/src/Command/MakerCommand.php b/src/Command/MakerCommand.php index 7453dc6ba..59ba888ed 100644 --- a/src/Command/MakerCommand.php +++ b/src/Command/MakerCommand.php @@ -57,10 +57,6 @@ protected function initialize(InputInterface $input, OutputInterface $output): v $dependencies = new DependencyBuilder(); $this->maker->configureDependencies($dependencies, $input); - if (!$dependencies->isPhpVersionSatisfied()) { - throw new RuntimeCommandException('The make:entity command requires that you use PHP 7.1 or higher.'); - } - if ($missingPackagesMessage = $dependencies->getMissingPackagesMessage($this->getName())) { throw new RuntimeCommandException($missingPackagesMessage); } diff --git a/src/Console/MigrationDiffFilteredOutput.php b/src/Console/MigrationDiffFilteredOutput.php index 65e81b96c..a03a4d3a5 100644 --- a/src/Console/MigrationDiffFilteredOutput.php +++ b/src/Console/MigrationDiffFilteredOutput.php @@ -14,9 +14,9 @@ use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Output\OutputInterface; -if (\PHP_VERSION_ID < 80000 - // look for the "string|iterable" type on OutputInterface::write() - || !(new \ReflectionMethod(OutputInterface::class, 'write'))->getParameters()[0]->getType()) { +// look for the "string|iterable" type on OutputInterface::write() +// @legacy - Use MigrationDiffFilteredOutput_php8 when Symfony 5.4 is no longer supported +if (!(new \ReflectionMethod(OutputInterface::class, 'write'))->getParameters()[0]->getType()) { class MigrationDiffFilteredOutput implements OutputInterface { use BaseMakerMigrationDiffFilteredOuputTrait; @@ -47,13 +47,12 @@ public function setDecorated($decorated) trait BaseMakerMigrationDiffFilteredOuputTrait { - private $output; - private $buffer = ''; - private $previousLineWasRemoved = false; + private string $buffer = ''; + private bool $previousLineWasRemoved = false; - public function __construct(OutputInterface $output) - { - $this->output = $output; + public function __construct( + private OutputInterface $output, + ) { } public function _write($messages, bool $newline = false, $options = 0) @@ -144,7 +143,7 @@ private function filterMessages($messages, bool $newLine) $this->previousLineWasRemoved = false; foreach ($hiddenPhrases as $hiddenPhrase) { - if (false !== strpos($message, $hiddenPhrase)) { + if (str_contains($message, $hiddenPhrase)) { $this->previousLineWasRemoved = true; unset($messages[$key]); diff --git a/src/ConsoleStyle.php b/src/ConsoleStyle.php index 40f1c909c..dee9a88c3 100644 --- a/src/ConsoleStyle.php +++ b/src/ConsoleStyle.php @@ -21,12 +21,10 @@ */ final class ConsoleStyle extends SymfonyStyle { - private $output; - - public function __construct(InputInterface $input, OutputInterface $output) - { - $this->output = $output; - + public function __construct( + InputInterface $input, + private OutputInterface $output, + ) { parent::__construct($input, $output); } diff --git a/src/DependencyBuilder.php b/src/DependencyBuilder.php index a06f7200f..f526c84f4 100644 --- a/src/DependencyBuilder.php +++ b/src/DependencyBuilder.php @@ -13,10 +13,8 @@ final class DependencyBuilder { - private $dependencies = []; - private $devDependencies = []; - - private $minimumPHPVersion = 70100; + private array $dependencies = []; + private array $devDependencies = []; /** * Add a dependency that will be reported if the given class is missing. @@ -44,7 +42,7 @@ public function addClassDependency(string $class, string $package, bool $require public function requirePHP71(): void { - // no-op - MakerBundle now required PHP 7.1 + trigger_deprecation('symfony/maker-bundle', 'v1.44.0', 'requirePHP71() is deprecated and will be removed in a future version.'); } /** @@ -110,14 +108,6 @@ public function getMissingPackagesMessage(string $commandName, $message = null): return $message; } - /** - * @internal - */ - public function isPhpVersionSatisfied(): bool - { - return \PHP_VERSION_ID >= $this->minimumPHPVersion; - } - private function getRequiredDependencyNames(array $dependencies): array { $packages = []; @@ -149,6 +139,6 @@ private function calculateMissingDependencies(array $dependencies): array return []; } - return array_unique(array_merge($missingPackages, $missingOptionalPackages)); + return array_unique([...$missingPackages, ...$missingOptionalPackages]); } } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 787672159..5c78dd994 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -22,12 +22,7 @@ class Configuration implements ConfigurationInterface public function getConfigTreeBuilder(): TreeBuilder { $treeBuilder = new TreeBuilder('maker'); - if (method_exists($treeBuilder, 'getRootNode')) { - $rootNode = $treeBuilder->getRootNode(); - } else { - // BC layer for symfony/config 4.1 and older - $rootNode = $treeBuilder->root('maker'); - } + $rootNode = $treeBuilder->getRootNode(); $rootNode ->children() diff --git a/src/Docker/DockerDatabaseServices.php b/src/Docker/DockerDatabaseServices.php index 29f1aac80..e0548de31 100644 --- a/src/Docker/DockerDatabaseServices.php +++ b/src/Docker/DockerDatabaseServices.php @@ -83,17 +83,11 @@ public static function getSuggestedServiceVersion(string $name): string public static function getMissingExtensionName(string $name): ?string { - switch ($name) { - case 'mariadb': - case 'mysql': - $driver = 'mysql'; - break; - case 'postgres': - $driver = 'pgsql'; - break; - default: - self::throwInvalidDatabase($name); - } + $driver = match ($name) { + 'mariadb', 'mysql' => 'mysql', + 'postgres' => 'pgsql', + default => self::throwInvalidDatabase($name), + }; if (!\in_array($driver, \PDO::getAvailableDrivers(), true)) { return $driver; diff --git a/src/Doctrine/DoctrineHelper.php b/src/Doctrine/DoctrineHelper.php index 551053f79..290e69047 100644 --- a/src/Doctrine/DoctrineHelper.php +++ b/src/Doctrine/DoctrineHelper.php @@ -68,7 +68,7 @@ public function doesClassUseDriver(string $className, string $driverClass): bool try { /** @var EntityManagerInterface $em */ $em = $this->getRegistry()->getManagerForClass($className); - } catch (\ReflectionException $exception) { + } catch (\ReflectionException) { // this exception will be thrown by the registry if the class isn't created yet. // an example case is the "make:entity" command, which needs to know which driver is used for the class to determine // if the class should be generated with attributes or annotations. If this exception is thrown, we will check based on the @@ -167,7 +167,7 @@ public function getMetadata(string $classOrNamespace = null, bool $disconnected if ($disconnected) { try { $loaded = $cmf->getAllMetadata(); - } catch (ORMMappingException|PersistenceMappingException $e) { + } catch (ORMMappingException|PersistenceMappingException) { $loaded = $this->isInstanceOf($cmf, AbstractClassMetadataFactory::class) ? $cmf->getLoadedMetadata() : []; } diff --git a/src/Doctrine/EntityDetails.php b/src/Doctrine/EntityDetails.php index 73d07b108..d0aa63e29 100644 --- a/src/Doctrine/EntityDetails.php +++ b/src/Doctrine/EntityDetails.php @@ -52,9 +52,7 @@ public function getFormFields(): array if (!empty($this->metadata->embeddedClasses)) { foreach (array_keys($this->metadata->embeddedClasses) as $embeddedClassKey) { - $fields = array_filter($fields, function ($v) use ($embeddedClassKey) { - return 0 !== strpos($v, $embeddedClassKey.'.'); - }); + $fields = array_filter($fields, static fn ($v) => !str_starts_with($v, $embeddedClassKey.'.')); } } diff --git a/src/Doctrine/EntityRegenerator.php b/src/Doctrine/EntityRegenerator.php index 7f5cb70dc..77e6ce02e 100644 --- a/src/Doctrine/EntityRegenerator.php +++ b/src/Doctrine/EntityRegenerator.php @@ -38,7 +38,7 @@ public function regenerateEntities(string $classOrNamespace): void { try { $metadata = $this->doctrineHelper->getMetadata($classOrNamespace); - } catch (MappingException|LegacyCommonMappingException|PersistenceMappingException $mappingException) { + } catch (MappingException|LegacyCommonMappingException|PersistenceMappingException) { $metadata = $this->doctrineHelper->getMetadata($classOrNamespace, true); } @@ -72,7 +72,7 @@ public function regenerateEntities(string $classOrNamespace): void $embeddedClasses = []; foreach ($classMetadata->embeddedClasses as $fieldName => $mapping) { - if (false !== strpos($fieldName, '.')) { + if (str_contains($fieldName, '.')) { continue; } @@ -91,7 +91,7 @@ public function regenerateEntities(string $classOrNamespace): void foreach ($classMetadata->fieldMappings as $fieldName => $mapping) { // skip embedded fields - if (false !== strpos($fieldName, '.')) { + if (str_contains($fieldName, '.')) { [$fieldName, $embeddedFiledName] = explode('.', $fieldName); $operations[$embeddedClasses[$fieldName]]->addEntityField($embeddedFiledName, $mapping); @@ -238,11 +238,11 @@ private function getMappedFieldsInEntity(ClassMetadata $classMetadata): array /** @var \ReflectionClass $classReflection */ $classReflection = $classMetadata->reflClass; - $targetFields = array_merge( - array_keys($classMetadata->fieldMappings), - array_keys($classMetadata->associationMappings), - array_keys($classMetadata->embeddedClasses) - ); + $targetFields = [ + ...array_keys($classMetadata->fieldMappings), + ...array_keys($classMetadata->associationMappings), + ...array_keys($classMetadata->embeddedClasses), + ]; if ($classReflection) { // exclude traits @@ -257,10 +257,8 @@ private function getMappedFieldsInEntity(ClassMetadata $classMetadata): array $targetFields = array_diff($targetFields, $traitProperties); // exclude inherited properties - $targetFields = array_filter($targetFields, static function ($field) use ($classReflection) { - return $classReflection->hasProperty($field) && - $classReflection->getProperty($field)->getDeclaringClass()->getName() == $classReflection->getName(); - }); + $targetFields = array_filter($targetFields, static fn ($field) => $classReflection->hasProperty($field) && + $classReflection->getProperty($field)->getDeclaringClass()->getName() === $classReflection->getName()); } return $targetFields; diff --git a/src/Event/ConsoleErrorSubscriber.php b/src/Event/ConsoleErrorSubscriber.php index b58a49338..c05c5f5ca 100644 --- a/src/Event/ConsoleErrorSubscriber.php +++ b/src/Event/ConsoleErrorSubscriber.php @@ -25,7 +25,7 @@ */ final class ConsoleErrorSubscriber implements EventSubscriberInterface { - private $setExitCode = false; + private bool $setExitCode = false; public function onConsoleError(ConsoleErrorEvent $event): void { diff --git a/src/EventRegistry.php b/src/EventRegistry.php index 37541a998..81df2a90f 100644 --- a/src/EventRegistry.php +++ b/src/EventRegistry.php @@ -43,7 +43,7 @@ class EventRegistry { // list of *known* events to always include (if they exist) - private static $newEventsMap = [ + private static array $newEventsMap = [ 'kernel.exception' => ExceptionEvent::class, 'kernel.request' => RequestEvent::class, 'kernel.response' => ResponseEvent::class, @@ -53,7 +53,7 @@ class EventRegistry 'kernel.terminate' => TerminateEvent::class, ]; - private static $eventsMap = [ + private static array $eventsMap = [ 'console.command' => ConsoleCommandEvent::class, 'console.terminate' => ConsoleTerminateEvent::class, 'console.error' => ConsoleErrorEvent::class, @@ -71,12 +71,9 @@ class EventRegistry 'security.switch_user' => SwitchUserEvent::class, ]; - private $eventDispatcher; - - public function __construct(EventDispatcherInterface $eventDispatcher) - { - $this->eventDispatcher = $eventDispatcher; - + public function __construct( + private EventDispatcherInterface $eventDispatcher, + ) { // Loop through the new event classes foreach (self::$newEventsMap as $eventName => $newEventClass) { // Check if the new event classes exist, if so replace the old one with the new. diff --git a/src/FileManager.php b/src/FileManager.php index 266228550..d70c7b24d 100644 --- a/src/FileManager.php +++ b/src/FileManager.php @@ -15,7 +15,6 @@ use Symfony\Bundle\MakerBundle\Util\MakerFileLinkFormatter; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Finder\Finder; /** * @author Javier Eguiluz @@ -25,26 +24,15 @@ */ class FileManager { - private $fs; - private $autoloaderUtil; - private $makerFileLinkFormatter; - private $rootDirectory; - /** @var SymfonyStyle */ - private $io; - private $twigDefaultPath; + private ?SymfonyStyle $io = null; public function __construct( - Filesystem $fs, - AutoloaderUtil $autoloaderUtil, - MakerFileLinkFormatter $makerFileLinkFormatter, - string $rootDirectory, - string $twigDefaultPath = null, + private Filesystem $fs, + private AutoloaderUtil $autoloaderUtil, + private MakerFileLinkFormatter $makerFileLinkFormatter, + private string $rootDirectory, + private ?string $twigDefaultPath = null, ) { - // move FileManagerTest stuff - // update EntityRegeneratorTest to mock the autoloader - $this->fs = $fs; - $this->autoloaderUtil = $autoloaderUtil; - $this->makerFileLinkFormatter = $makerFileLinkFormatter; $this->rootDirectory = rtrim($this->realPath($this->normalizeSlashes($rootDirectory)), '/'); $this->twigDefaultPath = $twigDefaultPath ? rtrim($this->relativizePath($twigDefaultPath), '/') : null; } @@ -77,13 +65,11 @@ public function dumpFile(string $filename, string $content): void $this->fs->dumpFile($absolutePath, $content); $relativePath = $this->relativizePath($filename); - if ($this->io) { - $this->io->comment(sprintf( - '%s: %s', - $comment, - $this->makerFileLinkFormatter->makeLinkedPath($absolutePath, $relativePath) - )); - } + $this->io?->comment(sprintf( + '%s: %s', + $comment, + $this->makerFileLinkFormatter->makeLinkedPath($absolutePath, $relativePath) + )); } public function fileExists($path): bool @@ -94,16 +80,14 @@ public function fileExists($path): bool /** * Attempts to make the path relative to the root directory. * - * @param string $absolutePath - * * @throws \Exception */ - public function relativizePath($absolutePath): string + public function relativizePath(string $absolutePath): string { $absolutePath = $this->normalizeSlashes($absolutePath); // see if the path is even in the root - if (false === strpos($absolutePath, $this->rootDirectory)) { + if (!str_contains($absolutePath, $this->rootDirectory)) { return $absolutePath; } @@ -111,7 +95,7 @@ public function relativizePath($absolutePath): string // str_replace but only the first occurrence $relativePath = ltrim(implode('', explode($this->rootDirectory, $absolutePath, 2)), '/'); - if (0 === strpos($relativePath, './')) { + if (str_starts_with($relativePath, './')) { $relativePath = substr($relativePath, 2); } @@ -127,22 +111,17 @@ public function getFileContents(string $path): string return file_get_contents($this->absolutizePath($path)); } - public function createFinder(string $in): Finder - { - $finder = new Finder(); - $finder->in($this->absolutizePath($in)); - - return $finder; - } - public function isPathInVendor(string $path): bool { - return 0 === strpos($this->normalizeSlashes($path), $this->normalizeSlashes($this->rootDirectory.'/vendor/')); + return str_starts_with( + $this->normalizeSlashes($path), + $this->normalizeSlashes($this->rootDirectory.'/vendor/') + ); } public function absolutizePath($path): string { - if (0 === strpos($path, '/')) { + if (str_starts_with($path, '/')) { return $path; } @@ -190,10 +169,8 @@ public function getPathForTemplate(string $filename): string /** * Resolve '../' in paths (like real_path), but for non-existent files. - * - * @param string $absolutePath */ - private function realPath($absolutePath): string + private function realPath(string $absolutePath): string { $finalParts = []; $currentIndex = -1; @@ -219,12 +196,10 @@ private function realPath($absolutePath): string $finalPath = implode('/', $finalParts); // Normalize: // => / // Normalize: /./ => / - $finalPath = str_replace(['//', '/./'], '/', $finalPath); - - return $finalPath; + return str_replace(['//', '/./'], '/', $finalPath); } - private function normalizeSlashes(string $path) + private function normalizeSlashes(string $path): string { return str_replace('\\', '/', $path); } diff --git a/src/Generator.php b/src/Generator.php index 28ac09a9e..9675c4094 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -23,26 +23,23 @@ */ class Generator { - private $fileManager; - private $twigHelper; - private $pendingOperations = []; - private $namespacePrefix; - private $phpCompatUtil; - private $templateComponentGenerator; - - public function __construct(FileManager $fileManager, string $namespacePrefix, PhpCompatUtil $phpCompatUtil = null, TemplateComponentGenerator $templateComponentGenerator = null) - { - $this->fileManager = $fileManager; + private GeneratorTwigHelper $twigHelper; + private array $pendingOperations = []; + private ?TemplateComponentGenerator $templateComponentGenerator; + + public function __construct( + private FileManager $fileManager, + private string $namespacePrefix, + PhpCompatUtil $phpCompatUtil = null, + TemplateComponentGenerator $templateComponentGenerator = null, + ) { $this->twigHelper = new GeneratorTwigHelper($fileManager); $this->namespacePrefix = trim($namespacePrefix, '\\'); - if (null === $phpCompatUtil) { - $phpCompatUtil = new PhpCompatUtil($fileManager); - - trigger_deprecation('symfony/maker-bundle', '1.25', 'Initializing Generator without providing an instance of PhpCompatUtil is deprecated.'); + if (null !== $phpCompatUtil) { + trigger_deprecation('symfony/maker-bundle', 'v1.44.0', 'Initializing Generator while providing an instance of PhpCompatUtil is deprecated.'); } - $this->phpCompatUtil = $phpCompatUtil; $this->templateComponentGenerator = $templateComponentGenerator; } @@ -151,7 +148,7 @@ public function createClassNameDetails(string $name, string $namespacePrefix, st // if this is a custom class, we may be completely different than the namespace prefix // the best way can do, is find the PSR4 prefix and use that - if (0 !== strpos($className, $fullNamespacePrefix)) { + if (!str_starts_with($className, $fullNamespacePrefix)) { $fullNamespacePrefix = $this->fileManager->getNamespacePrefixForClass($className); } @@ -163,7 +160,7 @@ public function getRootDirectory(): string return $this->fileManager->getRootDirectory(); } - private function addOperation(string $targetPath, string $templateName, array $variables) + private function addOperation(string $targetPath, string $templateName, array $variables): void { if ($this->fileManager->fileExists($targetPath)) { throw new RuntimeCommandException(sprintf('The file "%s" can\'t be generated because it already exists.', $this->fileManager->relativizePath($targetPath))); @@ -193,6 +190,8 @@ public function hasPendingOperations(): bool /** * Actually writes and file changes that are pending. + * + * @return void */ public function writeChanges() { @@ -231,6 +230,8 @@ public function generateController(string $controllerClassName, string $controll /** * Generate a template file. + * + * @return void */ public function generateTemplate(string $targetPath, string $templateName, array $variables = []) { diff --git a/src/GeneratorTwigHelper.php b/src/GeneratorTwigHelper.php index 47bc58b30..b0aca4545 100644 --- a/src/GeneratorTwigHelper.php +++ b/src/GeneratorTwigHelper.php @@ -16,16 +16,14 @@ */ final class GeneratorTwigHelper { - private $fileManager; - - public function __construct(FileManager $fileManager) - { - $this->fileManager = $fileManager; + public function __construct( + private FileManager $fileManager, + ) { } public function getEntityFieldPrintCode($entity, $field): string { - $twigField = preg_replace_callback('/(?!^)_([a-z0-9])/', function ($s) { + $twigField = preg_replace_callback('/(?!^)_([a-z0-9])/', static function ($s) { return strtoupper($s[1]); }, $field['fieldName']); $printCode = $entity.'.'.str_replace('_', '', $twigField); diff --git a/src/InputConfiguration.php b/src/InputConfiguration.php index 6d48da6e5..3d6dc056f 100644 --- a/src/InputConfiguration.php +++ b/src/InputConfiguration.php @@ -13,7 +13,7 @@ final class InputConfiguration { - private $nonInteractiveArguments = []; + private array $nonInteractiveArguments = []; /** * Call in MakerInterface::configureCommand() to disable the automatic interactive diff --git a/src/Maker/AbstractMaker.php b/src/Maker/AbstractMaker.php index 3d5a84841..50d8fcf6e 100644 --- a/src/Maker/AbstractMaker.php +++ b/src/Maker/AbstractMaker.php @@ -22,10 +22,16 @@ */ abstract class AbstractMaker implements MakerInterface { + /** + * @return void + */ public function interact(InputInterface $input, ConsoleStyle $io, Command $command) { } + /** + * @return void + */ protected function writeSuccessMessage(ConsoleStyle $io) { $io->newLine(); @@ -44,7 +50,7 @@ protected function addDependencies(array $dependencies, string $message = null): } return $dependencyBuilder->getMissingPackagesMessage( - $this->getCommandName(), + static::getCommandName(), $message ); } diff --git a/src/Maker/MakeAuthenticator.php b/src/Maker/MakeAuthenticator.php index 72d375e05..57fcdb8cb 100644 --- a/src/Maker/MakeAuthenticator.php +++ b/src/Maker/MakeAuthenticator.php @@ -218,7 +218,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen ); $generator->dumpFile($path, $newYaml); $securityYamlUpdated = true; - } catch (YamlManipulationFailedException $e) { + } catch (YamlManipulationFailedException) { } if (self::AUTH_TYPE_FORM_LOGIN === $input->getArgument('authenticator-type')) { diff --git a/src/Maker/MakeCommand.php b/src/Maker/MakeCommand.php index 1773df4aa..36e24b492 100644 --- a/src/Maker/MakeCommand.php +++ b/src/Maker/MakeCommand.php @@ -58,7 +58,7 @@ public function configureCommand(Command $command, InputConfiguration $inputConf public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator): void { $commandName = trim($input->getArgument('name')); - $commandNameHasAppPrefix = 0 === strpos($commandName, 'app:'); + $commandNameHasAppPrefix = str_starts_with($commandName, 'app:'); $commandClassNameDetails = $generator->createClassNameDetails( $commandNameHasAppPrefix ? substr($commandName, 4) : $commandName, diff --git a/src/Maker/MakeDockerDatabase.php b/src/Maker/MakeDockerDatabase.php index 2c32c857d..4da70c290 100644 --- a/src/Maker/MakeDockerDatabase.php +++ b/src/Maker/MakeDockerDatabase.php @@ -30,32 +30,26 @@ */ final class MakeDockerDatabase extends AbstractMaker { - private $fileManager; - private $composeFilePath; + private string $composeFilePath; + private ?ComposeFileManipulator $composeFileManipulator = null; /** - * @var ComposeFileManipulator + * @var ?string type of database selected by the user */ - private $composeFileManipulator; - - /** - * @var string type of database selected by the user - */ - private $databaseChoice; + private ?string $databaseChoice = null; /** * @var string Service identifier to be set in docker-compose.yaml */ - private $serviceName = 'database'; + private string $serviceName = 'database'; /** * @var string Version set in docker-compose.yaml for the service. e.g. latest */ - private $serviceVersion = 'latest'; + private string $serviceVersion = 'latest'; - public function __construct(FileManager $fileManager) + public function __construct(private FileManager $fileManager) { - $this->fileManager = $fileManager; } public static function getCommandName(): string diff --git a/src/Maker/MakeEntity.php b/src/Maker/MakeEntity.php index da4b0e493..2553d89aa 100644 --- a/src/Maker/MakeEntity.php +++ b/src/Maker/MakeEntity.php @@ -369,9 +369,9 @@ private function askForNextField(ConsoleStyle $io, array $fields, string $entity $defaultType = 'datetime_immutable'; } elseif ('_id' === $suffix) { $defaultType = 'integer'; - } elseif (0 === strpos($snakeCasedField, 'is_')) { + } elseif (str_starts_with($snakeCasedField, 'is_')) { $defaultType = 'boolean'; - } elseif (0 === strpos($snakeCasedField, 'has_')) { + } elseif (str_starts_with($snakeCasedField, 'has_')) { $defaultType = 'boolean'; } elseif ('uuid' === $snakeCasedField) { $defaultType = 'uuid'; @@ -479,9 +479,9 @@ private function printAvailableTypes(ConsoleStyle $io): void if (\is_string($subTypes) && $subTypes) { $line .= sprintf(' (%s)', $subTypes); } elseif (\is_array($subTypes) && !empty($subTypes)) { - $line .= sprintf(' (or %s)', implode(', ', array_map(function ($subType) { - return sprintf('%s', $subType); - }, $subTypes))); + $line .= sprintf(' (or %s)', implode(', ', array_map( + static fn ($subType) => sprintf('%s', $subType), $subTypes)) + ); foreach ($subTypes as $subType) { unset($allTypes[$subType]); @@ -508,9 +508,7 @@ private function printAvailableTypes(ConsoleStyle $io): void $io->writeln('Other Types'); // empty the values - $allTypes = array_map(function () { - return []; - }, $allTypes); + $allTypes = array_map(static fn () => [], $allTypes); $printSection($allTypes); } @@ -551,31 +549,27 @@ private function askRelationDetails(ConsoleStyle $io, string $generatedEntityCla $type = $this->askRelationType($io, $generatedEntityClass, $targetEntityClass); } - $askFieldName = function (string $targetClass, string $defaultValue) use ($io) { - return $io->ask( - sprintf('New field name inside %s', Str::getShortClassName($targetClass)), - $defaultValue, - function ($name) use ($targetClass) { - // it's still *possible* to create duplicate properties - by - // trying to generate the same property 2 times during the - // same make:entity run. property_exists() only knows about - // properties that *originally* existed on this class. - if (property_exists($targetClass, $name)) { - throw new \InvalidArgumentException(sprintf('The "%s" class already has a "%s" property.', $targetClass, $name)); - } - - return Validator::validateDoctrineFieldName($name, $this->doctrineHelper->getRegistry()); + $askFieldName = fn (string $targetClass, string $defaultValue) => $io->ask( + sprintf('New field name inside %s', Str::getShortClassName($targetClass)), + $defaultValue, + function ($name) use ($targetClass) { + // it's still *possible* to create duplicate properties - by + // trying to generate the same property 2 times during the + // same make:entity run. property_exists() only knows about + // properties that *originally* existed on this class. + if (property_exists($targetClass, $name)) { + throw new \InvalidArgumentException(sprintf('The "%s" class already has a "%s" property.', $targetClass, $name)); } - ); - }; - $askIsNullable = static function (string $propertyName, string $targetClass) use ($io) { - return $io->confirm(sprintf( - 'Is the %s.%s property allowed to be null (nullable)?', - Str::getShortClassName($targetClass), - $propertyName - )); - }; + return Validator::validateDoctrineFieldName($name, $this->doctrineHelper->getRegistry()); + } + ); + + $askIsNullable = static fn (string $propertyName, string $targetClass) => $io->confirm(sprintf( + 'Is the %s.%s property allowed to be null (nullable)?', + Str::getShortClassName($targetClass), + $propertyName + )); $askOrphanRemoval = static function (string $owningClass, string $inverseClass) use ($io) { $io->text([ @@ -807,7 +801,6 @@ private function createClassManipulator(string $path, ConsoleStyle $io, bool $ov $manipulator = new ClassSourceManipulator( sourceCode: $this->fileManager->getFileContents($path), overwrite: $overwrite, - useAttributesForDoctrineMapping: true ); $manipulator->setIo($io); @@ -841,9 +834,7 @@ private function getPropertyNames(string $class): array $reflClass = new \ReflectionClass($class); - return array_map(static function (\ReflectionProperty $prop) { - return $prop->getName(); - }, $reflClass->getProperties()); + return array_map(static fn (\ReflectionProperty $prop) => $prop->getName(), $reflClass->getProperties()); } /** @legacy Drop when Annotations are no longer supported */ diff --git a/src/Maker/MakeForm.php b/src/Maker/MakeForm.php index 4c93a3527..d5ee7ec84 100644 --- a/src/Maker/MakeForm.php +++ b/src/Maker/MakeForm.php @@ -67,7 +67,7 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma $entities = $this->entityHelper->getEntitiesForAutocomplete(); $question = new Question($argument->getDescription()); - $question->setValidator(function ($answer) use ($entities) {return Validator::existsOrNull($answer, $entities); }); + $question->setValidator(fn ($answer) => Validator::existsOrNull($answer, $entities)); $question->setAutocompleterValues($entities); $question->setMaxAttempts(3); diff --git a/src/Maker/MakeMessage.php b/src/Maker/MakeMessage.php index feaabdc55..1a2442014 100644 --- a/src/Maker/MakeMessage.php +++ b/src/Maker/MakeMessage.php @@ -58,13 +58,15 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma { $command->addArgument('chosen-transport', InputArgument::OPTIONAL); + $messengerData = []; + try { $manipulator = new YamlSourceManipulator($this->fileManager->getFileContents('config/packages/messenger.yaml')); $messengerData = $manipulator->getData(); - } catch (\Exception $e) { + } catch (\Exception) { } - if (!isset($messengerData, $messengerData['framework']['messenger']['transports'])) { + if (!isset($messengerData['framework']['messenger']['transports'])) { return; } diff --git a/src/Maker/MakeMigration.php b/src/Maker/MakeMigration.php index e52d8ed15..4640d21a1 100644 --- a/src/Maker/MakeMigration.php +++ b/src/Maker/MakeMigration.php @@ -104,12 +104,12 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $migrationOutput = $commandOutput->fetch(); - if (false !== strpos($migrationOutput, 'No changes detected')) { + if (str_contains($migrationOutput, 'No changes detected')) { $this->noChangesMessage($io); return; } - } catch (\Doctrine\Migrations\Generator\Exception\NoChangesDetected $exception) { + } catch (\Doctrine\Migrations\Generator\Exception\NoChangesDetected) { $this->noChangesMessage($io); return; diff --git a/src/Maker/MakeRegistrationForm.php b/src/Maker/MakeRegistrationForm.php index fb25f8ed7..407a59f88 100644 --- a/src/Maker/MakeRegistrationForm.php +++ b/src/Maker/MakeRegistrationForm.php @@ -228,7 +228,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $userDoctrineDetails = $this->doctrineHelper->createDoctrineDetails($userClassNameDetails->getFullName()); $userRepoVars = [ - 'repository_full_class_name' => 'Doctrine\ORM\EntityManagerInterface', + 'repository_full_class_name' => EntityManagerInterface::class, 'repository_class_name' => 'EntityManagerInterface', 'repository_var' => '$manager', ]; @@ -392,7 +392,6 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $userManipulator = new ClassSourceManipulator( sourceCode: file_get_contents($classDetails->getPath()), overwrite: false, - useAttributesForDoctrineMapping: true ); $userManipulator->setIo($io); diff --git a/src/Maker/MakeResetPassword.php b/src/Maker/MakeResetPassword.php index 4a1488015..6b0f6cb6e 100644 --- a/src/Maker/MakeResetPassword.php +++ b/src/Maker/MakeResetPassword.php @@ -356,7 +356,7 @@ private function setBundleConfig(ConsoleStyle $io, Generator $generator, string * reset_password.yaml exists, and was probably created by flex; * Let's replace it with a "clean" file. */ - if (1 >= \count($data[$symfonyCastsKey])) { + if (1 >= (is_countable($data[$symfonyCastsKey]) ? \count($data[$symfonyCastsKey]) : 0)) { $yaml = [ $symfonyCastsKey => [ 'request_password_repository' => $repositoryClassFullName, @@ -401,12 +401,10 @@ private function generateRequestEntity(Generator $generator, ClassNameDetails $r $generator->writeChanges(); - $useAttributesForDoctrineMapping = $this->doctrineHelper->isDoctrineSupportingAttributes() && $this->doctrineHelper->doesClassUsesAttributes($requestClassNameDetails->getFullName()); - $manipulator = new ClassSourceManipulator( sourceCode: $this->fileManager->getFileContents($requestEntityPath), overwrite: false, - useAttributesForDoctrineMapping: $useAttributesForDoctrineMapping + useAttributesForDoctrineMapping: $this->doctrineHelper->doesClassUsesAttributes($requestClassNameDetails->getFullName()), ); $manipulator->addInterface(ResetPasswordRequestInterface::class); diff --git a/src/Maker/MakeSerializerNormalizer.php b/src/Maker/MakeSerializerNormalizer.php index 65b9186ca..129901785 100644 --- a/src/Maker/MakeSerializerNormalizer.php +++ b/src/Maker/MakeSerializerNormalizer.php @@ -52,7 +52,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $normalizerClassNameDetails = $generator->createClassNameDetails( $input->getArgument('name'), 'Serializer\\Normalizer\\', - 'Normalizer' + \Normalizer::class ); $useStatements = new UseStatementGenerator([ diff --git a/src/Maker/MakeStimulusController.php b/src/Maker/MakeStimulusController.php index 2e15d3858..029d6c770 100644 --- a/src/Maker/MakeStimulusController.php +++ b/src/Maker/MakeStimulusController.php @@ -176,9 +176,9 @@ private function askForNextValue(ConsoleStyle $io, array $values, bool $isFirstV if ('_id' === $suffix = substr($snakeCasedField, -3)) { $defaultType = 'Number'; - } elseif (0 === strpos($snakeCasedField, 'is_')) { + } elseif (str_starts_with($snakeCasedField, 'is_')) { $defaultType = 'Boolean'; - } elseif (0 === strpos($snakeCasedField, 'has_')) { + } elseif (str_starts_with($snakeCasedField, 'has_')) { $defaultType = 'Boolean'; } diff --git a/src/Maker/MakeUser.php b/src/Maker/MakeUser.php index 854cf49b1..1bbb5da1f 100644 --- a/src/Maker/MakeUser.php +++ b/src/Maker/MakeUser.php @@ -74,7 +74,6 @@ public function configureCommand(Command $command, InputConfiguration $inputConf ->addOption('is-entity', null, InputOption::VALUE_NONE, 'Do you want to store user data in the database (via Doctrine)?') ->addOption('identity-property-name', null, InputOption::VALUE_REQUIRED, 'Enter a property name that will be the unique "display" name for the user (e.g. email, username, uuid)') ->addOption('with-password', null, InputOption::VALUE_NONE, 'Will this app be responsible for checking the password? Choose No if the password is actually checked by some other system (e.g. a single sign-on server)') - ->addOption('use-argon2', null, InputOption::VALUE_NONE, 'Use the Argon2i password encoder? (deprecated)') ->setHelp(file_get_contents(__DIR__.'/../Resources/help/MakeUser.txt')); $inputConfig->setArgumentAsNonInteractive('name'); @@ -120,10 +119,6 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $input->getOption('identity-property-name'), $input->getOption('with-password') ); - if ($input->getOption('use-argon2')) { - @trigger_error('The "--use-argon2" option is deprecated since MakerBundle 1.12.', \E_USER_DEPRECATED); - $userClassConfiguration->useArgon2(true); - } $userClassNameDetails = $generator->createClassNameDetails( $input->getArgument('name'), @@ -143,14 +138,17 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen // need to write changes early so we can modify the contents below $generator->writeChanges(); - // @legacy @todo - refactor for better naming conventions BEFORE next release. - $useAttributesForDoctrineMapping = $userClassConfiguration->isEntity() && ($this->doctrineHelper->isDoctrineSupportingAttributes()) && $this->doctrineHelper->doesClassUsesAttributes($userClassNameDetails->getFullName()); + $entityUsesAttributes = ($isEntity = $userClassConfiguration->isEntity()) && $this->doctrineHelper->doesClassUsesAttributes($userClassNameDetails->getFullName()); + + if ($isEntity && !$entityUsesAttributes) { + throw new \RuntimeException('MakeUser only supports attribute mapping with doctrine entities.'); + } // B) Implement UserInterface $manipulator = new ClassSourceManipulator( sourceCode: $this->fileManager->getFileContents($classPath), overwrite: true, - useAttributesForDoctrineMapping: $useAttributesForDoctrineMapping + useAttributesForDoctrineMapping: $entityUsesAttributes ); $manipulator->setIo($io); @@ -194,7 +192,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen ); $generator->dumpFile($path, $newYaml); $securityYamlUpdated = true; - } catch (YamlManipulationFailedException $e) { + } catch (YamlManipulationFailedException) { } } @@ -229,9 +227,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $nextSteps[] = 'Create a way to authenticate! See https://symfony.com/doc/current/security.html'; - $nextSteps = array_map(function ($step) { - return sprintf(' - %s', $step); - }, $nextSteps); + $nextSteps = array_map(static fn ($step) => sprintf(' - %s', $step), $nextSteps); $io->text($nextSteps); } diff --git a/src/Renderer/FormTypeRenderer.php b/src/Renderer/FormTypeRenderer.php index 081522d38..e6e8feb8b 100644 --- a/src/Renderer/FormTypeRenderer.php +++ b/src/Renderer/FormTypeRenderer.php @@ -24,11 +24,9 @@ */ final class FormTypeRenderer { - private $generator; - - public function __construct(Generator $generator) - { - $this->generator = $generator; + public function __construct( + private Generator $generator, + ) { } public function render(ClassNameDetails $formClassDetails, array $formFields, ClassNameDetails $boundClassDetails = null, array $constraintClasses = [], array $extraUseClasses = []): void diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index 5728e4aa1..d7370d286 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -49,7 +49,7 @@ - + null @@ -67,7 +67,6 @@ - diff --git a/src/Security/SecurityControllerBuilder.php b/src/Security/SecurityControllerBuilder.php index cadc5993e..d28b79ad0 100644 --- a/src/Security/SecurityControllerBuilder.php +++ b/src/Security/SecurityControllerBuilder.php @@ -12,7 +12,6 @@ namespace Symfony\Bundle\MakerBundle\Security; use Symfony\Bundle\MakerBundle\Util\ClassSourceManipulator; -use Symfony\Bundle\MakerBundle\Util\PhpCompatUtil; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; @@ -22,11 +21,6 @@ */ final class SecurityControllerBuilder { - public function __construct( - private PhpCompatUtil $phpCompatUtil, - ) { - } - public function addLoginMethod(ClassSourceManipulator $manipulator): void { $loginMethodBuilder = $manipulator->createMethodBuilder('login', 'Response', false); diff --git a/src/Security/UserClassBuilder.php b/src/Security/UserClassBuilder.php index 407f90ac5..bcd53b88f 100644 --- a/src/Security/UserClassBuilder.php +++ b/src/Security/UserClassBuilder.php @@ -34,7 +34,7 @@ public function addUserInterfaceImplementation(ClassSourceManipulator $manipulat $this->addPasswordImplementation($manipulator, $userClassConfig); - $this->addEraseCredentials($manipulator, $userClassConfig); + $this->addEraseCredentials($manipulator); } private function addPasswordImplementation(ClassSourceManipulator $manipulator, UserClassConfiguration $userClassConfig): void @@ -299,7 +299,7 @@ private function addGetSalt(ClassSourceManipulator $manipulator, UserClassConfig $manipulator->addMethodBuilder($builder); } - private function addEraseCredentials(ClassSourceManipulator $manipulator, UserClassConfiguration $userClassConfig): void + private function addEraseCredentials(ClassSourceManipulator $manipulator): void { // add eraseCredentials: always empty $builder = $manipulator->createMethodBuilder( diff --git a/src/Security/UserClassConfiguration.php b/src/Security/UserClassConfiguration.php index 9fb547269..fca14961a 100644 --- a/src/Security/UserClassConfiguration.php +++ b/src/Security/UserClassConfiguration.php @@ -18,7 +18,6 @@ */ final class UserClassConfiguration { - private bool $useArgon2 = false; private string $userProviderClass; public function __construct( @@ -43,22 +42,6 @@ public function hasPassword(): bool return $this->hasPassword; } - /** - * @deprecated since MakerBundle 1.12 - */ - public function useArgon2(bool $shouldUse): void - { - $this->useArgon2 = $shouldUse; - } - - /** - * @deprecated since MakerBundle 1.12 - */ - public function shouldUseArgon2(): bool - { - return $this->useArgon2; - } - public function getUserProviderClass(): string { return $this->userProviderClass; diff --git a/src/Str.php b/src/Str.php index b64585403..177919d67 100644 --- a/src/Str.php +++ b/src/Str.php @@ -21,8 +21,7 @@ */ final class Str { - /** @var Inflector|null */ - private static $inflector; + private static ?Inflector $inflector = null; /** * Looks for suffixes in strings in a case-insensitive way. @@ -203,6 +202,9 @@ public static function isValidPhpVariableName($name) return (bool) preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name, $matches); } + /** + * @return bool + */ public static function areClassesAlphabetical(string $class1, string $class2) { $arr1 = [$class1, $class2]; diff --git a/src/Test/MakerTestRunner.php b/src/Test/MakerTestRunner.php index 31c9b4aa9..fb9029d05 100644 --- a/src/Test/MakerTestRunner.php +++ b/src/Test/MakerTestRunner.php @@ -244,7 +244,6 @@ public function manipulateClass(string $filename, \Closure $callback): void $manipulator = new ClassSourceManipulator( sourceCode: $contents, overwrite: true, - useAttributesForDoctrineMapping: true ); $callback($manipulator); diff --git a/src/Util/AutoloaderUtil.php b/src/Util/AutoloaderUtil.php index a81bc7711..626555108 100644 --- a/src/Util/AutoloaderUtil.php +++ b/src/Util/AutoloaderUtil.php @@ -36,13 +36,13 @@ public function getPathForFutureClass(string $className): ?string // lookup is obviously modeled off of Composer's autoload logic foreach ($classLoader->getPrefixesPsr4() as $prefix => $paths) { - if (0 === strpos($className, $prefix)) { + if (str_starts_with($className, $prefix)) { return $paths[0].'/'.str_replace('\\', '/', substr($className, \strlen($prefix))).'.php'; } } foreach ($classLoader->getPrefixes() as $prefix => $paths) { - if (0 === strpos($className, $prefix)) { + if (str_starts_with($className, $prefix)) { return $paths[0].'/'.str_replace('\\', '/', $className).'.php'; } } @@ -61,7 +61,7 @@ public function getPathForFutureClass(string $className): ?string public function getNamespacePrefixForClass(string $className): string { foreach ($this->getClassLoader()->getPrefixesPsr4() as $prefix => $paths) { - if (0 === strpos($className, $prefix)) { + if (str_starts_with($className, $prefix)) { return $prefix; } } @@ -78,13 +78,13 @@ public function isNamespaceConfiguredToAutoload(string $namespace): bool $classLoader = $this->getClassLoader(); foreach ($classLoader->getPrefixesPsr4() as $prefix => $paths) { - if (0 === strpos($namespace, $prefix)) { + if (str_starts_with($namespace, $prefix)) { return true; } } foreach ($classLoader->getPrefixes() as $prefix => $paths) { - if (0 === strpos($namespace, $prefix)) { + if (str_starts_with($namespace, $prefix)) { return true; } } diff --git a/src/Util/ClassDetails.php b/src/Util/ClassDetails.php index 684014a69..337609494 100644 --- a/src/Util/ClassDetails.php +++ b/src/Util/ClassDetails.php @@ -70,6 +70,6 @@ public function doesDocBlockContainAnnotation(string $annotation): bool return false; } - return false !== strpos($docComment, $annotation); + return str_contains($docComment, $annotation); } } diff --git a/src/Util/ClassNameValue.php b/src/Util/ClassNameValue.php index 14d463e17..72d87b92f 100644 --- a/src/Util/ClassNameValue.php +++ b/src/Util/ClassNameValue.php @@ -16,7 +16,7 @@ /** * @internal */ -final class ClassNameValue +final class ClassNameValue implements \Stringable { public function __construct( private string $typeHint, @@ -38,7 +38,7 @@ public function isSelf(): bool return 'self' === $this->typeHint; } - public function __toString() + public function __toString(): string { return $this->getShortName(); } diff --git a/src/Util/ComposerAutoloaderFinder.php b/src/Util/ComposerAutoloaderFinder.php index 0b2a5b60e..ad307df0b 100644 --- a/src/Util/ComposerAutoloaderFinder.php +++ b/src/Util/ComposerAutoloaderFinder.php @@ -20,12 +20,8 @@ */ class ComposerAutoloaderFinder { - private $rootNamespace; - - /** - * @var ClassLoader|null - */ - private $classLoader = null; + private array $rootNamespace; + private ?ClassLoader $classLoader = null; public function __construct(string $rootNamespace) { @@ -96,13 +92,13 @@ private function locateMatchingClassLoader(ClassLoader $classLoader): ?ClassLoad if ('Symfony\\Bundle\\MakerBundle\\' === $prefix) { $makerClassLoader = $classLoader; } - if (0 === strpos($this->rootNamespace['psr4'], $prefix)) { + if (str_starts_with($this->rootNamespace['psr4'], $prefix)) { return $classLoader; } } foreach ($classLoader->getPrefixes() as $prefix => $paths) { - if (0 === strpos($this->rootNamespace['psr0'], $prefix)) { + if (str_starts_with($this->rootNamespace['psr0'], $prefix)) { return $classLoader; } } diff --git a/src/Util/MakerFileLinkFormatter.php b/src/Util/MakerFileLinkFormatter.php index b8721d34a..50f6a2712 100644 --- a/src/Util/MakerFileLinkFormatter.php +++ b/src/Util/MakerFileLinkFormatter.php @@ -19,16 +19,9 @@ */ final class MakerFileLinkFormatter { - private $fileLinkFormatter; - - public function __construct(FileLinkFormatter $fileLinkFormatter = null) - { - // Since nullable types are not available in 7.0; can be removed when php >= 7.1 required - if (0 == \func_num_args()) { - throw new \LogicException('$fileLinkFormatter argument is required'); - } - - $this->fileLinkFormatter = $fileLinkFormatter; + public function __construct( + private ?FileLinkFormatter $fileLinkFormatter = null, + ) { } public function makeLinkedPath(string $absolutePath, string $relativePath): string diff --git a/src/Validator.php b/src/Validator.php index d8cb8dc9d..56eb48a45 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -146,20 +146,17 @@ public static function validateBoolean($value) return $valueAsBool; } - public static function validatePropertyName(string $name) + public static function validatePropertyName(string $name): string { // check for valid PHP variable name - if (null !== $name && !Str::isValidPhpVariableName($name)) { + if (!Str::isValidPhpVariableName($name)) { throw new \InvalidArgumentException(sprintf('"%s" is not a valid PHP property name.', $name)); } return $name; } - /** - * @param ManagerRegistry|LegacyManagerRegistry $registry - */ - public static function validateDoctrineFieldName(string $name, $registry) + public static function validateDoctrineFieldName(string $name, ManagerRegistry|LegacyManagerRegistry $registry): string { if (!$registry instanceof ManagerRegistry && !$registry instanceof LegacyManagerRegistry) { throw new \InvalidArgumentException(sprintf('Argument 2 to %s::validateDoctrineFieldName must be an instance of %s, %s passed.', __CLASS__, ManagerRegistry::class, \is_object($registry) ? \get_class($registry) : \gettype($registry))); @@ -184,12 +181,12 @@ public static function validateEmailAddress(?string $email): string return $email; } - public static function existsOrNull(string $className = null, array $entities = []) + public static function existsOrNull(?string $className = null, array $entities = []): ?string { if (null !== $className) { self::validateClassName($className); - if (0 === strpos($className, '\\')) { + if (str_starts_with($className, '\\')) { self::classExists($className); } else { self::entityExists($className, $entities); @@ -220,7 +217,7 @@ public static function entityExists(string $className = null, array $entities = throw new RuntimeCommandException('There are no registered entities; please create an entity before using this command.'); } - if (0 === strpos($className, '\\')) { + if (str_starts_with($className, '\\')) { self::classExists($className, sprintf('Entity "%s" doesn\'t exist; please enter an existing one or create a new one.', $className)); } diff --git a/tests/Command/MakerCommandTest.php b/tests/Command/MakerCommandTest.php index 14429cb72..2091f7aad 100644 --- a/tests/Command/MakerCommandTest.php +++ b/tests/Command/MakerCommandTest.php @@ -18,7 +18,6 @@ use Symfony\Bundle\MakerBundle\FileManager; use Symfony\Bundle\MakerBundle\Generator; use Symfony\Bundle\MakerBundle\MakerInterface; -use Symfony\Bundle\MakerBundle\Util\PhpCompatUtil; use Symfony\Component\Console\Tester\CommandTester; class MakerCommandTest extends TestCase @@ -40,9 +39,7 @@ public function testExceptionOnMissingDependencies(): void $fileManager = $this->createMock(FileManager::class); - $mockPhpCompatUtil = $this->createMock(PhpCompatUtil::class); - - $command = new MakerCommand($maker, $fileManager, new Generator($fileManager, 'App', $mockPhpCompatUtil)); + $command = new MakerCommand($maker, $fileManager, new Generator($fileManager, 'App')); // needed because it's normally set by the Application $command->setName('make:foo'); $tester = new CommandTester($command); @@ -55,9 +52,7 @@ public function testExceptionOnUnknownRootNamespace(): void $fileManager = $this->createMock(FileManager::class); - $mockPhpCompatUtil = $this->createMock(PhpCompatUtil::class); - - $command = new MakerCommand($maker, $fileManager, new Generator($fileManager, 'Unknown', $mockPhpCompatUtil)); + $command = new MakerCommand($maker, $fileManager, new Generator($fileManager, 'Unknown')); // needed because it's normally set by the Application $command->setName('make:foo'); $tester = new CommandTester($command); diff --git a/tests/Doctrine/EntityRegeneratorTest.php b/tests/Doctrine/EntityRegeneratorTest.php index 55cee6a24..988d22e46 100644 --- a/tests/Doctrine/EntityRegeneratorTest.php +++ b/tests/Doctrine/EntityRegeneratorTest.php @@ -22,7 +22,6 @@ use Symfony\Bundle\MakerBundle\Generator; use Symfony\Bundle\MakerBundle\Util\AutoloaderUtil; use Symfony\Bundle\MakerBundle\Util\MakerFileLinkFormatter; -use Symfony\Bundle\MakerBundle\Util\PhpCompatUtil; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Filesystem\Filesystem; @@ -99,8 +98,7 @@ private function doTestRegeneration(string $sourceDir, Kernel $kernel, string $n $fileManager = new FileManager($fs, $autoloaderUtil, new MakerFileLinkFormatter(null), $tmpDir); $doctrineHelper = new DoctrineHelper('App\\Entity', $container->get('doctrine')); - $phpCompatUtil = new PhpCompatUtil($fileManager); - $generator = new Generator($fileManager, 'App\\', $phpCompatUtil); + $generator = new Generator($fileManager, 'App\\'); $entityClassGenerator = new EntityClassGenerator($generator, $doctrineHelper); $regenerator = new EntityRegenerator( $doctrineHelper, diff --git a/tests/GeneratorTest.php b/tests/GeneratorTest.php index 5993b54fd..51a290a28 100644 --- a/tests/GeneratorTest.php +++ b/tests/GeneratorTest.php @@ -14,7 +14,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\MakerBundle\FileManager; use Symfony\Bundle\MakerBundle\Generator; -use Symfony\Bundle\MakerBundle\Util\PhpCompatUtil; class GeneratorTest extends TestCase { @@ -28,9 +27,7 @@ public function testCreateClassNameDetails(string $name, string $prefix, string ->method('getNamespacePrefixForClass') ->willReturn('Foo'); - $mockPhpCompatUtil = $this->createMock(PhpCompatUtil::class); - - $generator = new Generator($fileManager, 'App\\', $mockPhpCompatUtil); + $generator = new Generator($fileManager, 'App\\'); $classNameDetails = $generator->createClassNameDetails($name, $prefix, $suffix); diff --git a/tests/Maker/MakeAuthenticatorTest.php b/tests/Maker/MakeAuthenticatorTest.php index 6c0a7894e..e94baed3c 100644 --- a/tests/Maker/MakeAuthenticatorTest.php +++ b/tests/Maker/MakeAuthenticatorTest.php @@ -76,7 +76,6 @@ public function getTestDetails(): \Generator 'make-auth/BlankAuthenticator.php', 'src/Security/BlankAuthenticator.php' ); - $runner->adjustAuthenticatorForLegacyPassportInterface('src/Security/BlankAuthenticator.php'); $runner->modifyYamlFile('config/packages/security.yaml', function (array $config) { $config['security']['firewalls']['main']['custom_authenticator'] = 'App\Security\BlankAuthenticator'; @@ -109,7 +108,6 @@ public function getTestDetails(): \Generator 'make-auth/BlankAuthenticator.php', 'src/Security/BlankAuthenticator.php' ); - $runner->adjustAuthenticatorForLegacyPassportInterface('src/Security/BlankAuthenticator.php'); $runner->modifyYamlFile('config/packages/security.yaml', function (array $config) { $config['security']['firewalls']['second'] = ['lazy' => true, 'custom_authenticator' => 'App\Security\BlankAuthenticator']; diff --git a/tests/Maker/MakeRegistrationFormTest.php b/tests/Maker/MakeRegistrationFormTest.php index f74567c82..80ad01e32 100644 --- a/tests/Maker/MakeRegistrationFormTest.php +++ b/tests/Maker/MakeRegistrationFormTest.php @@ -32,7 +32,6 @@ private function createRegistrationFormTest(): MakerTestDetails 'make-registration-form/standard_setup', '' ); - $runner->adjustAuthenticatorForLegacyPassportInterface('src/Security/StubAuthenticator.php'); if (60000 > $runner->getSymfonyVersion()) { /* diff --git a/tests/Maker/MakeUserTest.php b/tests/Maker/MakeUserTest.php index b3a59377e..b767429c4 100644 --- a/tests/Maker/MakeUserTest.php +++ b/tests/Maker/MakeUserTest.php @@ -32,7 +32,6 @@ public function getTestDetails(): \Generator 'make-user/standard_setup', '' ); - $runner->adjustAuthenticatorForLegacyPassportInterface('src/Security/AutomaticAuthenticator.php'); $runner->runMaker([ // user class name @@ -53,7 +52,6 @@ public function getTestDetails(): \Generator 'make-user/standard_setup', '' ); - $runner->adjustAuthenticatorForLegacyPassportInterface('src/Security/AutomaticAuthenticator.php'); $runner->runMaker([ // user class name (with non-traditional name) diff --git a/tests/Security/SecurityControllerBuilderTest.php b/tests/Security/SecurityControllerBuilderTest.php index b6743b254..0b46966ef 100644 --- a/tests/Security/SecurityControllerBuilderTest.php +++ b/tests/Security/SecurityControllerBuilderTest.php @@ -14,7 +14,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\MakerBundle\Security\SecurityControllerBuilder; use Symfony\Bundle\MakerBundle\Util\ClassSourceManipulator; -use Symfony\Bundle\MakerBundle\Util\PhpCompatUtil; class SecurityControllerBuilderTest extends TestCase { @@ -38,7 +37,7 @@ public function testLogoutMethod(): void public function testLoginAndLogoutMethod(): void { - $builder = $this->getSecurityControllerBuilder(); + $builder = new SecurityControllerBuilder(); $csm = $this->getClassSourceManipulator(); $builder->addLoginMethod($csm); @@ -52,7 +51,7 @@ public function testLoginAndLogoutMethod(): void private function runMethodTest(string $builderMethod, string $expectedFilePath): void { - $builder = $this->getSecurityControllerBuilder(); + $builder = new SecurityControllerBuilder(); $csm = $this->getClassSourceManipulator(); $builder->$builderMethod($csm); @@ -63,9 +62,4 @@ private function getClassSourceManipulator(): ClassSourceManipulator { return new ClassSourceManipulator(file_get_contents(__DIR__.'/fixtures/source/SecurityController.php')); } - - private function getSecurityControllerBuilder(): SecurityControllerBuilder - { - return new SecurityControllerBuilder($this->createMock(PhpCompatUtil::class)); - } } diff --git a/tests/Util/ClassSourceManipulatorTest.php b/tests/Util/ClassSourceManipulatorTest.php index 91b48a29e..43b3485f0 100644 --- a/tests/Util/ClassSourceManipulatorTest.php +++ b/tests/Util/ClassSourceManipulatorTest.php @@ -225,7 +225,7 @@ public function testAddEntityField(string $sourceFilename, string $propertyName, private function runAddEntityFieldTests(string $source, string $propertyName, array $fieldOptions, string $expected): void { - $manipulator = new ClassSourceManipulator($source, false, true); + $manipulator = new ClassSourceManipulator($source, false); $manipulator->addEntityField($propertyName, $fieldOptions); $this->assertSame($expected, $manipulator->getSourceCode()); @@ -304,7 +304,7 @@ public function testAddManyToOneRelation(string $sourceFilename, $expectedSource public function runAddManyToOneRelationTests(string $source, string $expected, RelationManyToOne $manyToOne): void { - $manipulator = new ClassSourceManipulator($source, false, true); + $manipulator = new ClassSourceManipulator($source, false); $manipulator->addManyToOneRelation($manyToOne); $this->assertSame($expected, $manipulator->getSourceCode()); @@ -402,7 +402,7 @@ public function testAddOneToManyRelation(string $sourceFilename, string $expecte private function runAddOneToManyRelationTests(string $source, string $expected, RelationOneToMany $oneToMany): void { - $manipulator = new ClassSourceManipulator($source, false, true); + $manipulator = new ClassSourceManipulator($source, false); $manipulator->addOneToManyRelation($oneToMany); $this->assertSame($expected, $manipulator->getSourceCode()); @@ -463,7 +463,7 @@ public function testAddManyToManyRelation(string $sourceFilename, $expectedSourc private function runAddManyToManyRelationTest(string $source, string $expected, RelationManyToMany $manyToMany): void { - $manipulator = new ClassSourceManipulator($source, false, true); + $manipulator = new ClassSourceManipulator($source, false); $manipulator->addManyToManyRelation($manyToMany); $this->assertSame($expected, $manipulator->getSourceCode()); @@ -522,7 +522,7 @@ public function testAddOneToOneRelation(string $sourceFilename, $expectedSourceF private function runAddOneToOneRelation(string $source, string $expected, RelationOneToOne $oneToOne): void { - $manipulator = new ClassSourceManipulator($source, false, true); + $manipulator = new ClassSourceManipulator($source, false); $manipulator->addOneToOneRelation($oneToOne); $this->assertSame($expected, $manipulator->getSourceCode()); diff --git a/tests/Util/PhpVersionTest.php b/tests/Util/PhpCompatUtilTest.php similarity index 59% rename from tests/Util/PhpVersionTest.php rename to tests/Util/PhpCompatUtilTest.php index 1411d1210..592ead565 100644 --- a/tests/Util/PhpVersionTest.php +++ b/tests/Util/PhpCompatUtilTest.php @@ -11,55 +11,16 @@ namespace Symfony\Bundle\MakerBundle\Tests\Util; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Bundle\MakerBundle\FileManager; use Symfony\Bundle\MakerBundle\Util\PhpCompatUtil; -use Symfony\Component\HttpKernel\Kernel; /** * @author Jesse Rushlow */ -class PhpVersionTest extends TestCase +class PhpCompatUtilTest extends TestCase { - /** - * @dataProvider phpVersionDataProvider - */ - public function testUsesPhpPlatformFromComposerJsonFileForCanUseAttributes(string $version, bool $expectedResult): void - { - $this->markTestSkipped('This test needs to be refactored if we keep the util.'); - $mockFileManager = $this->mockFileManager(sprintf('{"platform-overrides": {"php": "%s"}}', $version)); - - $version = new PhpCompatUtil($mockFileManager); - -// $result = $version->canUseAttributes(); - - /* - * Symfony 5.2 is required to compare the result. Otherwise it will always - * return false regardless of the PHP Version. If the test suite is run w/ - * Symfony < 5.2, we assert false here but still rely on the assertions above. - */ - if (Kernel::VERSION_ID < 50200) { - $expectedResult = false; - } - - self::assertSame($expectedResult, $result); - } - - public function phpVersionDataProvider(): \Generator - { - yield ['8', true]; - yield ['8.0', true]; - yield ['8.0.1', true]; - yield ['8RC1', true]; - yield ['8.1alpha1', true]; - yield ['8.0.0beta2', true]; - yield ['8beta', true]; - yield ['7', false]; - yield ['7.0', false]; - yield ['7.1.1', false]; - yield ['7.0.0RC3', false]; - } - public function testFallBackToPhpVersionWithoutLockFile(): void { $mockFileManager = $this->createMock(FileManager::class); @@ -99,10 +60,7 @@ public function testWithoutPlatformVersionSet(): void self::assertSame(\PHP_VERSION, $result); } - /** - * @return \PHPUnit\Framework\MockObject\MockObject|FileManager - */ - private function mockFileManager(string $json) + private function mockFileManager(string $json): MockObject|FileManager { $mockFileManager = $this->createMock(FileManager::class); $mockFileManager