Skip to content

Commit

Permalink
Removing hidden dependency on the security-bundle
Browse files Browse the repository at this point in the history
The Graphqlite bundle would fail to load of the security-bundle was not in the project (because of a hidden dependency on Symfony's UserInterface)
This fixes the issue.

Closes #72
  • Loading branch information
moufmouf committed Jun 8, 2020
1 parent b5fc672 commit 24addda
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 9 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Expand Up @@ -54,6 +54,9 @@ script:
#- ./vendor/bin/simple-phpunit $PHPUNIT_FLAGS
- if [[ $PHPSTAN == true ]]; then composer phpstan; fi
- ./vendor/bin/phpunit
# Let's test without the security bundle
- composer remove --dev symfony/security-bundle
- phpunit Tests/NoSecurityBundleTest.php

after_script:
- ./vendor/bin/php-coveralls -v
10 changes: 10 additions & 0 deletions DependencyInjection/GraphqliteCompilerPass.php
Expand Up @@ -11,6 +11,7 @@
use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
use Symfony\Component\Cache\Psr16Cache;
use TheCodingMachine\GraphQLite\Mappers\StaticClassListTypeMapper;
use function class_exists;
use Doctrine\Common\Annotations\AnnotationException;
use Doctrine\Common\Annotations\AnnotationReader as DoctrineAnnotationReader;
Expand Down Expand Up @@ -43,6 +44,7 @@
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use TheCodingMachine\CacheUtils\ClassBoundCache;
use TheCodingMachine\CacheUtils\ClassBoundCacheContract;
Expand Down Expand Up @@ -76,6 +78,7 @@
use TheCodingMachine\GraphQLite\Types\MutableObjectType;
use TheCodingMachine\GraphQLite\Types\ResolvableInputObjectType;
use function var_dump;
use TheCodingMachine\Graphqlite\Bundle\Types\SymfonyUserInterfaceType;

/**
* Detects controllers and types automatically and tag them.
Expand Down Expand Up @@ -192,6 +195,13 @@ public function process(ContainerBuilder $container): void
$container->removeDefinition(AggregateControllerQueryProviderFactory::class);
}

// Let's register the mapping with UserInterface if UserInterface is available.
if (class_exists(UserInterface::class)) {
$staticTypes = $container->getDefinition(StaticClassListTypeMapper::class)->getArgument(0);
$staticTypes[] = SymfonyUserInterfaceType::class;
$container->getDefinition(StaticClassListTypeMapper::class)->setArgument(0, $staticTypes);
}

foreach ($container->getDefinitions() as $id => $definition) {
if ($definition->isAbstract() || $definition->getClass() === null) {
continue;
Expand Down
1 change: 0 additions & 1 deletion Resources/config/container/graphqlite.xml
Expand Up @@ -107,7 +107,6 @@

<service id="TheCodingMachine\GraphQLite\Mappers\StaticClassListTypeMapperFactory">
<argument type="collection">
<argument>TheCodingMachine\Graphqlite\Bundle\Types\SymfonyUserInterfaceType</argument>
</argument>
<tag name="graphql.type_mapper_factory"/>
</service>
Expand Down
3 changes: 3 additions & 0 deletions Tests/Fixtures/config/services.yaml
Expand Up @@ -17,6 +17,9 @@ services:
resource: '../*'
exclude: '../{Entities}'

TheCodingMachine\Graphqlite\Bundle\Tests\NoSecurityBundleFixtures\:
resource: '../../NoSecurityBundleFixtures/*'

someService:
class: stdClass

Expand Down
40 changes: 32 additions & 8 deletions Tests/GraphqliteTestingKernel.php
Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\Routing\RouteCollectionBuilder;
use TheCodingMachine\Graphqlite\Bundle\GraphqliteBundle;
use Symfony\Component\Security\Core\User\User;
use function class_exists;

class GraphqliteTestingKernel extends Kernel
{
Expand Down Expand Up @@ -50,8 +51,28 @@ class GraphqliteTestingKernel extends Kernel
* @var int|null
*/
private $maximumQueryDepth;
/**
* @var array|string[]
*/
private $controllersNamespace;
/**
* @var array|string[]
*/
private $typesNamespace;

public function __construct(bool $enableSession = true, ?string $enableLogin = null, bool $enableSecurity = true, ?string $enableMe = null, bool $introspection = true, ?int $maximumQueryComplexity = null, ?int $maximumQueryDepth = null)
/**
* @param string[] $controllersNamespace
* @param string[] $typesNamespace
*/
public function __construct(bool $enableSession = true,
?string $enableLogin = null,
bool $enableSecurity = true,
?string $enableMe = null,
bool $introspection = true,
?int $maximumQueryComplexity = null,
?int $maximumQueryDepth = null,
array $controllersNamespace = ['TheCodingMachine\\Graphqlite\\Bundle\\Tests\\Fixtures\\Controller\\'],
array $typesNamespace = ['TheCodingMachine\\Graphqlite\\Bundle\\Tests\\Fixtures\\Types\\', 'TheCodingMachine\\Graphqlite\\Bundle\\Tests\\Fixtures\\Entities\\'])
{
parent::__construct('test', true);
$this->enableSession = $enableSession;
Expand All @@ -61,15 +82,18 @@ public function __construct(bool $enableSession = true, ?string $enableLogin = n
$this->introspection = $introspection;
$this->maximumQueryComplexity = $maximumQueryComplexity;
$this->maximumQueryDepth = $maximumQueryDepth;
$this->controllersNamespace = $controllersNamespace;
$this->typesNamespace = $typesNamespace;
}

public function registerBundles()
{
return [
new FrameworkBundle(),
new SecurityBundle(),
new GraphqliteBundle(),
];
$bundles = [ new FrameworkBundle() ];
if (class_exists(SecurityBundle::class)) {
$bundles[] = new SecurityBundle();
}
$bundles[] = new GraphqliteBundle();
return $bundles;
}

public function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
Expand Down Expand Up @@ -133,8 +157,8 @@ public function configureContainer(ContainerBuilder $c, LoaderInterface $loader)

$graphqliteConf = array(
'namespace' => [
'controllers' => ['TheCodingMachine\\Graphqlite\\Bundle\\Tests\\Fixtures\\Controller\\'],
'types' => ['TheCodingMachine\\Graphqlite\\Bundle\\Tests\\Fixtures\\Types\\', 'TheCodingMachine\\Graphqlite\\Bundle\\Tests\\Fixtures\\Entities\\']
'controllers' => $this->controllersNamespace,
'types' => $this->typesNamespace
],
);

Expand Down
17 changes: 17 additions & 0 deletions Tests/NoSecurityBundleFixtures/Controller/EchoController.php
@@ -0,0 +1,17 @@
<?php


namespace TheCodingMachine\Graphqlite\Bundle\Tests\NoSecurityBundleFixtures\Controller;


use TheCodingMachine\GraphQLite\Annotations\Query;

class EchoController
{
/**
* @Query()
*/
public function echoMsg(string $message): string {
return $message;
}
}
52 changes: 52 additions & 0 deletions Tests/NoSecurityBundleTest.php
@@ -0,0 +1,52 @@
<?php

namespace TheCodingMachine\Graphqlite\Bundle\Tests;

use function json_decode;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use function spl_object_hash;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\User\User;
use TheCodingMachine\Graphqlite\Bundle\Controller\GraphqliteController;
use TheCodingMachine\Graphqlite\Bundle\Security\AuthenticationService;
use TheCodingMachine\GraphQLite\GraphQLRuntimeException as GraphQLException;
use TheCodingMachine\GraphQLite\Schema;
use function var_dump;

/**
* This test class is supposed to work even if the security bundle is not installed in the project.
* It is here to check we don't have hidden dependencies on this bundle and that it remains optional.
*/
class NoSecurityBundleTest extends TestCase
{
public function testServiceWiring(): void
{
$kernel = new GraphqliteTestingKernel(true, null, false, null, true, null, null, ['TheCodingMachine\\Graphqlite\\Bundle\\Tests\\NoSecurityBundleFixtures\\Controller\\']);
$kernel->boot();
$container = $kernel->getContainer();

$schema = $container->get(Schema::class);
$this->assertInstanceOf(Schema::class, $schema);
$schema->assertValid();

$request = Request::create('/graphql', 'GET', ['query' => '
{
echoMsg(message: "Hello world")
}']);

$response = $kernel->handle($request);

$result = json_decode($response->getContent(), true);

$this->assertSame([
'data' => [
'echoMsg' => 'Hello world'
]
], $result);
}
}

0 comments on commit 24addda

Please sign in to comment.