Passed
Push — master ( 8ba30c...5485cd )
by Oleg
03:02
created

ApiSuiteCommand::generateConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace SlayerBirden\DFCodeGeneration\Command;
5
6
use Doctrine\Common\Annotations\AnnotationRegistry;
7
use SlayerBirden\DFCodeGeneration\Generator\Config\Config;
8
use SlayerBirden\DFCodeGeneration\Generator\Config\StandardProvider;
9
use SlayerBirden\DFCodeGeneration\Generator\Controllers\Add;
10
use SlayerBirden\DFCodeGeneration\Generator\Controllers\DecoratedProvider;
11
use SlayerBirden\DFCodeGeneration\Generator\Controllers\Delete;
12
use SlayerBirden\DFCodeGeneration\Generator\Controllers\EntityNamePluralDecorator;
13
use SlayerBirden\DFCodeGeneration\Generator\Controllers\Get;
14
use SlayerBirden\DFCodeGeneration\Generator\Controllers\Gets;
15
use SlayerBirden\DFCodeGeneration\Generator\Controllers\RelationsProviderDecorator;
16
use SlayerBirden\DFCodeGeneration\Generator\Controllers\UniqueProviderDecorator;
17
use SlayerBirden\DFCodeGeneration\Generator\Controllers\Update;
18
use SlayerBirden\DFCodeGeneration\Generator\Factory\Routes;
19
use SlayerBirden\DFCodeGeneration\Generator\Tests\Add as TestAdd;
20
use SlayerBirden\DFCodeGeneration\Generator\Tests\Delete as TestDelete;
21
use SlayerBirden\DFCodeGeneration\Generator\Tests\Get as TestGet;
22
use SlayerBirden\DFCodeGeneration\Generator\Tests\Gets as TestGets;
23
use SlayerBirden\DFCodeGeneration\Generator\Tests\IdRegistry;
24
use SlayerBirden\DFCodeGeneration\Generator\Tests\NullValuesRandomizer;
25
use SlayerBirden\DFCodeGeneration\Generator\Tests\ReflectionProviderFactory;
26
use SlayerBirden\DFCodeGeneration\Generator\Tests\Update as TestUpdate;
27
use SlayerBirden\DFCodeGeneration\Generator\Factory\SimpleProvider;
28
use SlayerBirden\DFCodeGeneration\Writer\OutputWriter;
29
use SlayerBirden\DFCodeGeneration\Writer\Psr4FileNameProvider;
30
use SlayerBirden\DFCodeGeneration\Writer\WriteInterface;
31
use Symfony\Component\Console\Command\Command;
32
use Symfony\Component\Console\Exception\InvalidArgumentException;
33
use Symfony\Component\Console\Exception\LogicException;
34
use Symfony\Component\Console\Input\InputArgument;
35
use Symfony\Component\Console\Input\InputInterface;
36
use Symfony\Component\Console\Input\InputOption;
37
use Symfony\Component\Console\Output\OutputInterface;
38
use SlayerBirden\DFCodeGeneration\Generator\Controllers\SimpleProvider as ControllerSimpleProvider;
39
40
class ApiSuiteCommand extends Command
41
{
42
    /**
43
     * @var OutputInterface
44
     */
45
    private $output;
46
    /**
47
     * @var string
48
     */
49
    private $entityClassName;
50
    /**
51
     * @var bool
52
     */
53
    private $force;
54
    /**
55
     * @var bool
56
     */
57
    private $tests;
58
    /**
59
     * @var null|WriteInterface
60
     */
61
    private $writer;
62
63 4
    public function __construct(?string $name = null, ?WriteInterface $writer = null)
64
    {
65 4
        parent::__construct($name);
66 4
        $this->writer = $writer;
67 4
    }
68
69 4
    protected function configure()
70
    {
71 4
        $this->setName('generate:api')
72 4
            ->setDescription('Api Suite for Entity.')
73 4
            ->setHelp('This command creates the full Api suite (CRUD + tests) for DataFlow Server Entity. Don\'t forget to use force flag if you want to write files.')
74 4
            ->addArgument('entity', InputArgument::REQUIRED, 'Entity class')
75 4
            ->addOption('tests', 't', InputOption::VALUE_NONE, 'Whether to create tests.')
76 4
            ->addOption('force', 'f', InputOption::VALUE_NONE, 'Without force flag no writes happen (only output).');
77 4
    }
78
79 4
    protected function initialize(InputInterface $input, OutputInterface $output)
80
    {
81 4
        $this->output = $output;
82 4
        $this->entityClassName = $input->getArgument('entity');
83 4
        $this->force = $input->getOption('force');
84 4
        $this->tests = $input->getOption('tests');
85
        // If it's not force mode we're using output writer
86 4
        if (!$this->force) {
87 2
            $this->writer = new OutputWriter($this->output, new Psr4FileNameProvider());
88
        }
89
90 4
        AnnotationRegistry::registerLoader('class_exists');
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\Common\Annotati...istry::registerLoader() has been deprecated: this method is deprecated and will be removed in doctrine/annotations 2.0 autoloading should be deferred to the globally registered autoloader by then. For now, use @example AnnotationRegistry::registerLoader('class_exists') ( Ignorable by Annotation )

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

90
        /** @scrutinizer ignore-deprecated */ AnnotationRegistry::registerLoader('class_exists');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
91 4
    }
92
93
    /**
94
     * {@inheritdoc}
95
     * @throws \Doctrine\Common\Annotations\AnnotationException
96
     * @throws \ReflectionException
97
     */
98 4
    protected function execute(InputInterface $input, OutputInterface $output)
99
    {
100 4
        if (!class_exists($this->entityClassName)) {
101
            throw new InvalidArgumentException('Entity Class does not exist.');
102
        }
103
104 4
        $this->generateControllerStack();
105 4
        $this->generateRoutes();
106 4
        $this->generateConfig();
107 4
        if ($this->tests) {
108 2
            $this->generateTests();
109
        }
110
111 4
        $output->writeln([
112 4
            '<error>IMPORTANT: please check all generated files before committing.</error>',
113
            '<error># You might want to run something like "php-cs-fixer" to make sure formatting is correct.</error>',
114
        ]);
115 4
    }
116
117 2
    private function generateTests(): void
118
    {
119 2
        $entityProviderFactory = new ReflectionProviderFactory(new IdRegistry());
120
        // 50% null values written by default
121 2
        $randomizer = new NullValuesRandomizer(.5);
122
123 2
        $files = [];
124 2
        $files[] = (new TestAdd($this->entityClassName, $entityProviderFactory, $randomizer))->generate();
125 2
        $files[] = (new TestDelete($this->entityClassName, $entityProviderFactory, $randomizer))->generate();
126 2
        $files[] = (new TestGet($this->entityClassName, $entityProviderFactory, $randomizer))->generate();
127 2
        $files[] = (new TestGets($this->entityClassName, $entityProviderFactory, $randomizer))->generate();
128 2
        $files[] = (new TestUpdate($this->entityClassName, $entityProviderFactory, $randomizer))->generate();
129
130 2
        array_walk($files, function ($contents) {
131 2
            $this->writer->write($contents);
0 ignored issues
show
Bug introduced by
The method write() does not exist on null. ( Ignorable by Annotation )

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

131
            $this->writer->/** @scrutinizer ignore-call */ 
132
                           write($contents);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
132 2
        });
133
134 2
        $this->output->writeln('<info>Acceptance tests generated</info>');
135 2
    }
136
137 4
    private function generateConfig(): void
138
    {
139 4
        $this->getWriter()->write(
140 4
            (new Config(new StandardProvider($this->entityClassName)))->generate()
141
        );
142
143 4
        $this->output->writeln('<info>Config generated</info>');
144 4
    }
145
146
    /**
147
     * @throws \Twig_Error_Loader
148
     * @throws \Twig_Error_Runtime
149
     * @throws \Twig_Error_Syntax
150
     */
151 4
    private function generateRoutes(): void
152
    {
153 4
        $this->getWriter()->write(
154 4
            (new Routes(new SimpleProvider($this->entityClassName)))->generate()
155
        );
156
157 4
        $this->output->writeln('<info>Routes provider generated</info>');
158 4
    }
159
160
    /**
161
     * @throws \Twig_Error_Loader
162
     * @throws \Twig_Error_Runtime
163
     * @throws \Twig_Error_Syntax
164
     */
165 4
    private function generateControllerStack(): void
166
    {
167 4
        $files = [];
168 4
        $files[] = (new Add(
169 4
            new DecoratedProvider(
170 4
                $this->entityClassName,
171 4
                new UniqueProviderDecorator($this->entityClassName),
172 4
                new RelationsProviderDecorator($this->entityClassName)
173
            )
174 4
        ))->generate();
175 4
        $files[] = (new Delete(new ControllerSimpleProvider($this->entityClassName)))->generate();
176 4
        $files[] = (new Get(new ControllerSimpleProvider($this->entityClassName)))->generate();
177 4
        $files[] = (new Gets(
178 4
            new DecoratedProvider(
179 4
                $this->entityClassName,
180 4
                new EntityNamePluralDecorator()
181
            )
182 4
        ))->generate();
183 4
        $files[] = (new Update(
184 4
            new DecoratedProvider(
185 4
                $this->entityClassName,
186 4
                new UniqueProviderDecorator($this->entityClassName),
187 4
                new RelationsProviderDecorator($this->entityClassName)
188
            )
189 4
        ))->generate();
190
191 4
        array_walk($files, function ($contents) {
192 4
            $this->writer->write($contents);
193 4
        });
194
195 4
        $this->output->writeln('<info>Controller stack generated</info>');
196 4
    }
197
198
    /**
199
     * @return WriteInterface
200
     */
201 4
    private function getWriter(): WriteInterface
202
    {
203 4
        if ($this->writer === null) {
204
            throw new LogicException('Writer is not defined!');
205
        }
206 4
        return $this->writer;
207
    }
208
}
209