ModelariumCodeCommand::generateFromModel()   C
last analyzed

Complexity

Conditions 13
Paths 41

Size

Total Lines 91
Code Lines 58

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 13
eloc 58
c 3
b 0
f 0
nc 41
nop 1
dl 0
loc 91
rs 6.6166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types=1);
2
3
namespace Modelarium\Laravel\Console\Commands;
4
5
use Formularium\Factory\CodeGeneratorFactory;
6
use HaydenPierce\ClassFinder\ClassFinder;
7
use Illuminate\Console\Command;
8
use Modelarium\Parser;
9
use Modelarium\GeneratedCollection;
10
use Modelarium\GeneratedItem;
11
use Modelarium\Laravel\Processor as LaravelProcessor;
12
use Modelarium\Options;
13
14
class ModelariumCodeCommand extends Command
15
{
16
    use WriterTrait;
0 ignored issues
show
introduced by
The trait Modelarium\Laravel\Console\Commands\WriterTrait requires some properties which are not provided by Modelarium\Laravel\Conso...s\ModelariumCodeCommand: $filename, $onlyIfNewFile, $contents
Loading history...
17
18
    /**
19
     * The name and signature of the console command.
20
     *
21
     * @var string
22
     */
23
    protected $signature = 'modelarium:code
24
        {name : The model name. Use "*" or "all" for all models}
25
        {--generator= : The generators to use [SQL, GraphQL, Typescript]}
26
        {--path= : The output directory. Defaults to `resources/{generator}/`}
27
        {--lighthouse : use lighthouse directives}
28
        {--overwrite : overwrite all files if they exist}
29
        {--prettier : run prettier on files}
30
        {--eslint : run eslint fix on files}
31
    ';
32
33
    /**
34
     * The console command description.
35
     *
36
     * @var string
37
     */
38
    protected $description = 'Generates code using Modelarium';
39
40
    /**
41
     * @var string CodeGenerator
42
     */
43
    protected $generatorName = "";
44
45
    /**
46
     * @var Parser
47
     */
48
    protected $parser = null;
49
50
    /**
51
     * @var Options
52
     */
53
    protected $modelariumOptions = null;
54
55
    /**
56
     * Create a new command instance.
57
     *
58
     * @return void
59
     */
60
    public function __construct()
61
    {
62
        parent::__construct();
63
64
        // read from Options()
65
        $this->modelariumOptions = new Options();
66
    }
67
68
    /**
69
     * Execute the console command.
70
     *
71
     * @return mixed
72
     */
73
    public function handle()
74
    {
75
        $name = $this->argument('name');
76
77
        // setup stuff
78
        $generatorName = $this->option('generator');
79
        if (!is_string($this->generatorName)) {
0 ignored issues
show
introduced by
The condition is_string($this->generatorName) is always true.
Loading history...
80
            $this->error('Please specify a single generator.');
81
            return;
82
        }
83
        if (empty($this->generatorName)) {
84
            $this->error('Which code format to generate. Example: `--generator=TypeScript`');
85
            return;
86
        }
87
        /**
88
         * @var string $generatorName
89
         */
90
        $this->generatorName = (string)$generatorName;
91
92
        $this->loadParser();
93
        if ($name === '*' || $name === 'all') {
94
            /** @var array<class-string> $classesInNamespace */
95
            $classesInNamespace = ClassFinder::getClassesInNamespace('App\\Models');
96
97
            foreach ($classesInNamespace as $class) {
98
                $reflection = new \ReflectionClass($class);
99
                if (!$reflection->isInstantiable()) {
100
                    continue;
101
                }
102
                $this->generateFromModel($class);
103
            }
104
            return;
105
        } elseif (is_array($name)) {
106
            // TODO
107
        } else {
108
            $this->generateFromModel('\\App\\Models\\' . $name);
109
        }
110
        $this->info('Finished frontend.');
111
    }
112
113
    protected function loadParser(): void
114
    {
115
        $files = [
116
            __DIR__ . '/../../../Types/Graphql/scalars.graphql'
117
        ];
118
        if ($this->option('lighthouse') || $this->modelariumOptions->getOption('modelarium', 'lighthouse')) {
119
            $files[] = __DIR__ . '/../../Graphql/definitionsLighthouse.graphql';
120
        }
121
122
        $path = base_path('graphql');
0 ignored issues
show
Bug introduced by
The function base_path was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

122
        $path = /** @scrutinizer ignore-call */ base_path('graphql');
Loading history...
123
        $dir = \Safe\scandir($path);
124
125
        // parse directives from lighthouse
126
        $modelNames = array_diff($dir, array('.', '..'));
127
128
        foreach ($modelNames as $n) {
129
            if (mb_strpos($n, '.graphql') === false) {
130
                continue;
131
            }
132
            $files[] = base_path('graphql/' . $n);
133
        }
134
        $this->parser = new Parser();
135
        $this->parser->setImport('directives.graphql', LaravelProcessor::getDirectivesGraphqlString());
136
        $this->parser->fromFiles($files);
137
    }
138
139
    protected function generateFromModel(string $name): void
140
    {
141
        $generator = CodeGeneratorFactory::factory($this->generatorName);
142
        $model = $name::getFormularium();
143
        $this->info("Starting $name...");
144
145
        $code = $generator->type($model);
146
147
        if (!$code) {
148
            $this->info('Nothing generated.');
149
            return;
150
        }
151
152
        $basepath = $this->option('path') ?: base_path('resources/' . $generator->getName());
0 ignored issues
show
Bug introduced by
The function base_path was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

152
        $basepath = $this->option('path') ?: /** @scrutinizer ignore-call */ base_path('resources/' . $generator->getName());
Loading history...
153
        if (!is_dir($basepath)) {
154
            \Safe\mkdir($basepath, 0777, true);
155
        }
156
157
        $collection = new GeneratedCollection();
158
        $collection->push(
159
            new GeneratedItem(
160
                GeneratedItem::TYPE_FRONTEND,
161
                $code,
162
                $generator->getFilename($model->getName())
163
            )
164
        );
165
166
        $datatypeDeclarations = $generator->datatypeDeclarations();
167
        if ($datatypeDeclarations) {
168
            $collection->push(
169
                new GeneratedItem(
170
                    GeneratedItem::TYPE_FRONTEND,
171
                    $datatypeDeclarations,
172
                    $generator->getFilename('Scalars')
173
                )
174
            );
175
        }
176
177
        if (!$collection->count()) {
178
            $this->info('Nothing generated.');
179
            return;
180
        }
181
182
        $writtenFiles = $this->writeFiles(
183
            $collection,
184
            $basepath,
185
            function (GeneratedItem $i) {
0 ignored issues
show
Unused Code introduced by
The parameter $i is not used and could be removed. ( Ignorable by Annotation )

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

185
            function (/** @scrutinizer ignore-unused */ GeneratedItem $i) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
186
                if ((bool)$this->option('overwrite') === true) {
187
                    return true;
188
                }
189
                return false;
190
            }
191
        );
192
        $this->info('Files generated.');
193
194
        if ($this->option('prettier') !== null ?: $this->modelariumOptions->getOption('frontend', 'prettier')) {
0 ignored issues
show
introduced by
The condition $this->option('prettier') !== null is always true.
Loading history...
195
            $this->info('Running prettier on generated files.');
196
            $useYarn = file_exists(base_path('yarn.lock'));
197
            if ($useYarn) {
198
                $command = "cd $basepath && npx prettier --write ";
199
            } else {
200
                $command = "cd $basepath && yarn prettier --write ";
201
            }
202
203
            // this runs all prettier commands in parallel.
204
            $run = array_reduce(
205
                $writtenFiles,
206
                function ($carry, $f) use ($command) {
207
                    return $carry . '(' . $command . $f . ') & ';
208
                }
209
            );
210
            shell_exec($run . ' wait');
211
        }
212
213
        if ($this->option('eslint') !== null ?: $this->modelariumOptions->getOption('frontend', 'eslint')) {
0 ignored issues
show
introduced by
The condition $this->option('eslint') !== null is always true.
Loading history...
214
            $this->info('Running eslint on generated files.');
215
            $useYarn = file_exists(base_path('yarn.lock'));
216
            if ($useYarn) {
217
                $command = "cd $basepath && npx eslint --fix ";
218
            } else {
219
                $command = "cd $basepath && yarn eslint --fix ";
220
            }
221
222
            // this runs all prettier commands in parallel.
223
            $run = array_reduce(
224
                $writtenFiles,
225
                function ($carry, $f) use ($command) {
226
                    return $carry . '(' . $command . $f . ') & ';
227
                }
228
            );
229
            shell_exec($run . ' wait');
230
        }
231
    }
232
}
233