diff --git a/composer.json b/composer.json index d3e79e0426..eea76d30ac 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "symfony/expression-language": "^4 || ^5 || ^6 || ^7", "thecodingmachine/cache-utils": "^1", "webonyx/graphql-php": "^v15.0", - "kcs/class-finder": "^0.4.0" + "kcs/class-finder": "^0.5.0" }, "require-dev": { "beberlei/porpaginas": "^1.2 || ^2.0", diff --git a/src/GlobControllerQueryProvider.php b/src/GlobControllerQueryProvider.php index 6fc7e659d1..f7ed17170e 100644 --- a/src/GlobControllerQueryProvider.php +++ b/src/GlobControllerQueryProvider.php @@ -6,7 +6,6 @@ use GraphQL\Type\Definition\FieldDefinition; use InvalidArgumentException; -use Kcs\ClassFinder\Finder\ComposerFinder; use Kcs\ClassFinder\Finder\FinderInterface; use Psr\Container\ContainerInterface; use Psr\SimpleCache\CacheInterface; @@ -33,7 +32,6 @@ final class GlobControllerQueryProvider implements QueryProviderInterface { /** @var array|null */ private array|null $instancesList = null; - private FinderInterface $finder; private AggregateControllerQueryProvider|null $aggregateControllerQueryProvider = null; private CacheContractInterface $cacheContract; @@ -47,11 +45,10 @@ public function __construct( private readonly ContainerInterface $container, private readonly AnnotationReader $annotationReader, private readonly CacheInterface $cache, - FinderInterface|null $finder = null, + private readonly FinderInterface $finder, int|null $cacheTtl = null, ) { - $this->finder = $finder ?? new ComposerFinder(); $this->cacheContract = new Psr16Adapter( $this->cache, str_replace(['\\', '{', '}', '(', ')', '/', '@', ':'], '_', $namespace), diff --git a/src/SchemaFactory.php b/src/SchemaFactory.php index e49f51e8a1..04e4bfa6ba 100644 --- a/src/SchemaFactory.php +++ b/src/SchemaFactory.php @@ -8,6 +8,7 @@ use Doctrine\Common\Annotations\PsrCachedReader; use Doctrine\Common\Annotations\Reader; use GraphQL\Type\SchemaConfig; +use Kcs\ClassFinder\Finder\ComposerFinder; use Kcs\ClassFinder\Finder\FinderInterface; use MyCLabs\Enum\Enum; use PackageVersions\Versions; @@ -343,8 +344,9 @@ public function createSchema(): Schema $cachedDocBlockFactory = new CachedDocBlockFactory($namespacedCache); $namingStrategy = $this->namingStrategy ?: new NamingStrategy(); $typeRegistry = new TypeRegistry(); + $finder = $this->finder ?? new ComposerFinder(); - $namespaceFactory = new NamespaceFactory($namespacedCache, $this->finder, $this->globTTL); + $namespaceFactory = new NamespaceFactory($namespacedCache, $finder, $this->globTTL); $nsList = array_map( static fn (string $namespace) => $namespaceFactory->createNamespace($namespace), $this->typeNamespaces, @@ -493,7 +495,7 @@ public function createSchema(): Schema $this->container, $annotationReader, $namespacedCache, - $this->finder, + $finder, $this->globTTL, ); } diff --git a/src/Utils/Namespaces/NS.php b/src/Utils/Namespaces/NS.php index 262a42494b..f1c51f3a18 100644 --- a/src/Utils/Namespaces/NS.php +++ b/src/Utils/Namespaces/NS.php @@ -79,7 +79,7 @@ public function getClassList(): array $this->classes = []; /** @var class-string $className */ /** @var ReflectionClass $reflector */ - foreach ($this->finder->inNamespace($this->namespace) as $className => $reflector) { + foreach ((clone $this->finder)->inNamespace($this->namespace) as $className => $reflector) { if (! ($reflector instanceof ReflectionClass)) { continue; } diff --git a/src/Utils/Namespaces/NamespaceFactory.php b/src/Utils/Namespaces/NamespaceFactory.php index e4d462cc2a..719c80bb22 100644 --- a/src/Utils/Namespaces/NamespaceFactory.php +++ b/src/Utils/Namespaces/NamespaceFactory.php @@ -4,7 +4,6 @@ namespace TheCodingMachine\GraphQLite\Utils\Namespaces; -use Kcs\ClassFinder\Finder\ComposerFinder; use Kcs\ClassFinder\Finder\FinderInterface; use Psr\SimpleCache\CacheInterface; @@ -15,11 +14,11 @@ */ final class NamespaceFactory { - private FinderInterface $finder; - - public function __construct(private readonly CacheInterface $cache, FinderInterface|null $finder = null, private int|null $globTTL = 2) - { - $this->finder = $finder ?? new ComposerFinder(); + public function __construct( + private readonly CacheInterface $cache, + private readonly FinderInterface $finder, + private int|null $globTTL = 2, + ) { } /** @param string $namespace A PHP namespace */ diff --git a/tests/AbstractQueryProviderTest.php b/tests/AbstractQueryProviderTest.php index 16b6de62d5..04c98fd4c8 100644 --- a/tests/AbstractQueryProviderTest.php +++ b/tests/AbstractQueryProviderTest.php @@ -9,6 +9,7 @@ use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\OutputType; use GraphQL\Type\Definition\Type; +use Kcs\ClassFinder\Finder\ComposerFinder; use phpDocumentor\Reflection\TypeResolver as PhpDocumentorTypeResolver; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; @@ -466,7 +467,7 @@ protected function getNamespaceFactory(): NamespaceFactory $arrayAdapter->setLogger(new ExceptionLogger()); $psr16Cache = new Psr16Cache($arrayAdapter); - $this->namespaceFactory = new NamespaceFactory($psr16Cache); + $this->namespaceFactory = new NamespaceFactory($psr16Cache, new ComposerFinder()); } return $this->namespaceFactory; } diff --git a/tests/Fixtures/BadNamespace/BadlyNamespacedClass.php b/tests/Fixtures/BadNamespace/BadlyNamespacedClass.php deleted file mode 100644 index 258dac6fd5..0000000000 --- a/tests/Fixtures/BadNamespace/BadlyNamespacedClass.php +++ /dev/null @@ -1,8 +0,0 @@ - static function (ContainerInterface $container) { return new Schema($container->get(QueryProviderInterface::class), $container->get(RecursiveTypeMapperInterface::class), $container->get(TypeResolver::class), $container->get(RootTypeMapperInterface::class)); }, + FinderInterface::class => fn () => new ComposerFinder(), QueryProviderInterface::class => static function (ContainerInterface $container) { $queryProvider = new GlobControllerQueryProvider( 'TheCodingMachine\\GraphQLite\\Fixtures\\Integration\\Controllers', @@ -94,6 +97,7 @@ public function createContainer(array $overloadedServices = []): ContainerInterf $container->get(BasicAutoWiringContainer::class), $container->get(AnnotationReader::class), new Psr16Cache(new ArrayAdapter()), + $container->get(FinderInterface::class), ); $queryProvider = new AggregateQueryProvider([ @@ -104,6 +108,7 @@ public function createContainer(array $overloadedServices = []): ContainerInterf $container->get(BasicAutoWiringContainer::class), $container->get(AnnotationReader::class), new Psr16Cache(new ArrayAdapter()), + $container->get(FinderInterface::class), ), ]); @@ -201,7 +206,10 @@ public function createContainer(array $overloadedServices = []): ContainerInterf NamespaceFactory::class => static function (ContainerInterface $container) { $arrayAdapter = new ArrayAdapter(); $arrayAdapter->setLogger(new ExceptionLogger()); - return new NamespaceFactory(new Psr16Cache($arrayAdapter)); + return new NamespaceFactory( + new Psr16Cache($arrayAdapter), + $container->get(FinderInterface::class), + ); }, GlobTypeMapper::class => static function (ContainerInterface $container) { $arrayAdapter = new ArrayAdapter(); diff --git a/website/docs/other-frameworks.mdx b/website/docs/other-frameworks.mdx index 64806bd84a..358e8095fd 100644 --- a/website/docs/other-frameworks.mdx +++ b/website/docs/other-frameworks.mdx @@ -98,6 +98,26 @@ use TheCodingMachine\GraphQLite\Context\Context; $result = GraphQL::executeQuery($schema, $query, null, new Context(), $variableValues); ``` +### Disabling autoloading + +GraphQLite uses `kcs/class-finder` to find all classes that have GraphQLite attributes. By default, it uses +autoloading under the hood. But if you have an older codebase that contains classes with incorrect or missing +namespaces, you may need to use `include_once` instead. To do so, you can overwrite the finder using `setFinder()`: + +```php +use Kcs\ClassFinder\Finder\ComposerFinder; +use TheCodingMachine\GraphQLite\SchemaFactory; + +$factory = new SchemaFactory($cache, $container); +$factory->addControllerNamespace('App\\Controllers\\') + ->addTypeNamespace('App\\') + ->setFinder( + (new ComposerFinder())->useAutoloading(false) + ); + +$schema = $factory->createSchema(); +``` + ## Minimal example The smallest working example using no framework is: