Passed
Push — master ( 41a7c0...823f6c )
by Bruno
15:50 queued 07:18
created

Processor::getDirectivesGraphql()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5.0909

Importance

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