Passed
Push — master ( ecc0e1...cd7371 )
by Kevin
29:55 queued 16:08
created

MakeFactory::generate()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 42
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 5.7629

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 23
c 1
b 0
f 0
dl 0
loc 42
ccs 22
cts 32
cp 0.6875
rs 9.2408
cc 5
nc 6
nop 3
crap 5.7629
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
use Symfony\Component\Console\Input\InputOption;
16
17
/**
18
 * @author Kevin Bond <[email protected]>
19
 */
20
final class MakeFactory extends AbstractMaker
21
{
22
    /** @var ManagerRegistry */
23
    private $managerRegistry;
24
25 20
    public function __construct(ManagerRegistry $managerRegistry)
26
    {
27 20
        $this->managerRegistry = $managerRegistry;
28 20
    }
29
30 4
    public static function getCommandName(): string
31
    {
32 4
        return 'make:factory';
33
    }
34
35 20
    public static function getCommandDescription(): string
36
    {
37
        return 'Creates a Foundry model factory for a Doctrine entity class';
38 20
    }
39 20
40 20
    public function configureCommand(Command $command, InputConfiguration $inputConfig): void
41
    {
42
        $command
43 20
            ->setDescription(self::getCommandDescription())
44 20
            ->addArgument('entity', InputArgument::OPTIONAL, 'Entity class to create a factory for')
45
            ->addOption('test', null, InputOption::VALUE_NONE, 'Create in <fg=yellow>tests/</> instead of <fg=yellow>src/</>')
46 20
        ;
47
48 20
        $inputConfig->setArgumentAsNonInteractive('entity');
49 12
    }
50
51
    public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void
52 8
    {
53 4
        if ($input->getArgument('entity')) {
54 4
            return;
55
        }
56
57 8
        if (!$input->getOption('test')) {
58 8
            $io->text('// Note: pass <fg=yellow>--test</> if you want to generate factories in your <fg=yellow>tests/</> directory');
59
            $io->newLine();
60 8
        }
61 8
62
        $argument = $command->getDefinition()->getArgument('entity');
63 20
        $entity = $io->choice($argument->getDescription(), $this->entityChoices());
64
65 20
        $input->setArgument('entity', $entity);
66
    }
67 20
68 4
    public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator): void
69
    {
70
        $class = $input->getArgument('entity');
71 20
72 4
        if (!\class_exists($class)) {
0 ignored issues
show
Bug introduced by
It seems like $class can also be of type null and string[]; however, parameter $class 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

72
        if (!\class_exists(/** @scrutinizer ignore-type */ $class)) {
Loading history...
73
            $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

73
            $class = $generator->createClassNameDetails(/** @scrutinizer ignore-type */ $class, 'Entity\\')->getFullName();
Loading history...
74
        }
75 16
76 16
        if (!\class_exists($class)) {
77 16
            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 $values of sprintf() does only seem to accept double|integer|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

77
            throw new RuntimeCommandException(\sprintf('Entity "%s" not found.', /** @scrutinizer ignore-type */ $input->getArgument('entity')));
Loading history...
78 16
        }
79 16
80
        $entity = new \ReflectionClass($class);
0 ignored issues
show
Bug introduced by
It seems like $class can also be of type string[]; however, parameter $objectOrClass of ReflectionClass::__construct() does only seem to accept object|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

80
        $entity = new \ReflectionClass(/** @scrutinizer ignore-type */ $class);
Loading history...
81
        $factory = $generator->createClassNameDetails(
82 16
            $entity->getShortName(),
83
            $input->getOption('test') ? 'Tests\\Factory' : 'Factory',
84 16
            'Factory'
85
        );
86 16
87
        $repository = new \ReflectionClass($this->managerRegistry->getRepository($entity->getName()));
88
89 16
        if (0 !== \mb_strpos($repository->getName(), $generator->getRootNamespace())) {
90 16
            // not using a custom repository
91 16
            $repository = null;
92
        }
93 16
94 16
        $generator->generateClass(
95
            $factory->getFullName(),
96
            __DIR__.'/../Resources/skeleton/Factory.tpl.php',
97
            [
98 16
                'entity' => $entity,
99
                'repository' => $repository,
100 16
            ]
101
        );
102 16
103 16
        $generator->writeChanges();
104
105
        $this->writeSuccessMessage($io);
106 16
107
        $io->text([
108 20
            'Next: Open your new factory and set default values/states.',
109
            'Find the documentation at https://github.com/zenstruck/foundry#model-factories',
110
        ]);
111 20
    }
112
113 8
    public function configureDependencies(DependencyBuilder $dependencies): void
114
    {
115 8
        // noop
116
    }
117 8
118 8
    private function entityChoices(): array
119 8
    {
120
        $choices = [];
121
122
        foreach ($this->managerRegistry->getManagers() as $manager) {
123 8
            foreach ($manager->getMetadataFactory()->getAllMetadata() as $metadata) {
124
                $choices[] = $metadata->getName();
125 8
            }
126
        }
127
128
        \sort($choices);
129
130
        return $choices;
131
    }
132
}
133