diff --git a/src/Doctrine/DoctrineMetadataFactory.php b/src/Doctrine/DoctrineMetadataFactory.php
index b5a616539..d1b7e067e 100644
--- a/src/Doctrine/DoctrineMetadataFactory.php
+++ b/src/Doctrine/DoctrineMetadataFactory.php
@@ -12,6 +12,9 @@
namespace Symfony\Bundle\MakerBundle\Doctrine;
use Doctrine\Common\Persistence\ManagerRegistry;
+use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
+use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
+use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
@@ -69,6 +72,30 @@ public function getMetadataForClass(string $entity): ?ClassMetadata
return null;
}
+ public function getMappingDriverForClass(string $className): ?MappingDriver
+ {
+ /** @var EntityManagerInterface $em */
+ $em = $this->registry->getManagerForClass($className);
+
+ if (null === $em) {
+ throw new \InvalidArgumentException(sprintf('Cannot find the entity manager for class "%s"', $className));
+ }
+
+ $metadataDriver = $em->getConfiguration()->getMetadataDriverImpl();
+
+ if (!$metadataDriver instanceof MappingDriverChain) {
+ return $metadataDriver;
+ }
+
+ foreach ($metadataDriver->getDrivers() as $namespace => $driver) {
+ if (0 === strpos($className, $namespace)) {
+ return $driver;
+ }
+ }
+
+ return $metadataDriver->getDefaultDriver();
+ }
+
/**
* @return array
*/
diff --git a/src/Maker/MakeEntity.php b/src/Maker/MakeEntity.php
index b7e252770..76ff2f779 100644
--- a/src/Maker/MakeEntity.php
+++ b/src/Maker/MakeEntity.php
@@ -15,8 +15,11 @@
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\Mapping\Column;
+use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Symfony\Bundle\MakerBundle\ConsoleStyle;
use Symfony\Bundle\MakerBundle\DependencyBuilder;
+use Symfony\Bundle\MakerBundle\Doctrine\DoctrineMetadataFactory;
+use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
use Symfony\Bundle\MakerBundle\Generator;
use Symfony\Bundle\MakerBundle\InputConfiguration;
use Symfony\Bundle\MakerBundle\Str;
@@ -122,7 +125,8 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
'Repository'
);
- if (!class_exists($entityClassDetails->getFullName())) {
+ $classExists = class_exists($entityClassDetails->getFullName());
+ if (!$classExists) {
$entityPath = $generator->generateClass(
$entityClassDetails->getFullName(),
'doctrine/Entity.tpl.php',
@@ -143,21 +147,26 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
);
$generator->writeChanges();
+ }
+
+ if (!$this->doesEntityUseAnnotationMapping($entityClassDetails->getFullName())) {
+ throw new RuntimeCommandException(sprintf('Only annotation mapping is supported by make:entity, but the %s class uses a different format. If you would like this command to generate the properties & getter/setter methods, add your mapping configuration, and then re-run this command with the --regenerate flag.', $entityClassDetails->getFullName()));
+ }
+ if ($classExists) {
+ $entityPath = $this->getPathOfClass($entityClassDetails->getFullName());
$io->text([
- '',
- 'Entity generated! Now let\'s add some fields!',
- 'You can always add more fields later manually or by re-running this command.',
+ 'Your entity already exists! So let\'s add some new fields!',
]);
} else {
- $entityPath = $this->getPathOfClass($entityClassDetails->getFullName());
$io->text([
- 'Your entity already exists! So let\'s add some new fields!',
+ '',
+ 'Entity generated! Now let\'s add some fields!',
+ 'You can always add more fields later manually or by re-running this command.',
]);
}
$currentFields = $this->getPropertyNames($entityClassDetails->getFullName());
-
$manipulator = $this->createClassManipulator($entityPath, $io, $overwrite);
$isFirstField = true;
@@ -782,4 +791,23 @@ private function getPropertyNames(string $class): array
return $prop->getName();
}, $reflClass->getProperties());
}
+
+ private function doesEntityUseAnnotationMapping(string $className): bool
+ {
+ $metadataFactory = new DoctrineMetadataFactory($this->registry);
+ if (!class_exists($className)) {
+ $otherClassMetadatas = $metadataFactory->getMetadataForNamespace(Str::getNamespace($className));
+
+ // if we have no metadata, we should assume this is the first class being mapped
+ if (empty($otherClassMetadatas)) {
+ return false;
+ }
+
+ $className = $otherClassMetadatas[0]->name;
+ }
+
+ $metadataFactory->getMappingDriverForClass($className);
+
+ return $metadataFactory instanceof AnnotationDriver;
+ }
}
diff --git a/src/Test/MakerTestCase.php b/src/Test/MakerTestCase.php
index fdef87019..c51a7a35c 100644
--- a/src/Test/MakerTestCase.php
+++ b/src/Test/MakerTestCase.php
@@ -93,7 +93,7 @@ protected function executeMakerCommand(MakerTestDetails $testDetails)
$makerProcess->run();
- if (!$makerProcess->isSuccessful()) {
+ if (!$makerProcess->isSuccessful() && !$testDetails->isCommandAllowedToFail()) {
throw new \Exception(sprintf('Running maker command failed: "%s" "%s"', $makerProcess->getOutput(), $makerProcess->getErrorOutput()));
}
diff --git a/src/Test/MakerTestDetails.php b/src/Test/MakerTestDetails.php
index 6c8a84200..241517de7 100644
--- a/src/Test/MakerTestDetails.php
+++ b/src/Test/MakerTestDetails.php
@@ -34,6 +34,8 @@ final class MakerTestDetails
private $argumentsString = '';
+ private $commandAllowedToFail = false;
+
/**
* @param MakerInterface $maker
* @param array $inputs
@@ -153,6 +155,13 @@ public function setArgumentsString(string $argumentsString): self
return $this;
}
+ public function setCommandAllowedToFail(bool $commandAllowedToFail): self
+ {
+ $this->commandAllowedToFail = $commandAllowedToFail;
+
+ return $this;
+ }
+
public function getInputs(): array
{
return $this->inputs;
@@ -216,4 +225,9 @@ public function getArgumentsString(): string
{
return $this->argumentsString;
}
+
+ public function isCommandAllowedToFail(): bool
+ {
+ return $this->commandAllowedToFail;
+ }
}
diff --git a/tests/Maker/FunctionalTest.php b/tests/Maker/FunctionalTest.php
index 1fa99f467..8d79e76c2 100644
--- a/tests/Maker/FunctionalTest.php
+++ b/tests/Maker/FunctionalTest.php
@@ -191,7 +191,7 @@ public function getCommandTests()
->updateSchemaAfterCommand()
];
- yield 'entity_many_to_one_simple' => [MakerTestDetails::createTest(
+ yield 'entity_many_to_one_simple_with_inverse' => [MakerTestDetails::createTest(
$this->getMakerInstance(MakeEntity::class),
[
// entity class name
@@ -476,6 +476,52 @@ public function getCommandTests()
->configureDatabase(false)
];
+ yield 'entity_xml_mapping_error_existing' => [MakerTestDetails::createTest(
+ $this->getMakerInstance(MakeEntity::class),
+ [
+ 'User',
+ ])
+ ->setFixtureFilesPath(__DIR__ . '/../fixtures/MakeEntityXmlMappingError')
+ ->addReplacement(
+ 'config/packages/doctrine.yaml',
+ 'type: annotation',
+ 'type: xml'
+ )
+ ->addReplacement(
+ 'config/packages/doctrine.yaml',
+ "dir: '%kernel.project_dir%/src/Entity'",
+ "dir: '%kernel.project_dir%/config/doctrine'"
+ )
+ ->configureDatabase(false)
+ ->setCommandAllowedToFail(true)
+ ->assert(function(string $output, string $directory) {
+ $this->assertContains('Only annotation mapping is supported', $output);
+ })
+ ];
+
+ yield 'entity_xml_mapping_error_new_class' => [MakerTestDetails::createTest(
+ $this->getMakerInstance(MakeEntity::class),
+ [
+ 'UserAvatarPhoto',
+ ])
+ ->setFixtureFilesPath(__DIR__ . '/../fixtures/MakeEntityXmlMappingError')
+ ->addReplacement(
+ 'config/packages/doctrine.yaml',
+ 'type: annotation',
+ 'type: xml'
+ )
+ ->addReplacement(
+ 'config/packages/doctrine.yaml',
+ "dir: '%kernel.project_dir%/src/Entity'",
+ "dir: '%kernel.project_dir%/config/doctrine'"
+ )
+ ->configureDatabase(false)
+ ->setCommandAllowedToFail(true)
+ ->assert(function(string $output, string $directory) {
+ $this->assertContains('Only annotation mapping is supported', $output);
+ })
+ ];
+
yield 'entity_updating_overwrite' => [MakerTestDetails::createTest(
$this->getMakerInstance(MakeEntity::class),
[
diff --git a/tests/fixtures/MakeEntityXmlMappingError/config/doctrine/User.orm.xml b/tests/fixtures/MakeEntityXmlMappingError/config/doctrine/User.orm.xml
new file mode 100644
index 000000000..322344224
--- /dev/null
+++ b/tests/fixtures/MakeEntityXmlMappingError/config/doctrine/User.orm.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/fixtures/MakeEntityXmlMappingError/src/Entity/User.php b/tests/fixtures/MakeEntityXmlMappingError/src/Entity/User.php
new file mode 100644
index 000000000..8c2e33ba5
--- /dev/null
+++ b/tests/fixtures/MakeEntityXmlMappingError/src/Entity/User.php
@@ -0,0 +1,16 @@
+id;
+ }
+
+ // add your own fields
+}