From 45ce6a41a3b50c41959374eea136803b38dfdfdf Mon Sep 17 00:00:00 2001 From: dantleech Date: Sat, 23 Aug 2014 11:18:36 +0200 Subject: [PATCH 01/26] Expanded scope of orm:info to include metadata information --- .../ORM/Tools/Console/Command/InfoCommand.php | 248 ++++++++++++++++-- 1 file changed, 231 insertions(+), 17 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php index f23fe22c1..9748a1094 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php @@ -23,6 +23,8 @@ use Doctrine\ORM\Mapping\MappingException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Helper\TableHelper; /** * Show information about mapped entities. @@ -33,6 +35,16 @@ use Symfony\Component\Console\Command\Command; */ class InfoCommand extends Command { + /** + * @var OutputInterface + */ + protected $output; + + /** + * @var array + */ + protected $out; + /** * {@inheritdoc} */ @@ -40,11 +52,16 @@ class InfoCommand extends Command { $this ->setName('orm:info') - ->setDescription('Show basic information about all mapped entities') + ->addArgument('entityName', InputArgument::OPTIONAL, 'Show detailed information about the given class') + ->setDescription('Validate and display information about informations') ->setHelp(<<%command.name% shows basic information about which -entities exist and possibly if their mapping information contains errors or -not. +The %command.name% without arguments shows basic information about +which entities exist and possibly if their mapping information contains errors +or not. + +You can display the complete metadata for a given entity by specifying it, e.g. + + %command.full_name% My\Namespace\Entity\MyEntity EOT ); } @@ -54,10 +71,100 @@ EOT */ protected function execute(InputInterface $input, OutputInterface $output) { + $entityName = $input->getArgument('entityName'); + /* @var $entityManager \Doctrine\ORM\EntityManager */ $entityManager = $this->getHelper('em')->getEntityManager(); - $entityClassNames = $entityManager->getConfiguration() + $this->output = $output; + $this->entityManager = $entityManager; + + if (null === $entityName) { + return $this->displayAll($output); + } else { + $this->displayEntity($entityName); + return 0; + } + } + + protected function displayAll() + { + $entityClassNames = $this->getMappedEntities(); + + $this->output->writeln(sprintf("Found %d mapped entities:", count($entityClassNames))); + + $failure = false; + + foreach ($entityClassNames as $entityClassName) { + try { + $meta = $this->entityManager->getClassMetadata($entityClassName); + $this->output->writeln(sprintf("[OK] %s", $entityClassName)); + } catch (MappingException $e) { + $this->output->writeln("[FAIL] ".$entityClassName); + $this->output->writeln(sprintf("%s", $e->getMessage())); + $this->output->writeln(''); + + $failure = true; + } + } + + return $failure ? 1 : 0; + } + + protected function displayEntity($entityName) + { + $meta = $this->getClassMetadata($entityName); + + $this->formatField('Name', $meta->name); + $this->formatField('Root entity name', $meta->rootEntityName); + $this->formatField('Custom generator definition', $meta->customGeneratorDefinition); + $this->formatField('Custom repository class', $meta->customRepositoryClassName); + $this->formatField('Mapped super class?', $meta->isMappedSuperclass); + $this->formatField('Embedded class?', $meta->isEmbeddedClass); + $this->formatListField('Parent classes', $meta->parentClasses); + $this->formatListField('Sub classes', $meta->subClasses); + $this->formatListField('Embedded classes', $meta->subClasses); + $this->formatField('Named queries', $meta->namedQueries); + $this->formatField('Named native queries', $meta->namedNativeQueries); + $this->formatField('SQL result set mappings', $meta->sqlResultSetMappings); + $this->formatField('Identifier', $meta->identifier); + $this->formatField('Inheritance type', $meta->inheritanceType); + $this->formatField('Discriminator column', $meta->discriminatorColumn); + $this->formatField('Discriminator value', $meta->discriminatorValue); + $this->formatField('Discriminator map', $meta->discriminatorMap); + $this->formatField('Generator type', $meta->generatorType); + $this->formatField('Table', $meta->table); + $this->formatField('Composite identifier?', $meta->isIdentifierComposite); + $this->formatField('Foreign identifier?', $meta->containsForeignIdentifier); + $this->formatField('Sequence generator definition', $meta->sequenceGeneratorDefinition); + $this->formatField('Table generator definition', $meta->tableGeneratorDefinition); + $this->formatField('Change tracking policy', $meta->changeTrackingPolicy); + $this->formatField('Versioned?', $meta->isVersioned); + $this->formatField('Version field', $meta->versionField); + $this->formatField('Read only?', $meta->isReadOnly); + + $this->formatEntityListeners($meta->entityListeners); + $this->formatAssociationMappings($meta->associationMappings); + $this->formatFieldMappings($meta->fieldMappings); + + if (class_exists('Symfony\Component\Console\Helper\TableHelper')) { + $table = new TableHelper(); + $table->setHeaders(array('Field', 'Value')); + foreach ($this->out as $tuple) { + $table->addRow($tuple); + } + $table->render($this->output); + } else { + foreach ($this->out as $tuple) { + list($label, $value) = $tuple; + $this->output->writeln(sprintf('%s: %s', $label, $value)); + } + } + } + + protected function getMappedEntities() + { + $entityClassNames = $this->entityManager->getConfiguration() ->getMetadataDriverImpl() ->getAllClassNames(); @@ -68,23 +175,130 @@ EOT ); } - $output->writeln(sprintf("Found %d mapped entities:", count($entityClassNames))); + return $entityClassNames; + } - $failure = false; + protected function getClassMetadata($entityName) + { + try { + $meta = $this->entityManager->getClassMetadata($entityName); + } catch (\Doctrine\Common\Persistence\Mapping\MappingException $e) { + $mappedEntities = $this->getMappedEntities(); + $matches = array_filter($mappedEntities, function ($mappedEntity) use ($entityName) { + if (preg_match('{' . $entityName . '}', $mappedEntity)) { + return true; + } - foreach ($entityClassNames as $entityClassName) { - try { - $entityManager->getClassMetadata($entityClassName); - $output->writeln(sprintf("[OK] %s", $entityClassName)); - } catch (MappingException $e) { - $output->writeln("[FAIL] ".$entityClassName); - $output->writeln(sprintf("%s", $e->getMessage())); - $output->writeln(''); + return false; + }); - $failure = true; + if (0 === count($matches)) { + throw new \InvalidArgumentException(sprintf( + 'Could not find any mapped Entity classes matching "%s"', + $entityName + )); + } + + if (1 === count($matches)) { + $meta = $this->entityManager->getClassMetadata(current($matches)); + } else { + throw new \InvalidArgumentException(sprintf( + 'Entity name "%s" is ambigous, possible matches: "%s"', + $entityName, implode(', ', $matches) + )); } } - return $failure ? 1 : 0; + return $meta; + } + + protected function formatValue($value, $formatBoolean = true) + { + if ('' === $value) { + return ''; + } + + if (null === $value) { + return 'Null'; + } + + if (empty($value)) { + return 'Empty'; + } + + if (is_array($value)) { + return json_encode($value); + } + + if (is_object($value)) { + return sprintf('<%s>', get_class($value)); + } + + if (is_scalar($value)) { + return $value; + } + + throw new \Exception(sprintf('Do not know how to format value "%s"', print_r($value, true))); + } + + protected function formatField($label, $value) + { + if (null === $value) { + $value = 'None'; + } + + $this->out[] = array(sprintf('%s', $label), $this->formatValue($value)); + } + + protected function formatListField($label, $values) + { + if (!$values) { + $out = 'Empty'; + } else { + $this->formatField($label, array_shift($values)); + + foreach ($values as $value) { + $this->formatField($label, $value); + } + } + + $this->formatField($label, $out); + } + + protected function formatAssociationMappings($associationMappings) + { + $this->formatField('Association mappings:', ''); + foreach ($associationMappings as $associationName => $mapping) { + $this->formatField(sprintf(' %s',$associationName), ''); + foreach ($mapping as $field => $value) { + $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); + } + } + } + + protected function formatEntityListeners($entityListeners) + { + $entityListenerNames = array(); + foreach ($entityListeners as $entityListener) { + $entityListenerNames[] = get_class($entityListener); + } + + $this->formatListField('Entity listeners', $entityListenerNames); + } + + protected function formatFieldMappings($fieldMappings) + { + $this->formatField('Field mappings:', ''); + foreach ($fieldMappings as $fieldName => $mapping) { + $this->formatField(sprintf(' %s',$fieldName), ''); + foreach ($mapping as $field => $value) { + $formatBoolean = true; + if (in_array($field, array('id'))) { + $formatBoolean = false; + } + + $this->formatField(sprintf(' %s', $field), $this->formatValue($value, $formatBoolean)); + } + } } } From 51cd8f7ce87c6e25817df58d56f4dc1c8d756d19 Mon Sep 17 00:00:00 2001 From: dantleech Date: Sat, 23 Aug 2014 11:44:54 +0200 Subject: [PATCH 02/26] Added test --- .../ORM/Tools/Console/Command/InfoCommand.php | 9 +- .../Tools/Console/Command/InfoCommandTest.php | 109 ++++++++++++++++++ 2 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php diff --git a/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php index 9748a1094..ea26c50f1 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php @@ -32,6 +32,7 @@ use Symfony\Component\Console\Helper\TableHelper; * @link www.doctrine-project.org * @since 2.1 * @author Benjamin Eberlei + * @author Daniel Leech */ class InfoCommand extends Command { @@ -62,6 +63,10 @@ or not. You can display the complete metadata for a given entity by specifying it, e.g. %command.full_name% My\Namespace\Entity\MyEntity + +You can also specify a partial class name (as a regex): + + %command.full_name% MyEntity EOT ); } @@ -253,7 +258,7 @@ EOT protected function formatListField($label, $values) { if (!$values) { - $out = 'Empty'; + $this->formatField($label, 'Empty'); } else { $this->formatField($label, array_shift($values)); @@ -261,8 +266,6 @@ EOT $this->formatField($label, $value); } } - - $this->formatField($label, $out); } protected function formatAssociationMappings($associationMappings) diff --git a/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php b/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php new file mode 100644 index 000000000..a46157497 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php @@ -0,0 +1,109 @@ +application = new Application(); + $command = new InfoCommand(); + + $this->application->setHelperSet(new HelperSet(array( + 'em' => new EntityManagerHelper($this->_em) + ))); + + $this->application->add($command); + + $this->command = $this->application->find('orm:info'); + $this->tester = new CommandTester($command); + } + + public function testListAllClasses() + { + $this->tester->execute(array( + 'command' => $this->command->getName(), + )); + + $this->assertContains('Doctrine\Tests\Models\Cache\AttractionInfo', $this->tester->getDisplay()); + $this->assertContains('Doctrine\Tests\Models\Cache\City', $this->tester->getDisplay()); + } + + public function testShowSpecificFuzzySingle() + { + $this->tester->execute(array( + 'command' => $this->command->getName(), + 'entityName' => 'AttractionInfo', + )); + + $display = $this->tester->getDisplay(); + $this->assertContains('Doctrine\Tests\Models\Cache\AttractionInfo', $display); + $this->assertContains('Root entity name', $display); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage possible matches: "Doctrine\Tests\Models\Cache\AttractionInfo + */ + public function testShowSpecificFuzzyAmbiguous() + { + $this->tester->execute(array( + 'command' => $this->command->getName(), + 'entityName' => 'Attraction', + )); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Could not find any mapped Entity classes matching "AttractionFooBar" + */ + public function testShowSpecificNotFound() + { + $this->tester->execute(array( + 'command' => $this->command->getName(), + 'entityName' => 'AttractionFooBar' + )); + } + + /** + * This test takes a long time + */ + public function testShowSpecificSmokeTest() + { + $entityClassNames = $this->_em->getConfiguration() + ->getMetadataDriverImpl() + ->getAllClassNames(); + + foreach ($entityClassNames as $entityClassName) { + $this->tester->Execute(array( + 'command' => $this->command->getName(), + 'entityName' => $entityClassName + )); + } + } +} From b5552a82e35cef764d1c97abc600d61d9301875c Mon Sep 17 00:00:00 2001 From: dantleech Date: Sat, 23 Aug 2014 13:33:58 +0200 Subject: [PATCH 03/26] Code review fixes --- .../ORM/Tools/Console/Command/InfoCommand.php | 72 +++++++++---------- .../Tools/Console/Command/InfoCommandTest.php | 21 +----- 2 files changed, 34 insertions(+), 59 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php index ea26c50f1..2bcc8a259 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php @@ -39,12 +39,12 @@ class InfoCommand extends Command /** * @var OutputInterface */ - protected $output; + private $output; /** * @var array */ - protected $out; + private $out; /** * {@inheritdoc} @@ -54,7 +54,7 @@ class InfoCommand extends Command $this ->setName('orm:info') ->addArgument('entityName', InputArgument::OPTIONAL, 'Show detailed information about the given class') - ->setDescription('Validate and display information about informations') + ->setDescription('Display information about mapped objects') ->setHelp(<<%command.name% without arguments shows basic information about which entities exist and possibly if their mapping information contains errors @@ -86,13 +86,14 @@ EOT if (null === $entityName) { return $this->displayAll($output); - } else { - $this->displayEntity($entityName); - return 0; } + + $this->displayEntity($entityName); + + return 0; } - protected function displayAll() + private function displayAll() { $entityClassNames = $this->getMappedEntities(); @@ -116,7 +117,7 @@ EOT return $failure ? 1 : 0; } - protected function displayEntity($entityName) + private function displayEntity($entityName) { $meta = $this->getClassMetadata($entityName); @@ -126,9 +127,9 @@ EOT $this->formatField('Custom repository class', $meta->customRepositoryClassName); $this->formatField('Mapped super class?', $meta->isMappedSuperclass); $this->formatField('Embedded class?', $meta->isEmbeddedClass); - $this->formatListField('Parent classes', $meta->parentClasses); - $this->formatListField('Sub classes', $meta->subClasses); - $this->formatListField('Embedded classes', $meta->subClasses); + $this->formatField('Parent classes', $meta->parentClasses); + $this->formatField('Sub classes', $meta->subClasses); + $this->formatField('Embedded classes', $meta->subClasses); $this->formatField('Named queries', $meta->namedQueries); $this->formatField('Named native queries', $meta->namedNativeQueries); $this->formatField('SQL result set mappings', $meta->sqlResultSetMappings); @@ -147,6 +148,7 @@ EOT $this->formatField('Versioned?', $meta->isVersioned); $this->formatField('Version field', $meta->versionField); $this->formatField('Read only?', $meta->isReadOnly); + $this->formatField('Foo', array('Foo', 'Bar', 'Boo')); $this->formatEntityListeners($meta->entityListeners); $this->formatAssociationMappings($meta->associationMappings); @@ -167,14 +169,14 @@ EOT } } - protected function getMappedEntities() + private function getMappedEntities() { $entityClassNames = $this->entityManager->getConfiguration() ->getMetadataDriverImpl() ->getAllClassNames(); if (!$entityClassNames) { - throw new \Exception( + throw new \InvalidArgumentException( 'You do not have any mapped Doctrine ORM entities according to the current configuration. '. 'If you have entities or mapping files you should check your mapping configuration for errors.' ); @@ -183,7 +185,7 @@ EOT return $entityClassNames; } - protected function getClassMetadata($entityName) + private function getClassMetadata($entityName) { try { $meta = $this->entityManager->getClassMetadata($entityName); @@ -217,7 +219,7 @@ EOT return $meta; } - protected function formatValue($value, $formatBoolean = true) + private function formatValue($value) { if ('' === $value) { return ''; @@ -227,11 +229,19 @@ EOT return 'Null'; } + if (is_bool($value)) { + return '' . ($value ? 'True' : 'False') . ''; + } + if (empty($value)) { return 'Empty'; } if (is_array($value)) { + if (version_compare(phpversion(), '5.4.0', '>=')) { + return json_encode($value, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + } + return json_encode($value); } @@ -243,10 +253,10 @@ EOT return $value; } - throw new \Exception(sprintf('Do not know how to format value "%s"', print_r($value, true))); + throw new \InvalidArgumentException(sprintf('Do not know how to format value "%s"', print_r($value, true))); } - protected function formatField($label, $value) + private function formatField($label, $value) { if (null === $value) { $value = 'None'; @@ -255,20 +265,7 @@ EOT $this->out[] = array(sprintf('%s', $label), $this->formatValue($value)); } - protected function formatListField($label, $values) - { - if (!$values) { - $this->formatField($label, 'Empty'); - } else { - $this->formatField($label, array_shift($values)); - - foreach ($values as $value) { - $this->formatField($label, $value); - } - } - } - - protected function formatAssociationMappings($associationMappings) + private function formatAssociationMappings($associationMappings) { $this->formatField('Association mappings:', ''); foreach ($associationMappings as $associationName => $mapping) { @@ -279,28 +276,23 @@ EOT } } - protected function formatEntityListeners($entityListeners) + private function formatEntityListeners($entityListeners) { $entityListenerNames = array(); foreach ($entityListeners as $entityListener) { $entityListenerNames[] = get_class($entityListener); } - $this->formatListField('Entity listeners', $entityListenerNames); + $this->formatField('Entity listeners', $entityListenerNames); } - protected function formatFieldMappings($fieldMappings) + private function formatFieldMappings($fieldMappings) { $this->formatField('Field mappings:', ''); foreach ($fieldMappings as $fieldName => $mapping) { $this->formatField(sprintf(' %s',$fieldName), ''); foreach ($mapping as $field => $value) { - $formatBoolean = true; - if (in_array($field, array('id'))) { - $formatBoolean = false; - } - - $this->formatField(sprintf(' %s', $field), $this->formatValue($value, $formatBoolean)); + $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); } } } diff --git a/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php b/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php index a46157497..41b4ab833 100644 --- a/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php +++ b/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php @@ -18,7 +18,7 @@ class InfoCommandTest extends OrmFunctionalTestCase private $application; /** - * @var \Doctrine\ORM\Tools\Console\Command\ClearCache\InfoCommand + * @var \Doctrine\ORM\Tools\Console\Command\InfoCommand */ private $command; @@ -68,7 +68,7 @@ class InfoCommandTest extends OrmFunctionalTestCase /** * @expectedException \InvalidArgumentException - * @expectedExceptionMessage possible matches: "Doctrine\Tests\Models\Cache\AttractionInfo + * @expectedExceptionMessage possible matches */ public function testShowSpecificFuzzyAmbiguous() { @@ -89,21 +89,4 @@ class InfoCommandTest extends OrmFunctionalTestCase 'entityName' => 'AttractionFooBar' )); } - - /** - * This test takes a long time - */ - public function testShowSpecificSmokeTest() - { - $entityClassNames = $this->_em->getConfiguration() - ->getMetadataDriverImpl() - ->getAllClassNames(); - - foreach ($entityClassNames as $entityClassName) { - $this->tester->Execute(array( - 'command' => $this->command->getName(), - 'entityName' => $entityClassName - )); - } - } } From c71b489e9efb4bb64590385d348576da1960671b Mon Sep 17 00:00:00 2001 From: dantleech Date: Fri, 29 Aug 2014 21:06:19 +0200 Subject: [PATCH 04/26] Added preg_quote and doc blocks --- .../ORM/Tools/Console/Command/InfoCommand.php | 53 ++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php index 2bcc8a259..054942713 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php @@ -93,6 +93,14 @@ EOT return 0; } + /** + * List all the mapped classes + * + * Returns the exit code, which will be 1 if there are any mapping exceptions + * encountered when listing the mapped classes. + * + * @return integer + */ private function displayAll() { $entityClassNames = $this->getMappedEntities(); @@ -117,6 +125,11 @@ EOT return $failure ? 1 : 0; } + /** + * Display all the mapping information for a single Entity. + * + * @param string $entityName Full or partial entity class name + */ private function displayEntity($entityName) { $meta = $this->getClassMetadata($entityName); @@ -169,6 +182,11 @@ EOT } } + /** + * Return all mapped entity class names + * + * @return array + */ private function getMappedEntities() { $entityClassNames = $this->entityManager->getConfiguration() @@ -185,6 +203,12 @@ EOT return $entityClassNames; } + /** + * Return the class metadata for the given entity + * name + * + * @param string $entityName Full or partial entity name + */ private function getClassMetadata($entityName) { try { @@ -192,7 +216,7 @@ EOT } catch (\Doctrine\Common\Persistence\Mapping\MappingException $e) { $mappedEntities = $this->getMappedEntities(); $matches = array_filter($mappedEntities, function ($mappedEntity) use ($entityName) { - if (preg_match('{' . $entityName . '}', $mappedEntity)) { + if (preg_match('{' . preg_quote($entityName) . '}', $mappedEntity)) { return true; } @@ -219,6 +243,11 @@ EOT return $meta; } + /** + * Format the given value for console output + * + * @param mixed $value + */ private function formatValue($value) { if ('' === $value) { @@ -256,6 +285,13 @@ EOT throw new \InvalidArgumentException(sprintf('Do not know how to format value "%s"', print_r($value, true))); } + /** + * Add the given label and value to the two column table + * output + * + * @param string $label Label for the value + * @param mixed $valueA Value to show + */ private function formatField($label, $value) { if (null === $value) { @@ -265,6 +301,11 @@ EOT $this->out[] = array(sprintf('%s', $label), $this->formatValue($value)); } + /** + * Format the association mappings + * + * @param array + */ private function formatAssociationMappings($associationMappings) { $this->formatField('Association mappings:', ''); @@ -276,6 +317,11 @@ EOT } } + /** + * Format the entity listeners + * + * @param array $entityListeners + */ private function formatEntityListeners($entityListeners) { $entityListenerNames = array(); @@ -286,6 +332,11 @@ EOT $this->formatField('Entity listeners', $entityListenerNames); } + /** + * Form the field mappings + * + * @param array $fieldMappings + */ private function formatFieldMappings($fieldMappings) { $this->formatField('Field mappings:', ''); From 37de75b2ae3c529d6bd3c04dc1a5e582d9f8f269 Mon Sep 17 00:00:00 2001 From: dantleech Date: Sun, 31 Aug 2014 09:27:16 +0200 Subject: [PATCH 05/26] Split new functionality into new command --- .../ORM/Tools/Console/Command/InfoCommand.php | 296 +---------------- .../Command/MappingDescribeCommand.php | 309 ++++++++++++++++++ .../Tools/Console/Command/InfoCommandTest.php | 36 -- .../Command/MappingDescribeCommandTest.php | 83 +++++ 4 files changed, 410 insertions(+), 314 deletions(-) create mode 100644 lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php create mode 100644 tests/Doctrine/Tests/ORM/Tools/Console/Command/MappingDescribeCommandTest.php diff --git a/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php index 054942713..f23fe22c1 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php @@ -23,8 +23,6 @@ use Doctrine\ORM\Mapping\MappingException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Helper\TableHelper; /** * Show information about mapped entities. @@ -32,20 +30,9 @@ use Symfony\Component\Console\Helper\TableHelper; * @link www.doctrine-project.org * @since 2.1 * @author Benjamin Eberlei - * @author Daniel Leech */ class InfoCommand extends Command { - /** - * @var OutputInterface - */ - private $output; - - /** - * @var array - */ - private $out; - /** * {@inheritdoc} */ @@ -53,20 +40,11 @@ class InfoCommand extends Command { $this ->setName('orm:info') - ->addArgument('entityName', InputArgument::OPTIONAL, 'Show detailed information about the given class') - ->setDescription('Display information about mapped objects') + ->setDescription('Show basic information about all mapped entities') ->setHelp(<<%command.name% without arguments shows basic information about -which entities exist and possibly if their mapping information contains errors -or not. - -You can display the complete metadata for a given entity by specifying it, e.g. - - %command.full_name% My\Namespace\Entity\MyEntity - -You can also specify a partial class name (as a regex): - - %command.full_name% MyEntity +The %command.name% shows basic information about which +entities exist and possibly if their mapping information contains errors or +not. EOT ); } @@ -76,47 +54,32 @@ EOT */ protected function execute(InputInterface $input, OutputInterface $output) { - $entityName = $input->getArgument('entityName'); - /* @var $entityManager \Doctrine\ORM\EntityManager */ $entityManager = $this->getHelper('em')->getEntityManager(); - $this->output = $output; - $this->entityManager = $entityManager; + $entityClassNames = $entityManager->getConfiguration() + ->getMetadataDriverImpl() + ->getAllClassNames(); - if (null === $entityName) { - return $this->displayAll($output); + if (!$entityClassNames) { + throw new \Exception( + 'You do not have any mapped Doctrine ORM entities according to the current configuration. '. + 'If you have entities or mapping files you should check your mapping configuration for errors.' + ); } - $this->displayEntity($entityName); - - return 0; - } - - /** - * List all the mapped classes - * - * Returns the exit code, which will be 1 if there are any mapping exceptions - * encountered when listing the mapped classes. - * - * @return integer - */ - private function displayAll() - { - $entityClassNames = $this->getMappedEntities(); - - $this->output->writeln(sprintf("Found %d mapped entities:", count($entityClassNames))); + $output->writeln(sprintf("Found %d mapped entities:", count($entityClassNames))); $failure = false; foreach ($entityClassNames as $entityClassName) { try { - $meta = $this->entityManager->getClassMetadata($entityClassName); - $this->output->writeln(sprintf("[OK] %s", $entityClassName)); + $entityManager->getClassMetadata($entityClassName); + $output->writeln(sprintf("[OK] %s", $entityClassName)); } catch (MappingException $e) { - $this->output->writeln("[FAIL] ".$entityClassName); - $this->output->writeln(sprintf("%s", $e->getMessage())); - $this->output->writeln(''); + $output->writeln("[FAIL] ".$entityClassName); + $output->writeln(sprintf("%s", $e->getMessage())); + $output->writeln(''); $failure = true; } @@ -124,227 +87,4 @@ EOT return $failure ? 1 : 0; } - - /** - * Display all the mapping information for a single Entity. - * - * @param string $entityName Full or partial entity class name - */ - private function displayEntity($entityName) - { - $meta = $this->getClassMetadata($entityName); - - $this->formatField('Name', $meta->name); - $this->formatField('Root entity name', $meta->rootEntityName); - $this->formatField('Custom generator definition', $meta->customGeneratorDefinition); - $this->formatField('Custom repository class', $meta->customRepositoryClassName); - $this->formatField('Mapped super class?', $meta->isMappedSuperclass); - $this->formatField('Embedded class?', $meta->isEmbeddedClass); - $this->formatField('Parent classes', $meta->parentClasses); - $this->formatField('Sub classes', $meta->subClasses); - $this->formatField('Embedded classes', $meta->subClasses); - $this->formatField('Named queries', $meta->namedQueries); - $this->formatField('Named native queries', $meta->namedNativeQueries); - $this->formatField('SQL result set mappings', $meta->sqlResultSetMappings); - $this->formatField('Identifier', $meta->identifier); - $this->formatField('Inheritance type', $meta->inheritanceType); - $this->formatField('Discriminator column', $meta->discriminatorColumn); - $this->formatField('Discriminator value', $meta->discriminatorValue); - $this->formatField('Discriminator map', $meta->discriminatorMap); - $this->formatField('Generator type', $meta->generatorType); - $this->formatField('Table', $meta->table); - $this->formatField('Composite identifier?', $meta->isIdentifierComposite); - $this->formatField('Foreign identifier?', $meta->containsForeignIdentifier); - $this->formatField('Sequence generator definition', $meta->sequenceGeneratorDefinition); - $this->formatField('Table generator definition', $meta->tableGeneratorDefinition); - $this->formatField('Change tracking policy', $meta->changeTrackingPolicy); - $this->formatField('Versioned?', $meta->isVersioned); - $this->formatField('Version field', $meta->versionField); - $this->formatField('Read only?', $meta->isReadOnly); - $this->formatField('Foo', array('Foo', 'Bar', 'Boo')); - - $this->formatEntityListeners($meta->entityListeners); - $this->formatAssociationMappings($meta->associationMappings); - $this->formatFieldMappings($meta->fieldMappings); - - if (class_exists('Symfony\Component\Console\Helper\TableHelper')) { - $table = new TableHelper(); - $table->setHeaders(array('Field', 'Value')); - foreach ($this->out as $tuple) { - $table->addRow($tuple); - } - $table->render($this->output); - } else { - foreach ($this->out as $tuple) { - list($label, $value) = $tuple; - $this->output->writeln(sprintf('%s: %s', $label, $value)); - } - } - } - - /** - * Return all mapped entity class names - * - * @return array - */ - private function getMappedEntities() - { - $entityClassNames = $this->entityManager->getConfiguration() - ->getMetadataDriverImpl() - ->getAllClassNames(); - - if (!$entityClassNames) { - throw new \InvalidArgumentException( - 'You do not have any mapped Doctrine ORM entities according to the current configuration. '. - 'If you have entities or mapping files you should check your mapping configuration for errors.' - ); - } - - return $entityClassNames; - } - - /** - * Return the class metadata for the given entity - * name - * - * @param string $entityName Full or partial entity name - */ - private function getClassMetadata($entityName) - { - try { - $meta = $this->entityManager->getClassMetadata($entityName); - } catch (\Doctrine\Common\Persistence\Mapping\MappingException $e) { - $mappedEntities = $this->getMappedEntities(); - $matches = array_filter($mappedEntities, function ($mappedEntity) use ($entityName) { - if (preg_match('{' . preg_quote($entityName) . '}', $mappedEntity)) { - return true; - } - - return false; - }); - - if (0 === count($matches)) { - throw new \InvalidArgumentException(sprintf( - 'Could not find any mapped Entity classes matching "%s"', - $entityName - )); - } - - if (1 === count($matches)) { - $meta = $this->entityManager->getClassMetadata(current($matches)); - } else { - throw new \InvalidArgumentException(sprintf( - 'Entity name "%s" is ambigous, possible matches: "%s"', - $entityName, implode(', ', $matches) - )); - } - } - - return $meta; - } - - /** - * Format the given value for console output - * - * @param mixed $value - */ - private function formatValue($value) - { - if ('' === $value) { - return ''; - } - - if (null === $value) { - return 'Null'; - } - - if (is_bool($value)) { - return '' . ($value ? 'True' : 'False') . ''; - } - - if (empty($value)) { - return 'Empty'; - } - - if (is_array($value)) { - if (version_compare(phpversion(), '5.4.0', '>=')) { - return json_encode($value, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); - } - - return json_encode($value); - } - - if (is_object($value)) { - return sprintf('<%s>', get_class($value)); - } - - if (is_scalar($value)) { - return $value; - } - - throw new \InvalidArgumentException(sprintf('Do not know how to format value "%s"', print_r($value, true))); - } - - /** - * Add the given label and value to the two column table - * output - * - * @param string $label Label for the value - * @param mixed $valueA Value to show - */ - private function formatField($label, $value) - { - if (null === $value) { - $value = 'None'; - } - - $this->out[] = array(sprintf('%s', $label), $this->formatValue($value)); - } - - /** - * Format the association mappings - * - * @param array - */ - private function formatAssociationMappings($associationMappings) - { - $this->formatField('Association mappings:', ''); - foreach ($associationMappings as $associationName => $mapping) { - $this->formatField(sprintf(' %s',$associationName), ''); - foreach ($mapping as $field => $value) { - $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); - } - } - } - - /** - * Format the entity listeners - * - * @param array $entityListeners - */ - private function formatEntityListeners($entityListeners) - { - $entityListenerNames = array(); - foreach ($entityListeners as $entityListener) { - $entityListenerNames[] = get_class($entityListener); - } - - $this->formatField('Entity listeners', $entityListenerNames); - } - - /** - * Form the field mappings - * - * @param array $fieldMappings - */ - private function formatFieldMappings($fieldMappings) - { - $this->formatField('Field mappings:', ''); - foreach ($fieldMappings as $fieldName => $mapping) { - $this->formatField(sprintf(' %s',$fieldName), ''); - foreach ($mapping as $field => $value) { - $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); - } - } - } } diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php new file mode 100644 index 000000000..2825b143c --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -0,0 +1,309 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Doctrine\ORM\Mapping\MappingException; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Helper\TableHelper; + +/** + * Show information about mapped entities. + * + * @link www.doctrine-project.org + * @since 2.4 + * @author Daniel Leech + */ +class MappingDescribeCommand extends Command +{ + /** + * @var OutputInterface + */ + private $output; + + /** + * @var array + */ + private $out; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('orm:mapping:describe') + ->addArgument('entityName', InputArgument::REQUIRED, 'Full or partial name of entity') + ->setDescription('Display information about mapped objects') + ->setHelp(<<%command.full_name% My\Namespace\Entity\MyEntity + +Or: + + %command.full_name% MyEntity +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $entityName = $input->getArgument('entityName'); + + /* @var $entityManager \Doctrine\ORM\EntityManager */ + $entityManager = $this->getHelper('em')->getEntityManager(); + + $this->output = $output; + $this->entityManager = $entityManager; + + $this->displayEntity($entityName); + + return 0; + } + + /** + * Display all the mapping information for a single Entity. + * + * @param string $entityName Full or partial entity class name + */ + private function displayEntity($entityName) + { + $meta = $this->getClassMetadata($entityName); + + $this->formatField('Name', $meta->name); + $this->formatField('Root entity name', $meta->rootEntityName); + $this->formatField('Custom generator definition', $meta->customGeneratorDefinition); + $this->formatField('Custom repository class', $meta->customRepositoryClassName); + $this->formatField('Mapped super class?', $meta->isMappedSuperclass); + $this->formatField('Embedded class?', $meta->isEmbeddedClass); + $this->formatField('Parent classes', $meta->parentClasses); + $this->formatField('Sub classes', $meta->subClasses); + $this->formatField('Embedded classes', $meta->subClasses); + $this->formatField('Named queries', $meta->namedQueries); + $this->formatField('Named native queries', $meta->namedNativeQueries); + $this->formatField('SQL result set mappings', $meta->sqlResultSetMappings); + $this->formatField('Identifier', $meta->identifier); + $this->formatField('Inheritance type', $meta->inheritanceType); + $this->formatField('Discriminator column', $meta->discriminatorColumn); + $this->formatField('Discriminator value', $meta->discriminatorValue); + $this->formatField('Discriminator map', $meta->discriminatorMap); + $this->formatField('Generator type', $meta->generatorType); + $this->formatField('Table', $meta->table); + $this->formatField('Composite identifier?', $meta->isIdentifierComposite); + $this->formatField('Foreign identifier?', $meta->containsForeignIdentifier); + $this->formatField('Sequence generator definition', $meta->sequenceGeneratorDefinition); + $this->formatField('Table generator definition', $meta->tableGeneratorDefinition); + $this->formatField('Change tracking policy', $meta->changeTrackingPolicy); + $this->formatField('Versioned?', $meta->isVersioned); + $this->formatField('Version field', $meta->versionField); + $this->formatField('Read only?', $meta->isReadOnly); + $this->formatField('Foo', array('Foo', 'Bar', 'Boo')); + + $this->formatEntityListeners($meta->entityListeners); + $this->formatAssociationMappings($meta->associationMappings); + $this->formatFieldMappings($meta->fieldMappings); + + if (class_exists('Symfony\Component\Console\Helper\TableHelper')) { + $table = new TableHelper(); + $table->setHeaders(array('Field', 'Value')); + foreach ($this->out as $tuple) { + $table->addRow($tuple); + } + $table->render($this->output); + } else { + foreach ($this->out as $tuple) { + list($label, $value) = $tuple; + $this->output->writeln(sprintf('%s: %s', $label, $value)); + } + } + } + + /** + * Return all mapped entity class names + * + * @return array + */ + private function getMappedEntities() + { + $entityClassNames = $this->entityManager->getConfiguration() + ->getMetadataDriverImpl() + ->getAllClassNames(); + + if (!$entityClassNames) { + throw new \InvalidArgumentException( + 'You do not have any mapped Doctrine ORM entities according to the current configuration. '. + 'If you have entities or mapping files you should check your mapping configuration for errors.' + ); + } + + return $entityClassNames; + } + + /** + * Return the class metadata for the given entity + * name + * + * @param string $entityName Full or partial entity name + */ + private function getClassMetadata($entityName) + { + try { + $meta = $this->entityManager->getClassMetadata($entityName); + } catch (\Doctrine\Common\Persistence\Mapping\MappingException $e) { + $mappedEntities = $this->getMappedEntities(); + $matches = array_filter($mappedEntities, function ($mappedEntity) use ($entityName) { + if (preg_match('{' . preg_quote($entityName) . '}', $mappedEntity)) { + return true; + } + + return false; + }); + + if (0 === count($matches)) { + throw new \InvalidArgumentException(sprintf( + 'Could not find any mapped Entity classes matching "%s"', + $entityName + )); + } + + if (1 === count($matches)) { + $meta = $this->entityManager->getClassMetadata(current($matches)); + } else { + throw new \InvalidArgumentException(sprintf( + 'Entity name "%s" is ambigous, possible matches: "%s"', + $entityName, implode(', ', $matches) + )); + } + } + + return $meta; + } + + /** + * Format the given value for console output + * + * @param mixed $value + */ + private function formatValue($value) + { + if ('' === $value) { + return ''; + } + + if (null === $value) { + return 'Null'; + } + + if (is_bool($value)) { + return '' . ($value ? 'True' : 'False') . ''; + } + + if (empty($value)) { + return 'Empty'; + } + + if (is_array($value)) { + if (version_compare(phpversion(), '5.4.0', '>=')) { + return json_encode($value, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + } + + return json_encode($value); + } + + if (is_object($value)) { + return sprintf('<%s>', get_class($value)); + } + + if (is_scalar($value)) { + return $value; + } + + throw new \InvalidArgumentException(sprintf('Do not know how to format value "%s"', print_r($value, true))); + } + + /** + * Add the given label and value to the two column table + * output + * + * @param string $label Label for the value + * @param mixed $valueA Value to show + */ + private function formatField($label, $value) + { + if (null === $value) { + $value = 'None'; + } + + $this->out[] = array(sprintf('%s', $label), $this->formatValue($value)); + } + + /** + * Format the association mappings + * + * @param array + */ + private function formatAssociationMappings($associationMappings) + { + $this->formatField('Association mappings:', ''); + foreach ($associationMappings as $associationName => $mapping) { + $this->formatField(sprintf(' %s',$associationName), ''); + foreach ($mapping as $field => $value) { + $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); + } + } + } + + /** + * Format the entity listeners + * + * @param array $entityListeners + */ + private function formatEntityListeners($entityListeners) + { + $entityListenerNames = array(); + foreach ($entityListeners as $entityListener) { + $entityListenerNames[] = get_class($entityListener); + } + + $this->formatField('Entity listeners', $entityListenerNames); + } + + /** + * Form the field mappings + * + * @param array $fieldMappings + */ + private function formatFieldMappings($fieldMappings) + { + $this->formatField('Field mappings:', ''); + foreach ($fieldMappings as $fieldName => $mapping) { + $this->formatField(sprintf(' %s',$fieldName), ''); + foreach ($mapping as $field => $value) { + $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); + } + } + } +} diff --git a/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php b/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php index 41b4ab833..4eafc0f27 100644 --- a/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php +++ b/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php @@ -53,40 +53,4 @@ class InfoCommandTest extends OrmFunctionalTestCase $this->assertContains('Doctrine\Tests\Models\Cache\AttractionInfo', $this->tester->getDisplay()); $this->assertContains('Doctrine\Tests\Models\Cache\City', $this->tester->getDisplay()); } - - public function testShowSpecificFuzzySingle() - { - $this->tester->execute(array( - 'command' => $this->command->getName(), - 'entityName' => 'AttractionInfo', - )); - - $display = $this->tester->getDisplay(); - $this->assertContains('Doctrine\Tests\Models\Cache\AttractionInfo', $display); - $this->assertContains('Root entity name', $display); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage possible matches - */ - public function testShowSpecificFuzzyAmbiguous() - { - $this->tester->execute(array( - 'command' => $this->command->getName(), - 'entityName' => 'Attraction', - )); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Could not find any mapped Entity classes matching "AttractionFooBar" - */ - public function testShowSpecificNotFound() - { - $this->tester->execute(array( - 'command' => $this->command->getName(), - 'entityName' => 'AttractionFooBar' - )); - } } diff --git a/tests/Doctrine/Tests/ORM/Tools/Console/Command/MappingDescribeCommandTest.php b/tests/Doctrine/Tests/ORM/Tools/Console/Command/MappingDescribeCommandTest.php new file mode 100644 index 000000000..92cb41184 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Tools/Console/Command/MappingDescribeCommandTest.php @@ -0,0 +1,83 @@ +application = new Application(); + $command = new MappingDescribeCommand(); + + $this->application->setHelperSet(new HelperSet(array( + 'em' => new EntityManagerHelper($this->_em) + ))); + + $this->application->add($command); + + $this->command = $this->application->find('orm:mapping:describe'); + $this->tester = new CommandTester($command); + } + + public function testShowSpecificFuzzySingle() + { + $this->tester->execute(array( + 'command' => $this->command->getName(), + 'entityName' => 'AttractionInfo', + )); + + $display = $this->tester->getDisplay(); + $this->assertContains('Doctrine\Tests\Models\Cache\AttractionInfo', $display); + $this->assertContains('Root entity name', $display); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage possible matches + */ + public function testShowSpecificFuzzyAmbiguous() + { + $this->tester->execute(array( + 'command' => $this->command->getName(), + 'entityName' => 'Attraction', + )); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Could not find any mapped Entity classes matching "AttractionFooBar" + */ + public function testShowSpecificNotFound() + { + $this->tester->execute(array( + 'command' => $this->command->getName(), + 'entityName' => 'AttractionFooBar' + )); + } +} + From e9d7c23261afe55e43c496ce489d8ff1aeb611a6 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 17:43:32 +0200 Subject: [PATCH 06/26] #1120 - MappingDescribeCommand can be `final` --- .../ORM/Tools/Console/Command/MappingDescribeCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 2825b143c..c9ffe46d8 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -33,7 +33,7 @@ use Symfony\Component\Console\Helper\TableHelper; * @since 2.4 * @author Daniel Leech */ -class MappingDescribeCommand extends Command +final class MappingDescribeCommand extends Command { /** * @var OutputInterface From cf078d8da815595f4299cbb6a6a3bdb242fcbf8d Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 17:49:28 +0200 Subject: [PATCH 07/26] #1120 - avoiding storing the `Doctrine\ORM\EntityManager` in the command itself --- .../Command/MappingDescribeCommand.php | 53 +++++++++++-------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index c9ffe46d8..2614c3cf8 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -19,12 +19,12 @@ namespace Doctrine\ORM\Tools\Console\Command; -use Doctrine\ORM\Mapping\MappingException; +use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\TableHelper; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Helper\TableHelper; /** * Show information about mapped entities. @@ -79,7 +79,7 @@ EOT $this->output = $output; $this->entityManager = $entityManager; - $this->displayEntity($entityName); + $this->displayEntity($entityName, $entityManager); return 0; } @@ -87,11 +87,12 @@ EOT /** * Display all the mapping information for a single Entity. * - * @param string $entityName Full or partial entity class name + * @param string $entityName Full or partial entity class name + * @param EntityManagerInterface $entityManager */ - private function displayEntity($entityName) + private function displayEntity($entityName, EntityManagerInterface $entityManager) { - $meta = $this->getClassMetadata($entityName); + $meta = $this->getClassMetadata($entityName, $entityManager); $this->formatField('Name', $meta->name); $this->formatField('Root entity name', $meta->rootEntityName); @@ -144,15 +145,18 @@ EOT /** * Return all mapped entity class names * - * @return array + * @param EntityManagerInterface $entityManager + * + * @return \Doctrine\ORM\Mapping\ClassMetadata[] */ - private function getMappedEntities() + private function getMappedEntities(EntityManagerInterface $entityManager) { - $entityClassNames = $this->entityManager->getConfiguration() - ->getMetadataDriverImpl() - ->getAllClassNames(); + $entityClassNames = $entityManager + ->getConfiguration() + ->getMetadataDriverImpl() + ->getAllClassNames(); - if (!$entityClassNames) { + if ( ! $entityClassNames) { throw new \InvalidArgumentException( 'You do not have any mapped Doctrine ORM entities according to the current configuration. '. 'If you have entities or mapping files you should check your mapping configuration for errors.' @@ -166,14 +170,17 @@ EOT * Return the class metadata for the given entity * name * - * @param string $entityName Full or partial entity name + * @param string $entityName Full or partial entity name + * @param EntityManagerInterface $entityManager + * + * @return \Doctrine\ORM\Mapping\ClassMetadata */ - private function getClassMetadata($entityName) + private function getClassMetadata($entityName, EntityManagerInterface $entityManager) { try { - $meta = $this->entityManager->getClassMetadata($entityName); + $meta = $entityManager->getClassMetadata($entityName); } catch (\Doctrine\Common\Persistence\Mapping\MappingException $e) { - $mappedEntities = $this->getMappedEntities(); + $mappedEntities = $this->getMappedEntities($entityManager); $matches = array_filter($mappedEntities, function ($mappedEntity) use ($entityName) { if (preg_match('{' . preg_quote($entityName) . '}', $mappedEntity)) { return true; @@ -190,7 +197,7 @@ EOT } if (1 === count($matches)) { - $meta = $this->entityManager->getClassMetadata(current($matches)); + $meta = $entityManager->getClassMetadata(current($matches)); } else { throw new \InvalidArgumentException(sprintf( 'Entity name "%s" is ambigous, possible matches: "%s"', @@ -206,6 +213,8 @@ EOT * Format the given value for console output * * @param mixed $value + * + * @return string */ private function formatValue($value) { @@ -245,11 +254,10 @@ EOT } /** - * Add the given label and value to the two column table - * output + * Add the given label and value to the two column table output * * @param string $label Label for the value - * @param mixed $valueA Value to show + * @param mixed $value A Value to show */ private function formatField($label, $value) { @@ -284,6 +292,7 @@ EOT private function formatEntityListeners($entityListeners) { $entityListenerNames = array(); + foreach ($entityListeners as $entityListener) { $entityListenerNames[] = get_class($entityListener); } From ed79648d7d26e2ac80aa3921bd727cedff03a0a0 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 17:51:17 +0200 Subject: [PATCH 08/26] #1120 - avoiding storing the `Doctrine\ORM\EntityManager` in the command itself --- .../ORM/Tools/Console/Command/MappingDescribeCommand.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 2614c3cf8..1894c5e44 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -77,7 +77,6 @@ EOT $entityManager = $this->getHelper('em')->getEntityManager(); $this->output = $output; - $this->entityManager = $entityManager; $this->displayEntity($entityName, $entityManager); From 7cf427cfbf386d85da947cf0893f255b2e179c04 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 17:53:40 +0200 Subject: [PATCH 09/26] #1120 - avoiding version comparisons when working with version-dependant constants --- .../ORM/Tools/Console/Command/MappingDescribeCommand.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 1894c5e44..1300a088d 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -234,7 +234,7 @@ EOT } if (is_array($value)) { - if (version_compare(phpversion(), '5.4.0', '>=')) { + if (defined('JSON_UNESCAPED_UNICODE') && defined('JSON_UNESCAPED_SLASHES')) { return json_encode($value, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); } @@ -275,8 +275,10 @@ EOT private function formatAssociationMappings($associationMappings) { $this->formatField('Association mappings:', ''); + foreach ($associationMappings as $associationName => $mapping) { - $this->formatField(sprintf(' %s',$associationName), ''); + $this->formatField(sprintf(' %s', $associationName), ''); + foreach ($mapping as $field => $value) { $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); } From a762158e9999a808b58dd73924ea804320be8871 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:11:42 +0200 Subject: [PATCH 10/26] #1120 - since we want to use `Symfony\Component\Console\Helper\Table`, `symfony/console:~2.5` is required --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a216eb192..80dc114f0 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "doctrine/collections": "~1.2", "doctrine/dbal": ">=2.5-dev,<2.6-dev", "doctrine/instantiator": "~1.0.1", - "symfony/console": "2.*" + "symfony/console": "~2.5" }, "require-dev": { "symfony/yaml": "~2.1", From dcdffbffc797752965bd473762167bc2abbc91ef Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:13:01 +0200 Subject: [PATCH 11/26] #1120 - assuming existence of `Symfony\Component\Console\Helper\Table` --- .../Command/MappingDescribeCommand.php | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 1300a088d..84b688d98 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -21,7 +21,7 @@ namespace Doctrine\ORM\Tools\Console\Command; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\TableHelper; +use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -43,7 +43,7 @@ final class MappingDescribeCommand extends Command /** * @var array */ - private $out; + private $out = array(); /** * {@inheritdoc} @@ -78,7 +78,7 @@ EOT $this->output = $output; - $this->displayEntity($entityName, $entityManager); + $this->displayEntity($entityName, $entityManager, $output); return 0; } @@ -89,7 +89,7 @@ EOT * @param string $entityName Full or partial entity class name * @param EntityManagerInterface $entityManager */ - private function displayEntity($entityName, EntityManagerInterface $entityManager) + private function displayEntity($entityName, EntityManagerInterface $entityManager, OutputInterface $output) { $meta = $this->getClassMetadata($entityName, $entityManager); @@ -126,19 +126,15 @@ EOT $this->formatAssociationMappings($meta->associationMappings); $this->formatFieldMappings($meta->fieldMappings); - if (class_exists('Symfony\Component\Console\Helper\TableHelper')) { - $table = new TableHelper(); - $table->setHeaders(array('Field', 'Value')); - foreach ($this->out as $tuple) { - $table->addRow($tuple); - } - $table->render($this->output); - } else { - foreach ($this->out as $tuple) { - list($label, $value) = $tuple; - $this->output->writeln(sprintf('%s: %s', $label, $value)); - } + $table = new Table($output); + + $table->setHeaders(array('Field', 'Value')); + + foreach ($this->out as $tuple) { + $table->addRow($tuple); } + + $table->render(); } /** From 100766e360166543120574d86676df302e7a8ea2 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:13:46 +0200 Subject: [PATCH 12/26] #1120 - Removing example `array('Foo', 'Bar', 'Boo')` dumped data --- .../ORM/Tools/Console/Command/MappingDescribeCommand.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 84b688d98..543dc6514 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -120,7 +120,6 @@ EOT $this->formatField('Versioned?', $meta->isVersioned); $this->formatField('Version field', $meta->versionField); $this->formatField('Read only?', $meta->isReadOnly); - $this->formatField('Foo', array('Foo', 'Bar', 'Boo')); $this->formatEntityListeners($meta->entityListeners); $this->formatAssociationMappings($meta->associationMappings); From 97fdd0adb71cbb129e416ea370db5f846eaef8f9 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:14:33 +0200 Subject: [PATCH 13/26] #1120 - cleaning up try-catch code when fetching metadata --- .../ORM/Tools/Console/Command/MappingDescribeCommand.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 543dc6514..1718df3cd 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -19,6 +19,7 @@ namespace Doctrine\ORM\Tools\Console\Command; +use Doctrine\Common\Persistence\Mapping\MappingException; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\Table; @@ -172,8 +173,8 @@ EOT private function getClassMetadata($entityName, EntityManagerInterface $entityManager) { try { - $meta = $entityManager->getClassMetadata($entityName); - } catch (\Doctrine\Common\Persistence\Mapping\MappingException $e) { + return $entityManager->getClassMetadata($entityName); + } catch (MappingException $e) { $mappedEntities = $this->getMappedEntities($entityManager); $matches = array_filter($mappedEntities, function ($mappedEntity) use ($entityName) { if (preg_match('{' . preg_quote($entityName) . '}', $mappedEntity)) { @@ -198,9 +199,9 @@ EOT $entityName, implode(', ', $matches) )); } - } - return $meta; + return $meta; + } } /** From 0f289a12701fad64655f34ce195219a0529cddce Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:21:45 +0200 Subject: [PATCH 14/26] #1120 - cs cleanups - moving success cases at the end of methods --- .../Command/MappingDescribeCommand.php | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 1718df3cd..65dac497c 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -142,7 +142,7 @@ EOT * * @param EntityManagerInterface $entityManager * - * @return \Doctrine\ORM\Mapping\ClassMetadata[] + * @return string[] */ private function getMappedEntities(EntityManagerInterface $entityManager) { @@ -175,33 +175,34 @@ EOT try { return $entityManager->getClassMetadata($entityName); } catch (MappingException $e) { - $mappedEntities = $this->getMappedEntities($entityManager); - $matches = array_filter($mappedEntities, function ($mappedEntity) use ($entityName) { + } + + $matches = array_filter( + $this->getMappedEntities($entityManager), + function ($mappedEntity) use ($entityName) { if (preg_match('{' . preg_quote($entityName) . '}', $mappedEntity)) { return true; } return false; - }); - - if (0 === count($matches)) { - throw new \InvalidArgumentException(sprintf( - 'Could not find any mapped Entity classes matching "%s"', - $entityName - )); } + ); - if (1 === count($matches)) { - $meta = $entityManager->getClassMetadata(current($matches)); - } else { - throw new \InvalidArgumentException(sprintf( - 'Entity name "%s" is ambigous, possible matches: "%s"', - $entityName, implode(', ', $matches) - )); - } - - return $meta; + if (! $matches) { + throw new \InvalidArgumentException(sprintf( + 'Could not find any mapped Entity classes matching "%s"', + $entityName + )); } + + if (count($matches) > 1) { + throw new \InvalidArgumentException(sprintf( + 'Entity name "%s" is ambigous, possible matches: "%s"', + $entityName, implode(', ', $matches) + )); + } + + return $entityManager->getClassMetadata(current($matches)); } /** @@ -231,7 +232,7 @@ EOT if (is_array($value)) { if (defined('JSON_UNESCAPED_UNICODE') && defined('JSON_UNESCAPED_SLASHES')) { - return json_encode($value, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + return json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); } return json_encode($value); @@ -305,8 +306,10 @@ EOT private function formatFieldMappings($fieldMappings) { $this->formatField('Field mappings:', ''); + foreach ($fieldMappings as $fieldName => $mapping) { $this->formatField(sprintf(' %s',$fieldName), ''); + foreach ($mapping as $field => $value) { $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); } From db74efbe34cf3e5694f53605fe95ce143a6bc82d Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:22:28 +0200 Subject: [PATCH 15/26] #1120 - test coverage annotations --- .../Command/MappingDescribeCommandTest.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/Doctrine/Tests/ORM/Tools/Console/Command/MappingDescribeCommandTest.php b/tests/Doctrine/Tests/ORM/Tools/Console/Command/MappingDescribeCommandTest.php index 92cb41184..017e94aee 100644 --- a/tests/Doctrine/Tests/ORM/Tools/Console/Command/MappingDescribeCommandTest.php +++ b/tests/Doctrine/Tests/ORM/Tools/Console/Command/MappingDescribeCommandTest.php @@ -2,14 +2,18 @@ namespace Doctrine\Tests\ORM\Tools\Console\Command; -use Doctrine\ORM\Tools\Console\Command\ClearCache\CollectionRegionCommand; -use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper; -use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Application; -use Doctrine\Tests\OrmFunctionalTestCase; use Doctrine\ORM\Tools\Console\Command\MappingDescribeCommand; +use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper; +use Doctrine\Tests\OrmFunctionalTestCase; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Tester\CommandTester; +/** + * Tests for {@see \Doctrine\ORM\Tools\Console\Command\MappingDescribeCommand} + * + * @covers \Doctrine\ORM\Tools\Console\Command\MappingDescribeCommand + */ class MappingDescribeCommandTest extends OrmFunctionalTestCase { /** From 250b38710cf76fcb9f09964e5e65cb1f4a04050f Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:23:50 +0200 Subject: [PATCH 16/26] #1120 - missing docblock parameter --- .../ORM/Tools/Console/Command/MappingDescribeCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 65dac497c..803b61fb8 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -89,6 +89,7 @@ EOT * * @param string $entityName Full or partial entity class name * @param EntityManagerInterface $entityManager + * @param OutputInterface $output */ private function displayEntity($entityName, EntityManagerInterface $entityManager, OutputInterface $output) { From 254a46e79c74b5e12c81c0423ef5e219354ff0fa Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:32:12 +0200 Subject: [PATCH 17/26] #1120 - avoiding mutable state for rows/output --- .../Command/MappingDescribeCommand.php | 102 ++++++++++-------- 1 file changed, 60 insertions(+), 42 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 803b61fb8..7a5872264 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -93,47 +93,51 @@ EOT */ private function displayEntity($entityName, EntityManagerInterface $entityManager, OutputInterface $output) { - $meta = $this->getClassMetadata($entityName, $entityManager); + $metadata = $this->getClassMetadata($entityName, $entityManager); - $this->formatField('Name', $meta->name); - $this->formatField('Root entity name', $meta->rootEntityName); - $this->formatField('Custom generator definition', $meta->customGeneratorDefinition); - $this->formatField('Custom repository class', $meta->customRepositoryClassName); - $this->formatField('Mapped super class?', $meta->isMappedSuperclass); - $this->formatField('Embedded class?', $meta->isEmbeddedClass); - $this->formatField('Parent classes', $meta->parentClasses); - $this->formatField('Sub classes', $meta->subClasses); - $this->formatField('Embedded classes', $meta->subClasses); - $this->formatField('Named queries', $meta->namedQueries); - $this->formatField('Named native queries', $meta->namedNativeQueries); - $this->formatField('SQL result set mappings', $meta->sqlResultSetMappings); - $this->formatField('Identifier', $meta->identifier); - $this->formatField('Inheritance type', $meta->inheritanceType); - $this->formatField('Discriminator column', $meta->discriminatorColumn); - $this->formatField('Discriminator value', $meta->discriminatorValue); - $this->formatField('Discriminator map', $meta->discriminatorMap); - $this->formatField('Generator type', $meta->generatorType); - $this->formatField('Table', $meta->table); - $this->formatField('Composite identifier?', $meta->isIdentifierComposite); - $this->formatField('Foreign identifier?', $meta->containsForeignIdentifier); - $this->formatField('Sequence generator definition', $meta->sequenceGeneratorDefinition); - $this->formatField('Table generator definition', $meta->tableGeneratorDefinition); - $this->formatField('Change tracking policy', $meta->changeTrackingPolicy); - $this->formatField('Versioned?', $meta->isVersioned); - $this->formatField('Version field', $meta->versionField); - $this->formatField('Read only?', $meta->isReadOnly); + $rows = array( + $this->formatField('Name', $metadata->name), + $this->formatField('Root entity name', $metadata->rootEntityName), + $this->formatField('Custom generator definition', $metadata->customGeneratorDefinition), + $this->formatField('Custom repository class', $metadata->customRepositoryClassName), + $this->formatField('Mapped super class?', $metadata->isMappedSuperclass), + $this->formatField('Embedded class?', $metadata->isEmbeddedClass), + $this->formatField('Parent classes', $metadata->parentClasses), + $this->formatField('Sub classes', $metadata->subClasses), + $this->formatField('Embedded classes', $metadata->subClasses), + $this->formatField('Named queries', $metadata->namedQueries), + $this->formatField('Named native queries', $metadata->namedNativeQueries), + $this->formatField('SQL result set mappings', $metadata->sqlResultSetMappings), + $this->formatField('Identifier', $metadata->identifier), + $this->formatField('Inheritance type', $metadata->inheritanceType), + $this->formatField('Discriminator column', $metadata->discriminatorColumn), + $this->formatField('Discriminator value', $metadata->discriminatorValue), + $this->formatField('Discriminator map', $metadata->discriminatorMap), + $this->formatField('Generator type', $metadata->generatorType), + $this->formatField('Table', $metadata->table), + $this->formatField('Composite identifier?', $metadata->isIdentifierComposite), + $this->formatField('Foreign identifier?', $metadata->containsForeignIdentifier), + $this->formatField('Sequence generator definition', $metadata->sequenceGeneratorDefinition), + $this->formatField('Table generator definition', $metadata->tableGeneratorDefinition), + $this->formatField('Change tracking policy', $metadata->changeTrackingPolicy), + $this->formatField('Versioned?', $metadata->isVersioned), + $this->formatField('Version field', $metadata->versionField), + $this->formatField('Read only?', $metadata->isReadOnly), - $this->formatEntityListeners($meta->entityListeners); - $this->formatAssociationMappings($meta->associationMappings); - $this->formatFieldMappings($meta->fieldMappings); + $this->formatEntityListeners($metadata->entityListeners), + ); + + $rows = array_merge( + $rows, + $this->formatAssociationMappings($metadata->associationMappings), + $this->formatFieldMappings($metadata->fieldMappings) + ); $table = new Table($output); $table->setHeaders(array('Field', 'Value')); - foreach ($this->out as $tuple) { - $table->addRow($tuple); - } + array_map(array($table, 'addRow'), $rows); $table->render(); } @@ -255,6 +259,8 @@ EOT * * @param string $label Label for the value * @param mixed $value A Value to show + * + * @return array */ private function formatField($label, $value) { @@ -262,31 +268,38 @@ EOT $value = 'None'; } - $this->out[] = array(sprintf('%s', $label), $this->formatValue($value)); + return array(sprintf('%s', $label), $this->formatValue($value)); } /** * Format the association mappings * * @param array + * + * @return array */ private function formatAssociationMappings($associationMappings) { - $this->formatField('Association mappings:', ''); + $output = array(); + $output[] = $this->formatField('Association mappings:', ''); foreach ($associationMappings as $associationName => $mapping) { - $this->formatField(sprintf(' %s', $associationName), ''); + $output[] = $this->formatField(sprintf(' %s', $associationName), ''); foreach ($mapping as $field => $value) { - $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); + $output[] = $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); } } + + return $output; } /** * Format the entity listeners * * @param array $entityListeners + * + * @return array */ private function formatEntityListeners($entityListeners) { @@ -296,24 +309,29 @@ EOT $entityListenerNames[] = get_class($entityListener); } - $this->formatField('Entity listeners', $entityListenerNames); + return $this->formatField('Entity listeners', $entityListenerNames); } /** * Form the field mappings * * @param array $fieldMappings + * + * @return array */ private function formatFieldMappings($fieldMappings) { - $this->formatField('Field mappings:', ''); + $output = array(); + $output[] = $this->formatField('Field mappings:', ''); foreach ($fieldMappings as $fieldName => $mapping) { - $this->formatField(sprintf(' %s',$fieldName), ''); + $output[] = $this->formatField(sprintf(' %s',$fieldName), ''); foreach ($mapping as $field => $value) { - $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); + $output[] = $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); } } + + return $output; } } From 574f3ea909e9c3556bac582e5fbd822b57179a15 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:34:06 +0200 Subject: [PATCH 18/26] #1120 - map functions over array iteration/mutation --- .../Console/Command/MappingDescribeCommand.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 7a5872264..f68825da0 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -301,15 +301,17 @@ EOT * * @return array */ - private function formatEntityListeners($entityListeners) + private function formatEntityListeners(array $entityListeners) { - $entityListenerNames = array(); - - foreach ($entityListeners as $entityListener) { - $entityListenerNames[] = get_class($entityListener); - } - - return $this->formatField('Entity listeners', $entityListenerNames); + return $this->formatField( + 'Entity listeners', + array_map( + function ($entityListener) { + return get_class($entityListener); + }, + $entityListeners + ) + ); } /** From 39a8a31de9c537fe223f511160942edda36ee04a Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:34:42 +0200 Subject: [PATCH 19/26] #1120 - removing unused private properties --- .../Console/Command/MappingDescribeCommand.php | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index f68825da0..896d29054 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -36,16 +36,6 @@ use Symfony\Component\Console\Output\OutputInterface; */ final class MappingDescribeCommand extends Command { - /** - * @var OutputInterface - */ - private $output; - - /** - * @var array - */ - private $out = array(); - /** * {@inheritdoc} */ @@ -74,11 +64,9 @@ EOT { $entityName = $input->getArgument('entityName'); - /* @var $entityManager \Doctrine\ORM\EntityManager */ + /* @var $entityManager \Doctrine\ORM\EntityManagerInterface */ $entityManager = $this->getHelper('em')->getEntityManager(); - $this->output = $output; - $this->displayEntity($entityName, $entityManager, $output); return 0; From 806068b0dfde0128832aeefe290cd56c3b331d9a Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:36:08 +0200 Subject: [PATCH 20/26] #1120 - removing useless variables, refactoring --- .../Command/MappingDescribeCommand.php | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 896d29054..8217fa370 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -81,51 +81,51 @@ EOT */ private function displayEntity($entityName, EntityManagerInterface $entityManager, OutputInterface $output) { - $metadata = $this->getClassMetadata($entityName, $entityManager); - - $rows = array( - $this->formatField('Name', $metadata->name), - $this->formatField('Root entity name', $metadata->rootEntityName), - $this->formatField('Custom generator definition', $metadata->customGeneratorDefinition), - $this->formatField('Custom repository class', $metadata->customRepositoryClassName), - $this->formatField('Mapped super class?', $metadata->isMappedSuperclass), - $this->formatField('Embedded class?', $metadata->isEmbeddedClass), - $this->formatField('Parent classes', $metadata->parentClasses), - $this->formatField('Sub classes', $metadata->subClasses), - $this->formatField('Embedded classes', $metadata->subClasses), - $this->formatField('Named queries', $metadata->namedQueries), - $this->formatField('Named native queries', $metadata->namedNativeQueries), - $this->formatField('SQL result set mappings', $metadata->sqlResultSetMappings), - $this->formatField('Identifier', $metadata->identifier), - $this->formatField('Inheritance type', $metadata->inheritanceType), - $this->formatField('Discriminator column', $metadata->discriminatorColumn), - $this->formatField('Discriminator value', $metadata->discriminatorValue), - $this->formatField('Discriminator map', $metadata->discriminatorMap), - $this->formatField('Generator type', $metadata->generatorType), - $this->formatField('Table', $metadata->table), - $this->formatField('Composite identifier?', $metadata->isIdentifierComposite), - $this->formatField('Foreign identifier?', $metadata->containsForeignIdentifier), - $this->formatField('Sequence generator definition', $metadata->sequenceGeneratorDefinition), - $this->formatField('Table generator definition', $metadata->tableGeneratorDefinition), - $this->formatField('Change tracking policy', $metadata->changeTrackingPolicy), - $this->formatField('Versioned?', $metadata->isVersioned), - $this->formatField('Version field', $metadata->versionField), - $this->formatField('Read only?', $metadata->isReadOnly), - - $this->formatEntityListeners($metadata->entityListeners), - ); - - $rows = array_merge( - $rows, - $this->formatAssociationMappings($metadata->associationMappings), - $this->formatFieldMappings($metadata->fieldMappings) - ); $table = new Table($output); $table->setHeaders(array('Field', 'Value')); - array_map(array($table, 'addRow'), $rows); + $metadata = $this->getClassMetadata($entityName, $entityManager); + + array_map( + array($table, 'addRow'), + array_merge( + array( + $this->formatField('Name', $metadata->name), + $this->formatField('Root entity name', $metadata->rootEntityName), + $this->formatField('Custom generator definition', $metadata->customGeneratorDefinition), + $this->formatField('Custom repository class', $metadata->customRepositoryClassName), + $this->formatField('Mapped super class?', $metadata->isMappedSuperclass), + $this->formatField('Embedded class?', $metadata->isEmbeddedClass), + $this->formatField('Parent classes', $metadata->parentClasses), + $this->formatField('Sub classes', $metadata->subClasses), + $this->formatField('Embedded classes', $metadata->subClasses), + $this->formatField('Named queries', $metadata->namedQueries), + $this->formatField('Named native queries', $metadata->namedNativeQueries), + $this->formatField('SQL result set mappings', $metadata->sqlResultSetMappings), + $this->formatField('Identifier', $metadata->identifier), + $this->formatField('Inheritance type', $metadata->inheritanceType), + $this->formatField('Discriminator column', $metadata->discriminatorColumn), + $this->formatField('Discriminator value', $metadata->discriminatorValue), + $this->formatField('Discriminator map', $metadata->discriminatorMap), + $this->formatField('Generator type', $metadata->generatorType), + $this->formatField('Table', $metadata->table), + $this->formatField('Composite identifier?', $metadata->isIdentifierComposite), + $this->formatField('Foreign identifier?', $metadata->containsForeignIdentifier), + $this->formatField('Sequence generator definition', $metadata->sequenceGeneratorDefinition), + $this->formatField('Table generator definition', $metadata->tableGeneratorDefinition), + $this->formatField('Change tracking policy', $metadata->changeTrackingPolicy), + $this->formatField('Versioned?', $metadata->isVersioned), + $this->formatField('Version field', $metadata->versionField), + $this->formatField('Read only?', $metadata->isReadOnly), + + $this->formatEntityListeners($metadata->entityListeners), + ), + $this->formatAssociationMappings($metadata->associationMappings), + $this->formatFieldMappings($metadata->fieldMappings) + ) + ); $table->render(); } From 1208cc836a1d35eeb393b4518e9d289eda0b37f0 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:41:14 +0200 Subject: [PATCH 21/26] #1120 - registering the new `MappingDescribeCommand` with the ORM's `ConsoleRunner` --- lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php b/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php index c69e2342b..55ec3791c 100644 --- a/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php +++ b/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php @@ -107,7 +107,8 @@ class ConsoleRunner new \Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand(), new \Doctrine\ORM\Tools\Console\Command\RunDqlCommand(), new \Doctrine\ORM\Tools\Console\Command\ValidateSchemaCommand(), - new \Doctrine\ORM\Tools\Console\Command\InfoCommand() + new \Doctrine\ORM\Tools\Console\Command\InfoCommand(), + new \Doctrine\ORM\Tools\Console\Command\MappingDescribeCommand(), )); } From d5d64b756d07a65ba28518396fb1813913e00502 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:42:14 +0200 Subject: [PATCH 22/26] #1120 - removed redundant `if` block --- .../ORM/Tools/Console/Command/MappingDescribeCommand.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 8217fa370..d7943551e 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -173,11 +173,7 @@ EOT $matches = array_filter( $this->getMappedEntities($entityManager), function ($mappedEntity) use ($entityName) { - if (preg_match('{' . preg_quote($entityName) . '}', $mappedEntity)) { - return true; - } - - return false; + return preg_match('{' . preg_quote($entityName) . '}', $mappedEntity); } ); From 29e99b2b89a66a4a2f9bb835844c2535335ab681 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 18:57:58 +0200 Subject: [PATCH 23/26] #1120 - removed duplication: field and association mappings actually use the same dump format --- .../Command/MappingDescribeCommand.php | 42 ++++--------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index d7943551e..771fdffac 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -62,12 +62,10 @@ EOT */ protected function execute(InputInterface $input, OutputInterface $output) { - $entityName = $input->getArgument('entityName'); - /* @var $entityManager \Doctrine\ORM\EntityManagerInterface */ $entityManager = $this->getHelper('em')->getEntityManager(); - $this->displayEntity($entityName, $entityManager, $output); + $this->displayEntity($input->getArgument('entityName'), $entityManager, $output); return 0; } @@ -122,8 +120,10 @@ EOT $this->formatEntityListeners($metadata->entityListeners), ), - $this->formatAssociationMappings($metadata->associationMappings), - $this->formatFieldMappings($metadata->fieldMappings) + array($this->formatField('Association mappings:', '')), + $this->formatMappings($metadata->associationMappings), + array($this->formatField('Field mappings:', '')), + $this->formatMappings($metadata->fieldMappings) ) ); @@ -262,13 +262,12 @@ EOT * * @return array */ - private function formatAssociationMappings($associationMappings) + private function formatMappings(array $propertyMappings) { - $output = array(); - $output[] = $this->formatField('Association mappings:', ''); + $output = array(); - foreach ($associationMappings as $associationName => $mapping) { - $output[] = $this->formatField(sprintf(' %s', $associationName), ''); + foreach ($propertyMappings as $propertyName => $mapping) { + $output[] = $this->formatField(sprintf(' %s', $propertyName), ''); foreach ($mapping as $field => $value) { $output[] = $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); @@ -297,27 +296,4 @@ EOT ) ); } - - /** - * Form the field mappings - * - * @param array $fieldMappings - * - * @return array - */ - private function formatFieldMappings($fieldMappings) - { - $output = array(); - $output[] = $this->formatField('Field mappings:', ''); - - foreach ($fieldMappings as $fieldName => $mapping) { - $output[] = $this->formatField(sprintf(' %s',$fieldName), ''); - - foreach ($mapping as $field => $value) { - $output[] = $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); - } - } - - return $output; - } } From 9ccb56a7ab8c96e22135d282bf0bae8ac2eb26fc Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 19 Oct 2014 19:56:21 +0200 Subject: [PATCH 24/26] #1120 - applying CS fixes as per @dantleech's review --- .../ORM/Tools/Console/Command/MappingDescribeCommand.php | 5 ++--- .../Tests/ORM/Tools/Console/Command/InfoCommandTest.php | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 771fdffac..ab7ea5577 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -54,7 +54,7 @@ Or: %command.full_name% MyEntity EOT - ); + ); } /** @@ -79,7 +79,6 @@ EOT */ private function displayEntity($entityName, EntityManagerInterface $entityManager, OutputInterface $output) { - $table = new Table($output); $table->setHeaders(array('Field', 'Value')); @@ -177,7 +176,7 @@ EOT } ); - if (! $matches) { + if ( ! $matches) { throw new \InvalidArgumentException(sprintf( 'Could not find any mapped Entity classes matching "%s"', $entityName diff --git a/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php b/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php index 4eafc0f27..5594299ac 100644 --- a/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php +++ b/tests/Doctrine/Tests/ORM/Tools/Console/Command/InfoCommandTest.php @@ -32,7 +32,7 @@ class InfoCommandTest extends OrmFunctionalTestCase parent::setUp(); $this->application = new Application(); - $command = new InfoCommand(); + $command = new InfoCommand(); $this->application->setHelperSet(new HelperSet(array( 'em' => new EntityManagerHelper($this->_em) From 95bc0fb456d1b29121fa79860451639e9a8eaa8c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Mon, 20 Oct 2014 18:49:54 +0200 Subject: [PATCH 25/26] #1120 - using the `Symfony\Component\Console\Helper\TableHelper` for `symfony/symfony:~2.3` compatibility (Instead of `Symfony\Component\Console\Helper\Table`) --- .../ORM/Tools/Console/Command/MappingDescribeCommand.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index ab7ea5577..47a00b996 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -22,7 +22,7 @@ namespace Doctrine\ORM\Tools\Console\Command; use Doctrine\Common\Persistence\Mapping\MappingException; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -79,7 +79,7 @@ EOT */ private function displayEntity($entityName, EntityManagerInterface $entityManager, OutputInterface $output) { - $table = new Table($output); + $table = new TableHelper(); $table->setHeaders(array('Field', 'Value')); @@ -126,7 +126,7 @@ EOT ) ); - $table->render(); + $table->render($output); } /** From ea6f2130b4cab88635d35a848d37b35f1e43d407 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Mon, 20 Oct 2014 18:51:39 +0200 Subject: [PATCH 26/26] #1120 - downgrading requirement for `symfony/console` to `~2.3` Just need `Symfony\Component\Console\Helper\TableHelper` availability --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 80dc114f0..6a26d79a0 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "doctrine/collections": "~1.2", "doctrine/dbal": ">=2.5-dev,<2.6-dev", "doctrine/instantiator": "~1.0.1", - "symfony/console": "~2.5" + "symfony/console": "~2.3" }, "require-dev": { "symfony/yaml": "~2.1",