Passed
Push — master ( b5e05b...1ff55b )
by Bruno
07:17
created

ModelariumFrontendCommand   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 66
c 5
b 0
f 0
dl 0
loc 150
rs 10
wmc 17

4 Methods

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

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

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

137
        $basepath = /** @scrutinizer ignore-call */ base_path('resources/js/components/');
Loading history...
138
        $writtenFiles = $this->writeFiles(
139
            $collection,
140
            $basepath,
141
            (bool)$this->option('overwrite')
142
        );
143
        $this->info('Files generated.');
144
145
        if ($this->option('prettier')) {
146
            $this->info('Running prettier on generated files.');
147
            $useYarn = file_exists(base_path('yarn.lock'));
148
            if ($useYarn) {
149
                $command = "cd $basepath && npx prettier --write ";
150
            } else {
151
                $command = "cd $basepath && yarn prettier --write ";
152
            }
153
154
            // this runs all prettier commands in parallel.
155
            $run = array_reduce(
156
                $writtenFiles,
157
                function ($carry, $f) use ($command) {
158
                    return $carry . '(' . $command . $f . ') & ';
159
                }
160
            );
161
            shell_exec($run . ' wait');
162
        }
163
    }
164
}
165