Skip to content

Commit 947d4ae

Browse files
authored
Merge pull request #166 from thecodingmachine/6.0
SF 6 support
2 parents 8ebb4dd + 6ddc70d commit 947d4ae

File tree

16 files changed

+81
-91
lines changed

16 files changed

+81
-91
lines changed

.github/workflows/test.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ jobs:
1111
name: test
1212
strategy:
1313
matrix:
14-
install-args: ['', '--prefer-lowest']
15-
php-version: ['7.4', '8.0']
14+
install-args: ['']
15+
php-version: ['8.1']
1616
fail-fast: false
1717
steps:
1818
# Cancel previous runs of the same branch

.travis.yml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,10 @@ matrix:
1717
- php: 8.1
1818
env: PHPSTAN=true COVERAGE=true PHPUNIT_FLAGS="-v --coverage-text"
1919

20-
- php: 8.0
21-
22-
# Test the oldest possible release - SF 5.4, PHP 7.4, without security-bundle
23-
- php: 7.4
24-
env: PHPSTAN=true COMPOSER1=true TESTNOSECURITYBUNDLE=true COMPOSER_FLAGS="--prefer-stable --prefer-lowest"
25-
2620
allow_failures:
2721
# Minimum supported dependencies with the latest and oldest PHP version
2822
- php: 8.1
2923
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" SYMFONY_DEPRECATIONS_HELPER="weak_vendors"
30-
- php: 7.4
31-
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" SYMFONY_DEPRECATIONS_HELPER="weak_vendors"
3224
# Dev-master is allowed to fail.
3325
- env: STABILITY="dev"
3426

@@ -39,10 +31,7 @@ before_install:
3931
- if ! [ -v "$DEPENDENCIES" ]; then composer require --no-update ${DEPENDENCIES}; fi;
4032

4133
install:
42-
# To be removed when this issue will be resolved: https://github.com/composer/composer/issues/5355
43-
- if [[ "$COMPOSER_FLAGS" == *"--prefer-lowest"* ]]; then composer update --prefer-dist --no-interaction --prefer-stable --quiet; fi
4434
- composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction
45-
#- ./vendor/bin/simple-phpunit install
4635

4736
script:
4837
- composer validate --strict --no-check-lock

Command/DumpSchemaCommand.php

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
namespace TheCodingMachine\GraphQLite\Bundle\Command;
66

7-
use GraphQL\Type\Definition\TypeWithFields;
7+
use GraphQL\Type\Schema as TypeSchema;
88
use GraphQL\Utils\SchemaPrinter;
9+
use Symfony\Component\Console\Attribute\AsCommand;
910
use Symfony\Component\Console\Command\Command;
1011
use Symfony\Component\Console\Input\InputInterface;
1112
use Symfony\Component\Console\Input\InputOption;
@@ -16,10 +17,9 @@
1617
/**
1718
* Shamelessly stolen from Api Platform
1819
*/
20+
#[AsCommand('graphqlite:dump-schema')]
1921
class DumpSchemaCommand extends Command
2022
{
21-
protected static $defaultName = 'graphqlite:dump-schema';
22-
2323
/**
2424
* @var Schema
2525
*/
@@ -43,10 +43,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
4343
{
4444
$io = new SymfonyStyle($input, $output);
4545

46-
// Trying to guarantee deterministic order
47-
$this->sortSchema();
48-
49-
$schemaExport = SchemaPrinter::doPrint($this->schema);
46+
$schemaExport = SchemaPrinterForGraphQLite::doPrint($this->schema, ['sortTypes' => true]);
5047

5148
$filename = $input->getOption('output');
5249
if (\is_string($filename)) {
@@ -58,24 +55,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5855

5956
return 0;
6057
}
58+
}
6159

62-
private function sortSchema(): void
63-
{
64-
$config = $this->schema->getConfig();
65-
66-
$refl = new \ReflectionProperty(TypeWithFields::class, 'fields');
67-
$refl->setAccessible(true);
68-
69-
if ($config->query) {
70-
$fields = $config->query->getFields();
71-
ksort($fields);
72-
$refl->setValue($config->query, $fields);
73-
}
60+
class SchemaPrinterForGraphQLite extends SchemaPrinter {
7461

75-
if ($config->mutation) {
76-
$fields = $config->mutation->getFields();
77-
ksort($fields);
78-
$refl->setValue($config->mutation, $fields);
79-
}
62+
protected static function hasDefaultRootOperationTypes(TypeSchema $schema): bool
63+
{
64+
return $schema->getQueryType() === $schema->getType('Query')
65+
&& $schema->getMutationType() === $schema->getType('Mutation')
66+
// Commenting this out because graphqlite cannot map Subscription type
67+
// && $schema->getSubscriptionType() === $schema->getType('Subscription');
68+
;
8069
}
81-
}
70+
}

Controller/GraphQLiteController.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ public function handleRequest(Request $request): Response
7878
if (json_last_error() !== JSON_ERROR_NONE) {
7979
throw new \RuntimeException('Invalid JSON received in POST body: '.json_last_error_msg());
8080
}
81+
if (!is_array($parsedBody)){
82+
throw new \RuntimeException('Expecting associative array from request, got ' . gettype($parsedBody));
83+
}
8184
$psr7Request = $psr7Request->withParsedBody($parsedBody);
8285
}
8386

