Passed
Push — master ( 829500...1175ab )
by Kevin
08:08
created

MakeFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
1
<?php
2
3
namespace Zenstruck\Foundry\Bundle\Maker;
4
5
use Doctrine\Persistence\ManagerRegistry;
6
use Symfony\Bundle\MakerBundle\ConsoleStyle;
7
use Symfony\Bundle\MakerBundle\DependencyBuilder;
8
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
9
use Symfony\Bundle\MakerBundle\Generator;
10
use Symfony\Bundle\MakerBundle\InputConfiguration;
11
use Symfony\Bundle\MakerBundle\Maker\AbstractMaker;
12
use Symfony\Component\Console\Command\Command;
13
use Symfony\Component\Console\Input\InputArgument;
14
use Symfony\Component\Console\Input\InputInterface;
15
16
/**
17
 * @author Kevin Bond <[email protected]>
18
 */
19
final class MakeFactory extends AbstractMaker
20
{
21
    private ManagerRegistry $managerRegistry;
22
23
    public function __construct(ManagerRegistry $managerRegistry)
24
    {
25
        $this->managerRegistry = $managerRegistry;
26
    }
27
28
    public static function getCommandName(): string
29
    {
30
        return 'make:factory';
31
    }
32
33
    public function configureCommand(Command $command, InputConfiguration $inputConfig): void
34
    {
35
        $command
36
            ->setDescription('Creates a custom factory for a Doctrine entity class')
37
            ->addArgument('entity', InputArgument::OPTIONAL, 'Entity class to create a factory for')
38
        ;
39
40
        $inputConfig->setArgumentAsNonInteractive('entity');
41
    }
42
43
    public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void
44
    {
45
        if ($input->getArgument('entity')) {
46
            return;
47
        }
48
49
        $argument = $command->getDefinition()->getArgument('entity');
50
        $entity = $io->choice($argument->getDescription(), $this->entityChoices());
51
52
        $input->setArgument('entity', $entity);
53
    }
54
55
    public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator): void
56
    {
57
        $class = $input->getArgument('entity');
58
59
        if (!\class_exists($class)) {
0 ignored issues
show
Bug introduced by
It seems like $class can also be of type string[]; however, parameter $class_name of class_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

59
        if (!\class_exists(/** @scrutinizer ignore-type */ $class)) {
Loading history...
60
            $class = $generator->createClassNameDetails($class, 'Entity\\')->getFullName();
0 ignored issues
show
Bug introduced by
It seems like $class can also be of type null and string[]; however, parameter $name of Symfony\Bundle\MakerBund...reateClassNameDetails() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

60
            $class = $generator->createClassNameDetails(/** @scrutinizer ignore-type */ $class, 'Entity\\')->getFullName();
Loading history...
61
        }
62
63
        if (!\class_exists($class)) {
64
            throw new RuntimeCommandException(\sprintf('Entity "%s" not found.', $input->getArgument('entity')));
0 ignored issues
show
Bug introduced by
It seems like $input->getArgument('entity') can also be of type string[]; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

64
            throw new RuntimeCommandException(\sprintf('Entity "%s" not found.', /** @scrutinizer ignore-type */ $input->getArgument('entity')));
Loading history...
65
        }
66
67
        $entity = new \ReflectionClass($class);
68
        $factory = $generator->createClassNameDetails(
69
            $entity->getShortName(),
70
            'Tests\\Factories\\',
71
            'Factory'
72
        );
73
74
        $repository = new \ReflectionClass($this->managerRegistry->getRepository($entity->getName()));
75
76
        if (0 !== \mb_strpos($repository->getName(), $generator->getRootNamespace())) {
77
            // not using a custom repository
78
            $repository = null;
79
        }
80
81
        $generator->generateClass(
82
            $factory->getFullName(),
83
            __DIR__.'/../Resources/skeleton/Factory.tpl.php',
84
            [
85
                'entity' => $entity,
86
                'repository' => $repository,
87
            ]
88
        );
89
90
        $generator->writeChanges();
91
92
        $this->writeSuccessMessage($io);
93
94
        $io->text([
95
            'Next: Open your new factory and set default values/states.',
96
            'Find the documentation at https://github.com/zenstruck/foundry#model-factories',
97
        ]);
98
    }
99
100
    public function configureDependencies(DependencyBuilder $dependencies): void
101
    {
102
        // noop
103
    }
104
105
    private function entityChoices(): array
106
    {
107
        // todo remove choices that already have a factory
108
        $choices = [];
109
110
        foreach ($this->managerRegistry->getManagers() as $manager) {
111
            foreach ($manager->getMetadataFactory()->getAllMetadata() as $metadata) {
112
                $choices[] = $metadata->getName();
113
            }
114
        }
115
116
        return $choices;
117
    }
118
}
119