Passed
Push — master ( 05064d...ef0947 )
by Bruno
04:00
created

ModelariumFrontendCommand::generateFromModel()   B

Complexity

Conditions 10
Paths 4

Size

Total Lines 59
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 10
eloc 38
nc 4
nop 1
dl 0
loc 59
rs 7.6666
c 4
b 0
f 0

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\FrameworkComposer;
6
use Formularium\StringUtil;
7
use HaydenPierce\ClassFinder\ClassFinder;
8
use Illuminate\Console\Command;
9
use Modelarium\Parser;
10
use Modelarium\Frontend\FrontendGenerator;
11
use Modelarium\GeneratedItem;
12
use Modelarium\Laravel\Processor as LaravelProcessor;
13
14
use function Modelarium\Laravel\Targets\endsWith;
15
16
class ModelariumFrontendCommand extends Command
17
{
18
    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...delariumFrontendCommand: $filename, $onlyIfNewFile, $contents
Loading history...
19
20
    /**
21
     * The name and signature of the console command.
22
     *
23
     * @var string
24
     */
25
    protected $signature = 'modelarium:frontend
26
        {name : The model name. Use "*" or "all" for all models}
27
        {--framework=* : The frameworks to use}
28
        {--lighthouse : use lighthouse directives}
29
        {--overwrite-graphql : overwrite graphql files if they exist}
30
        {--overwrite-match= : overwrite files that contain this string}
31
        {--overwrite : overwrite all files if they exist}
32
        {--prettier : run prettier on files}
33
    ';
34
35
    /**
36
     * The console command description.
37
     *
38
     * @var string
39
     */
40
    protected $description = 'Creates frontend using Modelarium';
41
42
    /**
43
     * @var string[] List of Frameworks to be passed to the FrameworkComposer
44
     */
45
    protected $frameworks;
46
47
    /**
48
     * @var Parser
49
     */
50
    protected $parser = null;
51
52
    /**
53
     * Create a new command instance.
54
     *
55
     * @return void
56
     */
57
    public function __construct()
58
    {
59
        parent::__construct();
60
    }
61
62
    /**
63
     * Execute the console command.
64
     *
65
     * @return mixed
66
     */
67
    public function handle()
68
    {
69
        $name = $this->argument('name');
70
71
        // setup stuff
72
        // @phpstan-ignore-next-line
73
        $this->frameworks = $this->option('framework');
74
        if (empty($this->frameworks)) {
75
            $this->error('If you are generating frontend you need to specify frameworks. Example: `--framework=HTML --framework=Bootstrap --framework=Vue`');
76
            return;
77
        }
78
        if (!is_array($this->frameworks)) {
0 ignored issues
show
introduced by
The condition is_array($this->frameworks) is always true.
Loading history...
79
            // @phpstan-ignore-next-line
80
            $this->frameworks = [$this->frameworks];
81
        }
82
      
83
        $this->loadParser();
84
        if ($name === '*' || $name === 'all') {
85
            /** @var array<class-string> $classesInNamespace */
86
            $classesInNamespace = ClassFinder::getClassesInNamespace('App\\Models');
87
88
            foreach ($classesInNamespace as $class) {
89
                $reflection = new \ReflectionClass($class);
90
                if (!$reflection->isInstantiable()) {
91
                    continue;
92
                }
93
                $this->generateFromModel($class);
94
            }
95
            return;
96
        } elseif (is_array($name)) {
97
            // TODO
98
        } else {
99
            $this->generateFromModel($name);
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type null; however, parameter $name of Modelarium\Laravel\Conso...nd::generateFromModel() 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

99
            $this->generateFromModel(/** @scrutinizer ignore-type */ $name);
Loading history...
100
        }
101
        $this->info('Finished frontend.');
102
    }
103
104
    protected function loadParser(): void
105
    {
106
        $files = [
107
            __DIR__ . '/../../../Types/Graphql/scalars.graphql'
108
        ];
109
        if ($this->option('lighthouse')) {
110
            $files[] = __DIR__ . '/../../Graphql/definitionsLighthouse.graphql';
111
        }
112
113
        $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

113
        $path = /** @scrutinizer ignore-call */ base_path('graphql');
Loading history...
114
        $dir = \Safe\scandir($path);
115
116
        // parse directives from lighthouse
117
        $modelNames = array_diff($dir, array('.', '..'));
118
        
119
        foreach ($modelNames as $n) {
120
            if (mb_strpos($n, '.graphql') === false) {
121
                continue;
122
            }
123
            $files[] = base_path('graphql/' . $n);
124
        }
125
        $this->parser = new Parser();
126
        $this->parser->setImport('directives.graphql', LaravelProcessor::getDirectivesGraphqlString());
127
        $this->parser->fromFiles($files);
128
    }
129
130
    protected function generateFromModel(string $name): void
131
    {
132
        $composer = FrameworkComposer::create($this->frameworks);
133
        $model = $name::getFormularium();
134
135
        $generator = new FrontendGenerator($composer, $model, $this->parser);
136
        $collection = $generator->generate();
137
    
138
        if (!$collection->count()) {
139
            $this->info('Nothing generated.');
140
            return;
141
        }
142
143
        $basepath = base_path('resources/js/components/');
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

143
        $basepath = /** @scrutinizer ignore-call */ base_path('resources/js/components/');
Loading history...
144
        $writtenFiles = $this->writeFiles(
145
            $collection,
146
            $basepath,
147
            function (GeneratedItem $i) {
148
                if ((bool)$this->option('overwrite') === true) {
149
                    return true;
150
                }
151
                if ((bool)$this->option('overwrite-graphql') === true) {
152
                    if (
153
                        StringUtil::endsWith($i->filename, '.graphql')
154
                    ) {
155
                        return true;
156
                    } elseif (StringUtil::endsWith($i->filename, 'model.js')) {
157
                        return true;
158
                    }
159
                }
160
                if ($this->option('overwrite-match')) {
161
                    if (
162
                        mb_strpos($i->filename, $this->option('overwrite-match')) !== false
163
                    ) {
164
                        return true;
165
                    }
166
                }
167
                return false;
168
            }
169
        );
170
        $this->info('Files generated.');
171
172
        if ($this->option('prettier')) {
173
            $this->info('Running prettier on generated files.');
174
            $useYarn = file_exists(base_path('yarn.lock'));
175
            if ($useYarn) {
176
                $command = "cd $basepath && npx prettier --write ";
177
            } else {
178
                $command = "cd $basepath && yarn prettier --write ";
179
            }
180
181
            // this runs all prettier commands in parallel.
182
            $run = array_reduce(
183
                $writtenFiles,
184
                function ($carry, $f) use ($command) {
185
                    return $carry . '(' . $command . $f . ') & ';
186
                }
187
            );
188
            shell_exec($run . ' wait');
189
        }
190
    }
191
}
192