Passed
Push — master ( a0d881...ad9c9b )
by Bruno
09:28
created

Processor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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