Skip to content

Commit

Permalink
graphql ok
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka committed Aug 10, 2023
1 parent aa33674 commit 0f8509c
Show file tree
Hide file tree
Showing 32 changed files with 570 additions and 137 deletions.
150 changes: 147 additions & 3 deletions src/Api/IdentifiersExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,154 @@

namespace ApiPlatform\Api;

class_exists(\ApiPlatform\Metadata\IdentifiersExtractor::class);
use ApiPlatform\Metadata\Exception\RuntimeException;
use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation;
use ApiPlatform\Metadata\HttpOperation;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
use ApiPlatform\Metadata\Util\ResourceClassInfoTrait;
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;

if (false) {
final class IdentifiersExtractor extends \ApiPlatform\Metadata\IdentifiersExtractor
/**
* {@inheritdoc}
*
* @deprecated use ApiPlatform\Metadata\IdentifiersExtractor instead
*
* @author Antoine Bluchet <[email protected]>
*/
final class IdentifiersExtractor implements IdentifiersExtractorInterface
{
use ResourceClassInfoTrait;
private readonly PropertyAccessorInterface $propertyAccessor;

public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, private readonly PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, private readonly PropertyMetadataFactoryInterface $propertyMetadataFactory, PropertyAccessorInterface $propertyAccessor = null)
{
$this->resourceMetadataFactory = $resourceMetadataFactory;
$this->resourceClassResolver = $resourceClassResolver;
$this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor();
}

/**
* {@inheritdoc}
*
* TODO: 3.0 identifiers should be stringable?
*/
public function getIdentifiersFromItem(object $item, Operation $operation = null, array $context = []): array
{
if (!$this->isResourceClass($this->getObjectClass($item))) {
return ['id' => $this->propertyAccessor->getValue($item, 'id')];
}

if ($operation && $operation->getClass()) {
return $this->getIdentifiersFromOperation($item, $operation, $context);
}

$resourceClass = $this->getResourceClass($item, true);
$operation ??= $this->resourceMetadataFactory->create($resourceClass)->getOperation(null, false, true);

return $this->getIdentifiersFromOperation($item, $operation, $context);
}

private function getIdentifiersFromOperation(object $item, Operation $operation, array $context = []): array
{
if ($operation instanceof HttpOperation) {
$links = $operation->getUriVariables();
} elseif ($operation instanceof GraphQlOperation) {
$links = $operation->getLinks();
}

$identifiers = [];
foreach ($links ?? [] as $link) {
if (1 < (is_countable($link->getIdentifiers()) ? \count($link->getIdentifiers()) : 0)) {
$compositeIdentifiers = [];
foreach ($link->getIdentifiers() as $identifier) {
$compositeIdentifiers[$identifier] = $this->getIdentifierValue($item, $link->getFromClass() ?? $operation->getClass(), $identifier, $link->getParameterName());
}

$identifiers[$link->getParameterName()] = CompositeIdentifierParser::stringify($compositeIdentifiers);
continue;
}

$parameterName = $link->getParameterName();
$identifiers[$parameterName] = $this->getIdentifierValue($item, $link->getFromClass() ?? $operation->getClass(), $link->getIdentifiers()[0], $parameterName, $link->getToProperty());
}

return $identifiers;
}

/**
* Gets the value of the given class property.
*/
private function getIdentifierValue(object $item, string $class, string $property, string $parameterName, string $toProperty = null): float|bool|int|string
{
if ($item instanceof $class) {
try {
return $this->resolveIdentifierValue($this->propertyAccessor->getValue($item, $property), $parameterName);
} catch (NoSuchPropertyException $e) {
throw new RuntimeException('Not able to retrieve identifiers.', $e->getCode(), $e);
}
}

if ($toProperty) {
return $this->resolveIdentifierValue($this->propertyAccessor->getValue($item, "$toProperty.$property"), $parameterName);
}

$resourceClass = $this->getResourceClass($item, true);
foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) {
$propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName);

$types = $propertyMetadata->getBuiltinTypes();
if (null === ($type = $types[0] ?? null)) {
continue;
}

try {
if ($type->isCollection()) {
$collectionValueType = $type->getCollectionValueTypes()[0] ?? null;

if (null !== $collectionValueType && $collectionValueType->getClassName() === $class) {
return $this->resolveIdentifierValue($this->propertyAccessor->getValue($item, sprintf('%s[0].%s', $propertyName, $property)), $parameterName);
}
}

if ($type->getClassName() === $class) {
return $this->resolveIdentifierValue($this->propertyAccessor->getValue($item, "$propertyName.$property"), $parameterName);
}
} catch (NoSuchPropertyException $e) {
throw new RuntimeException('Not able to retrieve identifiers.', $e->getCode(), $e);
}
}