DependencyInjection/Configuration.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
class Configuration implements ConfigurationInterface
1010
{
11+
/**
12+
* @return TreeBuilder
13+
*/
1114
public function getConfigTreeBuilder()
1215
{
1316
$treeBuilder = new TreeBuilder('graphqlite');

DependencyInjection/GraphQLiteCompilerPass.php

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
1616
use TheCodingMachine\GraphQLite\Mappers\StaticClassListTypeMapperFactory;
1717
use Webmozart\Assert\Assert;
18+
use function assert;
1819
use function class_exists;
1920
use Doctrine\Common\Annotations\AnnotationReader as DoctrineAnnotationReader;
2021
use Doctrine\Common\Annotations\AnnotationRegistry;
@@ -75,18 +76,18 @@ public function process(ContainerBuilder $container): void
7576
{
7677
$reader = $this->getAnnotationReader();
7778
$cacheDir = $container->getParameter('kernel.cache_dir');
78-
Assert::string($cacheDir);
79+
assert(is_string($cacheDir));
7980
$this->cacheDir = $cacheDir;
8081
//$inputTypeUtils = new InputTypeUtils($reader, $namingStrategy);
8182

8283
// Let's scan the whole container and tag the services that belong to the namespace we want to inspect.
8384
$controllersNamespaces = $container->getParameter('graphqlite.namespace.controllers');
84-
Assert::isIterable($controllersNamespaces);
8585
$typesNamespaces = $container->getParameter('graphqlite.namespace.types');
86-
Assert::isIterable($typesNamespaces);
86+
assert(is_iterable($controllersNamespaces));
87+
assert(is_iterable($typesNamespaces));
8788

8889
$firewallName = $container->getParameter('graphqlite.security.firewall_name');
89-
Assert::string($firewallName);
90+
assert(is_string($firewallName));
9091
$firewallConfigServiceName = 'security.firewall.map.config.'.$firewallName;
9192

9293
// 2 seconds of TTL in environment mode. Otherwise, let's cache forever!
@@ -128,7 +129,11 @@ public function process(ContainerBuilder $container): void
128129

129130
if ($disableLogin === false) {
130131
// Let's do some dark magic. We need the user provider. We need its name. It is stored in the "config" object.
131-
$provider = $container->findDefinition('security.firewall.map.config.'.$firewallName)->getArgument(5);
132+
$providerConfigKey = 'security.firewall.map.config.'.$firewallName;
133+
$provider = $container->findDefinition($providerConfigKey)->getArgument(5);
134+
if (!is_string($provider)){
135+
throw new GraphQLException('Expecting to find user provider name from ' . $providerConfigKey);
136+
}
132137

133138
$container->findDefinition(LoginController::class)->setArgument(0, new Reference($provider));
134139

@@ -157,7 +162,7 @@ public function process(ContainerBuilder $container): void
157162
// ServerConfig rules
158163
$serverConfigDefinition = $container->findDefinition(ServerConfig::class);
159164
$rulesDefinition = [];
160-
if ($container->getParameter('graphqlite.security.introspection') === false) {
165+
if ($container->getParameter('graphqlite.security.disableIntrospection')) {
161166
$rulesDefinition[] = $container->findDefinition(DisableIntrospection::class);
162167
}
163168

@@ -191,6 +196,9 @@ public function process(ContainerBuilder $container): void
191196
// Let's register the mapping with UserInterface if UserInterface is available.
192197
if (interface_exists(UserInterface::class)) {
193198
$staticTypes = $container->getDefinition(StaticClassListTypeMapperFactory::class)->getArgument(0);
199+
if (!is_array($staticTypes)){
200+
throw new GraphQLException(sprintf('Expecting array in %s, arg #1', StaticClassListTypeMapperFactory::class));
201+
}
194202
$staticTypes[] = SymfonyUserInterfaceType::class;
195203
$container->getDefinition(StaticClassListTypeMapperFactory::class)->setArgument(0, $staticTypes);
196204
}
@@ -294,6 +302,9 @@ private function registerController(string $controllerClassName, ContainerBuilde
294302
{
295303
$aggregateQueryProvider = $container->findDefinition(AggregateControllerQueryProviderFactory::class);
296304
$controllersList = $aggregateQueryProvider->getArgument(0);
305+
if (!is_array($controllersList)){
306+
throw new GraphQLException(sprintf('Expecting array in %s, arg #1', AggregateControllerQueryProviderFactory::class));
307+
}
297308
$controllersList[] = $controllerClassName;
298309
$aggregateQueryProvider->setArgument(0, $controllersList);
299310
}
@@ -336,7 +347,14 @@ private function makePublicInjectedServices(ReflectionClass $refClass, Annotatio
336347
return $services;
337348
});
338349

350+
if (!is_array($services)){
351+
throw new GraphQLException('An error occurred in compiler pass');
352+
}
353+
339354
foreach ($services as $service) {
355+
if (!is_string($service)){
356+
throw new GraphQLException('expecting string as service');
357+
}
340358
if ($container->hasAlias($service)) {
341359
$container->getAlias($service)->setPublic(true);
342360
} else {

DependencyInjection/GraphQLiteExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ function($namespace): string {
7272
$container->setParameter('graphqlite.namespace.types', $namespaceType);
7373
$container->setParameter('graphqlite.security.enable_login', $enableLogin);
7474
$container->setParameter('graphqlite.security.enable_me', $enableMe);
75-
$container->setParameter('graphqlite.security.introspection', $config['security']['introspection'] ?? true);
75+
$container->setParameter('graphqlite.security.disableIntrospection', !($config['security']['introspection'] ?? true));
7676
$container->setParameter('graphqlite.security.maximum_query_complexity', $config['security']['maximum_query_complexity'] ?? null);
7777
$container->setParameter('graphqlite.security.maximum_query_depth', $config['security']['maximum_query_depth'] ?? null);
7878
$container->setParameter('graphqlite.security.firewall_name', $config['security']['firewall_name'] ?? 'main');

GraphiQL/EndpointResolver.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use Overblog\GraphiQLBundle\Config\GraphiQLControllerEndpoint;
66
use Overblog\GraphiQLBundle\Config\GraphQLEndpoint\GraphQLEndpointInvalidSchemaException;
77
use Symfony\Component\HttpFoundation\RequestStack;
8-
use Webmozart\Assert\Assert;
8+
use function assert;
99

1010
final class EndpointResolver implements GraphiQLControllerEndpoint
1111
{
@@ -19,18 +19,24 @@ public function __construct(RequestStack $requestStack)
1919
$this->requestStack = $requestStack;
2020
}
2121

22+
/**
23+
* @return string
24+
*/
2225
public function getBySchema($name)
2326
{
2427
if ('default' === $name) {
2528
$request = $this->requestStack->getCurrentRequest();
26-
Assert::notNull($request);
29+
assert(!is_null($request));
2730

2831
return $request->getBaseUrl().'/graphql';
2932
}
3033

3134
throw GraphQLEndpointInvalidSchemaException::forSchemaAndResolver($name, self::class);
3235
}
3336

37+
/**
38+
* @return string
39+
*/
3440
public function getDefault()
3541
{
3642
return $this->getBySchema('default');

Mappers/RequestParameter.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,8 @@ class RequestParameter implements ParameterInterface
1515
/**
1616
* @param array<string, mixed> $args
1717
* @param mixed $context
18-
*
19-
* @return mixed
2018
*/
21-
public function resolve(?object $source, array $args, $context, ResolveInfo $info)
19+
public function resolve(?object $source, array $args, $context, ResolveInfo $info): mixed
2220
{
2321
if (!$context instanceof SymfonyRequestContextInterface) {
2422
throw new GraphQLException('Cannot type-hint on a Symfony Request object in your query/mutation/field. The request context must implement SymfonyRequestContextInterface.');

Resources/config/container/graphqlite.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@
7474
</call>
7575
</service>
7676

77-
<service id="GraphQL\Validator\Rules\DisableIntrospection" />
77+
<service id="GraphQL\Validator\Rules\DisableIntrospection">
78+
<argument key="$enabled">%graphqlite.security.disableIntrospection%</argument>
79+
</service>
7880

7981
<service id="GraphQL\Validator\Rules\QueryComplexity" />
8082

0 commit comments

Comments
 (0)