Skip to content

Fixes to make CI green #96

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Jun 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
matrix:
install-args: ['', '--prefer-lowest']
php-version: ['7.2', '7.3', '7.4', '8.0']
fail-fast: false
steps:
# Cancel previous runs of the same branch
- name: cancel
Expand All @@ -36,7 +37,7 @@ jobs:
- name: composer-cache
uses: actions/[email protected]
with:
path: ${{ needs.prepare.outputs.composercachedir }}
path: ${{ steps.composercache.outputs.dir }}
key: composer-${{ hashFiles('**/composer.json') }}-${{ matrix.install-args }}
restore-keys: |
composer-${{ hashFiles('**/composer.json') }}-${{ matrix.install-args }}
Expand All @@ -45,12 +46,11 @@ jobs:

- name: composer
run: |
composer check-platform-reqs --no-interaction
composer update ${{ matrix.install-args }} --no-interaction --no-progress --prefer-dist

- name: phpunit
run: |
vendor/bin/phpunit
vendor/bin/simple-phpunit --no-coverage

- name: phpstan-cache
uses: actions/[email protected]
Expand All @@ -66,5 +66,4 @@ jobs:
- name: phpstan
run: |
mkdir -p .phpstan-cache
APP_ENV=dev bin/console cache:clear
vendor/bin/phpstan analyse --no-progress --no-interaction --memory-limit=1G
1 change: 1 addition & 0 deletions Controller/GraphQL/LoginController.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public function login(string $userName, string $password, Request $request): Use

// Fire the login event manually
$event = new InteractiveLoginEvent($request, $token);
// @phpstan-ignore-next-line BC for Symfony4
$this->eventDispatcher->dispatch($event, 'security.interactive_login');

return $user;
Expand Down
10 changes: 4 additions & 6 deletions Controller/GraphqliteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,16 @@ private function handlePsr7Request(ServerRequestInterface $request, Request $sym
return new JsonResponse($result->toArray($this->debug), $httpCodeDecider->decideHttpStatusCode($result));
}
if (is_array($result)) {
$finalResult = array_map(function (ExecutionResult $executionResult) {
$finalResult = array_map(function (ExecutionResult $executionResult): array {
return $executionResult->toArray($this->debug);
}, $result);
// Let's return the highest result.
$statuses = array_map([$httpCodeDecider, 'decideHttpStatusCode'], $result);
$status = empty($statuses) ? 500 : max($statuses);

return new JsonResponse($finalResult, $status);
}
if ($result instanceof Promise) {
throw new RuntimeException('Only SyncPromiseAdapter is supported');
}
/* @phpstan-ignore-next-line */
throw new RuntimeException('Unexpected response from StandardServer::executePsrRequest'); // @codeCoverageIgnore

throw new RuntimeException('Only SyncPromiseAdapter is supported');
}
}
34 changes: 25 additions & 9 deletions DependencyInjection/GraphqliteCompilerPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Symfony\Component\Cache\Psr16Cache;
use TheCodingMachine\GraphQLite\Mappers\StaticClassListTypeMapper;
use TheCodingMachine\GraphQLite\Mappers\StaticClassListTypeMapperFactory;
use Webmozart\Assert\Assert;
use function class_exists;
use Doctrine\Common\Annotations\AnnotationException;
use Doctrine\Common\Annotations\AnnotationReader as DoctrineAnnotationReader;
Expand Down Expand Up @@ -102,14 +103,19 @@ class GraphqliteCompilerPass implements CompilerPassInterface
public function process(ContainerBuilder $container): void
{
$reader = $this->getAnnotationReader();
$this->cacheDir = $container->getParameter('kernel.cache_dir');
$cacheDir = $container->getParameter('kernel.cache_dir');
Assert::string($cacheDir);
$this->cacheDir = $cacheDir;
//$inputTypeUtils = new InputTypeUtils($reader, $namingStrategy);

// Let's scan the whole container and tag the services that belong to the namespace we want to inspect.
$controllersNamespaces = $container->getParameter('graphqlite.namespace.controllers');
Assert::isIterable($controllersNamespaces);
$typesNamespaces = $container->getParameter('graphqlite.namespace.types');
Assert::isIterable($typesNamespaces);

$firewallName = $container->getParameter('graphqlite.security.firewall_name');
Assert::string($firewallName);
$firewallConfigServiceName = 'security.firewall.map.config.'.$firewallName;

// 2 seconds of TTL in environment mode. Otherwise, let's cache forever!
Expand Down Expand Up @@ -183,14 +189,23 @@ public function process(ContainerBuilder $container): void
if ($container->getParameter('graphqlite.security.introspection') === false) {
$rulesDefinition[] = $container->findDefinition(DisableIntrospection::class);
}
if ($container->getParameter('graphqlite.security.maximum_query_complexity')) {
$complexity = (int) $container->getParameter('graphqlite.security.maximum_query_complexity');
$rulesDefinition[] = $container->findDefinition(QueryComplexity::class)->setArgument(0, $complexity);

$complexity = $container->getParameter('graphqlite.security.maximum_query_complexity');
if ($complexity) {
Assert::integerish($complexity);

$rulesDefinition[] = $container->findDefinition(QueryComplexity::class)
->setArgument(0, (int) $complexity);
}
if ($container->getParameter('graphqlite.security.maximum_query_depth')) {
$depth = (int) $container->getParameter('graphqlite.security.maximum_query_depth');
$rulesDefinition[] = $container->findDefinition(QueryDepth::class)->setArgument(0, $depth);

$depth = $container->getParameter('graphqlite.security.maximum_query_depth');
if ($depth) {
Assert::integerish($depth);

$rulesDefinition[] = $container->findDefinition(QueryDepth::class)
->setArgument(0, (int) $depth);
}

$serverConfigDefinition->addMethodCall('setValidationRules', [$rulesDefinition]);

if ($disableMe === false) {
Expand Down Expand Up @@ -333,7 +348,7 @@ private function mapAdderToTag(string $tag, string $methodName, ContainerBuilder
*/
private function makePublicInjectedServices(ReflectionClass $refClass, AnnotationReader $reader, ContainerBuilder $container, bool $isController): void
{
$services = $this->getCodeCache()->get($refClass, function() use ($refClass, $reader, $container, $isController) {
$services = $this->getCodeCache()->get($refClass, function() use ($refClass, $reader, $container, $isController): array {
$services = [];
foreach ($refClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
$field = $reader->getRequestAnnotation($method, Field::class) ?? $reader->getRequestAnnotation($method, Query::class) ?? $reader->getRequestAnnotation($method, Mutation::class);
Expand All @@ -347,6 +362,7 @@ private function makePublicInjectedServices(ReflectionClass $refClass, Annotatio
}
}
}

return $services;
});

Expand Down Expand Up @@ -485,7 +501,7 @@ private function getClassList(string $namespace, int $globTtl = 2, bool $recursi
// 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;
// Does it exists now?
// @phpstan-ignore-next-line Does it exist now?
if (! class_exists($className, false)) {
continue;
}
Expand Down
28 changes: 12 additions & 16 deletions DependencyInjection/GraphqliteExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ public function load(array $configs, ContainerBuilder $container): void
if (!is_array($controllers)) {
$controllers = [ $controllers ];
}
$namespaceController = array_map(function($namespace) { return rtrim($namespace, '\\') . '\\'; }, $controllers);
$namespaceController = array_map(
function($namespace): string {
return rtrim($namespace, '\\') . '\\';
},
$controllers
);
} else {
$namespaceController = [];
}
Expand All @@ -51,7 +56,12 @@ public function load(array $configs, ContainerBuilder $container): void
if (!is_array($types)) {
$types = [ $types ];
}
$namespaceType = array_map(function($namespace) { return rtrim($namespace, '\\') . '\\'; }, $types);
$namespaceType = array_map(
function($namespace): string {
return rtrim($namespace, '\\') . '\\';
},
$types
);
} else {
$namespaceType = [];
}
Expand Down Expand Up @@ -84,20 +94,6 @@ public function load(array $configs, ContainerBuilder $container): void
->addTag('graphql.root_type_mapper_factory');
}

private function getNamespaceDir(string $namespace): string
{
$classNameMapper = ClassNameMapper::createFromComposerFile(null, null, true);

$possibleFileNames = $classNameMapper->getPossibleFileNames($namespace.'Xxx');
if (count($possibleFileNames) > 1) {
throw new \RuntimeException(sprintf('According to your composer.json, classes belonging to the "%s" namespace can be located in several directories: %s. This is an issue for the GraphQLite lib. Please make sure that a namespace can only be resolved to one PHP file.', $namespace, implode(", ", $possibleFileNames)));
} elseif (empty($possibleFileNames)) {
throw new \RuntimeException(sprintf('Files in namespace "%s" cannot be autoloaded by Composer. Please set up a PSR-4 autoloader in Composer or change the namespace configured in "graphqlite.namespace.controllers" and "graphqlite.namespace.types"', $namespace));
}

return substr($possibleFileNames[0], 0, -8);
}

/**
* @param array<string, int> $debug
* @return int
Expand Down
2 changes: 0 additions & 2 deletions DependencyInjection/OverblogGraphiQLEndpointWiringPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace TheCodingMachine\Graphqlite\Bundle\DependencyInjection;

use Overblog\GraphiQLBundle\Config\GraphiQLControllerEndpoint;
use Overblog\GraphiQLBundle\Config\GraphqlEndpoint\RootResolver;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
Expand Down
6 changes: 6 additions & 0 deletions GraphiQL/EndpointResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
namespace TheCodingMachine\Graphqlite\Bundle\GraphiQL;

use Overblog\GraphiQLBundle\Config\GraphiQLControllerEndpoint;
use Overblog\GraphiQLBundle\Config\GraphQLEndpoint\GraphQLEndpointInvalidSchemaException;
use Symfony\Component\HttpFoundation\RequestStack;
use Webmozart\Assert\Assert;

final class EndpointResolver implements GraphiQLControllerEndpoint
{
/**
* @var RequestStack
*/
protected $requestStack;

public function __construct(RequestStack $requestStack)
Expand All @@ -18,6 +23,7 @@ public function getBySchema($name)
{
if ('default' === $name) {
$request = $this->requestStack->getCurrentRequest();
Assert::notNull($request);

return $request->getBaseUrl().'/graphql';
}
Expand Down
5 changes: 3 additions & 2 deletions Mappers/RequestParameterMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\Type;
use ReflectionNamedType;
use ReflectionParameter;
use Symfony\Component\HttpFoundation\Request;
use TheCodingMachine\GraphQLite\Annotations\ParameterAnnotations;
Expand All @@ -15,13 +16,13 @@

class RequestParameterMiddleware implements ParameterMiddlewareInterface
{

public function mapParameter(ReflectionParameter $parameter, DocBlock $docBlock, ?Type $paramTagType, ParameterAnnotations $parameterAnnotations, ParameterHandlerInterface $next): ParameterInterface
{
$parameterType = $parameter->getType();
if ($parameterType && $parameterType->getName() === Request::class) {
if ($parameterType instanceof ReflectionNamedType && $parameterType->getName() === Request::class) {
return new RequestParameter();
}

return $next->mapParameter($parameter, $docBlock, $paramTagType, $parameterAnnotations);
}
}
13 changes: 12 additions & 1 deletion Server/ServerConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
namespace TheCodingMachine\Graphqlite\Bundle\Server;

use GraphQL\Error\InvariantViolation;
use GraphQL\GraphQL;
use GraphQL\Language\AST\DocumentNode;
use GraphQL\Server\OperationParams;
use GraphQL\Utils\Utils;
use GraphQL\Validator\DocumentValidator;
use GraphQL\Validator\Rules\ValidationRule;
Expand All @@ -27,7 +30,15 @@ class ServerConfig extends \GraphQL\Server\ServerConfig
*/
public function setValidationRules($validationRules)
{
parent::setValidationRules(array_merge(DocumentValidator::defaultRules(), $validationRules));
parent::setValidationRules(
function (OperationParams $params, DocumentNode $doc, string $operationType) use ($validationRules): array {
$validationRules = is_callable($validationRules)
? $validationRules($params, $doc, $operationType)
: $validationRules;

return array_merge(DocumentValidator::defaultRules(), $validationRules);
}
);

return $this;
}
Expand Down
3 changes: 3 additions & 0 deletions Tests/FunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,9 @@ private function logIn(ContainerInterface $container)
$container->get('security.token_storage')->setToken($token);
}

/**
* @requires PHP 8.0
*/
public function testPhp8Attributes(): void
{
$kernel = new GraphqliteTestingKernel();
Expand Down
1 change: 1 addition & 0 deletions Tests/NoSecurityBundleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ 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();
self::assertNotNull($container);

$schema = $container->get(Schema::class);
$this->assertInstanceOf(Schema::class, $schema);
Expand Down
30 changes: 27 additions & 3 deletions Types/SymfonyUserInterfaceType.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,36 @@

namespace TheCodingMachine\Graphqlite\Bundle\Types;

use Symfony\Component\Security\Core\Role\Role;
use TheCodingMachine\GraphQLite\Annotations\Field;
use TheCodingMachine\GraphQLite\Annotations\SourceField;
use TheCodingMachine\GraphQLite\Annotations\Type;
use Symfony\Component\Security\Core\User\UserInterface;
use TheCodingMachine\GraphQLite\FieldNotFoundException;

/**
* @Type(class=UserInterface::class)
* @SourceField(name="userName")
*/
class SymfonyUserInterfaceType
{
/**
* @Field
*/
public function getUserName(UserInterface $user): string
{
// @phpstan-ignore-next-line Forward Compatibility for Symfony >=5.3
if (method_exists($user, 'getUserIdentifier')) {
return $user->getUserIdentifier();
}

// @phpstan-ignore-next-line Backward Compatibility for Symfony <5.3
if (method_exists($user, 'getUsername')) {
return $user->getUsername();
}

throw FieldNotFoundException::missingField(UserInterface::class, 'userName');
}

/**
* @Field()
* @return string[]
Expand All @@ -22,8 +41,13 @@ public function getRoles(UserInterface $user): array
{
$roles = [];
foreach ($user->getRoles() as $role) {
$roles[] = (string) $role;
// @phpstan-ignore-next-line BC for Symfony 4
if (class_exists(Role::class) && $role instanceof Role) {
$role = $role->getRole();
}

$roles[] = $role;
}
return $roles;
}
}
}
Loading