throw new RuntimeException('Not able to retrieve identifiers.');
}

/**
* TODO: in 3.0 this method just uses $identifierValue instanceof \Stringable and we remove the weird behavior.
*
* @param mixed|\Stringable $identifierValue
*/
private function resolveIdentifierValue(mixed $identifierValue, string $parameterName): float|bool|int|string
{
if (null === $identifierValue) {
throw new RuntimeException('No identifier value found, did you forget to persist the entity?');
}

if (\is_scalar($identifierValue)) {
return $identifierValue;
}

if ($identifierValue instanceof \Stringable) {
return (string) $identifierValue;
}

if ($identifierValue instanceof \BackedEnum) {
return (string) $identifierValue->value;
}

throw new RuntimeException(sprintf('We were not able to resolve the identifier matching parameter "%s".', $parameterName));
}
}
4 changes: 2 additions & 2 deletions src/Api/IdentifiersExtractorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@

namespace ApiPlatform\Api;

class_alias(\ApiPlatform\Metadata\IdentifiersExtractorInterface::class, \ApiPlatform\Api\IdentifiersExtractorInterface::class);
class_exists(\ApiPlatform\Metadata\IdentifiersExtractorInterface::class);

if (false) {
if (!class_exists(IdentifiersExtractorInterface::class)) {
interface IdentifiersExtractorInterface extends \ApiPlatform\Metadata\IdentifiersExtractorInterface
{
}
Expand Down
4 changes: 2 additions & 2 deletions src/Api/IriConverterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@

namespace ApiPlatform\Api;

class_alias(\ApiPlatform\Metadata\IriConverterInterface::class, \ApiPlatform\Api\IriConverterInterface::class);
class_exists(\ApiPlatform\Metadata\IriConverterInterface::class);

if (false) {
if (!class_exists(IriConverterInterface::class)) {
interface IriConverterInterface extends \ApiPlatform\Metadata\IriConverterInterface
{
}
Expand Down
6 changes: 4 additions & 2 deletions src/Api/ResourceClassResolverInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@

namespace ApiPlatform\Api;

class_alias(\ApiPlatform\Metadata\ResourceClassResolverInterface::class, \ApiPlatform\Api\ResourceClassResolverInterface::class);
class_exists(\ApiPlatform\Metadata\ResourceClassResolverInterface::class);

if (false) {
interface ResourceClassResolverInterface extends \ApiPlatform\Metadata\ResourceClassResolverInterface {}
interface ResourceClassResolverInterface extends \ApiPlatform\Metadata\ResourceClassResolverInterface
{
}
}
24 changes: 5 additions & 19 deletions src/Api/UriVariablesConverterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,10 @@

namespace ApiPlatform\Api;

use ApiPlatform\Exception\InvalidIdentifierException;
class_exists(\ApiPlatform\Metadata\UriVariablesConverterInterface::class);

/**
* Identifier converter.
*
* @author Antoine Bluchet <[email protected]>
*/
interface UriVariablesConverterInterface
{
/**
* Takes an array of strings representing URI variables (identifiers) and transform their values to the expected type.
*
* @param array $data URI variables to convert to PHP values
* @param string $class The class to which the URI variables belong to
*
* @throws InvalidIdentifierException
*
* @return array Array indexed by identifiers properties with their values denormalized
*/
public function convert(array $data, string $class, array $context = []): array;
if (!class_exists(UriVariablesConverterInterface::class)) {
interface UriVariablesConverterInterface extends \ApiPlatform\Metadata\UriVariablesConverterInterface
{
}
}
145 changes: 75 additions & 70 deletions src/Elasticsearch/composer.json
Original file line number Diff line number Diff line change
@@ -1,77 +1,82 @@
{
"name": "api-platform/elasticseach",
"description": "Elasticsearch support",
"type": "library",
"keywords": [
"Filter",
"Elasticsearch"
],
"homepage": "https://api-platform.com",
"license": "MIT",
"authors": [
{
"name": "Kévin Dunglas",
"email": "[email protected]",
"homepage": "https://dunglas.fr"
"name": "api-platform/elasticseach",
"description": "Elasticsearch support",
"type": "library",
"keywords": [
"Filter",
"Elasticsearch"
],
"homepage": "https://api-platform.com",
"license": "MIT",
"authors": [
{
"name": "Kévin Dunglas",
"email": "[email protected]",
"homepage": "https://dunglas.fr"
},
{
"name": "API Platform Community",
"homepage": "https://api-platform.com/community/contributors"
}
],
"require": {
"php": ">=8.1",
"api-platform/metadata": "*@dev || ^3.1",
"api-platform/state": "*@dev || ^3.1",
"api-platform/serializer": "*@dev || ^3.1",
"elasticsearch/elasticsearch": "^7.11.0",
"symfony/cache": "^6.1",
"symfony/console": "^6.2",
"symfony/property-info": "^6.1",
"symfony/serializer": "^6.1",
"symfony/uid": "^6.1",
"symfony/property-access": "^6.1"
},
{
"name": "API Platform Community",
"homepage": "https://api-platform.com/community/contributors"
}
],
"require": {
"php": ">=8.1",
"api-platform/metadata": "*@dev || ^3.1",
"api-platform/state": "*@dev || ^3.1",
"elasticsearch/elasticsearch": "^7.11.0",
"symfony/cache": "^6.1",
"symfony/console": "^6.2",
"symfony/property-info": "^6.1",
"symfony/serializer": "^6.1",
"symfony/uid": "^6.1",
"symfony/property-access": "^6.1"
},
"conflict": {
"elasticsearch/elasticsearch": ">=8.0"
},
"require-dev": {
"phpspec/prophecy-phpunit": "^2.0",
"symfony/phpunit-bridge": "^6.1"
},
"autoload": {
"psr-4": {
"ApiPlatform\\Elasticsearch\\": ""
"conflict": {
"elasticsearch/elasticsearch": ">=8.0"
},
"exclude-from-classmap": [
"/Tests/"
]
},
"config": {
"preferred-install": {
"*": "dist"
"require-dev": {
"phpspec/prophecy-phpunit": "^2.0",
"symfony/phpunit-bridge": "^6.1"
},
"autoload": {
"psr-4": {
"ApiPlatform\\Elasticsearch\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"sort-packages": true,
"allow-plugins": {
"composer/package-versions-deprecated": true,
"phpstan/extension-installer": true
}
},
"extra": {
"branch-alias": {
"dev-main": "3.2.x-dev"
"config": {
"preferred-install": {
"*": "dist"
},
"sort-packages": true,
"allow-plugins": {
"composer/package-versions-deprecated": true,
"phpstan/extension-installer": true
}
},
"symfony": {
"require": "^6.1"
}
},
"repositories": [
{
"type": "path",
"url": "../Metadata"
"extra": {
"branch-alias": {
"dev-main": "3.2.x-dev"
},
"symfony": {
"require": "^6.1"
}
},
{
"type": "path",
"url": "../State"
}
]
"repositories": [
{
"type": "path",
"url": "../Metadata"
},
{
"type": "path",
"url": "../State"
},
{
"type": "path",
"url": "../Serializer"
}
]
}
6 changes: 5 additions & 1 deletion src/Exception/InvalidArgumentException.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@

namespace ApiPlatform\Exception;

use ApiPlatform\Metadata\Exception\InvalidArgumentException as MetadataInvalidArgumentException;

/**
* Invalid argument exception.
*
* @author Kévin Dunglas <[email protected]>
*
* @deprecated use \ApiPlatform\Metadata\Exception\InvalidArgumentException
*/
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
class InvalidArgumentException extends MetadataInvalidArgumentException
{
}
Loading

0 comments on commit 0f8509c

Please sign in to comment.