Skip to content

Commit 7746a77

Browse files
committed
Merge branch 'master' of github.com:grynchuk/graphqlite into fix-prefetch-in-batch-requests
2 parents dbeb874 + 9898bd9 commit 7746a77

File tree

163 files changed

+4624
-2002
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

163 files changed

+4624
-2002
lines changed

.github/workflows/continuous_integration.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ jobs:
1818
strategy:
1919
matrix:
2020
install-args: ['', '--prefer-lowest']
21-
php-version: ['8.1', '8.2']
21+
php-version: ['8.1', '8.2', '8.3']
2222
fail-fast: false
2323

2424
steps:
2525
# Cancel previous runs of the same branch
2626
- name: cancel
27-
uses: styfle/cancel-workflow-action@0.10.1
27+
uses: styfle/cancel-workflow-action@0.12.1
2828
with:
2929
access_token: ${{ github.token }}
3030

3131
- name: "Checkout"
32-
uses: "actions/checkout@v3"
32+
uses: "actions/checkout@v4"
3333

3434
- name: "Install PHP with extensions"
3535
uses: "shivammathur/setup-php@v2"
@@ -44,7 +44,7 @@ jobs:
4444
echo "::set-output name=dir::$(composer config cache-files-dir)"
4545
4646
- name: composer-cache
47-
uses: actions/cache@v3
47+
uses: actions/cache@v4
4848
with:
4949
path: ${{ steps.composercache.outputs.dir }}
5050
key: composer-${{ hashFiles('**/composer.json') }}-${{ matrix.install-args }}
@@ -61,7 +61,7 @@ jobs:
6161
run: "vendor/bin/phpunit"
6262

6363
- name: phpstan-cache
64-
uses: actions/cache@v3
64+
uses: actions/cache@v4
6565
with:
6666
key: phpstan-${{ matrix.php-version }}-${{ matrix.install-args }}-${{ github.ref }}-${{ github.sha }}
6767
path: .phpstan-cache
@@ -76,16 +76,16 @@ jobs:
7676

7777
- name: "Run coding standard checks with squizlabs/php_codesniffer"
7878
run: "composer cs-check"
79-
if: ${{ matrix.php-version == '7.2' }} # Do not suggest using features after 7.2
8079

8180
- name: "Archive code coverage results"
82-
uses: actions/upload-artifact@v3
81+
uses: actions/upload-artifact@v4
8382
with:
8483
name: "codeCoverage"
8584
path: "build"
85+
overwrite: true
8686

87-
- uses: codecov/codecov-action@v3.1.4 # upload the coverage to codecov
87+
- uses: codecov/codecov-action@v4.0.1 # upload the coverage to codecov
8888
with:
89-
fail_ci_if_error: true # optional (default = false)
90-
# Do not upload in forks, and only on php8, latest deps
91-
if: ${{ github.repository == 'thecodingmachine/graphqlite' && matrix.php-version == '8.0' && matrix.install-args == '' }}
89+
fail_ci_if_error: false # optional (default = false) - Need CODECOV_TOKEN
90+
# Do not upload in forks, and only on php8.3, latest deps
91+
if: ${{ github.repository == 'thecodingmachine/graphqlite' && matrix.php-version == '8.3' && matrix.install-args == '' }}

.github/workflows/doc_generation.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ jobs:
1919
steps:
2020

2121
- name: "Checkout"
22-
uses: "actions/checkout@v3"
22+
uses: "actions/checkout@v4"
2323

2424
- name: "Setup NodeJS"
25-
uses: actions/setup-node@v3
25+
uses: actions/setup-node@v4
2626
with:
2727
node-version: '16.x'
2828

@@ -36,7 +36,7 @@ jobs:
3636

3737
- name: "Deploy website"
3838
if: "${{ github.event_name == 'push' || github.event_name == 'release' }}"
39-
uses: JamesIves/github-pages-deploy-action@v4.4.2
39+
uses: JamesIves/github-pages-deploy-action@v4.5.0
4040
with:
4141
token: ${{ secrets.GITHUB_TOKEN }}
4242
branch: gh-pages # The branch the action should deploy to.

