Skip to content

Commit

Permalink
Merge 7169ef6 into a3b833f
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka committed Dec 17, 2021
2 parents a3b833f + 7169ef6 commit 01c2efd
Show file tree
Hide file tree
Showing 112 changed files with 3,544 additions and 1,424 deletions.
45 changes: 23 additions & 22 deletions .github/workflows/ci.yml
Expand Up @@ -68,7 +68,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Cache PHPStan results
Expand Down Expand Up @@ -142,7 +142,7 @@ jobs:
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
if: (!startsWith(matrix.php, '7.1'))
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down Expand Up @@ -238,7 +238,7 @@ jobs:
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
if: (!startsWith(matrix.php, '7.1'))
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down Expand Up @@ -358,7 +358,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi --prefer-lowest
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Clear test app cache
run: tests/Fixtures/app/console cache:clear --ansi
- name: Install PHPUnit
Expand Down Expand Up @@ -398,7 +398,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi --prefer-lowest
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down Expand Up @@ -449,7 +449,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down Expand Up @@ -501,7 +501,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down Expand Up @@ -550,7 +550,7 @@ jobs:
run: |
composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down Expand Up @@ -640,7 +640,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install Elasticsearch-php # there is a version matrix for this package: https://packagist.org/packages/elasticsearch/elasticsearch
run: composer require "elasticsearch/elasticsearch:v7.14.0" --no-interaction --no-progress --ansi
- name: Install PHPUnit
Expand Down Expand Up @@ -684,7 +684,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down Expand Up @@ -734,7 +734,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Flag held back Symfony packages
env:
symfony_version: ${{ matrix.symfony }}
Expand Down Expand Up @@ -796,7 +796,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Flag held back Symfony packages
env:
symfony_version: ${{ matrix.symfony }}
Expand Down Expand Up @@ -846,25 +846,26 @@ jobs:
path: ${{ steps.composercache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components and Rector dependencies
run: composer require symfony/intl symfony/uid rector/rector --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid rector/rector:0.12.5 --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
run: rm -Rf tests/Fixtures/app/var/cache/*
- name: Convert annotations to attributes
run: |
tests/Fixtures/app/console api:rector:upgrade tests/Fixtures/TestBundle/Document --transform-apisubresource -s
tests/Fixtures/app/console api:rector:upgrade tests/Fixtures/TestBundle/Document --annotation-to-api-resource -s
tests/Fixtures/app/console api:rector:upgrade tests/Fixtures/TestBundle/Entity --transform-apisubresource -s
tests/Fixtures/app/console api:rector:upgrade tests/Fixtures/TestBundle/Entity --annotation-to-api-resource -s
tests/Fixtures/app/console api:rector:upgrade tests/Fixtures/TestBundle/Document --transform-apisubresource -s -n
tests/Fixtures/app/console api:rector:upgrade tests/Fixtures/TestBundle/Document --annotation-to-api-resource -s -n
tests/Fixtures/app/console api:rector:upgrade tests/Fixtures/TestBundle/Entity --transform-apisubresource -s -n
tests/Fixtures/app/console api:rector:upgrade tests/Fixtures/TestBundle/Entity --annotation-to-api-resource -s -n
- name: Clear test app cache
run: rm -Rf tests/Fixtures/app/var/cache/*
- name: Run Behat tests
run: |
mkdir -p build/logs/behat
vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction
continue-on-error: true
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v1
Expand Down Expand Up @@ -937,7 +938,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install phpunit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down Expand Up @@ -985,7 +986,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install phpunit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down Expand Up @@ -1032,7 +1033,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down Expand Up @@ -1076,7 +1077,7 @@ jobs:
- name: Update project dependencies
run: composer update --no-interaction --no-progress --ansi
- name: Require Symfony components
run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi
run: composer require symfony/uid --dev --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
Expand Down
1 change: 0 additions & 1 deletion CHANGELOG.md
Expand Up @@ -32,7 +32,6 @@
* GraphQL: **BC** Fix security on association collection properties. The collection resource `item_query` security is no longer used. `ApiProperty` security can now be used to secure collection (or any other) properties. (#4143)
* Deprecate `allow_plain_identifiers` option (#4167)
* Exception: Add the ability to customize multiple status codes based on the validation exception (#4017)
* GraphQL: Fix graphql fetching with Elasticsearch (#4217)
* ApiLoader: Support `_format` resolving (#4292)
* Metadata: new namespace `ApiPlatform\Metadata` instead of `ApiPlatform\Core\Metadata`, for example `ApiPlatform\Metadata\ApiResource` (#4351)
* Metadata: deprecation of `ApiPlatform\Core\Annotation` (#4351)
Expand Down
1 change: 0 additions & 1 deletion behat.yml.dist
Expand Up @@ -84,7 +84,6 @@ elasticsearch:
contexts:
- 'ApiPlatform\Core\Tests\Behat\CommandContext'
- 'ApiPlatform\Core\Tests\Behat\ElasticsearchContext'
- 'ApiPlatform\Core\Tests\Behat\GraphqlContext'
- 'ApiPlatform\Core\Tests\Behat\JsonContext'
- 'Behat\MinkExtension\Context\MinkContext'
- 'behatch:context:rest'
Expand Down
8 changes: 4 additions & 4 deletions docs/adr/0003-uri-variables.md
Expand Up @@ -37,7 +37,7 @@ We will use a POPO to define URI variables, for now these options are available:
uriVariables: [
'companyId' => new UriVariable(
targetClass: Company::class,
inverseProperty: null,
targetProperty: null,
property: 'company'
identifiers: ['id'],
compositeIdentifier: true,
Expand All @@ -53,7 +53,7 @@ Where `uriVariables` keys are the URI template's variable names. Its value is a

- `targetClass` is the PHP FQDN of the class this value belongs to
- `property` represents the property, the URI Variable is mapped to in the current class
- `inverseProperty` represents the property, the URI Variable is mapped to in the related class and is not available in the current class
- `targetProperty` represents the property, the URI Variable is mapped to in the related class and is not available in the current class
- `identifiers` are the properties of the targetClass to which we map the URI variable
- `compositeIdentifier` is used to match a single variable to multiple identifiers (`ida=1;idb=2` to `class::ida` and `class::idb`)

Expand Down Expand Up @@ -122,7 +122,7 @@ class Company {
}
```

Note that the above is a shortcut for: `new UriVariable(targetClass: Employee::class, inverseProperty: 'company')`
Note that the above is a shortcut for: `new UriVariable(targetClass: Employee::class, targetProperty: 'company')`

Corresponding DQL:

Expand Down Expand Up @@ -259,7 +259,7 @@ class Employee {
#[ApiResource("/employees/{employeeId}/company", uriVariables: [
'employeeId' => new UriVariable(
targetClass: Employee::class,
inverseProperty: 'company'
targetProperty: 'company'
property: null,
identifiers: ['id'],
compositeIdentifier: true
Expand Down
146 changes: 146 additions & 0 deletions docs/adr/0004-link.md
@@ -0,0 +1,146 @@
# Link

* Status: accepted
* Deciders: @dunglas, @soyuka, @alanpoulain

Implementation: [#4536][pull/4536]

## Context and Problem Statement

The [URI Variables](0003-uri-variables.md) ADR introduces a new `UriVariable` POPO.
In GraphQL, having URI variables make no sense: this object needs either an alias or needs to be named differently.

## Considered Options

* Create a `Traverser` alias for GraphQL.
* Rename `UriVariable` to `Link`.

## Decision Outcome

We chose to rename `UriVariable` to `Link` in order to simplify the codebase.
However the `uriVariables` parameter in the REST operations will not be renamed since it makes sense to have this name.
GraphQL operations don't need to have links at the operation level, a `Link` attribute on the property will be used instead if necessary (the main use case is when a `toProperty` is necessary).

To follow this renaming, the properties in `Link` are also renamed:
- `targetClass` becomes `fromClass`
- `inverseProperty` becomes `fromProperty`
- `property` becomes `toProperty`

New properties are also necessary:
- `toClass` for GraphQL because GraphQL needs to find the right `Link`
- `expandedValue` for REST in order to convert an URI variable to the corresponding route part (for instance in the case of the URI template `/questions/{questionId}/{questionAnswer}/related_questions`, the expanded value for `questionAnswer` could be `answer`)

### Classical Example

```php
<?php

#[Query]
#[Get]
class Company
{
public $id;

#[ORM\OneToMany(targetEntity: Employee::class, mappedBy: 'company')]
// will automatically create:
#[Link(fromClass: Company::class, fromProperty: 'employees')]
/** @var Employee[] */
public iterable $employees;
}
```

```php
<?php

#[Query]
#[GetCollection('/companies/{companyId}/employees', uriVariables: [
'companyId' => new Link(
fromClass: Company::class,
fromProperty: 'employees'
)
])]
class Employee
{
public $id;

#[ORM\ManyToOne(targetEntity: Company::class, inversedBy: 'employees')]
public Company $company;
}
```

The GraphQL query equivalent to a `GET` to `/companies/2/employees` can now be done:

```graphql
{
companies(id: "/companies/2") {
employees {
edges {
node {
id
}
}
}
}
}
```

### Inverted Example

In this example, the relation between the employee and the company is only hold by the employee.

```php
<?php

