Skip to content

Commit 298ef96

Browse files
committed
generate a SchemaCompiledEvent when Type files are generated
fixes #718
1 parent e0cfa21 commit 298ef96

File tree

5 files changed

+121
-1
lines changed

5 files changed

+121
-1
lines changed

docs/events/index.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,91 @@ class TypeDecorator
186186
}
187187
}
188188
```
189+
190+
Schema Compiled
191+
----------------
192+
193+
*Event:* `Overblog\GraphQLBundle\Event\SchemaCompiledEvent`
194+
195+
Used to modify types before schema registration.
196+
197+
Example:
198+
199+
```php
200+
<?php declare(strict_types=1);
201+
202+
namespace App\Infra\GraphQL\CacheWarmer;
203+
204+
use GraphQL\Utils\SchemaPrinter;
205+
use Overblog\GraphQLBundle\Event\SchemaCompiledEvent;
206+
use Overblog\GraphQLBundle\Request\Executor as RequestExecutor;
207+
use Overblog\GraphQLBundle\Request\ParserInterface;
208+
use Symfony\Component\Console\Event\ConsoleCommandEvent;
209+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
210+
use Symfony\Component\HttpKernel\Event\RequestEvent;
211+
212+
class GraphQLSchemaDumperSubscriber implements EventSubscriberInterface
213+
{
214+
private RequestExecutor $requestExecutor;
215+
216+
private string $projectDir;
217+
218+
private bool $schemaWasRecompiled = false;
219+
220+
public function __construct(RequestExecutor $requestExecutor, string $projectDir)
221+
{
222+
$this->requestExecutor = $requestExecutor;
223+
$this->projectDir = $projectDir;
224+
}
225+
226+
public function onSchemaCompiled(): void
227+
{
228+
$this->schemaWasRecompiled = true;
229+
}
230+
231+
public function dumpSchema(): void
232+
{
233+
if (!$this->schemaWasRecompiled) {
234+
return;
235+
}
236+
237+
file_put_contents(
238+
"{$this->projectDir}/schema.graphql",
239+
SchemaPrinter::doPrint($this->requestExecutor->getSchema()),
240+
) or die("failed to save {$this->projectDir}/schema.graphql");
241+
242+
$result = $this->requestExecutor
243+
->execute(null, [
244+
ParserInterface::PARAM_QUERY => <<<GQL
245+
query {
246+
__schema {
247+
types {
248+
kind
249+
name
250+
possibleTypes {
251+
name
252+
}
253+
}
254+
}
255+
}
256+
GQL,
257+
ParserInterface::PARAM_VARIABLES => [],
258+
])
259+
->toArray();
260+
261+
file_put_contents(
262+
"{$this->projectDir}/schema-fragments.json",
263+
\json_encode($result, \JSON_PRETTY_PRINT),
264+
) or die("failed to save {$this->projectDir}/schema-fragments.json");
265+
}
266+
267+
public static function getSubscribedEvents()
268+
{
269+
return [
270+
SchemaCompiledEvent::class => "onSchemaCompiled",
271+
RequestEvent::class => "dumpSchema",
272+
ConsoleCommandEvent::class => "dumpSchema",
273+
];
274+
}
275+
}
276+
```

src/Event/SchemaCompiledEvent.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Overblog\GraphQLBundle\Event;
6+
7+
use Symfony\Contracts\EventDispatcher\Event;
8+
9+
final class SchemaCompiledEvent extends Event
10+
{
11+
}

src/Generator/TypeGenerator.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
use Composer\Autoload\ClassLoader;
88
use Overblog\GraphQLBundle\Config\Processor;
9+
use Overblog\GraphQLBundle\Event\SchemaCompiledEvent;
910
use Symfony\Component\Filesystem\Filesystem;
11+
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
1012
use function array_merge;
1113
use function file_exists;
1214
use function file_put_contents;
@@ -33,12 +35,14 @@ class TypeGenerator
3335
private ?string $baseCacheDir;
3436
private string $classNamespace;
3537
private TypeBuilder $typeBuilder;
38+
private EventDispatcherInterface $eventDispatcher;
3639

3740
public function __construct(
3841
string $classNamespace,
3942
?string $cacheDir,
4043
array $configs,
4144
TypeBuilder $typeBuilder,
45+
EventDispatcherInterface $eventDispatcher,
4246
bool $useClassMap = true,
4347
?string $baseCacheDir = null,
4448
?int $cacheDirMask = null
@@ -48,6 +52,7 @@ public function __construct(
4852
$this->useClassMap = $useClassMap;
4953
$this->baseCacheDir = $baseCacheDir;
5054
$this->typeBuilder = $typeBuilder;
55+
$this->eventDispatcher = $eventDispatcher;
5156
$this->classNamespace = $classNamespace;
5257

5358
if (null === $cacheDirMask) {
@@ -120,6 +125,8 @@ public function compile(int $mode): array
120125
$this->loadClasses(true);
121126
}
122127

128+
$this->eventDispatcher->dispatch(new SchemaCompiledEvent());
129+
123130
return $classes;
124131
}
125132

src/Resources/config/services.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ services:
6464
- "%overblog_graphql.cache_dir%"
6565
- "%overblog_graphql_types.config%"
6666
- '@Overblog\GraphQLBundle\Generator\TypeBuilder'
67+
- '@Symfony\Contracts\EventDispatcher\EventDispatcherInterface'
6768
- "%overblog_graphql.use_classloader_listener%"
6869
- "%kernel.cache_dir%"
6970
- "%overblog_graphql.cache_dir_permissions%"

tests/Generator/TypeGeneratorTest.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
namespace Overblog\GraphQLBundle\Tests\Generator;
66

77
use Generator;
8+
use Overblog\GraphQLBundle\Event\SchemaCompiledEvent;
89
use Overblog\GraphQLBundle\Generator\TypeBuilder;
910
use PHPUnit\Framework\TestCase;
11+
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
1012

1113
class TypeGeneratorTest extends TestCase
1214
{
@@ -20,14 +22,25 @@ class TypeGeneratorTest extends TestCase
2022
public function testCacheDirPermissions($expectedMask, $cacheDir, $cacheDirMask): void
2123
{
2224
$typeBuilder = $this->createMock(TypeBuilder::class);
25+
$eventDispatcher = $this->createMock(EventDispatcherInterface::class);
2326

2427
$mask = (new TypeGenerator(
25-
'App', $cacheDir, [], $typeBuilder, true, null, $cacheDirMask
28+
'App', $cacheDir, [], $typeBuilder, $eventDispatcher, true, null, $cacheDirMask
2629
))->getCacheDirMask();
2730

2831
$this->assertSame($expectedMask, $mask);
2932
}
3033

34+
public function testCompiledEvent(): void
35+
{
36+
$typeBuilder = $this->createMock(TypeBuilder::class);
37+
$eventDispatcher = $this->getMockBuilder(EventDispatcherInterface::class)->getMock();
38+
39+
$eventDispatcher->expects($this->once())->method('dispatch')->with($this->equalTo(new SchemaCompiledEvent()));
40+
41+
(new TypeGenerator('App', null, [], $typeBuilder, $eventDispatcher))->compile(TypeGenerator::MODE_DRY_RUN);
42+
}
43+
3144
public function getPermissionsProvider(): Generator
3245
{
3346
// default permission when using default cache dir

0 commit comments

Comments
 (0)