Completed
Push — master ( 81ce9d...1672d9 )
by Oleg
03:54
created

ApiSuiteCommand::getWriter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 6
ccs 3
cts 4
cp 0.75
crap 2.0625
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\ReflectionProviderFactory;
25
use SlayerBirden\DFCodeGeneration\Generator\Tests\Update as TestUpdate;
26
use SlayerBirden\DFCodeGeneration\Generator\Factory\SimpleProvider;
27
use SlayerBirden\DFCodeGeneration\Writer\OutputWriter;
28
use SlayerBirden\DFCodeGeneration\Writer\Psr4FileNameProvider;
29
use SlayerBirden\DFCodeGeneration\Writer\WriteInterface;
30
use Symfony\Component\Console\Command\Command;
31
use Symfony\Component\Console\Exception\InvalidArgumentException;
32
use Symfony\Component\Console\Exception\LogicException;
33
use Symfony\Component\Console\Input\InputArgument;
34
use Symfony\Component\Console\Input\InputInterface;
35
use Symfony\Component\Console\Input\InputOption;
36
use Symfony\Component\Console\Output\OutputInterface;
37
use SlayerBirden\DFCodeGeneration\Generator\Controllers\SimpleProvider as ControllerSimpleProvider;
38
39
class ApiSuiteCommand extends Command
40
{
41
    /**
42
     * @var OutputInterface
43
     */
44
    private $output;
45
    /**
46
     * @var string
47
     */
48
    private $entityClassName;
49
    /**
50
     * @var bool
51
     */
52
    private $force;
53
    /**
54
     * @var bool
55
     */
56
    private $tests;
57
    /**
58
     * @var null|WriteInterface
59
     */
60
    private $writer;
61
62 4
    public function __construct(?string $name = null, ?WriteInterface $writer = null)
63
    {
64 4
        parent::__construct($name);
65 4
        $this->writer = $writer;
66 4
    }
67
68 4
    protected function configure()
69
    {
70 4
        $this->setName('generate:api')
71 4
            ->setDescription('Api Suite for Entity.')
72 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.')
73 4
            ->addArgument('entity', InputArgument::REQUIRED, 'Entity class')
74 4
            ->addOption('tests', 't', InputOption::VALUE_NONE, 'Whether to create tests.')
75 4
            ->addOption('force', 'f', InputOption::VALUE_NONE, 'Without force flag no writes happen (only output).');
76 4
    }
77
78 4
    protected function initialize(InputInterface $input, OutputInterface $output)
79
    {
80 4
        $this->output = $output;
81 4
        $this->entityClassName = $input->getArgument('entity');
82 4
        $this->force = $input->getOption('force');
83 4
        $this->tests = $input->getOption('tests');
84
        // If it's not force mode we're using output writer
85 4
        if (!$this->force) {
86 2
            $this->writer = new OutputWriter($this->output, new Psr4FileNameProvider());
87
        }
88
89 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

89
        /** @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...
90 4
    }
91
92
    /**
93
     * {@inheritdoc}
94
     * @throws \Doctrine\Common\Annotations\AnnotationException
95
     * @throws \ReflectionException
96
     */
97 4
    protected function execute(InputInterface $input, OutputInterface $output)
98
    {
99 4
        if (!class_exists($this->entityClassName)) {
100
            throw new InvalidArgumentException('Entity Class does not exist.');
101
        }
102
103 4
        $this->generateControllerStack();
104 4
        $this->generateRoutes();
105 4
        $this->generateConfig();
106 4
        if ($this->tests) {
107 2
            $this->generateTests();
108
        }
109
110 4
        $output->writeln([
111 4
            '<error>IMPORTANT: please check all generated files before committing.</error>',
112
            '<error># You might want to run something like "php-cs-fixer" to make sure formatting is correct.</error>',
113
        ]);
114 4
    }
115
116 2
    private function generateTests(): void
117
    {
118 2
        $entityProviderFactory = new ReflectionProviderFactory(new IdRegistry());
119
120 2
        $files = [];
121 2
        $files[] = (new TestAdd($this->entityClassName, $entityProviderFactory))->generate();
122 2
        $files[] = (new TestDelete($this->entityClassName, $entityProviderFactory))->generate();
123 2
        $files[] = (new TestGet($this->entityClassName, $entityProviderFactory))->generate();
124 2
        $files[] = (new TestGets($this->entityClassName, $entityProviderFactory))->generate();
125 2
        $files[] = (new TestUpdate($this->entityClassName, $entityProviderFactory))->generate();
126
127 2
        array_walk($files, function ($contents) {
128 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

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