#[Query]
#[GetCollection('/companies/{companyId}/employees', uriVariables: [
'companyId' => new Link(
fromClass: Company::class,
toProperty: 'company'
)
])]
class Employee
{
public $id;

#[ORM\ManyToMany(targetEntity: Company::class)]
#[ORM\JoinTable(name: 'employees_companies')]
#[ORM\JoinColumn(name: 'employee_id', referencedColumnName: 'id')]
#[ORM\InverseJoinColumn(name: 'company_id', referencedColumnName: 'id', unique: true)]
public Company $company;
}
```

```php
<?php

#[Query]
#[Get]
class Company
{
public $id;

#[Link('company')]
// equivalent to:
#[Link(fromClass: Company::class, toClass: Employee::class, toProperty: 'company')]
/** @var Employee[] */
public iterable $employees;
}
```

The GraphQL query equivalent to a `GET` to `/companies/2/employees` can now be done:

```graphql
{
companies(id: "/companies/2") {
employees {
edges {
node {
id
}
}
}
}
}
```

[pull/4536]: https://github.com/api-platform/core/pull/4536 "Link implementation"
4 changes: 2 additions & 2 deletions features/doctrine/eager_loading.feature
Expand Up @@ -17,7 +17,7 @@ Feature: Eager Loading
LEFT JOIN thirdLevel_a1.fourthLevel fourthLevel_a2
LEFT JOIN o.relatedToDummyFriend relatedToDummyFriend_a3
LEFT JOIN relatedToDummyFriend_a3.dummyFriend dummyFriend_a4
WHERE o.id = :id_id
WHERE o.id = :id_p1
"""

Scenario: Eager loading for the search filter
Expand Down Expand Up @@ -74,7 +74,7 @@ Feature: Eager Loading
FROM ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTravel o
LEFT JOIN o.car car_a1
LEFT JOIN o.passenger passenger_a2
WHERE o.id = :id_id
WHERE o.id = :id_p1
"""

Scenario: Eager loading for a relation with complex sub-query filter
Expand Down

0 comments on commit 01c2efd

Please sign in to comment.