Test Failed
Pull Request — master (#58)
by Dmitriy
02:42
created

DefaultController::preview()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 17
c 2
b 0
f 0
dl 0
loc 28
ccs 0
cts 16
cp 0
rs 9.0777
cc 6
nc 5
nop 2
crap 42
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Gii\Controller;
6
7
use Psr\Http\Message\ResponseInterface;
8
use ReflectionClass;
9
use ReflectionParameter;
10
use Yiisoft\DataResponse\DataResponse;
11
use Yiisoft\DataResponse\DataResponseFactoryInterface;
12
use Yiisoft\Http\Status;
13
use Yiisoft\RequestModel\Attribute\Query;
14
use Yiisoft\Validator\RulesDumper;
15
use Yiisoft\Validator\RulesProvider\AttributesRulesProvider;
16
use Yiisoft\Yii\Gii\Component\CodeFile\CodeFile;
17
use Yiisoft\Yii\Gii\Component\CodeFile\CodeFileWriteOperationEnum;
18
use Yiisoft\Yii\Gii\Component\CodeFile\CodeFileWriter;
19
use Yiisoft\Yii\Gii\Exception\InvalidGeneratorCommandException;
20
use Yiisoft\Yii\Gii\Generator\CommandHydrator;
21
use Yiisoft\Yii\Gii\GeneratorCommandInterface;
22
use Yiisoft\Yii\Gii\GeneratorInterface;
23
use Yiisoft\Yii\Gii\GiiInterface;
24
use Yiisoft\Yii\Gii\Request\GeneratorRequest;
25
26
final class DefaultController
27
{
28
    public function __construct(private DataResponseFactoryInterface $responseFactory)
29
    {
30
    }
31
32
    public function list(GiiInterface $gii): ResponseInterface
33
    {
34
        $generators = $gii->getGenerators();
35
36
        return $this->responseFactory->createResponse([
37
            'generators' => array_map($this->serializeGenerator(...), array_values($generators)),
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected ')' on line 37 at column 67
Loading history...
38
        ]);
39
    }
40
41
    private function serializeGenerator(GeneratorInterface $generator): array
42
    {
43
        /**
44
         * @psalm-var $commandClass class-string<GeneratorCommandInterface>
45
         */
46
        $commandClass = $generator::getCommandClass();
47
48
        $dataset = new AttributesRulesProvider($commandClass);
49
        $rules = $dataset->getRules();
50
        $dumpedRules = (new RulesDumper())->asArray($rules);
51
        $attributes = $commandClass::getAttributes();
52
        $hints = $commandClass::getHints();
53
        $labels = $commandClass::getAttributeLabels();
54
55
        $reflection = new ReflectionClass($commandClass);
56
        $constructorParameters = $reflection->getConstructor()->getParameters();
57
58
        $attributesResult = [];
59
        foreach ($attributes as $attributeName) {
60
            $reflectionProperty = $reflection->getProperty($attributeName);
61
            $defaultValue = $reflectionProperty->hasDefaultValue()
62
                ? $reflectionProperty->getDefaultValue()
63
                : $this->findReflectionParameter($attributeName, $constructorParameters)?->getDefaultValue();
64
            $attributesResult[$attributeName] = [
65
                'defaultValue' => $defaultValue,
66
                'hint' => $hints[$attributeName] ?? null,
67
                'label' => $labels[$attributeName] ?? null,
68
                'rules' => $dumpedRules[$attributeName] ?? [],
69
            ];
70
        }
71
72
        return [
73
            'id' => $generator::getId(),
74
            'name' => $generator::getName(),
75
            'description' => $generator::getDescription(),
76
            'commandClass' => $commandClass,
77
            'attributes' => $attributesResult,
78
            //            'templatePath' => $generator->getTemplatePath(),
79
            //            'templates' => $generator->getTemplates(),
80
            'directory' => $generator->getDirectory(),
81
        ];
82
    }
83
84
    public function get(GeneratorRequest $request): ResponseInterface
85
    {
86
        $generator = $request->getGenerator();
87
88
        return $this->responseFactory->createResponse(
89
            $this->serializeGenerator($generator)
90
        );
91
    }
92
93
    /**
94
     * @param ReflectionParameter[] $constructorParameters
95
     */
96
    private function findReflectionParameter(string $name, array $constructorParameters): ReflectionParameter|null
97
    {
98
        foreach ($constructorParameters as $parameter) {
99
            if ($parameter->getName() === $name) {
100
                return $parameter;
101
            }
102
        }
103
        return null;
104
    }
105
106
    public function generate(
107
        GeneratorRequest $request,
108
        CodeFileWriter $codeFileWriter,
109
        CommandHydrator $commandHydrator
110
    ): ResponseInterface {
111
        $generator = $request->getGenerator();
112
        $command = $commandHydrator->hydrate($generator::getCommandClass(), $request->getBody());
113
        $answers = $request->getAnswers();
114
        try {
115
            $files = $generator->generate($command);
116
        } catch (InvalidGeneratorCommandException $e) {
117
            return $this->createErrorResponse($e);
118
        }
119
        $result = $codeFileWriter->write($files, $answers);
120
121
        return $this->responseFactory->createResponse(array_values($result->getResults()));
122
    }
123
124
    public function preview(
125
        GeneratorRequest $request,
126
        CommandHydrator $commandHydrator,
127
        #[Query('file')] ?string $file = null
128
    ): ResponseInterface {
129
        $generator = $request->getGenerator();
130
        $command = $commandHydrator->hydrate($generator::getCommandClass(), $request->getBody());
131
132
        try {
133
            $files = $generator->generate($command);
134
        } catch (InvalidGeneratorCommandException $e) {
135
            return $this->createErrorResponse($e);
136
        }
137
        if ($file === null) {
138
            return $this->responseFactory->createResponse([
139
                'files' => array_map($this->serializeCodeFile(...), array_values($files)),
140
                'operations' => CodeFileWriteOperationEnum::getLabels(),
141
            ]);
142
        }
143
144
        foreach ($files as $generatedFile) {
145
            if ($generatedFile->getId() === $file) {
146
                $content = $generatedFile->preview();
147
                return $this->responseFactory->createResponse(
148
                    ['content' => $content ?: 'Preview is not available for this file type.']
149
                );
150
            }
151
        }
152
153
        return $this->responseFactory->createResponse(
154
            ['message' => "Code file not found: $file"],
155
            Status::UNPROCESSABLE_ENTITY
156
        );
157
    }
158
159
    public function diff(
160
        GeneratorRequest $request,
161
        CommandHydrator $commandHydrator,
162
        #[Query('file')] string $file
163
    ): ResponseInterface {
164
        $generator = $request->getGenerator();
165
        $command = $commandHydrator->hydrate($generator::getCommandClass(), $request->getBody());
166
167
        try {
168
            $files = $generator->generate($command);
169
        } catch (InvalidGeneratorCommandException $e) {
170
            return $this->createErrorResponse($e);
171
        }
172
173
        foreach ($files as $generatedFile) {
174
            if ($generatedFile->getId() === $file) {
175
                return $this->responseFactory->createResponse(['diff' => $generatedFile->diff()]);
176
            }
177
        }
178
        return $this->responseFactory->createResponse(
179
            ['message' => "Code file not found: $file"],
180
            Status::UNPROCESSABLE_ENTITY
181
        );
182
    }
183
184
    private function createErrorResponse(InvalidGeneratorCommandException $e): DataResponse
185
    {
186
        return $this->responseFactory->createResponse(
187
        // TODO: fix
188
            ['errors' => $e->getResult()->getErrorMessagesIndexedByAttribute()],
189
            Status::UNPROCESSABLE_ENTITY
190
        );
191
    }
192
193
    private function serializeCodeFile(CodeFile $file): array
194
    {
195
        return [
196
            'id' => $file->getId(),
197
            'content' => $file->getContent(),
198
            'operation' => $file->getOperation()->value,
199
            'state' => $file->getState()->value,
200
            'path' => $file->getPath(),
201
            'relativePath' => $file->getRelativePath(),
202
            'type' => $file->getType(),
203
            'preview' => $file->preview(),
204
        ];
205
    }
206
}
207