Passed
Push — master ( 749702...63d29a )
by Bruno
06:22 queued 02:05
created

Processor   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 317
Duplicated Lines 0 %

Test Coverage

Coverage 75.24%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 96
c 4
b 0
f 0
dl 0
loc 317
ccs 79
cts 105
cp 0.7524
rs 9.36
wmc 38

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setRunModel() 0 5 1
A getDirectivesGraphql() 0 25 5
A processMutation() 0 13 4
A processFiles() 0 4 1
B processType() 0 34 8
B process() 0 35 9
A setRunMigration() 0 5 1
A setRunEvent() 0 5 1
A getDirectivesGraphqlString() 0 3 1
A setRunSeed() 0 5 1
A processString() 0 4 1
A setRunFactory() 0 5 1
A createSeederClass() 0 9 1
A setRunPolicy() 0 5 1
A processStrings() 0 4 1
1
<?php declare(strict_types=1);
2
3
namespace Modelarium\Laravel;
4
5
use GraphQL\Type\Definition\ObjectType;
6
use GraphQL\Type\Definition\Type;
7
use HaydenPierce\ClassFinder\ClassFinder;
8
use Modelarium\Exception\Exception;
9
use Modelarium\GeneratedCollection;
10
use Modelarium\GeneratedItem;
11
use Modelarium\Laravel\Targets\EventGenerator;
12
use Modelarium\Laravel\Targets\FactoryGenerator;
13
use Modelarium\Laravel\Targets\MigrationGenerator;
14
use Modelarium\Laravel\Targets\ModelGenerator;
15
use Modelarium\Laravel\Targets\PolicyGenerator;
16
use Modelarium\Laravel\Targets\SeedGenerator;
17
use Modelarium\Parser;
18
use Modelarium\Processor as ModelariumProcessor;
19
use Nette\PhpGenerator\ClassType;
20
use Nuwave\Lighthouse\Schema\Factories\DirectiveFactory;
21
22
use function Safe\class_implements;
23
24
class Processor extends ModelariumProcessor
25
{
26
    /**
27
     * @var Parser
28
     */
29
    protected $parser = null;
30
31
    /**
32
     * @var bool
33
     */
34
    protected $runMigration = true;
35
36
    /**
37
     * @var bool
38
     */
39
    protected $runSeed = true;
40
41
    /**
42
     * @var bool
43
     */
44
    protected $runFactory = true;
45
46
    /**
47
     * @var bool
48
     */
49
    protected $runModel = true;
50
51
    /**
52
     * @var bool
53
     */
54
    protected $runPolicy = true;
55
56
    /**
57
     * @var bool
58
     */
59
    protected $runEvent = true;
60
61
    /**
62
     * DatabaseSeeder class for Laravel
63
     *
64
     * @var ClassType
65
     */
66
    protected $seederClass = null;
67
68 8
    public function __construct()
69
    {
70 8
        $this->parser = new Parser();
71 8
        $this->parser->setImport('directives.graphql', self::getDirectivesGraphqlString());
72 8
    }
73
74
    /**
75
     * Scan the given namespaces for directive classes.
76
     *
77
     * @param  string[]  $directiveNamespaces
78
     * @return array<string, string>
79
     */
80 8
    public static function getDirectivesGraphql($directiveNamespaces = [ 'Modelarium\Laravel\Lighthouse\Directives' ]): array
81
    {
82 8
        $directives = [];
83
84 8
        foreach ($directiveNamespaces as $directiveNamespace) {
85
            /** @var array<class-string> $classesInNamespace */
86 8
            $classesInNamespace = ClassFinder::getClassesInNamespace($directiveNamespace);
87
88 8
            foreach ($classesInNamespace as $class) {
89 8
                $reflection = new \ReflectionClass($class);
90 8
                if (! $reflection->isInstantiable()) {
91
                    continue;
92
                }
93
94 8
                if (! is_a($class, \Nuwave\Lighthouse\Schema\Directives\BaseDirective::class, true)) {
95
                    continue;
96
                }
97
                
98 8
                $name = DirectiveFactory::directiveName((string)$class);
99
                // @phpstan-ignore-next-line
100 8
                $directives[$name] = trim($class::definition());
101
            }
102
        }
103
104 8
        return $directives;
105
    }
106
107
    /**
108
     * Scan the given namespaces for directive classes.
109
     *
110
     * @param  string[]  $directiveNamespaces
111
     * @return string
112
     */
113 8
    public static function getDirectivesGraphqlString($directiveNamespaces = [ 'Modelarium\\Laravel\\Lighthouse\\Directives' ]): string
114
    {
115 8
        return implode("\n\n", self::getDirectivesGraphql($directiveNamespaces));
116
    }
117
118
    /**
119
     *
120
     * @param string[] $files
121
     * @return GeneratedCollection
122
     */
123
    public function processFiles(array $files): GeneratedCollection
124
    {
125
        $this->parser->fromFiles($files);
126
        return $this->process();
127
    }
128
129
    /**
130
     *
131
     * @param string $data
132
     * @return GeneratedCollection
133
     */
134 7
    public function processString(string $data): GeneratedCollection
135
    {
136 7
        $this->parser->fromString($data);
137 7
        return $this->process();
138
    }
139
140
    /**
141
     *
142
     * @param string[] $data
143
     * @return GeneratedCollection
144
     */
145 1
    public function processStrings(array $data): GeneratedCollection
146
    {
147 1
        $this->parser->fromStrings($data);
148 1
        return $this->process();
149
    }
150
151
    /**
152
     *
153
     * @return GeneratedCollection
154
     */
155 8
    public function process(): GeneratedCollection
156
    {
157 8
        $schema = $this->parser->getSchema();
158 8
        $typeMap = $schema->getTypeMap();
159
160 8
        $this->collection = new GeneratedCollection();
161 8
        if ($this->runSeed) {
162 8
            $this->createSeederClass();
163
        }
164
165 8
        foreach ($typeMap as $name => $object) {
166 8
            if ($object instanceof ObjectType) {
167 8
                if ($name === 'Query' || $name === 'Mutation' || $name === 'Subscription' || $name === 'Can') {
168 1
                    continue;
169
                }
170 8
                $g = $this->processType((string)$name, $object);
171 8
                $this->collection = $this->collection->merge($g);
172
            }
173
        }
174
175 8
        $this->collection = $this->collection->merge($this->processMutation($schema->getMutationType()));
176
177 8
        if ($this->runSeed) {
178 8
            $printer = new \Nette\PhpGenerator\PsrPrinter;
179 8
            $seeder = "<?php\n\n" . $printer->printClass($this->seederClass);
180 8
            $this->collection->add(
181 8
                new GeneratedItem(
182 8
                    GeneratedItem::TYPE_SEED,
183
                    $seeder,
184 8
                    SeedGenerator::getBasePath('database/seeds/DatabaseSeeder.php')
185
                )
186
            );
187
        }
188
189 8
        return $this->collection;
190
    }
191
192 8
    protected function processType(string $name, ObjectType $object): GeneratedCollection
193
    {
194 8
        $collection = new GeneratedCollection();
195 8
        if (str_starts_with($name, '__')) {
196
            // internal type
197 8
            return $collection;
198
        }
199
200
        // @typeSkip
201 8
        $directives = $object->astNode->directives;
202 8
        foreach ($directives as $directive) {
203
            $dName = $directive->name->value;
204
            if ($dName === 'typeSkip') {
205
                return $collection;
206
            }
207
        }
208
209 8
        if ($this->runMigration) {
210 8
            $collection = $collection->merge((new MigrationGenerator($this->parser, $name, $object))->generate());
211
        }
212 8
        if ($this->runSeed) {
213 8
            $generator = new SeedGenerator($this->parser, $name, $object);
214 8
            $collection = $collection->merge($generator->generate());
215
216 8
            $this->seederClass->getMethod('run')
217 8
                ->addBody('$this->call(' . $generator->getStudlyName() . 'Seeder::class);');
218
        }
219 8
        if ($this->runFactory) {
220 8
            $collection = $collection->merge((new FactoryGenerator($this->parser, $name, $object))->generate());
221
        }
222 8
        if ($this->runModel) {
223 8
            $collection = $collection->merge((new ModelGenerator($this->parser, $name, $object))->generate());
224
        }
225 8
        return $collection;
226
    }
227
228 8
    protected function processMutation(?Type $object):  GeneratedCollection
229
    {
230 8
        $collection = new GeneratedCollection();
231 8
        if (!$object) {
232 7
            return $collection;
233
        }
234 1
        if ($this->runPolicy) {
235 1
            $collection = $collection->merge((new PolicyGenerator($this->parser, 'Mutation', $object))->generate());
236
        }
237 1
        if ($this->runEvent) {
238 1
            $collection = $collection->merge((new EventGenerator($this->parser, 'Mutation', $object))->generate());
239
        }
240 1
        return $collection;
241
    }
242
243
    /**
244
     * Generates the DatabaseSeeder class.
245
     *
246
     * @return void
247
     */
248 8
    protected function createSeederClass(): void
249
    {
250 8
        $this->seederClass = new \Nette\PhpGenerator\ClassType('DatabaseSeeder');
251 8
        $this->seederClass->setExtends('Illuminate\Database\Seeder')
252 8
            ->addComment("This file was automatically generated by Modelarium.");
253
254 8
        $this->seederClass->addMethod('run')
255 8
                ->setPublic()
256 8
                ->addComment("Seed the application\'s database.\n@return void");
257 8
    }
258
259
    /**
260
     * Set the value of runMigration
261
     *
262
     * @param  bool  $runMigration
263
     *
264
     * @return  self
265
     */
266
    public function setRunMigration(bool $runMigration): self
267
    {
268
        $this->runMigration = $runMigration;
269
270
        return $this;
271
    }
272
273
    /**
274
     * Set the value of runSeed
275
     *
276
     * @param  bool  $runSeed
277
     *
278
     * @return  self
279
     */
280
    public function setRunSeed(bool $runSeed): self
281
    {
282
        $this->runSeed = $runSeed;
283
284
        return $this;
285
    }
286
287
    /**
288
     * Set the value of runFactory
289
     *
290
     * @param  bool  $runFactory
291
     *
292
     * @return  self
293
     */
294
    public function setRunFactory(bool $runFactory): self
295
    {
296
        $this->runFactory = $runFactory;
297
298
        return $this;
299
    }
300
301
    /**
302
     * Set the value of runModel
303
     *
304
     * @param  bool  $runModel
305
     *
306
     * @return  self
307
     */
308
    public function setRunModel(bool $runModel): self
309
    {
310
        $this->runModel = $runModel;
311
312
        return $this;
313
    }
314
315
    /**
316
     * Set the value of runPolicy
317
     *
318
     * @param  bool  $runPolicy
319
     *
320
     * @return  self
321
     */
322
    public function setRunPolicy(bool $runPolicy): self
323
    {
324
        $this->runPolicy = $runPolicy;
325
326
        return $this;
327
    }
328
329
    /**
330
     * Set the value of runEvent
331
     *
332
     * @param  bool  $runEvent
333
     *
334
     * @return  self
335
     */
336
    public function setRunEvent(bool $runEvent): self
337
    {
338
        $this->runEvent = $runEvent;
339
340
        return $this;
341
    }
342
}
343