composer.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
"composer/package-versions-deprecated": "^1.8",
1717
"phpdocumentor/reflection-docblock": "^4.3 || ^5.0",
1818
"phpdocumentor/type-resolver": "^1.4",
19-
"psr/container": "^2",
19+
"psr/container": "^1.1 || ^2",
2020
"psr/http-factory": "^1",
21-
"psr/http-message": "^1.0.1",
21+
"psr/http-message": "^1.0.1 || ^2.0",
2222
"psr/http-server-handler": "^1",
2323
"psr/http-server-middleware": "^1",
24-
"psr/simple-cache": "^1.0.1",
25-
"symfony/cache": "^4.3 || ^5 || ^6",
26-
"symfony/expression-language": "^4 || ^5 || ^6",
24+
"psr/simple-cache": "^1.0.1 || ^2 || ^3",
25+
"symfony/cache": "^4.3 || ^5 || ^6 || ^7",
26+
"symfony/expression-language": "^4 || ^5 || ^6 || ^7",
2727
"thecodingmachine/cache-utils": "^1",
2828
"thecodingmachine/class-explorer": "^1.1.0",
2929
"webonyx/graphql-php": "^v15.0"
@@ -38,7 +38,7 @@
3838
"phpstan/extension-installer": "^1.1",
3939
"phpstan/phpstan": "^1.9",
4040
"phpunit/phpunit": "^8.5.19 || ^9.5.8",
41-
"symfony/var-dumper": "^5.4 || ^6.0",
41+
"symfony/var-dumper": "^5.4 || ^6.0 || ^7",
4242
"thecodingmachine/phpstan-strict-rules": "^1.0"
4343
},
4444
"suggest": {

phpstan.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ parameters:
1717
- "#Parameter .* of class ReflectionMethod constructor expects string(\\|null)?, object\\|string given.#"
1818
- "#PHPDoc tag @throws with type Psr\\\\SimpleCache\\\\InvalidArgumentException is not subtype of Throwable#"
1919
- '#Variable \$context might not be defined.#'
20+
- '#Parameter \#1 \$callable of class TheCodingMachine\\GraphQLite\\Middlewares\\ServiceResolver constructor expects array{object, string}&callable\(\): mixed, array{object, non-empty-string} given.#'
2021
-
2122
message: '#Parameter .* of class GraphQL\\Error\\Error constructor expects#'
2223
path: src/Exceptions/WebonyxErrorHandler.php

src/AggregateControllerQueryProvider.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@ class AggregateControllerQueryProvider implements QueryProviderInterface
2929
* @param iterable<string> $controllers A list of controllers name in the container.
3030
* @param ContainerInterface $controllersContainer The container we will fetch controllers from.
3131
*/
32-
public function __construct(private readonly iterable $controllers, private readonly FieldsBuilder $fieldsBuilder, private readonly ContainerInterface $controllersContainer)
33-
{
32+
public function __construct(
33+
private readonly iterable $controllers,
34+
private readonly FieldsBuilder $fieldsBuilder,
35+
private readonly ContainerInterface $controllersContainer,
36+
) {
3437
}
3538

3639
/** @return array<string,FieldDefinition> */
@@ -52,13 +55,26 @@ public function getMutations(): array
5255
$mutationList = [];
5356

5457
foreach ($this->controllers as $controllerName) {
55-
$controller = $this->controllersContainer->get($controllerName);
58+
$controller = $this->controllersContainer->get($controllerName);
5659
$mutationList[$controllerName] = $this->fieldsBuilder->getMutations($controller);
5760
}
5861

5962
return $this->flattenList($mutationList);
6063
}
6164

65+
/** @return array<string, FieldDefinition> */
66+
public function getSubscriptions(): array
67+
{
68+
$subscriptionList = [];
69+
70+
foreach ($this->controllers as $controllerName) {
71+
$controller = $this->controllersContainer->get($controllerName);
72+
$subscriptionList[$controllerName] = $this->fieldsBuilder->getSubscriptions($controller);
73+
}
74+
75+
return $this->flattenList($subscriptionList);
76+
}
77+
6278
/**
6379
* @param array<string, array<string, FieldDefinition>> $list
6480
*

src/AggregateControllerQueryProviderFactory.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@ class AggregateControllerQueryProviderFactory implements QueryProviderFactoryInt
1515
* @param iterable<string> $controllers A list of controllers name in the container.
1616
* @param ContainerInterface $controllersContainer The container we will fetch controllers from.
1717
*/
18-
public function __construct(private readonly iterable $controllers, private readonly ContainerInterface $controllersContainer)
19-
{
18+
public function __construct(
19+
private readonly iterable $controllers,
20+
private readonly ContainerInterface $controllersContainer,
21+
) {
2022
}
2123

2224
public function create(FactoryContext $context): QueryProviderInterface
2325
{
24-
return new AggregateControllerQueryProvider($this->controllers, $context->getFieldsBuilder(), $this->controllersContainer);
26+
return new AggregateControllerQueryProvider(
27+
$this->controllers,
28+
$context->getFieldsBuilder(),
29+
$this->controllersContainer,
30+
);
2531
}
2632
}

src/AggregateQueryProvider.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ class AggregateQueryProvider implements QueryProviderInterface
2020
/** @param QueryProviderInterface[] $queryProviders */
2121
public function __construct(iterable $queryProviders)
2222
{
23-
$this->queryProviders = is_array($queryProviders) ? $queryProviders : iterator_to_array($queryProviders);
23+
$this->queryProviders = is_array($queryProviders)
24+
? $queryProviders
25+
: iterator_to_array($queryProviders);
2426
}
2527

2628
/** @return QueryField[] */
@@ -48,4 +50,17 @@ public function getMutations(): array
4850

4951
return array_merge(...$mutationsArray);
5052
}
53+
54+
/** @return QueryField[] */
55+
public function getSubscriptions(): array
56+
{
57+
$subscriptionsArray = array_map(static function (QueryProviderInterface $queryProvider) {
58+
return $queryProvider->getSubscriptions();
59+
}, $this->queryProviders);
60+
if ($subscriptionsArray === []) {
61+
return [];
62+
}
63+
64+
return array_merge(...$subscriptionsArray);
65+
}
5166
}

