Skip to content

[GraphQL] Embedded entities support for mutations #1765

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

Conversation

alanpoulain
Copy link
Member

@alanpoulain alanpoulain commented Mar 12, 2018

Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #1750
License MIT
Doc PR

TODO:

  • Unit tests

Add a new InputUnionType to allow using either an IRI or data for relations.
It allows to modify embedded entities or to update a related existing resource (#1363).

@alanpoulain alanpoulain force-pushed the fix/graphql-embedded-entities branch 2 times, most recently from f2ded97 to 24aeec8 Compare March 19, 2018 15:11
Copy link
Member

@dunglas dunglas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(partial review)

@@ -77,6 +77,10 @@
<argument type="service" id="api_platform.item_data_provider" on-invalid="ignore" />
<argument>%api_platform.allow_plain_identifiers%</argument>

<call method="setItemNormalizer">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use setter injection in API Platform. Can you inject it directly in the constructor please?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done it this way because the constructor of AbstractItemNormalizer has a lot of dependencies and I would need to copy it in this normalizer. But I can do it if you prefer.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WDYT @dunglas?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I prefer to copy them. Please :)

*/
public function denormalize($data, $class, $format = null, array $context = [])
{
return $this->itemNormalizer->denormalize($data, $class, $format, $context);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you use parent:: directly? It feels weird to me to inject an item normalizer in another one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't because the default item normalizer is final. And I need it because I don't want to duplicate the code needed to update related existing resources.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the final keyword and add a @final PHPDoc annotation then. It will be cleaner IMHO.

*
* @author Alan Poulain <[email protected]>
*/
class InputUnionType extends Type implements InputType, LeafType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final

*/
public function getTypes(): array
{
if (null === $this->types) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use a guard clause (if (null !== $this->types) return...).

public function getTypes(): array
{
if (null === $this->types) {
if (!isset($this->config['types'])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if ($types = $this->config['types'] ?? null) {
    if (\is_callable($types)) {
        $types = \call_user_func($this->config['types']);
    }
}


$types = $this->getTypes();
Utils::invariant(
!empty($types),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't empty can be removed? You can also inline this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've copied it from here: https://github.com/webonyx/graphql-php/blob/master/src/Type/Definition/UnionType.php#L137
I think we can make a count instead. Do you agree?

{
foreach ($this->getTypes() as $type) {
if ($type instanceof LeafType) {
if (null !== $parsed = $type->parseLiteral($valueNode)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be merged with the previous line:

if ($type instanceof LeafType && null !== $parsed = $type->parseLiteral($valueNode))

@alanpoulain alanpoulain force-pushed the fix/graphql-embedded-entities branch from 24aeec8 to 952b56e Compare March 20, 2018 11:14

Utils::assertValidName($config['name']);

Config::validate($config, [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Config class is deprecated, see webonyx/graphql-php#148.

public function isValidValue($value): bool
{
foreach ($this->getTypes() as $type) {
if ($type instanceof LeafType) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if ($type instanceof LeafType && $type->isValidValue($value)) {
    return true;
}

public function isValidLiteral($valueNode): bool
{
foreach ($this->getTypes() as $type) {
if ($type instanceof LeafType) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if ($type instanceof LeafType && $type->isValidLiteral($valueNode)) {
    return true;
}

@dunglas
Copy link
Member

dunglas commented Mar 20, 2018

It should target master, it's a new feature.

/**
* @var array
*/
public $config;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private?

@alanpoulain alanpoulain force-pushed the fix/graphql-embedded-entities branch from 952b56e to 8c626bd Compare March 26, 2018 10:24
@alanpoulain alanpoulain changed the base branch from 2.2 to master March 26, 2018 10:24
@alanpoulain alanpoulain force-pushed the fix/graphql-embedded-entities branch from 8c626bd to 69ca00d Compare March 26, 2018 12:39
@alanpoulain
Copy link
Member Author

@dunglas @meyerbaptiste Fixed.

@alanpoulain alanpoulain force-pushed the fix/graphql-embedded-entities branch 2 times, most recently from b20591a to 4b670a1 Compare March 26, 2018 13:01
}
}

throw new InvariantViolation(sprintf('Types in union cannot represent value: %s', Utils::printSafe($value)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@throws is missing.

}
}

throw new Error(sprintf('Types in union cannot represent value: %s', Utils::printSafeJson($value)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@throws is missing.

}

/**
* @throws InvariantViolation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be replaced by {@inheritdoc}.

@alanpoulain alanpoulain force-pushed the fix/graphql-embedded-entities branch from 4b670a1 to b4415e5 Compare March 27, 2018 15:17
@alanpoulain
Copy link
Member Author

@meyerbaptiste Done.

@dunglas dunglas merged commit d7ada1b into api-platform:master Mar 28, 2018
@dunglas
Copy link
Member

dunglas commented Mar 28, 2018

Thank you very much @alanpoulain

@CvekCoding
Copy link
Contributor

@alanpoulain let me ask you why this fix was not merged in production branch?

@alanpoulain
Copy link
Member Author

Explanation about why this has been removed is here: #1886

@CvekCoding
Copy link
Contributor

@alanpoulain thanks. Looks like it's not solved yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants