diff --git a/Neos.Flow/Classes/Command/DoctrineCommandController.php b/Neos.Flow/Classes/Command/DoctrineCommandController.php index c7d4f14826..e6b81de9b3 100644 --- a/Neos.Flow/Classes/Command/DoctrineCommandController.php +++ b/Neos.Flow/Classes/Command/DoctrineCommandController.php @@ -14,15 +14,18 @@ use Doctrine\Common\Persistence\Mapping\ClassMetadata; use Doctrine\Common\Util\Debug; use Doctrine\Migrations\Exception\MigrationException; +use Doctrine\ORM\Tools\ToolsException; use Neos\Flow\Annotations as Flow; use Neos\Flow\Cli\CommandController; +use Neos\Flow\Cli\Exception\StopCommandException; use Neos\Flow\Error\Debugger; use Neos\Flow\Log\ThrowableStorageInterface; use Neos\Flow\Log\Utility\LogEnvironment; -use Neos\Flow\Mvc\Exception\StopActionException; use Neos\Flow\Package; use Neos\Flow\Package\PackageManager; use Neos\Flow\Persistence\Doctrine\Service as DoctrineService; +use Neos\Flow\Utility\Exception as UtilityException; +use Neos\Utility\Exception\FilesException; use Neos\Utility\Files; use Psr\Log\LoggerInterface; @@ -67,7 +70,7 @@ class DoctrineCommandController extends CommandController * @param array $settings * @return void */ - public function injectSettings(array $settings) + public function injectSettings(array $settings): void { $this->settings = $settings['persistence']; } @@ -75,7 +78,7 @@ public function injectSettings(array $settings) /** * @param LoggerInterface $logger */ - public function injectLogger(LoggerInterface $logger) + public function injectLogger(LoggerInterface $logger): void { $this->logger = $logger; } @@ -84,9 +87,11 @@ public function injectLogger(LoggerInterface $logger) * Compile the Doctrine proxy classes * * @return void + * @throws UtilityException + * @throws FilesException * @Flow\Internal */ - public function compileProxiesCommand() + public function compileProxiesCommand(): void { $this->doctrineService->compileProxies(); } @@ -102,10 +107,10 @@ public function compileProxiesCommand() * any way. * * @return void + * @throws StopCommandException * @see neos.flow:doctrine:entitystatus - * @throws StopActionException */ - public function validateCommand() + public function validateCommand(): void { $this->outputLine(); $classesAndErrors = $this->doctrineService->validateMapping(); @@ -133,11 +138,12 @@ public function validateCommand() * * @param string $output A file to write SQL to, instead of executing it * @return void + * @throws ToolsException + * @throws StopCommandException * @see neos.flow:doctrine:update * @see neos.flow:doctrine:migrate - * @throws StopActionException */ - public function createCommand(string $output = null) + public function createCommand(string $output = null): void { if (!$this->isDatabaseConfigured()) { $this->outputLine('Database schema creation has been SKIPPED, the driver and host backend options are not set in /Configuration/Settings.yaml.'); @@ -162,11 +168,11 @@ public function createCommand(string $output = null) * @param boolean $unsafeMode If set, foreign keys, sequences and tables can potentially be dropped. * @param string $output A file to write SQL to, instead of executing the update directly * @return void + * @throws StopCommandException * @see neos.flow:doctrine:create * @see neos.flow:doctrine:migrate - * @throws StopActionException */ - public function updateCommand(bool $unsafeMode = false, string $output = null) + public function updateCommand(bool $unsafeMode = false, string $output = null): void { if (!$this->isDatabaseConfigured()) { $this->outputLine('Database schema update has been SKIPPED, the driver and host backend options are not set in /Configuration/Settings.yaml.'); @@ -192,9 +198,10 @@ public function updateCommand(bool $unsafeMode = false, string $output = null) * @param boolean $dumpMappingData If set, the mapping data will be output * @param string $entityClassName If given, the mapping data for just this class will be output * @return void + * @throws \Doctrine\ORM\ORMException * @see neos.flow:doctrine:validate */ - public function entityStatusCommand(bool $dumpMappingData = false, string $entityClassName = null) + public function entityStatusCommand(bool $dumpMappingData = false, string $entityClassName = null): void { $info = $this->doctrineService->getEntityStatus(); @@ -218,19 +225,17 @@ public function entityStatusCommand(bool $dumpMappingData = false, string $entit $this->outputLine(); } } - } else { - if (array_key_exists($entityClassName, $info) && $info[$entityClassName] instanceof ClassMetadata) { - $entityStatus = $info[$entityClassName]; - $this->outputLine('[OK] %s', [$entityClassName]); - if ($dumpMappingData) { - Debugger::clearState(); - $this->outputLine(Debugger::renderDump($entityStatus, 0, true, true)); - } - } else { - $this->outputLine('[FAIL] %s', [$entityClassName]); - $this->outputLine('Class not found.'); - $this->outputLine(); + } elseif (array_key_exists($entityClassName, $info) && $info[$entityClassName] instanceof ClassMetadata) { + $entityStatus = $info[$entityClassName]; + $this->outputLine('[OK] %s', [$entityClassName]); + if ($dumpMappingData) { + Debugger::clearState(); + $this->outputLine(Debugger::renderDump($entityStatus, 0, true, true)); } + } else { + $this->outputLine('[FAIL] %s', [$entityClassName]); + $this->outputLine('Class not found.'); + $this->outputLine(); } } } @@ -247,10 +252,9 @@ public function entityStatusCommand(bool $dumpMappingData = false, string $entit * @param integer $offset Offset the result by this number * @param integer $limit Limit the result to this number * @return void - * @throws \InvalidArgumentException - * @throws StopActionException + * @throws StopCommandException */ - public function dqlCommand(int $depth = 3, string $hydrationMode = 'array', int $offset = null, int $limit = null) + public function dqlCommand(int $depth = 3, string $hydrationMode = 'array', int $offset = null, int $limit = null): void { if (!$this->isDatabaseConfigured()) { $this->outputLine('DQL query is not possible, the driver and host backend options are not set in /Configuration/Settings.yaml.'); @@ -278,13 +282,13 @@ public function dqlCommand(int $depth = 3, string $hydrationMode = 'array', int * @param boolean $showMigrations Output a list of all migrations and their status * @param boolean $showDescriptions Show descriptions for the migrations (enables versions display) * @return void + * @throws StopCommandException * @see neos.flow:doctrine:migrate * @see neos.flow:doctrine:migrationexecute * @see neos.flow:doctrine:migrationgenerate * @see neos.flow:doctrine:migrationversion - * @throws StopActionException */ - public function migrationStatusCommand(bool $showMigrations = false, bool $showDescriptions = false) + public function migrationStatusCommand(bool $showMigrations = false, bool $showDescriptions = false): void { if (!$this->isDatabaseConfigured()) { $this->outputLine('Doctrine migration status not available, the driver and host backend options are not set in /Configuration/Settings.yaml.'); @@ -309,13 +313,14 @@ public function migrationStatusCommand(bool $showMigrations = false, bool $showD * @param boolean $dryRun Whether to do a dry run or not * @param boolean $quiet If set, only the executed migration versions will be output, one per line * @return void + * @throws MigrationException + * @throws StopCommandException * @see neos.flow:doctrine:migrationstatus * @see neos.flow:doctrine:migrationexecute * @see neos.flow:doctrine:migrationgenerate * @see neos.flow:doctrine:migrationversion - * @throws StopActionException */ - public function migrateCommand(string $version = null, string $output = null, bool $dryRun = false, bool $quiet = false) + public function migrateCommand(string $version = null, string $output = null, bool $dryRun = false, bool $quiet = false): void { if (!$this->isDatabaseConfigured()) { $this->outputLine('Doctrine migration not possible, the driver and host backend options are not set in /Configuration/Settings.yaml.'); @@ -346,7 +351,7 @@ public function migrateCommand(string $version = null, string $output = null, bo * @return void * @Flow\Signal */ - protected function emitAfterDatabaseMigration() + protected function emitAfterDatabaseMigration(): void { } @@ -360,13 +365,14 @@ protected function emitAfterDatabaseMigration() * @param string $output A file to write SQL to, instead of executing it * @param boolean $dryRun Whether to do a dry run or not * @return void + * @throws MigrationException + * @throws StopCommandException * @see neos.flow:doctrine:migrate * @see neos.flow:doctrine:migrationstatus * @see neos.flow:doctrine:migrationgenerate * @see neos.flow:doctrine:migrationversion - * @throws StopActionException */ - public function migrationExecuteCommand(string $version, string $direction = 'up', string $output = null, bool $dryRun = false) + public function migrationExecuteCommand(string $version, string $direction = 'up', string $output = null, bool $dryRun = false): void { if (!$this->isDatabaseConfigured()) { $this->outputLine('Doctrine migration not possible, the driver and host backend options are not set in /Configuration/Settings.yaml.'); @@ -390,14 +396,13 @@ public function migrationExecuteCommand(string $version, string $direction = 'up * @param boolean $add The migration to mark as migrated * @param boolean $delete The migration to mark as not migrated * @return void - * @throws \InvalidArgumentException - * @throws StopActionException + * @throws StopCommandException * @see neos.flow:doctrine:migrate * @see neos.flow:doctrine:migrationstatus * @see neos.flow:doctrine:migrationexecute * @see neos.flow:doctrine:migrationgenerate */ - public function migrationVersionCommand(string $version, bool $add = false, bool $delete = false) + public function migrationVersionCommand(string $version, bool $add = false, bool $delete = false): void { if (!$this->isDatabaseConfigured()) { $this->outputLine('Doctrine migration not possible, the driver and host backend options are not set in /Configuration/Settings.yaml.'); @@ -438,14 +443,16 @@ public function migrationVersionCommand(string $version, bool $add = false, bool * @param string $filterExpression Only include tables/sequences matching the filter expression regexp * @param boolean $force Generate migrations even if there are migrations left to execute * @return void - * @throws StopActionException - * @throws \Neos\Utility\Exception\FilesException + * @throws \Doctrine\DBAL\DBALException + * @throws \Doctrine\ORM\ORMException + * @throws StopCommandException + * @throws FilesException * @see neos.flow:doctrine:migrate * @see neos.flow:doctrine:migrationstatus * @see neos.flow:doctrine:migrationexecute * @see neos.flow:doctrine:migrationversion */ - public function migrationGenerateCommand(bool $diffAgainstCurrent = true, string $filterExpression = null, bool $force = false) + public function migrationGenerateCommand(bool $diffAgainstCurrent = true, string $filterExpression = null, bool $force = false): void { // "driver" is used only for Doctrine, thus we (mis-)use it here // additionally, when no host is set, skip this step, assuming no DB is needed @@ -468,7 +475,7 @@ public function migrationGenerateCommand(bool $diffAgainstCurrent = true, string } } - list($status, $migrationClassPathAndFilename) = $this->doctrineService->generateMigration($diffAgainstCurrent, $filterExpression); + [$status, $migrationClassPathAndFilename] = $this->doctrineService->generateMigration($diffAgainstCurrent, $filterExpression); $this->outputLine('%s', [$status]); $this->outputLine(); @@ -512,9 +519,9 @@ public function migrationGenerateCommand(bool $diffAgainstCurrent = true, string * * @param \Exception $exception * @return void - * @throws StopActionException + * @throws StopCommandException */ - protected function handleException(\Exception $exception) + protected function handleException(\Exception $exception): void { $this->outputLine('%s', [$exception->getMessage()]); $this->outputLine(); @@ -525,13 +532,9 @@ protected function handleException(\Exception $exception) $this->quit(1); } - protected function isDatabaseConfigured() + protected function isDatabaseConfigured(): bool { // "driver" is used only for Doctrine, thus we (mis-)use it here - if ($this->settings['backendOptions']['driver'] === null) { - return false; - } - - return true; + return !($this->settings['backendOptions']['driver'] === null); } } diff --git a/Neos.Flow/Classes/Persistence/Doctrine/CountWalker.php b/Neos.Flow/Classes/Persistence/Doctrine/CountWalker.php index f9864cb79c..6d6b4ca6ef 100644 --- a/Neos.Flow/Classes/Persistence/Doctrine/CountWalker.php +++ b/Neos.Flow/Classes/Persistence/Doctrine/CountWalker.php @@ -8,7 +8,11 @@ * with this package in the file License-BSD.txt. * * */ +use Doctrine\ORM\Query\AST\AggregateExpression; use Doctrine\ORM\Query\AST\PathExpression; +use Doctrine\ORM\Query\AST\SelectExpression; +use Doctrine\ORM\Query\AST\SelectStatement; +use Doctrine\ORM\Query\TreeWalkerAdapter; use Neos\Flow\Annotations as Flow; /** @@ -16,20 +20,20 @@ * * @Flow\Proxy(false) */ -class CountWalker extends \Doctrine\ORM\Query\TreeWalkerAdapter +class CountWalker extends TreeWalkerAdapter { /** * Walks down a SelectStatement AST node, modifying it to retrieve a COUNT * - * @param \Doctrine\ORM\Query\AST\SelectStatement $AST + * @param SelectStatement $AST * @return void */ - public function walkSelectStatement(\Doctrine\ORM\Query\AST\SelectStatement $AST) + public function walkSelectStatement(SelectStatement $AST) { $parent = null; $parentName = null; foreach ($this->_getQueryComponents() as $dqlAlias => $qComp) { - if ($qComp['parent'] === null && $qComp['nestingLevel'] == 0) { + if ($qComp['parent'] === null && $qComp['nestingLevel'] === 0) { $parent = $qComp; $parentName = $dqlAlias; break; @@ -43,8 +47,8 @@ public function walkSelectStatement(\Doctrine\ORM\Query\AST\SelectStatement $AST $pathExpression->type = PathExpression::TYPE_STATE_FIELD; $AST->selectClause->selectExpressions = [ - new \Doctrine\ORM\Query\AST\SelectExpression( - new \Doctrine\ORM\Query\AST\AggregateExpression('count', $pathExpression, true), null + new SelectExpression( + new AggregateExpression('count', $pathExpression, true), null ) ]; diff --git a/Neos.Flow/Classes/Persistence/Doctrine/DataTypes/JsonArrayType.php b/Neos.Flow/Classes/Persistence/Doctrine/DataTypes/JsonArrayType.php index 4d2de088f8..f2344dd74e 100755 --- a/Neos.Flow/Classes/Persistence/Doctrine/DataTypes/JsonArrayType.php +++ b/Neos.Flow/Classes/Persistence/Doctrine/DataTypes/JsonArrayType.php @@ -1,8 +1,10 @@ reflectionService->isClassAnnotatedWith($propertyClassName, Flow\Entity::class) || $this->reflectionService->isClassAnnotatedWith($propertyClassName, Flow\ValueObject::class) - || $this->reflectionService->isClassAnnotatedWith($propertyClassName, \Doctrine\ORM\Mapping\Entity::class) + || $this->reflectionService->isClassAnnotatedWith($propertyClassName, ORMEntity::class) ) ) { $value = [ diff --git a/Neos.Flow/Classes/Persistence/Doctrine/DataTypes/ObjectArray.php b/Neos.Flow/Classes/Persistence/Doctrine/DataTypes/ObjectArray.php index 1b3e3df31a..e0d229e65f 100644 --- a/Neos.Flow/Classes/Persistence/Doctrine/DataTypes/ObjectArray.php +++ b/Neos.Flow/Classes/Persistence/Doctrine/DataTypes/ObjectArray.php @@ -1,8 +1,10 @@ persistenceManager->isNewObject($value) === false + } + + if ($this->persistenceManager->isNewObject($value) === false && ( $this->reflectionService->isClassAnnotatedWith($propertyClassName, Flow\Entity::class) || $this->reflectionService->isClassAnnotatedWith($propertyClassName, Flow\ValueObject::class) - || $this->reflectionService->isClassAnnotatedWith($propertyClassName, \Doctrine\ORM\Mapping\Entity::class) - ) - ) { + || $this->reflectionService->isClassAnnotatedWith($propertyClassName, Entity::class) + )) { $value = [ '__flow_object_type' => $propertyClassName, '__identifier' => $this->persistenceManager->getIdentifierByObject($value) diff --git a/Neos.Flow/Classes/Persistence/Doctrine/EntityManagerConfiguration.php b/Neos.Flow/Classes/Persistence/Doctrine/EntityManagerConfiguration.php index 77cbb04542..5a43460a7b 100644 --- a/Neos.Flow/Classes/Persistence/Doctrine/EntityManagerConfiguration.php +++ b/Neos.Flow/Classes/Persistence/Doctrine/EntityManagerConfiguration.php @@ -15,9 +15,12 @@ use Doctrine\Common\EventManager; use Doctrine\Common\EventSubscriber; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\Cache\DefaultCacheFactory; use Doctrine\ORM\Configuration; use Doctrine\ORM\EntityManager; +use Neos\Cache\Exception\NoSuchCacheException; use Neos\Flow\Cache\CacheManager; use Neos\Flow\Configuration\Exception\InvalidConfigurationException; use Neos\Flow\ObjectManagement\ObjectManagerInterface; @@ -51,7 +54,7 @@ class EntityManagerConfiguration * @return void * @throws InvalidConfigurationException */ - public function injectSettings(array $settings) + public function injectSettings(array $settings): void { $this->settings = $settings['persistence']; if (!is_array($this->settings['doctrine'])) { @@ -68,7 +71,7 @@ public function injectSettings(array $settings) * @throws InvalidConfigurationException * @throws IllegalObjectTypeException */ - public function configureEntityManager(Connection $connection, Configuration $config, EventManager $eventManager) + public function configureEntityManager(Connection $connection, Configuration $config, EventManager $eventManager): void { if (isset($this->settings['doctrine']['sqlLogger']) && is_string($this->settings['doctrine']['sqlLogger']) && class_exists($this->settings['doctrine']['sqlLogger'])) { $this->enableSqlLogger($this->settings['doctrine']['sqlLogger'], $config); @@ -98,7 +101,7 @@ public function configureEntityManager(Connection $connection, Configuration $co * @param Configuration $doctrineConfiguration * @throws InvalidConfigurationException */ - protected function enableSqlLogger(string $configuredSqlLogger, Configuration $doctrineConfiguration) + protected function enableSqlLogger(string $configuredSqlLogger, Configuration $doctrineConfiguration): void { $sqlLoggerInstance = new $configuredSqlLogger(); if ($sqlLoggerInstance instanceof SQLLogger) { @@ -113,7 +116,7 @@ protected function enableSqlLogger(string $configuredSqlLogger, Configuration $d * @param EventManager $eventManager * @throws IllegalObjectTypeException */ - protected function registerEventSubscribers(array $configuredSubscribers, EventManager $eventManager) + protected function registerEventSubscribers(array $configuredSubscribers, EventManager $eventManager): void { foreach ($configuredSubscribers as $subscriberClassName) { $subscriber = $this->objectManager->get($subscriberClassName); @@ -128,7 +131,7 @@ protected function registerEventSubscribers(array $configuredSubscribers, EventM * @param array $configuredListeners * @param EventManager $eventManager */ - protected function registerEventListeners(array $configuredListeners, EventManager $eventManager) + protected function registerEventListeners(array $configuredListeners, EventManager $eventManager): void { foreach ($configuredListeners as $listenerOptions) { $listener = $this->objectManager->get($listenerOptions['listener']); @@ -144,7 +147,7 @@ protected function registerEventListeners(array $configuredListeners, EventManag * @param Configuration $doctrineConfiguration * @return void */ - protected function applyDqlSettingsToConfiguration(array $configuredSettings, Configuration $doctrineConfiguration) + protected function applyDqlSettingsToConfiguration(array $configuredSettings, Configuration $doctrineConfiguration): void { if (isset($configuredSettings['customStringFunctions'])) { $doctrineConfiguration->setCustomStringFunctions($configuredSettings['customStringFunctions']); @@ -161,8 +164,9 @@ protected function applyDqlSettingsToConfiguration(array $configuredSettings, Co * Apply basic cache configuration for the metadata, query and result caches. * * @param Configuration $config + * @throws NoSuchCacheException */ - protected function applyCacheConfiguration(Configuration $config) + protected function applyCacheConfiguration(Configuration $config): void { $cache = new CacheAdapter(); // must use ObjectManager in compile phase... @@ -182,8 +186,9 @@ protected function applyCacheConfiguration(Configuration $config) * @param array $configuredSettings * @param Configuration $doctrineConfiguration * @return void + * @throws NoSuchCacheException */ - protected function applySecondLevelCacheSettingsToConfiguration(array $configuredSettings, Configuration $doctrineConfiguration) + protected function applySecondLevelCacheSettingsToConfiguration(array $configuredSettings, Configuration $doctrineConfiguration): void { if (!isset($configuredSettings['enable']) || $configuredSettings['enable'] !== true) { return; @@ -208,7 +213,7 @@ protected function applySecondLevelCacheSettingsToConfiguration(array $configure // must use ObjectManager in compile phase... $cache->setCache($this->objectManager->get(CacheManager::class)->getCache('Flow_Persistence_Doctrine_SecondLevel')); - $factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($regionsConfiguration, $cache); + $factory = new DefaultCacheFactory($regionsConfiguration, $cache); $doctrineConfiguration->getSecondLevelCacheConfiguration()->setCacheFactory($factory); } @@ -217,9 +222,9 @@ protected function applySecondLevelCacheSettingsToConfiguration(array $configure * * @param Configuration $config * @param EntityManager $entityManager - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ - public function enhanceEntityManager(Configuration $config, EntityManager $entityManager) + public function enhanceEntityManager(Configuration $config, EntityManager $entityManager): void { if (isset($this->settings['doctrine']['dbal']['mappingTypes']) && is_array($this->settings['doctrine']['dbal']['mappingTypes'])) { foreach ($this->settings['doctrine']['dbal']['mappingTypes'] as $typeName => $typeConfiguration) { diff --git a/Neos.Flow/Classes/Persistence/Doctrine/Exception/DatabaseException.php b/Neos.Flow/Classes/Persistence/Doctrine/Exception/DatabaseException.php index d59046c372..ee42b5c1a1 100644 --- a/Neos.Flow/Classes/Persistence/Doctrine/Exception/DatabaseException.php +++ b/Neos.Flow/Classes/Persistence/Doctrine/Exception/DatabaseException.php @@ -11,11 +11,13 @@ * source code. */ +use Neos\Flow\Persistence\Exception as PersistenceException; + /** * An generic database exception * * @api */ -class DatabaseException extends \Neos\Flow\Persistence\Exception +class DatabaseException extends PersistenceException { } diff --git a/Neos.Flow/Classes/Persistence/Doctrine/Mapping/Driver/FlowAnnotationDriver.php b/Neos.Flow/Classes/Persistence/Doctrine/Mapping/Driver/FlowAnnotationDriver.php index ede05b57fa..e9a703813f 100644 --- a/Neos.Flow/Classes/Persistence/Doctrine/Mapping/Driver/FlowAnnotationDriver.php +++ b/Neos.Flow/Classes/Persistence/Doctrine/Mapping/Driver/FlowAnnotationDriver.php @@ -16,6 +16,7 @@ use Doctrine\Common\Persistence\Mapping\ClassMetadata; use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver as DoctrineMappingDriverInterface; use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Events; use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder; use Doctrine\ORM\Mapping as ORM; @@ -198,7 +199,7 @@ public function loadMetadataForClass($className, ClassMetadata $metadata) if ($entityAnnotation->repositoryClass !== null) { $metadata->setCustomRepositoryClass($entityAnnotation->repositoryClass); } elseif ($classSchema->getRepositoryClassName() !== null) { - if ($this->reflectionService->isClassImplementationOf($classSchema->getRepositoryClassName(), \Doctrine\ORM\EntityRepository::class)) { + if ($this->reflectionService->isClassImplementationOf($classSchema->getRepositoryClassName(), EntityRepository::class)) { $metadata->setCustomRepositoryClass($classSchema->getRepositoryClassName()); } } @@ -502,9 +503,9 @@ protected function inferJoinTableNameFromClassAndPropertyName($className, $prope // Truncate a second time if the property name was too long as well: if (strlen($prefix . $suffix) > $this->getMaxIdentifierLength()) { return $this->truncateIdentifier($prefix . $suffix, $this->getMaxIdentifierLength()); - } else { - return $prefix . $suffix; } + + return $prefix . $suffix; } /** @@ -582,9 +583,9 @@ protected function evaluatePropertyAnnotations(ORM\ClassMetadataInfo $metadata) $classSchema = $this->getClassSchema($className); foreach ($class->getProperties() as $property) { - if (!$classSchema->hasProperty($property->getName()) + if (($metadata->isMappedSuperclass && !$property->isPrivate()) + || !$classSchema->hasProperty($property->getName()) || $classSchema->isPropertyTransient($property->getName()) - || $metadata->isMappedSuperclass && !$property->isPrivate() || $metadata->isInheritedField($property->getName()) || $metadata->isInheritedAssociation($property->getName()) || $metadata->isInheritedEmbeddedClass($property->getName())) { diff --git a/Neos.Flow/Classes/Persistence/Doctrine/Mapping/Exception/ClassSchemaNotFoundException.php b/Neos.Flow/Classes/Persistence/Doctrine/Mapping/Exception/ClassSchemaNotFoundException.php index 3fe5bb1612..110036416e 100644 --- a/Neos.Flow/Classes/Persistence/Doctrine/Mapping/Exception/ClassSchemaNotFoundException.php +++ b/Neos.Flow/Classes/Persistence/Doctrine/Mapping/Exception/ClassSchemaNotFoundException.php @@ -11,11 +11,13 @@ * source code. */ +use Neos\Flow\Persistence\Exception as PersistenceException; + /** * A Class Schema Not Found Exception * * @api */ -class ClassSchemaNotFoundException extends \Neos\Flow\Persistence\Exception +class ClassSchemaNotFoundException extends PersistenceException { } diff --git a/Neos.Flow/Classes/Persistence/Doctrine/PersistenceManager.php b/Neos.Flow/Classes/Persistence/Doctrine/PersistenceManager.php index 14da0a742c..9bcd57329a 100644 --- a/Neos.Flow/Classes/Persistence/Doctrine/PersistenceManager.php +++ b/Neos.Flow/Classes/Persistence/Doctrine/PersistenceManager.php @@ -14,7 +14,9 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Exception\ConnectionException; use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\ORMException; use Doctrine\ORM\Tools\SchemaTool; +use Doctrine\ORM\UnitOfWork; use Neos\Flow\Annotations as Flow; use Neos\Flow\Log\ThrowableStorageInterface; use Neos\Flow\Log\Utility\LogEnvironment; @@ -88,7 +90,7 @@ public function persistAll($onlyWhitelistedObjects = false) { if ($onlyWhitelistedObjects) { $unitOfWork = $this->entityManager->getUnitOfWork(); - /** @var \Doctrine\ORM\UnitOfWork $unitOfWork */ + /** @var UnitOfWork $unitOfWork */ $unitOfWork->computeChangeSets(); $objectsToBePersisted = $unitOfWork->getScheduledEntityUpdates() + $unitOfWork->getScheduledEntityDeletions() + $unitOfWork->getScheduledEntityInsertions(); foreach ($objectsToBePersisted as $object) { @@ -141,7 +143,7 @@ public function clearState() */ public function isNewObject($object) { - return ($this->entityManager->getUnitOfWork()->getEntityState($object, \Doctrine\ORM\UnitOfWork::STATE_NEW) === \Doctrine\ORM\UnitOfWork::STATE_NEW); + return ($this->entityManager->getUnitOfWork()->getEntityState($object, UnitOfWork::STATE_NEW) === UnitOfWork::STATE_NEW); } /** @@ -168,7 +170,7 @@ public function getIdentifierByObject($object) if ($this->entityManager->contains($object)) { try { return current($this->entityManager->getUnitOfWork()->getEntityIdentifier($object)); - } catch (\Doctrine\ORM\ORMException $exception) { + } catch (ORMException $exception) { } } return null; @@ -195,9 +197,9 @@ public function getObjectByIdentifier($identifier, $objectType = null, $useLazyL } if ($useLazyLoading === true) { return $this->entityManager->getReference($objectType, $identifier); - } else { - return $this->entityManager->find($objectType, $identifier); } + + return $this->entityManager->find($objectType, $identifier); } /** @@ -224,12 +226,12 @@ public function add($object) { if (!$this->isNewObject($object)) { throw new KnownObjectException('The object of type "' . get_class($object) . '" (identifier: "' . $this->getIdentifierByObject($object) . '") which was passed to EntityManager->add() is not a new object. Check the code which adds this entity to the repository and make sure that only objects are added which were not persisted before. Alternatively use update() for updating existing objects."', 1337934295); - } else { - try { - $this->entityManager->persist($object); - } catch (\Exception $exception) { - throw new PersistenceException('Could not add object of type "' . get_class($object) . '"', 1337934455, $exception); - } + } + + try { + $this->entityManager->persist($object); + } catch (\Exception $exception) { + throw new PersistenceException('Could not add object of type "' . get_class($object) . '"', 1337934455, $exception); } } @@ -300,10 +302,10 @@ public function compile() $this->logger->info('Doctrine 2 setup finished', LogEnvironment::fromMethodName(__METHOD__)); return true; - } else { - $this->logger->notice('Doctrine 2 setup skipped, driver and path backend options not set!'); - return false; } + + $this->logger->notice('Doctrine 2 setup skipped, driver and path backend options not set!'); + return false; } /** diff --git a/Neos.Flow/Classes/Persistence/Doctrine/Query.php b/Neos.Flow/Classes/Persistence/Doctrine/Query.php index 377158bd75..110e1c716a 100644 --- a/Neos.Flow/Classes/Persistence/Doctrine/Query.php +++ b/Neos.Flow/Classes/Persistence/Doctrine/Query.php @@ -11,7 +11,13 @@ * source code. */ +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\DBAL\DBALException; +use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\ORMException; +use Doctrine\ORM\Query\Expr\Comparison; +use Doctrine\ORM\QueryBuilder; use Neos\Flow\Annotations as Flow; use Neos\Flow\Log\ThrowableStorageInterface; use Neos\Flow\Log\Utility\LogEnvironment; @@ -46,12 +52,12 @@ class Query implements QueryInterface protected $throwableStorage; /** - * @var \Doctrine\ORM\QueryBuilder + * @var QueryBuilder */ protected $queryBuilder; /** - * @var \Doctrine\ORM\EntityManager + * @var EntityManager */ protected $entityManager; @@ -191,11 +197,11 @@ public function getResult() $query->useResultCache(true); } return $query->getResult(); - } catch (\Doctrine\ORM\ORMException $ormException) { + } catch (ORMException $ormException) { $message = $this->throwableStorage->logThrowable($ormException); $this->logger->error($message, LogEnvironment::fromMethodName(__METHOD__)); return []; - } catch (\Doctrine\DBAL\DBALException $dbalException) { + } catch (DBALException $dbalException) { $message = $this->throwableStorage->logThrowable($dbalException); $this->logger->debug($message); @@ -259,7 +265,7 @@ public function count() $numberOfResults = min($numberOfResults, $limit); } return $numberOfResults; - } catch (\Doctrine\ORM\ORMException $ormException) { + } catch (ORMException $ormException) { $message = $this->throwableStorage->logThrowable($ormException); $this->logger->error($message, LogEnvironment::fromMethodName(__METHOD__)); return 0; @@ -472,7 +478,7 @@ public function logicalNot($constraint) * @param string $propertyName The name of the property to compare against * @param mixed $operand The value to compare with * @param boolean $caseSensitive Whether the equality test should be done case-sensitive for strings - * @return object + * @return Comparison|string * @api */ public function equals($propertyName, $operand, $caseSensitive = true) @@ -519,7 +525,7 @@ public function like($propertyName, $operand, $caseSensitive = true) * * @param string $propertyName The name of the multivalued property to compare against * @param mixed $operand The value to compare with - * @return object + * @return string * @throws InvalidQueryException if used on a single-valued property * @api */ @@ -632,7 +638,7 @@ public function addParameters($parameters) /** * Gets all defined query parameters for the query being constructed. * - * @return array + * @return ArrayCollection */ public function getParameters() { @@ -745,7 +751,7 @@ public function __clone() } /** - * @return \Doctrine\ORM\QueryBuilder + * @return QueryBuilder */ public function getQueryBuilder() { diff --git a/Neos.Flow/Classes/Persistence/Doctrine/Repository.php b/Neos.Flow/Classes/Persistence/Doctrine/Repository.php index 75f108d941..0054937dc2 100644 --- a/Neos.Flow/Classes/Persistence/Doctrine/Repository.php +++ b/Neos.Flow/Classes/Persistence/Doctrine/Repository.php @@ -15,9 +15,11 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Internal\Hydration\IterableResult; +use Doctrine\ORM\QueryBuilder; use Neos\Flow\Annotations as Flow; use Neos\Flow\Persistence\Exception\IllegalObjectTypeException; use Neos\Flow\Persistence\PersistenceManagerInterface; +use Neos\Flow\Persistence\QueryResultInterface; use Neos\Flow\Persistence\RepositoryInterface; /** @@ -119,7 +121,7 @@ public function remove($object) /** * Finds all entities in the repository. * - * @return \Neos\Flow\Persistence\QueryResultInterface The query result + * @return QueryResultInterface The query result * @api */ public function findAll() @@ -134,7 +136,7 @@ public function findAll() */ public function findAllIterator() { - /** @var \Doctrine\ORM\QueryBuilder $queryBuilder */ + /** @var QueryBuilder $queryBuilder */ $queryBuilder = $this->entityManager->createQueryBuilder(); return $queryBuilder ->select('entity') @@ -200,8 +202,7 @@ public function createQuery() */ public function createDqlQuery($dqlString) { - $dqlQuery = $this->entityManager->createQuery($dqlString); - return $dqlQuery; + return $this->entityManager->createQuery($dqlString); } /** @@ -284,10 +285,14 @@ public function __call($method, $arguments) if (isset($method[10]) && strpos($method, 'findOneBy') === 0) { $propertyName = lcfirst(substr($method, 9)); return $query->matching($query->equals($propertyName, $arguments[0], $caseSensitive))->execute($cacheResult)->getFirst(); - } elseif (isset($method[8]) && strpos($method, 'countBy') === 0) { + } + + if (isset($method[8]) && strpos($method, 'countBy') === 0) { $propertyName = lcfirst(substr($method, 7)); return $query->matching($query->equals($propertyName, $arguments[0], $caseSensitive))->count(); - } elseif (isset($method[7]) && strpos($method, 'findBy') === 0) { + } + + if (isset($method[7]) && strpos($method, 'findBy') === 0) { $propertyName = lcfirst(substr($method, 6)); return $query->matching($query->equals($propertyName, $arguments[0], $caseSensitive))->execute($cacheResult); } diff --git a/Neos.Flow/Classes/Persistence/Doctrine/Service.php b/Neos.Flow/Classes/Persistence/Doctrine/Service.php index 32a77cd008..d8e751162e 100644 --- a/Neos.Flow/Classes/Persistence/Doctrine/Service.php +++ b/Neos.Flow/Classes/Persistence/Doctrine/Service.php @@ -11,8 +11,10 @@ * source code. */ +use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Schema\AbstractAsset; use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\Schema; use Doctrine\Migrations\Configuration\Configuration; @@ -24,6 +26,8 @@ use Doctrine\Migrations\Version\Version; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\MappingException; +use Doctrine\ORM\ORMException; +use Doctrine\ORM\Proxy\ProxyFactory; use Doctrine\ORM\Tools\SchemaTool; use Doctrine\ORM\Tools\SchemaValidator; use Doctrine\ORM\Tools\ToolsException; @@ -31,10 +35,11 @@ use Neos\Flow\Package\PackageInterface; use Neos\Flow\Package\PackageManager; use Neos\Flow\Reflection\DocCommentParser; -use Neos\Utility\Exception\FilesException; -use Neos\Utility\ObjectAccess; +use Neos\Flow\Utility\Environment; use Neos\Flow\Utility\Exception; +use Neos\Utility\Exception\FilesException; use Neos\Utility\Files; +use Neos\Utility\ObjectAccess; /** * Service class for tasks related to Doctrine @@ -43,7 +48,7 @@ */ class Service { - const DOCTRINE_MIGRATIONSTABLENAME = 'flow_doctrine_migrationstatus'; + public const DOCTRINE_MIGRATIONSTABLENAME = 'flow_doctrine_migrationstatus'; /** * @var array @@ -64,7 +69,7 @@ class Service /** * @Flow\Inject - * @var \Neos\Flow\Utility\Environment + * @var Environment */ protected $environment; @@ -74,7 +79,7 @@ class Service * * @return array */ - public function validateMapping() + public function validateMapping(): ?array { try { $validator = new SchemaValidator($this->entityManager); @@ -89,10 +94,10 @@ public function validateMapping() * exist, this will throw an exception. * * @param string $outputPathAndFilename A file to write SQL to, instead of executing it - * @return string + * @return void * @throws ToolsException */ - public function createSchema($outputPathAndFilename = null) + public function createSchema($outputPathAndFilename = null): void { $schemaTool = new SchemaTool($this->entityManager); $allMetaData = $this->entityManager->getMetadataFactory()->getAllMetadata(); @@ -110,9 +115,9 @@ public function createSchema($outputPathAndFilename = null) * * @param boolean $safeMode * @param string $outputPathAndFilename A file to write SQL to, instead of executing it - * @return string + * @return void */ - public function updateSchema($safeMode = true, $outputPathAndFilename = null) + public function updateSchema($safeMode = true, $outputPathAndFilename = null): void { $schemaTool = new SchemaTool($this->entityManager); $allMetaData = $this->entityManager->getMetadataFactory()->getAllMetadata(); @@ -129,11 +134,12 @@ public function updateSchema($safeMode = true, $outputPathAndFilename = null) * * @return void * @throws FilesException + * @throws Exception */ - public function compileProxies() + public function compileProxies(): void { Files::emptyDirectoryRecursively(Files::concatenatePaths([$this->environment->getPathToTemporaryDirectory(), 'Doctrine/Proxies'])); - /** @var \Doctrine\ORM\Proxy\ProxyFactory $proxyFactory */ + /** @var ProxyFactory $proxyFactory */ $proxyFactory = $this->entityManager->getProxyFactory(); $proxyFactory->generateProxyClasses($this->entityManager->getMetadataFactory()->getAllMetadata()); } @@ -143,9 +149,9 @@ public function compileProxies() * mapping information contains errors or not. * * @return array - * @throws \Doctrine\ORM\ORMException + * @throws ORMException */ - public function getEntityStatus() + public function getEntityStatus(): array { $info = []; $entityClassNames = $this->entityManager->getConfiguration()->getMetadataDriverImpl()->getAllClassNames(); @@ -187,19 +193,20 @@ public function runDql($dql, $hydrationMode = \Doctrine\ORM\Query::HYDRATE_OBJEC * Return the configuration needed for Migrations. * * @return Configuration - * @throws DBALException + * @throws MigrationException */ - protected function getMigrationConfiguration() + protected function getMigrationConfiguration(): Configuration { $this->output = []; $that = $this; + $outputWriter = new OutputWriter( - function ($message) use ($that) { + static function ($message) use ($that) { $that->output[] = $message; } ); - /** @var \Doctrine\DBAL\Connection $connection */ + /** @var Connection $connection */ $connection = $this->entityManager->getConnection(); $schemaManager = $connection->getSchemaManager(); if ($schemaManager->tablesExist(['flow3_doctrine_migrationstatus']) === true) { @@ -222,9 +229,8 @@ function ($message) use ($that) { * Returns the current migration status as an array. * * @return array - * @throws DBALException */ - public function getMigrationStatus() + public function getMigrationStatus(): array { $configuration = $this->getMigrationConfiguration(); @@ -236,7 +242,7 @@ public function getMigrationStatus() $numNewMigrations = count(array_diff($availableMigrations, $executedMigrations)); return [ - 'Name' => $configuration->getName() ? $configuration->getName() : 'Doctrine Database Migrations', + 'Name' => $configuration->getName() ?: 'Doctrine Database Migrations', 'Database Driver' => $configuration->getConnection()->getDriver()->getName(), 'Database Name' => $configuration->getConnection()->getDatabase(), 'Configuration Source' => 'manually configured', @@ -261,19 +267,17 @@ public function getMigrationStatus() * @param boolean $showMigrations * @param boolean $showDescriptions * @return string - * @throws \ReflectionException - * @throws DBALException */ - public function getFormattedMigrationStatus($showMigrations = false, $showDescriptions = false) + public function getFormattedMigrationStatus($showMigrations = false, $showDescriptions = false): string { $statusInformation = $this->getMigrationStatus(); $output = PHP_EOL . '== Configuration' . PHP_EOL; foreach ($statusInformation as $name => $value) { - if ($name == 'New Migrations') { + if ($name === 'New Migrations') { $value = $value > 0 ? '' . $value . '' : 0; } - if ($name == 'Executed Unavailable Migrations') { + if ($name === 'Executed Unavailable Migrations') { $value = $value > 0 ? '' . $value . '' : 0; } $output .= ' > ' . $name . ': ' . str_repeat(' ', 35 - strlen($name)) . $value . PHP_EOL; @@ -295,7 +299,7 @@ public function getFormattedMigrationStatus($showMigrations = false, $showDescri $packageKey = $this->getPackageKeyFromMigrationVersion($version); $croppedPackageKey = strlen($packageKey) < 30 ? $packageKey : substr($packageKey, 0, 29) . '~'; $packageKeyColumn = ' ' . str_pad($croppedPackageKey, 30, ' '); - $isMigrated = in_array($version->getVersion(), $executedMigrations); + $isMigrated = in_array($version->getVersion(), $executedMigrations, true); $status = $isMigrated ? 'migrated' : 'not migrated'; $migrationDescription = ''; if ($showDescriptions) { @@ -329,10 +333,10 @@ public function getFormattedMigrationStatus($showMigrations = false, $showDescri * @return string * @throws \ReflectionException */ - protected function getPackageKeyFromMigrationVersion(Version $version) + protected function getPackageKeyFromMigrationVersion(Version $version): string { $sortedAvailablePackages = $this->packageManager->getAvailablePackages(); - usort($sortedAvailablePackages, function (PackageInterface $packageOne, PackageInterface $packageTwo) { + usort($sortedAvailablePackages, static function (PackageInterface $packageOne, PackageInterface $packageTwo) { return strlen($packageTwo->getPackagePath()) - strlen($packageOne->getPackagePath()); }); @@ -357,14 +361,16 @@ protected function getPackageKeyFromMigrationVersion(Version $version) * @param Configuration $configuration * @return string */ - protected function getFormattedVersionAlias($alias, Configuration $configuration) + protected function getFormattedVersionAlias($alias, Configuration $configuration): string { $version = $configuration->resolveVersionAlias($alias); if ($version === null) { - if ($alias == 'next') { + if ($alias === 'next') { return 'Already at latest version'; - } elseif ($alias == 'prev') { + } + + if ($alias === 'prev') { return 'Already at first version'; } } @@ -387,15 +393,15 @@ protected function getFormattedVersionAlias($alias, Configuration $configuration * @return string * @throws \ReflectionException */ - protected function getMigrationDescription(Version $version, DocCommentParser $parser) + protected function getMigrationDescription(Version $version, DocCommentParser $parser): ?string { if ($version->getMigration()->getDescription()) { return $version->getMigration()->getDescription(); - } else { - $reflectedClass = new \ReflectionClass($version->getMigration()); - $parser->parseDocComment($reflectedClass->getDocComment()); - return str_replace([chr(10), chr(13)], ' ', $parser->getDescription()); } + + $reflectedClass = new \ReflectionClass($version->getMigration()); + $parser->parseDocComment($reflectedClass->getDocComment()); + return str_replace([chr(10), chr(13)], ' ', $parser->getDescription()); } /** @@ -409,9 +415,8 @@ protected function getMigrationDescription(Version $version, DocCommentParser $p * @param boolean $quiet Whether to do a quiet run or not * @return string * @throws MigrationException - * @throws DBALException */ - public function executeMigrations($version = null, $outputPathAndFilename = null, $dryRun = false, $quiet = false) + public function executeMigrations($version = null, $outputPathAndFilename = null, $dryRun = false, $quiet = false): ?string { $configuration = $this->getMigrationConfiguration(); $configuration->setIsDryRun($dryRun); @@ -433,9 +438,9 @@ public function executeMigrations($version = null, $outputPathAndFilename = null } } return $output; - } else { - return implode(PHP_EOL, $this->output); } + + return implode(PHP_EOL, $this->output); } /** @@ -448,7 +453,6 @@ public function executeMigrations($version = null, $outputPathAndFilename = null * @param boolean $dryRun Whether to do a dry run or not * @return string * @throws MigrationException - * @throws DBALException */ public function executeMigration($version, $direction = 'up', $outputPathAndFilename = null, bool $dryRun = false): string { @@ -524,17 +528,16 @@ public function markAsMigrated($version, $markAsMigrated): void * @param string $filterExpression * @return array Path to the new file * @throws DBALException - * @throws \Doctrine\ORM\ORMException - * @throws FilesException + * @throws ORMException */ - public function generateMigration($diffAgainstCurrent = true, $filterExpression = null) + public function generateMigration($diffAgainstCurrent = true, $filterExpression = null): array { $configuration = $this->getMigrationConfiguration(); $up = null; $down = null; if ($diffAgainstCurrent === true) { - /** @var \Doctrine\DBAL\Connection $connection */ + /** @var Connection $connection */ $connection = $this->entityManager->getConnection(); if ($filterExpression) { @@ -609,7 +612,6 @@ private function resolveTableName(string $name): string * @param string $down * @return string * @throws \RuntimeException - * @throws FilesException */ protected function writeMigrationClassToFile(Configuration $configuration, ?string $up, ?string $down): string { @@ -621,7 +623,7 @@ protected function writeMigrationClassToFile(Configuration $configuration, ?stri $path = Files::concatenatePaths([$configuration->getMigrationsDirectory(), $className . '.php']); try { Files::createDirectoryRecursively(dirname($path)); - } catch (Exception $exception) { + } catch (FilesException $exception) { throw new \RuntimeException(sprintf('Migration target directory "%s" does not exist.', dirname($path)), 1303298536, $exception); } @@ -713,7 +715,7 @@ protected function buildCodeFromSql(Configuration $configuration, array $sql): s * @return string * @throws DBALException */ - public function getDatabasePlatformName() + public function getDatabasePlatformName(): string { return ucfirst($this->entityManager->getConnection()->getDatabasePlatform()->getName()); } @@ -754,34 +756,34 @@ public function getDatabasePlatformName() * @param string $replace * @return array */ - public static function getForeignKeyHandlingSql(Schema $schema, AbstractPlatform $platform, $tableNames, $search, $replace) + public static function getForeignKeyHandlingSql(Schema $schema, AbstractPlatform $platform, $tableNames, $search, $replace): array { $foreignKeyHandlingSql = ['drop' => [], 'add' => []]; $tables = $schema->getTables(); foreach ($tables as $table) { $foreignKeys = $table->getForeignKeys(); foreach ($foreignKeys as $foreignKey) { - if (!in_array($table->getName(), $tableNames) && !in_array($foreignKey->getForeignTableName(), $tableNames)) { + if (!in_array($table->getName(), $tableNames, true) && !in_array($foreignKey->getForeignTableName(), $tableNames, true)) { continue; } $localColumns = $foreignKey->getLocalColumns(); $foreignColumns = $foreignKey->getForeignColumns(); if (in_array($search, $foreignColumns) || in_array($search, $localColumns)) { - if (in_array($foreignKey->getLocalTableName(), $tableNames)) { + if (in_array($foreignKey->getLocalTableName(), $tableNames, true)) { array_walk( $localColumns, - function (&$value) use ($search, $replace) { + static function (&$value) use ($search, $replace) { if ($value === $search) { $value = $replace; } } ); } - if (in_array($foreignKey->getForeignTableName(), $tableNames)) { + if (in_array($foreignKey->getForeignTableName(), $tableNames, true)) { array_walk( $foreignColumns, - function (&$value) use ($search, $replace) { + static function (&$value) use ($search, $replace) { if ($value === $search) { $value = $replace; } @@ -789,7 +791,7 @@ function (&$value) use ($search, $replace) { ); } - $identifierConstructorCallback = function ($columnName) { + $identifierConstructorCallback = static function ($columnName) { return new Identifier($columnName); }; $localColumns = array_map($identifierConstructorCallback, $localColumns);