src/Annotations/Cost.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TheCodingMachine\GraphQLite\Annotations;
6+
7+
use Attribute;
8+
9+
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_METHOD)]
10+
class Cost implements MiddlewareAnnotationInterface
11+
{
12+
/**
13+
* @param int $complexity Complexity for that field
14+
* @param string[] $multipliers Names of fields by value of which complexity will be multiplied
15+
* @param ?int $defaultMultiplier Default multiplier value if all multipliers are missing/null
16+
*/
17+
public function __construct(
18+
public readonly int $complexity = 1,
19+
public readonly array $multipliers = [],
20+
public readonly int|null $defaultMultiplier = null,
21+
) {
22+
}
23+
}

src/Annotations/Field.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
use Attribute;
88

9+
use function trigger_error;
10+
11+
use const E_USER_DEPRECATED;
12+
913
/**
1014
* @Annotation
1115
* @Target({"PROPERTY", "METHOD"})
@@ -44,6 +48,7 @@ class Field extends AbstractRequest
4448
public function __construct(array $attributes = [], string|null $name = null, string|null $outputType = null, string|null $prefetchMethod = null, string|array|null $for = null, string|null $description = null, string|null $inputType = null)
4549
{
4650
parent::__construct($attributes, $name, $outputType);
51+
4752
$this->prefetchMethod = $prefetchMethod ?? $attributes['prefetchMethod'] ?? null;
4853
$this->description = $description ?? $attributes['description'] ?? null;
4954
$this->inputType = $inputType ?? $attributes['inputType'] ?? null;
@@ -54,6 +59,16 @@ public function __construct(array $attributes = [], string|null $name = null, st
5459
}
5560

5661
$this->for = (array) $forValue;
62+
63+
if (! $this->prefetchMethod) {
64+
return;
65+
}
66+
67+
trigger_error(
68+
"Using #[Field(prefetchMethod='" . $this->prefetchMethod . "')] on fields is deprecated in favor " .
69+
"of #[Prefetch('" . $this->prefetchMethod . "')] \$data attribute on the parameter itself.",
70+
E_USER_DEPRECATED,
71+
);
5772
}
5873

5974
/**

src/Annotations/MiddlewareAnnotations.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ public function __construct(private array $annotations)
2121
/**
2222
* Return annotations of the $className type
2323
*
24-
* @return array<int, MiddlewareAnnotationInterface>
24+
* @param class-string<TAnnotation> $className
25+
*
26+
* @return array<int, TAnnotation>
27+
*
28+
* @template TAnnotation of MiddlewareAnnotationInterface
2529
*/
2630
public function getAnnotationsByType(string $className): array
2731
{
@@ -32,6 +36,12 @@ public function getAnnotationsByType(string $className): array
3236

3337
/**
3438
* Returns at most 1 annotation of the $className type.
39+
*
40+
* @param class-string<TAnnotation> $className
41+
*
42+
* @return TAnnotation|null
43+
*
44+
* @template TAnnotation of MiddlewareAnnotationInterface
3545
*/
3646
public function getAnnotationByType(string $className): MiddlewareAnnotationInterface|null
3747
{

src/Annotations/Prefetch.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TheCodingMachine\GraphQLite\Annotations;
6+
7+
use Attribute;
8+
use TheCodingMachine\GraphQLite\GraphQLRuntimeException;
9+
10+
#[Attribute(Attribute::TARGET_PARAMETER)]
11+
class Prefetch implements ParameterAnnotationInterface
12+
{
13+
/** @param string|(callable&array{class-string, string}) $callable */
14+
public function __construct(public readonly string|array $callable)
15+
{
16+
}
17+
18+
public function getTarget(): string
19+
{
20+
// This is only needed for using #[Prefetch] as a Doctrine attribute, which it doesn't support.
21+
throw new GraphQLRuntimeException();
22+
}
23+
}

src/Annotations/Subscription.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TheCodingMachine\GraphQLite\Annotations;
6+
7+
use Attribute;
8+
9+
/**
10+
* @Annotation
11+
* @Target({"METHOD"})
12+
* @Attributes({
13+
* @Attribute("outputType", type = "string"),
14+
* })
15+
*/
16+
#[Attribute(Attribute::TARGET_METHOD)]
17+
class Subscription extends AbstractRequest
18+
{
19+
}

src/Context/Context.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
namespace TheCodingMachine\GraphQLite\Context;
66

77
use SplObjectStorage;
8+
use TheCodingMachine\GraphQLite\Parameters\ParameterInterface;
89
use TheCodingMachine\GraphQLite\PrefetchBuffer;
9-
use TheCodingMachine\GraphQLite\QueryField;
1010

1111
/**
1212
* A context class that should be passed to the Webonyx executor.
@@ -24,7 +24,7 @@ public function __construct()
2424
* Returns the prefetch buffer associated to the field $field.
2525
* (the buffer is created on the fly if it does not exist yet).
2626
*/
27-
public function getPrefetchBuffer(QueryField $field): PrefetchBuffer
27+
public function getPrefetchBuffer(ParameterInterface $field): PrefetchBuffer
2828
{
2929
if ($this->prefetchBuffers->offsetExists($field)) {
3030
$prefetchBuffer = $this->prefetchBuffers->offsetGet($field);

src/Context/ContextInterface.php

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

55
namespace TheCodingMachine\GraphQLite\Context;
66

7+
use TheCodingMachine\GraphQLite\Parameters\ParameterInterface;
78
use TheCodingMachine\GraphQLite\PrefetchBuffer;
8-
use TheCodingMachine\GraphQLite\QueryField;
99

1010
/**
1111
* A context class that should be passed to the Webonyx executor.
@@ -18,5 +18,5 @@ interface ContextInterface
1818
* Returns the prefetch buffer associated to the field $field.
1919
* (the buffer is created on the fly if it does not exist yet).
2020
*/
21-
public function getPrefetchBuffer(QueryField $field): PrefetchBuffer;
21+
public function getPrefetchBuffer(ParameterInterface $field): PrefetchBuffer;
2222
}

src/Exceptions/GraphQLAggregateException.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class GraphQLAggregateException extends Exception implements GraphQLAggregateExc
2323
public function __construct(iterable $exceptions = [])
2424
{
2525
parent::__construct('Many exceptions have be thrown:');
26+
2627
foreach ($exceptions as $exception) {
2728
$this->add($exception);
2829
}

0 commit comments

Comments
 (0)