diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index 94e9a36..1882ae9 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
install-args: ['']
- php-version: ['8.1']
+ php-version: ['8.2']
fail-fast: false
steps:
# Cancel previous runs of the same branch
diff --git a/Tests/Fixtures/Entities/BadClass.php b/Tests/Fixtures/Entities/BadClass.php
deleted file mode 100644
index 7c89188..0000000
--- a/Tests/Fixtures/Entities/BadClass.php
+++ /dev/null
@@ -1,8 +0,0 @@
-=8.1",
"ext-json": "*",
- "thecodingmachine/graphqlite" : "^6.0",
- "thecodingmachine/graphqlite-symfony-validator-bridge" : "^6.0",
+ "thecodingmachine/graphqlite" : "^8",
+ "thecodingmachine/graphqlite-symfony-validator-bridge": "^7.1.1",
"symfony/config": "^6.4 || ^7",
"symfony/console": "^6.4 || ^7",
"symfony/framework-bundle": "^6.4 || ^7",
"symfony/validator": "^6.4 || ^7",
"symfony/translation": "^6.4 || ^7",
- "doctrine/annotations": "^1.13 || ^2.0.1",
"symfony/psr-http-message-bridge": "^2.0 || ^7.0",
"nyholm/psr7": "^1.1",
"laminas/laminas-diactoros": "^2.2.2 || ^3",
@@ -42,21 +41,25 @@
"composer/semver": "^3.4"
},
"conflict": {
- "mouf/classname-mapper": "<1.0.2",
"symfony/event-dispatcher": "<4.3",
"symfony/security-core": "<4.3",
"symfony/routing": "<4.3",
"phpdocumentor/type-resolver": "<1.4"
},
"scripts": {
- "phpstan": "phpstan analyse GraphQLiteBundle.php DependencyInjection/ Controller/ Resources/ Security/ -c phpstan.neon --level=7 --no-progress"
+ "phpstan": "phpstan analyse -c phpstan.neon --level=7 --no-progress"
},
"suggest": {
- "symfony/security-bundle": "To use @Logged or @Right annotations"
+ "symfony/security-bundle": "To use #[Logged] or #[Right] attributes"
},
"autoload" : {
"psr-4" : {
- "TheCodingMachine\\GraphQLite\\Bundle\\" : ""
+ "TheCodingMachine\\GraphQLite\\Bundle\\" : "src"
+ }
+ },
+ "autoload-dev" : {
+ "psr-4" : {
+ "TheCodingMachine\\GraphQLite\\Bundle\\Tests\\" : "tests"
}
},
"extra": {
diff --git a/phpstan.neon b/phpstan.neon
index fe0c558..f4dcf24 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -8,7 +8,7 @@ parameters:
- vendor
- cache
- .phpstan-cache
- - Tests
+ - tests
level: max
polluteScopeWithLoopInitialAssignments: false
polluteScopeWithAlwaysIterableForeach: false
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index cdfcc0f..97d95df 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -16,22 +16,17 @@
-
- ./Tests/
+
+ ./tests/
- ./
+ ./src/
- cache
- build
- ./Resources
- ./Tests
- ./vendor
- ./var
+ ./src/Resources
diff --git a/Command/DumpSchemaCommand.php b/src/Command/DumpSchemaCommand.php
similarity index 100%
rename from Command/DumpSchemaCommand.php
rename to src/Command/DumpSchemaCommand.php
diff --git a/Context/SymfonyGraphQLContext.php b/src/Context/SymfonyGraphQLContext.php
similarity index 100%
rename from Context/SymfonyGraphQLContext.php
rename to src/Context/SymfonyGraphQLContext.php
diff --git a/Context/SymfonyRequestContextInterface.php b/src/Context/SymfonyRequestContextInterface.php
similarity index 100%
rename from Context/SymfonyRequestContextInterface.php
rename to src/Context/SymfonyRequestContextInterface.php
diff --git a/Controller/GraphQL/InvalidUserPasswordException.php b/src/Controller/GraphQL/InvalidUserPasswordException.php
similarity index 87%
rename from Controller/GraphQL/InvalidUserPasswordException.php
rename to src/Controller/GraphQL/InvalidUserPasswordException.php
index 48bdbbc..e409002 100644
--- a/Controller/GraphQL/InvalidUserPasswordException.php
+++ b/src/Controller/GraphQL/InvalidUserPasswordException.php
@@ -10,6 +10,6 @@ class InvalidUserPasswordException extends GraphQLException
{
public static function create(Exception $previous = null): self
{
- return new self('The provided user / password is incorrect.', 401, $previous, 'Security');
+ return new self('The provided user / password is incorrect.', 401, $previous, ['category' => 'Security']);
}
}
diff --git a/Controller/GraphQL/LoginController.php b/src/Controller/GraphQL/LoginController.php
similarity index 97%
rename from Controller/GraphQL/LoginController.php
rename to src/Controller/GraphQL/LoginController.php
index de07ddf..08ed1f2 100644
--- a/Controller/GraphQL/LoginController.php
+++ b/src/Controller/GraphQL/LoginController.php
@@ -54,11 +54,7 @@ public function __construct(UserProviderInterface $userProvider, UserPasswordHas
$this->eventDispatcher = $eventDispatcher;
}
- /**
- * @Mutation()
- *
- * @phpstan-return TUser
- */
+ #[Mutation]
public function login(string $userName, string $password, Request $request): UserInterface
{
try {
@@ -95,9 +91,7 @@ public function login(string $userName, string $password, Request $request): Use
return $user;
}
- /**
- * @Mutation()
- */
+ #[Mutation]
public function logout(Request $request): bool
{
$this->tokenStorage->setToken(null);
diff --git a/Controller/GraphQL/MeController.php b/src/Controller/GraphQL/MeController.php
similarity index 96%
rename from Controller/GraphQL/MeController.php
rename to src/Controller/GraphQL/MeController.php
index 087832a..16c389c 100644
--- a/Controller/GraphQL/MeController.php
+++ b/src/Controller/GraphQL/MeController.php
@@ -18,9 +18,7 @@ public function __construct(TokenStorageInterface $tokenStorage)
$this->tokenStorage = $tokenStorage;
}
- /**
- * @Query()
- */
+ #[Query]
public function me(): ?UserInterface
{
$token = $this->tokenStorage->getToken();
diff --git a/Controller/GraphQLiteController.php b/src/Controller/GraphQLiteController.php
similarity index 100%
rename from Controller/GraphQLiteController.php
rename to src/Controller/GraphQLiteController.php
index 6988566..9ef3d44 100644
--- a/Controller/GraphQLiteController.php
+++ b/src/Controller/GraphQLiteController.php
@@ -4,22 +4,17 @@
namespace TheCodingMachine\GraphQLite\Bundle\Controller;
-use Laminas\Diactoros\ResponseFactory;
-use Laminas\Diactoros\ServerRequestFactory;
-use Laminas\Diactoros\StreamFactory;
-use Laminas\Diactoros\UploadedFileFactory;
-use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
-use TheCodingMachine\GraphQLite\Http\HttpCodeDecider;
-use TheCodingMachine\GraphQLite\Http\HttpCodeDeciderInterface;
-use function array_map;
use GraphQL\Executor\ExecutionResult;
use GraphQL\Server\ServerConfig;
use GraphQL\Server\StandardServer;
use GraphQL\Upload\UploadMiddleware;
-use function class_exists;
-use function json_decode;
+use Laminas\Diactoros\ResponseFactory;
+use Laminas\Diactoros\ServerRequestFactory;
+use Laminas\Diactoros\StreamFactory;
+use Laminas\Diactoros\UploadedFileFactory;
use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;
+use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
@@ -27,6 +22,11 @@
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use TheCodingMachine\GraphQLite\Bundle\Context\SymfonyGraphQLContext;
+use TheCodingMachine\GraphQLite\Http\HttpCodeDecider;
+use TheCodingMachine\GraphQLite\Http\HttpCodeDeciderInterface;
+use function array_map;
+use function class_exists;
+use function json_decode;
/**
* Listens to every single request and forward Graphql requests to Graphql Webonix standardServer.
diff --git a/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php
similarity index 100%
rename from DependencyInjection/Configuration.php
rename to src/DependencyInjection/Configuration.php
diff --git a/DependencyInjection/GraphQLiteCompilerPass.php b/src/DependencyInjection/GraphQLiteCompilerPass.php
similarity index 81%
rename from DependencyInjection/GraphQLiteCompilerPass.php
rename to src/DependencyInjection/GraphQLiteCompilerPass.php
index bee4783..acc29d0 100644
--- a/DependencyInjection/GraphQLiteCompilerPass.php
+++ b/src/DependencyInjection/GraphQLiteCompilerPass.php
@@ -3,36 +3,26 @@
namespace TheCodingMachine\GraphQLite\Bundle\DependencyInjection;
-use Doctrine\Common\Annotations\PsrCachedReader;
+use Generator;
use GraphQL\Server\ServerConfig;
use GraphQL\Validator\Rules\DisableIntrospection;
use GraphQL\Validator\Rules\QueryComplexity;
use GraphQL\Validator\Rules\QueryDepth;
+use Kcs\ClassFinder\Finder\ComposerFinder;
+use Psr\SimpleCache\CacheInterface;
+use ReflectionClass;
+use ReflectionMethod;
use ReflectionNamedType;
+use ReflectionParameter;
use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
use Symfony\Component\Cache\Psr16Cache;
-use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
-use TheCodingMachine\GraphQLite\Mappers\StaticClassListTypeMapperFactory;
-use Webmozart\Assert\Assert;
-use function assert;
-use function class_exists;
-use Doctrine\Common\Annotations\AnnotationReader as DoctrineAnnotationReader;
-use Doctrine\Common\Annotations\AnnotationRegistry;
-use Mouf\Composer\ClassNameMapper;
-use Psr\SimpleCache\CacheInterface;
-use ReflectionParameter;
-use function filter_var;
-use function function_exists;
-use ReflectionClass;
-use ReflectionMethod;
-use function ini_get;
-use function interface_exists;
-use function strpos;
+use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use TheCodingMachine\CacheUtils\ClassBoundCache;
@@ -40,7 +30,6 @@
use TheCodingMachine\CacheUtils\ClassBoundCacheContractInterface;
use TheCodingMachine\CacheUtils\ClassBoundMemoryAdapter;
use TheCodingMachine\CacheUtils\FileBoundCache;
-use TheCodingMachine\ClassExplorer\Glob\GlobClassExplorer;
use TheCodingMachine\GraphQLite\AggregateControllerQueryProviderFactory;
use TheCodingMachine\GraphQLite\AnnotationReader;
use TheCodingMachine\GraphQLite\Annotations\Autowire;
@@ -49,25 +38,32 @@
use TheCodingMachine\GraphQLite\Annotations\Query;
use TheCodingMachine\GraphQLite\Bundle\Controller\GraphQL\LoginController;
use TheCodingMachine\GraphQLite\Bundle\Controller\GraphQL\MeController;
+use TheCodingMachine\GraphQLite\Bundle\Types\SymfonyUserInterfaceType;
use TheCodingMachine\GraphQLite\GraphQLRuntimeException as GraphQLException;
+use TheCodingMachine\GraphQLite\Mappers\StaticClassListTypeMapperFactory;
use TheCodingMachine\GraphQLite\Mappers\StaticTypeMapper;
use TheCodingMachine\GraphQLite\SchemaFactory;
-use TheCodingMachine\GraphQLite\Bundle\Types\SymfonyUserInterfaceType;
+use Webmozart\Assert\Assert;
+use function assert;
+use function class_exists;
+use function filter_var;
+use function ini_get;
+use function interface_exists;
+use function strpos;
/**
* Detects controllers and types automatically and tag them.
*/
class GraphQLiteCompilerPass implements CompilerPassInterface
{
- /**
- * @var AnnotationReader
- */
- private $annotationReader;
+ private ?AnnotationReader $annotationReader = null;
+
+ private string $cacheDir;
+
+ private ?CacheInterface $cache = null;
+
+ private ?ClassBoundCacheContractInterface $codeCache = null;
- /**
- * @var string
- */
- private $cacheDir;
/**
* You can modify the container here before it is dumped to PHP code.
@@ -240,14 +236,14 @@ public function process(ContainerBuilder $container): void
}
foreach ($controllersNamespaces as $controllersNamespace) {
- $schemaFactory->addMethodCall('addControllerNamespace', [ $controllersNamespace ]);
+ $schemaFactory->addMethodCall('addNamespace', [ $controllersNamespace ]);
foreach ($this->getClassList($controllersNamespace) as $className => $refClass) {
$this->makePublicInjectedServices($refClass, $reader, $container, true);
}
}
foreach ($typesNamespaces as $typeNamespace) {
- $schemaFactory->addMethodCall('addTypeNamespace', [ $typeNamespace ]);
+ $schemaFactory->addMethodCall('addNamespace', [ $typeNamespace ]);
foreach ($this->getClassList($typeNamespace) as $className => $refClass) {
$this->makePublicInjectedServices($refClass, $reader, $container, false);
}
@@ -301,19 +297,25 @@ public function process(ContainerBuilder $container): void
private function registerController(string $controllerClassName, ContainerBuilder $container): void
{
$aggregateQueryProvider = $container->findDefinition(AggregateControllerQueryProviderFactory::class);
+
$controllersList = $aggregateQueryProvider->getArgument(0);
if (!is_array($controllersList)){
throw new GraphQLException(sprintf('Expecting array in %s, arg #1', AggregateControllerQueryProviderFactory::class));
}
+
$controllersList[] = $controllerClassName;
$aggregateQueryProvider->setArgument(0, $controllersList);
+
+ $serviceLocatorMap = [];
+ foreach ($controllersList as $controller) {
+ $serviceLocatorMap[$controller] = new Reference($controller);
+ }
+
+ $aggregateQueryProvider->setArgument(1, new ServiceLocatorArgument($serviceLocatorMap));
}
/**
* Register a method call on SchemaFactory for each tagged service, passing the service in parameter.
- *
- * @param string $tag
- * @param string $methodName
*/
private function mapAdderToTag(string $tag, string $methodName, ContainerBuilder $container, Definition $schemaFactory): void
{
@@ -365,39 +367,33 @@ private function makePublicInjectedServices(ReflectionClass $refClass, Annotatio
}
/**
- * @param ReflectionMethod $method
- * @param ContainerBuilder $container
* @return array key = value = service name
*/
private function getListOfInjectedServices(ReflectionMethod $method, ContainerBuilder $container): array
{
+ /** @var array $services */
$services = [];
- /**
- * @var Autowire[] $autowireAnnotations
- */
- $autowireAnnotations = $this->getAnnotationReader()->getMethodAnnotations($method, Autowire::class);
-
$parametersByName = null;
- foreach ($autowireAnnotations as $autowire) {
- $target = $autowire->getTarget();
-
- if ($parametersByName === null) {
- $parametersByName = self::getParametersByName($method);
- }
+ $annotations = $this->getAnnotationReader()->getParameterAnnotationsPerParameter($method->getParameters());
+ foreach ($annotations as $parameterName => $parameterAnnotations) {
+ $parameterAutowireAnnotation = $parameterAnnotations->getAnnotationsByType(Autowire::class);
+ foreach ($parameterAutowireAnnotation as $autowire) {
+ $id = $autowire->getIdentifier();
+ if ($id !== null) {
+ $services[$id] = $id;
+ continue;
+ }
- if (!isset($parametersByName[$target])) {
- throw new GraphQLException('In method '.$method->getDeclaringClass()->getName().'::'.$method->getName().', the @Autowire annotation refers to a non existing parameter named "'.$target.'"');
- }
+ $parametersByName ??= self::getParametersByName($method);
+ if (!isset($parametersByName[$parameterName])) {
+ throw new \LogicException('Should not happen');
+ }
- $id = $autowire->getIdentifier();
- if ($id !== null) {
- $services[$id] = $id;
- } else {
- $parameter = $parametersByName[$target];
+ $parameter = $parametersByName[$parameterName];
$type = $parameter->getType();
- if ($type !== null && $type instanceof ReflectionNamedType) {
+ if ($type instanceof ReflectionNamedType) {
$fqcn = $type->getName();
if ($container->has($fqcn)) {
$services[$fqcn] = $fqcn;
@@ -410,7 +406,6 @@ private function getListOfInjectedServices(ReflectionMethod $method, ContainerBu
}
/**
- * @param ReflectionMethod $method
* @return array
*/
private static function getParametersByName(ReflectionMethod $method): array
@@ -423,33 +418,14 @@ private static function getParametersByName(ReflectionMethod $method): array
}
/**
- * Returns a cached Doctrine annotation reader.
+ * Returns a GraphQLite annotation reader.
* Note: we cannot get the annotation reader service in the container as we are in a compiler pass.
*/
private function getAnnotationReader(): AnnotationReader
{
- if ($this->annotationReader === null) {
- // @phpstan-ignore-next-line "registerLoader exists in doctrine/annotations:v1.x"
- if (method_exists(AnnotationRegistry::class, 'registerLoader')) {
- AnnotationRegistry::registerLoader('class_exists');
- }
-
- $doctrineAnnotationReader = new DoctrineAnnotationReader();
-
- if (ApcuAdapter::isSupported()) {
- $doctrineAnnotationReader = new PsrCachedReader($doctrineAnnotationReader, new ApcuAdapter('graphqlite'), true);
- }
-
- $this->annotationReader = new AnnotationReader($doctrineAnnotationReader, AnnotationReader::LAX_MODE);
- }
- return $this->annotationReader;
+ return $this->annotationReader ??= new AnnotationReader();
}
- /**
- * @var CacheInterface
- */
- private $cache;
-
private function getPsr16Cache(): CacheInterface
{
if ($this->cache === null) {
@@ -459,54 +435,33 @@ private function getPsr16Cache(): CacheInterface
$this->cache = new Psr16Cache(new PhpFilesAdapter('graphqlite_bundle', 0, $this->cacheDir));
}
}
+
return $this->cache;
}
- /**
- * @var ClassBoundCacheContractInterface
- */
- private $codeCache;
-
private function getCodeCache(): ClassBoundCacheContractInterface
{
- if ($this->codeCache === null) {
- $this->codeCache = new ClassBoundCacheContract(new ClassBoundMemoryAdapter(new ClassBoundCache(new FileBoundCache($this->getPsr16Cache()))));
- }
- return $this->codeCache;
+ return $this->codeCache ??= new ClassBoundCacheContract(
+ new ClassBoundMemoryAdapter(new ClassBoundCache(new FileBoundCache($this->getPsr16Cache())))
+ );
}
/**
* Returns the array of globbed classes.
* Only instantiable classes are returned.
*
- * @return array> Key: fully qualified class name
+ * @return Generator, void, void>
*/
- private function getClassList(string $namespace, int $globTtl = 2, bool $recursive = true): array
+ private function getClassList(string $namespace): Generator
{
- $explorer = new GlobClassExplorer($namespace, $this->getPsr16Cache(), $globTtl, ClassNameMapper::createFromComposerFile(null, null, true), $recursive);
- $allClasses = $explorer->getClassMap();
- $classes = [];
- foreach ($allClasses as $className => $phpFile) {
- if (! class_exists($className, false)) {
- // Let's try to load the file if it was not imported yet.
- // We are importing the file manually to avoid triggering the autoloader.
- // The autoloader might trigger errors if the file does not respect PSR-4 or if the
- // Symfony DebugAutoLoader is installed. (see https://github.com/thecodingmachine/graphqlite/issues/216)
- require_once $phpFile;
- // @phpstan-ignore-next-line Does it exist now?
- if (! class_exists($className, false)) {
- continue;
- }
- }
-
- $refClass = new ReflectionClass($className);
- if (! $refClass->isInstantiable()) {
- continue;
- }
- $classes[$className] = $refClass;
+ // dev note: this code will be broken if there's a broken class (which has mismatch in real namespace
+ // with PSR-4 configuration) in the configured namespace
+ // see also: https://github.com/alekitto/class-finder/issues/24#issuecomment-2480847327
+ $finder = new ComposerFinder();
+ foreach ($finder->inNamespace($namespace) as $class) {
+ assert($class instanceof ReflectionClass);
+ yield $class->getName() => $class;
}
-
- return $classes;
}
}
diff --git a/DependencyInjection/GraphQLiteExtension.php b/src/DependencyInjection/GraphQLiteExtension.php
similarity index 97%
rename from DependencyInjection/GraphQLiteExtension.php
rename to src/DependencyInjection/GraphQLiteExtension.php
index 8fa97ce..7142518 100644
--- a/DependencyInjection/GraphQLiteExtension.php
+++ b/src/DependencyInjection/GraphQLiteExtension.php
@@ -5,15 +5,15 @@
use GraphQL\Error\DebugFlag;
-use TheCodingMachine\GraphQLite\Mappers\Root\RootTypeMapperFactoryInterface;
-use function array_map;
use GraphQL\Server\ServerConfig;
use GraphQL\Type\Definition\ObjectType;
-use function rtrim;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
+use TheCodingMachine\GraphQLite\Mappers\Root\RootTypeMapperFactoryInterface;
+use function array_map;
+use function rtrim;
class GraphQLiteExtension extends Extension
{
@@ -43,7 +43,7 @@ public function load(array $configs, ContainerBuilder $container): void
}
$namespaceController = array_map(
function($namespace): string {
- return rtrim($namespace, '\\') . '\\';
+ return rtrim($namespace, '\\');
},
$controllers
);
@@ -57,7 +57,7 @@ function($namespace): string {
}
$namespaceType = array_map(
function($namespace): string {
- return rtrim($namespace, '\\') . '\\';
+ return rtrim($namespace, '\\');
},
$types
);
diff --git a/DependencyInjection/OverblogGraphiQLEndpointWiringPass.php b/src/DependencyInjection/OverblogGraphiQLEndpointWiringPass.php
similarity index 100%
rename from DependencyInjection/OverblogGraphiQLEndpointWiringPass.php
rename to src/DependencyInjection/OverblogGraphiQLEndpointWiringPass.php
diff --git a/GraphQLiteBundle.php b/src/GraphQLiteBundle.php
similarity index 100%
rename from GraphQLiteBundle.php
rename to src/GraphQLiteBundle.php
index b9005ab..95f9c16 100644
--- a/GraphQLiteBundle.php
+++ b/src/GraphQLiteBundle.php
@@ -3,13 +3,13 @@
namespace TheCodingMachine\GraphQLite\Bundle;
-use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
-use TheCodingMachine\GraphQLite\Bundle\DependencyInjection\GraphQLiteExtension;
-use TheCodingMachine\GraphQLite\Bundle\DependencyInjection\OverblogGraphiQLEndpointWiringPass;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use TheCodingMachine\GraphQLite\Bundle\DependencyInjection\GraphQLiteCompilerPass;
+use TheCodingMachine\GraphQLite\Bundle\DependencyInjection\GraphQLiteExtension;
+use TheCodingMachine\GraphQLite\Bundle\DependencyInjection\OverblogGraphiQLEndpointWiringPass;
class GraphQLiteBundle extends Bundle
{
diff --git a/GraphiQL/EndpointResolver.php b/src/GraphiQL/EndpointResolver.php
similarity index 100%
rename from GraphiQL/EndpointResolver.php
rename to src/GraphiQL/EndpointResolver.php
diff --git a/Mappers/RequestParameter.php b/src/Mappers/RequestParameter.php
similarity index 100%
rename from Mappers/RequestParameter.php
rename to src/Mappers/RequestParameter.php
diff --git a/Mappers/RequestParameterMiddleware.php b/src/Mappers/RequestParameterMiddleware.php
similarity index 100%
rename from Mappers/RequestParameterMiddleware.php
rename to src/Mappers/RequestParameterMiddleware.php
diff --git a/Resources/config/container/graphqlite.xml b/src/Resources/config/container/graphqlite.xml
similarity index 95%
rename from Resources/config/container/graphqlite.xml
rename to src/Resources/config/container/graphqlite.xml
index bda653f..545ec0e 100644
--- a/Resources/config/container/graphqlite.xml
+++ b/src/Resources/config/container/graphqlite.xml
@@ -5,10 +5,6 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
-
- LAX_MODE
-
-
@@ -30,19 +26,20 @@
+
-
+
+
+
-
- %graphqlite.annotations.error_mode%
-
+
diff --git a/Resources/config/routes.xml b/src/Resources/config/routes.xml
similarity index 100%
rename from Resources/config/routes.xml
rename to src/Resources/config/routes.xml
diff --git a/Security/AuthenticationService.php b/src/Security/AuthenticationService.php
similarity index 100%
rename from Security/AuthenticationService.php
rename to src/Security/AuthenticationService.php
diff --git a/Security/AuthorizationService.php b/src/Security/AuthorizationService.php
similarity index 100%
rename from Security/AuthorizationService.php
rename to src/Security/AuthorizationService.php
diff --git a/Server/ServerConfig.php b/src/Server/ServerConfig.php
similarity index 100%
rename from Server/ServerConfig.php
rename to src/Server/ServerConfig.php
diff --git a/Types/SymfonyUserInterfaceType.php b/src/Types/SymfonyUserInterfaceType.php
similarity index 93%
rename from Types/SymfonyUserInterfaceType.php
rename to src/Types/SymfonyUserInterfaceType.php
index f895319..26ea2f4 100644
--- a/Types/SymfonyUserInterfaceType.php
+++ b/src/Types/SymfonyUserInterfaceType.php
@@ -9,14 +9,10 @@
use Symfony\Component\Security\Core\User\UserInterface;
use TheCodingMachine\GraphQLite\FieldNotFoundException;
-/**
- * @Type(class=UserInterface::class)
- */
+#[Type(class: UserInterface::class)]
class SymfonyUserInterfaceType
{
- /**
- * @Field
- */
+ #[Field]
public function getUserName(UserInterface $user): string
{
// @phpstan-ignore-next-line Forward Compatibility for Symfony >=5.3
@@ -33,9 +29,9 @@ public function getUserName(UserInterface $user): string
}
/**
- * @Field()
* @return string[]
*/
+ #[Field]
public function getRoles(UserInterface $user): array
{
$roles = [];
diff --git a/Tests/Command/DumpSchemaCommandTest.php b/tests/Command/DumpSchemaCommandTest.php
similarity index 100%
rename from Tests/Command/DumpSchemaCommandTest.php
rename to tests/Command/DumpSchemaCommandTest.php
diff --git a/Tests/Fixtures/Controller/MyException.php b/tests/Fixtures/Controller/MyException.php
similarity index 100%
rename from Tests/Fixtures/Controller/MyException.php
rename to tests/Fixtures/Controller/MyException.php
diff --git a/Tests/Fixtures/Controller/TestGraphqlController.php b/tests/Fixtures/Controller/TestGraphqlController.php
similarity index 70%
rename from Tests/Fixtures/Controller/TestGraphqlController.php
rename to tests/Fixtures/Controller/TestGraphqlController.php
index 17c5ba0..d768e61 100644
--- a/Tests/Fixtures/Controller/TestGraphqlController.php
+++ b/tests/Fixtures/Controller/TestGraphqlController.php
@@ -20,19 +20,16 @@
class TestGraphqlController
{
-
- /**
- * @Query()
- */
+ #[Query]
public function test(string $foo): string
{
return 'echo ' .$foo;
}
/**
- * @Query()
* @return Product[]
*/
+ #[Query]
public function products(): array
{
return [
@@ -40,99 +37,76 @@ public function products(): array
];
}
- /**
- * @Query()
- */
+ #[Query]
public function contact(): Contact
{
return new Contact('Mouf');
}
- /**
- * @Mutation()
- */
+ #[Mutation]
public function saveProduct(Product $product): Product
{
return $product;
}
/**
- * @Query()
* @return Contact[]
*/
+ #[Query]
public function contacts(): ArrayResult
{
return new ArrayResult([new Contact('Mouf')]);
}
- /**
- * @Query()
- * @return string
- */
+ #[Query]
public function triggerException(int $code = 0): string
{
throw new MyException('Boom', $code);
}
- /**
- * @Query()
- * @return string
- */
+ #[Query]
public function triggerAggregateException(): string
{
$exception1 = new GraphQLException('foo', 401);
- $exception2 = new GraphQLException('bar', 404, null, 'MyCat', ['field' => 'baz', 'category' => 'MyCat']);
+ $exception2 = new GraphQLException('bar', 404, null, ['field' => 'baz', 'category' => 'MyCat']);
throw new GraphQLAggregateException([$exception1, $exception2]);
}
- /**
- * @Query()
- * @Logged()
- * @FailWith(null)
- * @return string
- */
+ #[Query]
+ #[Logged]
+ #[FailWith(null)]
public function loggedQuery(): string
{
return 'foo';
}
- /**
- * @Query()
- * @Right("ROLE_ADMIN")
- * @FailWith(null)
- * @return string
- */
+ #[Query]
+ #[Right('ROLE_ADMIN')]
+ #[FailWith(null)]
public function withAdminRight(): string
{
return 'foo';
}
- /**
- * @Query()
- * @Right("ROLE_USER")
- * @FailWith(null)
- * @return string
- */
+ #[Query]
+ #[Right('ROLE_USER')]
+ #[FailWith(null)]
public function withUserRight(): string
{
return 'foo';
}
- /**
- * @Query()
- * @return string
- */
+ #[Query]
public function getUri(Request $request): string
{
return $request->getPathInfo();
}
- /**
- * @Query
- * @Assertion(for="email", constraint=@Assert\Email())
- */
- public function findByMail(string $email = 'a@a.com'): string
- {
+ #[Query]
+ public function findByMail(
+ #[Assertion(constraint: new Assert\Email())]
+ string $email = 'a@a.com'
+ ): string {
return $email;
}
}
diff --git a/Tests/Fixtures/Controller/TestPhp8GraphqlController.php b/tests/Fixtures/Controller/TestPhp8GraphqlController.php
similarity index 100%
rename from Tests/Fixtures/Controller/TestPhp8GraphqlController.php
rename to tests/Fixtures/Controller/TestPhp8GraphqlController.php
diff --git a/Tests/Fixtures/Entities/Contact.php b/tests/Fixtures/Entities/Contact.php
similarity index 59%
rename from Tests/Fixtures/Entities/Contact.php
rename to tests/Fixtures/Entities/Contact.php
index bfbbb5c..fc90f60 100644
--- a/Tests/Fixtures/Entities/Contact.php
+++ b/tests/Fixtures/Entities/Contact.php
@@ -1,18 +1,14 @@
name = $name;
}
- /**
- * @Field(name="name")
- */
+ #[Field(name: 'name')]
public function getName(): string
{
return $this->name;
}
- /**
- * @Field()
- * @Autowire(for="$testService")
- * @Autowire(for="$someService", identifier="someService")
- * @Autowire(for="$someAlias", identifier="someAlias")
- * @return string
- */
- public function injectService(TestGraphqlController $testService = null, stdClass $someService = null, stdClass $someAlias = null): string
- {
+ #[Field]
+ public function injectService(
+ #[Autowire]
+ TestGraphqlController $testService = null,
+ #[Autowire(identifier: 'someService')]
+ stdClass $someService = null,
+ #[Autowire(identifier: 'someAlias')]
+ stdClass $someAlias = null,
+ ): string {
if (!$testService instanceof TestGraphqlController || $someService === null || $someAlias === null) {
return 'KO';
}
+
return 'OK';
}
- /**
- * @Field(prefetchMethod="prefetchData")
- */
+ #[Field(prefetchMethod: 'prefetchData')]
public function injectServicePrefetch($prefetchData): string
{
return $prefetchData;
}
- /**
- * @Autowire(for="$someOtherService", identifier="someOtherService")
- */
- public function prefetchData(iterable $iterable, stdClass $someOtherService = null)
- {
+ public function prefetchData(
+ iterable $iterable,
+ #[Autowire(identifier: 'someOtherService')]
+ stdClass $someOtherService = null,
+ ) {
if ($someOtherService === null) {
return 'KO';
}
return 'OK';
}
- /**
- * @Field()
- */
+ #[Field]
public function getManager(): ?Contact
{
return null;
diff --git a/Tests/Fixtures/Entities/Product.php b/tests/Fixtures/Entities/Product.php
similarity index 99%
rename from Tests/Fixtures/Entities/Product.php
rename to tests/Fixtures/Entities/Product.php
index b77e094..d33194a 100644
--- a/Tests/Fixtures/Entities/Product.php
+++ b/tests/Fixtures/Entities/Product.php
@@ -1,9 +1,7 @@
getName());
diff --git a/Tests/Fixtures/Types/ProductFactory.php b/tests/Fixtures/Types/ProductFactory.php
similarity index 90%
rename from Tests/Fixtures/Types/ProductFactory.php
rename to tests/Fixtures/Types/ProductFactory.php
index c28f853..1e38b91 100644
--- a/Tests/Fixtures/Types/ProductFactory.php
+++ b/tests/Fixtures/Types/ProductFactory.php
@@ -9,10 +9,7 @@
class ProductFactory
{
-
- /**
- * @Factory()
- */
+ #[Factory]
public function buildProduct(string $name, float $price): Product
{
return new Product($name, $price);
diff --git a/Tests/Fixtures/Types/ProductType.php b/tests/Fixtures/Types/ProductType.php
similarity index 79%
rename from Tests/Fixtures/Types/ProductType.php
rename to tests/Fixtures/Types/ProductType.php
index 94e3d8c..2aa3831 100644
--- a/Tests/Fixtures/Types/ProductType.php
+++ b/tests/Fixtures/Types/ProductType.php
@@ -10,16 +10,12 @@
use TheCodingMachine\GraphQLite\Bundle\Tests\Fixtures\Entities\Product;
-/**
- * @Type(class=Product::class)
- * @SourceField(name="name")
- * @SourceField(name="price")
- */
+#[Type(class: Product::class)]
+#[SourceField(name: 'name')]
+#[SourceField(name: 'price')]
class ProductType
{
- /**
- * @Field()
- */
+ #[Field]
public function getSeller(Product $product): ?Contact
{
return null;
diff --git a/Tests/Fixtures/config/services.yaml b/tests/Fixtures/config/services.yaml
similarity index 100%
rename from Tests/Fixtures/config/services.yaml
rename to tests/Fixtures/config/services.yaml
diff --git a/Tests/FunctionalTest.php b/tests/FunctionalTest.php
similarity index 100%
rename from Tests/FunctionalTest.php
rename to tests/FunctionalTest.php
index 896485f..cdc90ed 100644
--- a/Tests/FunctionalTest.php
+++ b/tests/FunctionalTest.php
@@ -2,17 +2,17 @@
namespace TheCodingMachine\GraphQLite\Bundle\Tests;
-use Symfony\Component\Security\Core\User\InMemoryUser;
-use function json_decode;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
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\InMemoryUser;
use TheCodingMachine\GraphQLite\Bundle\Controller\GraphQLiteController;
use TheCodingMachine\GraphQLite\GraphQLRuntimeException as GraphQLException;
use TheCodingMachine\GraphQLite\Schema;
+use function json_decode;
class FunctionalTest extends TestCase
{
diff --git a/Tests/GraphQLiteTestingKernel.php b/tests/GraphQLiteTestingKernel.php
similarity index 92%
rename from Tests/GraphQLiteTestingKernel.php
rename to tests/GraphQLiteTestingKernel.php
index 5ec06d1..c92ad95 100644
--- a/Tests/GraphQLiteTestingKernel.php
+++ b/tests/GraphQLiteTestingKernel.php
@@ -188,7 +188,7 @@ public function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
$container->loadFromExtension('graphqlite', $graphqliteConf);
});
- $confDir = $this->getProjectDir().'/Tests/Fixtures/config';
+ $confDir = $this->getProjectDir().'/tests/Fixtures/config';
$loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
@@ -199,12 +199,19 @@ public function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
// Note: typing is disabled because using different classes in Symfony 4 and 5
protected function configureRoutes(/*RoutingConfigurator*/ $routes)
{
- $routes->import(__DIR__.'/../Resources/config/routes.xml');
+ $routes->import(__DIR__.'/../src/Resources/config/routes.xml');
}
public function getCacheDir(): string
{
- return __DIR__.'/../cache/'.($this->enableSession?'withSession':'withoutSession').$this->enableLogin.($this->enableSecurity?'withSecurity':'withoutSecurity').$this->enableMe.'_'.($this->introspection?'withIntrospection':'withoutIntrospection').'_'.$this->maximumQueryComplexity.'_'.$this->maximumQueryDepth.'_'.md5(serialize($this->controllersNamespace).'_'.md5(serialize($this->typesNamespace)));
+ $prefix = ($this->enableSession?'withSession':'withoutSession')
+ .$this->enableLogin
+ .($this->enableSecurity?'withSecurity':'withoutSecurity')
+ .$this->enableMe
+ .'_'
+ .($this->introspection?'withIntrospection':'withoutIntrospection');
+
+ return __DIR__.'/../cache/'.$prefix.'_'.$this->maximumQueryComplexity.'_'.$this->maximumQueryDepth.'_'.md5(serialize($this->controllersNamespace).'_'.md5(serialize($this->typesNamespace)));
}
public function process(ContainerBuilder $container): void
diff --git a/Tests/NoSecurityBundleFixtures/Controller/EchoController.php b/tests/NoSecurityBundleFixtures/Controller/EchoController.php
similarity index 88%
rename from Tests/NoSecurityBundleFixtures/Controller/EchoController.php
rename to tests/NoSecurityBundleFixtures/Controller/EchoController.php
index 64dfe19..3521ed2 100644
--- a/Tests/NoSecurityBundleFixtures/Controller/EchoController.php
+++ b/tests/NoSecurityBundleFixtures/Controller/EchoController.php
@@ -1,16 +1,12 @@
clear();
+ }
+
$kernel = new GraphQLiteTestingKernel(true, null, false, null, true, null, null, ['TheCodingMachine\\GraphQLite\\Bundle\\Tests\\NoSecurityBundleFixtures\\Controller\\']);
$kernel->boot();
$container = $kernel->getContainer();
- self::assertNotNull($container);
$schema = $container->get(Schema::class);
$this->assertInstanceOf(Schema::class, $schema);