Passed
Push — master ( e23bc1...ee0f92 )
by Kevin
03:07
created

MakeFactory   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Test Coverage

Coverage 69.74%

Importance

Changes 0
Metric Value
eloc 45
dl 0
loc 104
ccs 53
cts 76
cp 0.6974
rs 10
c 0
b 0
f 0
wmc 15

7 Methods

Rating   Name   Duplication   Size   Complexity  
A configureDependencies() 0 2 1
A entityChoices() 0 11 3
A configureCommand() 0 9 1
A generate() 0 42 5
A interact() 0 15 3
A __construct() 0 3 1
A getCommandName() 0 3 1
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 10
    public function __construct(ManagerRegistry $managerRegistry)
26
    {
27 10
        $this->managerRegistry = $managerRegistry;
28 10
    }
29
30 2
    public static function getCommandName(): string
31
    {
32 2
        return 'make:factory';
33
    }
34
35 10
    public function configureCommand(Command $command, InputConfiguration $inputConfig): void
36
    {
37
        $command
38 10
            ->setDescription('Creates a Foundry model factory for a Doctrine entity class')
39 10
            ->addArgument('entity', InputArgument::OPTIONAL, 'Entity class to create a factory for')
40 10
            ->addOption('test', null, InputOption::VALUE_NONE, 'Create in <fg=yellow>tests/</> instead of <fg=yellow>src/</>')
41
        ;
42
43 10
        $inputConfig->setArgumentAsNonInteractive('entity');
44 10
    }
45
46 10
    public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void
47
    {
48 10
        if ($input->getArgument('entity')) {
49 6
            return;
50
        }
51
52 4
        if (!$input->getOption('test')) {
53 2
            $io->text('// Note: pass <fg=yellow>--test</> if you want to generate factories in your <fg=yellow>tests/</> directory');
54 2
            $io->newLine();
55
        }
56
57 4
        $argument = $command->getDefinition()->getArgument('entity');
58 4
        $entity = $io->choice($argument->getDescription(), $this->entityChoices());
59
60 4
        $input->setArgument('entity', $entity);
61 4
    }
62
63 10
    public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator): void
64
    {
65 10
        $class = $input->getArgument('entity');
66
67 10
        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

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

68
            $class = $generator->createClassNameDetails(/** @scrutinizer ignore-type */ $class, 'Entity\\')->getFullName();
Loading history...
69
        }
70
71 10
        if (!\class_exists($class)) {
72 2
            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

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