Skip to content

feat(graphql): added support for graphql subscriptions to work for actions #6904

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
43 changes: 43 additions & 0 deletions src/GraphQl/Serializer/ItemNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use ApiPlatform\GraphQl\State\Provider\NoopProvider;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\GraphQl\Query;
use ApiPlatform\Metadata\GraphQl\QueryCollection;
use ApiPlatform\Metadata\IdentifiersExtractorInterface;
use ApiPlatform\Metadata\IriConverterInterface;
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
Expand All @@ -26,6 +27,7 @@
use ApiPlatform\Metadata\Util\ClassInfoTrait;
use ApiPlatform\Serializer\CacheKeyTrait;
use ApiPlatform\Serializer\ItemNormalizer as BaseItemNormalizer;
use Doctrine\Common\Collections\Collection;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
Expand Down Expand Up @@ -106,6 +108,11 @@
$data[self::ITEM_IDENTIFIERS_KEY] = $this->identifiersExtractor->getIdentifiersFromItem($object, $context['operation'] ?? null);
}

if (isset($context['graphql_operation_name']) && 'mercure_subscription' === $context['graphql_operation_name'] && \is_object($object) && isset($data['id']) && !isset($data['_id'])) {
$data['_id'] = $data['id'];
$data['id'] = $this->iriConverter->getIriFromResource($object);

Check warning on line 113 in src/GraphQl/Serializer/ItemNormalizer.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Serializer/ItemNormalizer.php#L112-L113

Added lines #L112 - L113 were not covered by tests
}

return $data;
}

Expand All @@ -120,10 +127,46 @@
return [...$attributeValue];
}

// Handle relationships for mercure subscriptions
if ($operation instanceof QueryCollection && 'mercure_subscription' === $context['graphql_operation_name'] && $attributeValue instanceof Collection && !$attributeValue->isEmpty()) {
$relationContext = $context;

Check warning on line 132 in src/GraphQl/Serializer/ItemNormalizer.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Serializer/ItemNormalizer.php#L131-L132

Added lines #L131 - L132 were not covered by tests
// Grab collection attributes
$relationContext['attributes'] = $context['attributes']['collection'];

Check warning on line 134 in src/GraphQl/Serializer/ItemNormalizer.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Serializer/ItemNormalizer.php#L134

Added line #L134 was not covered by tests
// Iterate over the collection and normalize each item
$data['collection'] = $attributeValue
->map(fn ($item) => $this->normalize($item, $format, $relationContext))
// Convert the collection to an array
->toArray();

Check warning on line 139 in src/GraphQl/Serializer/ItemNormalizer.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Serializer/ItemNormalizer.php#L136-L139

Added lines #L136 - L139 were not covered by tests

// Handle pagination if it's enabled in the query
return $this->addPagination($attributeValue, $data, $context);

Check warning on line 142 in src/GraphQl/Serializer/ItemNormalizer.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Serializer/ItemNormalizer.php#L142

Added line #L142 was not covered by tests
}

// to-many are handled directly by the GraphQL resolver
return [];
}

private function addPagination(Collection $collection, array $data, array $context): array

Check warning on line 149 in src/GraphQl/Serializer/ItemNormalizer.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Serializer/ItemNormalizer.php#L149

Added line #L149 was not covered by tests
{
if ($context['attributes']['paginationInfo'] ?? false) {
$data['paginationInfo'] = [];
if (\array_key_exists('hasNextPage', $context['attributes']['paginationInfo'])) {
$data['paginationInfo']['hasNextPage'] = $collection->count() > ($context['pagination']['itemsPerPage'] ?? 10);

Check warning on line 154 in src/GraphQl/Serializer/ItemNormalizer.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Serializer/ItemNormalizer.php#L151-L154

Added lines #L151 - L154 were not covered by tests
}
if (\array_key_exists('itemsPerPage', $context['attributes']['paginationInfo'])) {
$data['paginationInfo']['itemsPerPage'] = $context['pagination']['itemsPerPage'] ?? 10;

Check warning on line 157 in src/GraphQl/Serializer/ItemNormalizer.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Serializer/ItemNormalizer.php#L156-L157

Added lines #L156 - L157 were not covered by tests
}
if (\array_key_exists('lastPage', $context['attributes']['paginationInfo'])) {
$data['paginationInfo']['lastPage'] = (int) ceil($collection->count() / ($context['pagination']['itemsPerPage'] ?? 10));

Check warning on line 160 in src/GraphQl/Serializer/ItemNormalizer.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Serializer/ItemNormalizer.php#L159-L160

Added lines #L159 - L160 were not covered by tests
}
if (\array_key_exists('totalCount', $context['attributes']['paginationInfo'])) {
$data['paginationInfo']['totalCount'] = $collection->count();

Check warning on line 163 in src/GraphQl/Serializer/ItemNormalizer.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Serializer/ItemNormalizer.php#L162-L163

Added lines #L162 - L163 were not covered by tests
}
}

return $data;

Check warning on line 167 in src/GraphQl/Serializer/ItemNormalizer.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Serializer/ItemNormalizer.php#L167

Added line #L167 was not covered by tests
}

/**
* {@inheritdoc}
*/
Expand Down
4 changes: 4 additions & 0 deletions src/GraphQl/State/Processor/SubscriptionProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use ApiPlatform\GraphQl\Subscription\OperationAwareSubscriptionManagerInterface;
use ApiPlatform\GraphQl\Subscription\SubscriptionManagerInterface;
use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation;
use ApiPlatform\Metadata\GraphQl\Subscription;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;

Expand Down Expand Up @@ -49,6 +50,9 @@

$hub = \is_array($mercure) ? ($mercure['hub'] ?? null) : null;
$data['mercureUrl'] = $this->mercureSubscriptionIriGenerator->generateMercureUrl($subscriptionId, $hub);
if ($operation instanceof Subscription) {
$data['isCollection'] = $operation->isCollection();

Check warning on line 54 in src/GraphQl/State/Processor/SubscriptionProcessor.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/State/Processor/SubscriptionProcessor.php#L53-L54

Added lines #L53 - L54 were not covered by tests
}
}

return $data;
Expand Down
14 changes: 14 additions & 0 deletions src/GraphQl/Subscription/SubscriptionIdentifierGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,21 @@
public function generateSubscriptionIdentifier(array $fields): string
{
unset($fields['mercureUrl'], $fields['clientSubscriptionId']);
$fields = $this->removeTypename($fields);

Check warning on line 26 in src/GraphQl/Subscription/SubscriptionIdentifierGenerator.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionIdentifierGenerator.php#L26

Added line #L26 was not covered by tests
Copy link
Member

Choose a reason for hiding this comment

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

why is this needed?

Copy link
Contributor Author

@psihius psihius Jan 17, 2025

Choose a reason for hiding this comment

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

When executing a subscription GraphQL query, the __typename key is not present in fields in the SubscriptionProcessor, but when you get fields in doctrine subscriber to publish updates, the __typename is present in the fields. That results in different sha256 hashes as subscription id, which breaks publishing.


return hash('sha256', print_r($fields, true));
}

private function removeTypename(array $data): array

Check warning on line 31 in src/GraphQl/Subscription/SubscriptionIdentifierGenerator.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionIdentifierGenerator.php#L31

Added line #L31 was not covered by tests
{
foreach ($data as $key => $value) {
if ('__typename' === $key) {
unset($data[$key]);
} elseif (\is_array($value)) {
$data[$key] = $this->removeTypename($value);

Check warning on line 37 in src/GraphQl/Subscription/SubscriptionIdentifierGenerator.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionIdentifierGenerator.php#L33-L37

Added lines #L33 - L37 were not covered by tests
}
}

return $data;

Check warning on line 41 in src/GraphQl/Subscription/SubscriptionIdentifierGenerator.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionIdentifierGenerator.php#L41

Added line #L41 was not covered by tests
}
}
195 changes: 167 additions & 28 deletions src/GraphQl/Subscription/SubscriptionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,43 +47,124 @@
$fields = $info->getFieldSelection(\PHP_INT_MAX);
$this->arrayRecursiveSort($fields, 'ksort');
$iri = $operation ? $this->getIdentifierFromOperation($operation, $context['args'] ?? []) : $this->getIdentifierFromContext($context);
if (null === $iri) {
if (empty($iri)) {

Check warning on line 50 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L50

Added line #L50 was not covered by tests
Copy link
Member

Choose a reason for hiding this comment

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

let's avoid a function call here if this can return an empty array we should fix the return type of the above functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It also returns an empty string if you provide a value, but it's not a valid URI. That's why I made empty call instead of doing null === $iri || '' === $iri || [] === $iri.
Those 2 methods called above are part of a IdentifierTrait trait, means all call sides will need modification.

return null;
}

$options = $operation ? ($operation->getMercure() ?? false) : false;
$private = $options['private'] ?? false;
$privateFields = $options['private_fields'] ?? [];
$previousObject = $context['graphql_context']['previous_object'] ?? null;
if ($private && $privateFields && $previousObject) {
foreach ($options['private_fields'] as $privateField) {
$fields['__private_field_'.$privateField] = $this->getResourceId($privateField, $previousObject);

Check warning on line 60 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L54-L60

Added lines #L54 - L60 were not covered by tests
}
}
if ($operation instanceof Subscription && $operation->isCollection()) {
$subscriptionId = $this->updateSubscriptionCollectionCacheData(
$iri,
$fields,
);

Check warning on line 67 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L63-L67

Added lines #L63 - L67 were not covered by tests
} else {
$subscriptionId = $this->updateSubscriptionItemCacheData(
$iri,
$fields,
$result,
$private,
$privateFields,
$previousObject
);

Check warning on line 76 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L69-L76

Added lines #L69 - L76 were not covered by tests
}

return $subscriptionId;

Check warning on line 79 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L79

Added line #L79 was not covered by tests
}

public function getPushPayloads(object $object, string $type): array

Check warning on line 82 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L82

Added line #L82 was not covered by tests
{
if ('delete' === $type) {
$payloads = $this->getDeletePushPayloads($object);

Check warning on line 85 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L84-L85

Added lines #L84 - L85 were not covered by tests
} else {
$payloads = $this->getCreatedOrUpdatedPayloads($object);

Check warning on line 87 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L87

Added line #L87 was not covered by tests
}

return $payloads;

Check warning on line 90 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L90

Added line #L90 was not covered by tests
}

/**
* @return array<array>
*/
private function getSubscriptionsFromIri(string $iri): array

Check warning on line 96 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L96

Added line #L96 was not covered by tests
{
$subscriptionsCacheItem = $this->subscriptionsCache->getItem($this->encodeIriToCacheKey($iri));
$subscriptions = [];

if ($subscriptionsCacheItem->isHit()) {
$subscriptions = $subscriptionsCacheItem->get();
foreach ($subscriptions as [$subscriptionId, $subscriptionFields, $subscriptionResult]) {
if ($subscriptionFields === $fields) {
return $subscriptionId;
}
}
return $subscriptionsCacheItem->get();

Check warning on line 101 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L101

Added line #L101 was not covered by tests
}

$subscriptionId = $this->subscriptionIdentifierGenerator->generateSubscriptionIdentifier($fields);
unset($result['clientSubscriptionId']);
$subscriptions[] = [$subscriptionId, $fields, $result];
$subscriptionsCacheItem->set($subscriptions);
$this->subscriptionsCache->save($subscriptionsCacheItem);
return [];

Check warning on line 104 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L104

Added line #L104 was not covered by tests
}

return $subscriptionId;
private function removeItemFromSubscriptionCache(string $iri): void

Check warning on line 107 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L107

Added line #L107 was not covered by tests
{
$cacheKey = $this->encodeIriToCacheKey($iri);
if ($this->subscriptionsCache->hasItem($cacheKey)) {
$this->subscriptionsCache->deleteItem($cacheKey);

Check warning on line 111 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L109-L111

Added lines #L109 - L111 were not covered by tests
}
}

private function encodeIriToCacheKey(string $iri): string

Check warning on line 115 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L115

Added line #L115 was not covered by tests
{
return str_replace('/', '_', $iri);

Check warning on line 117 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L117

Added line #L117 was not covered by tests
}

public function getPushPayloads(object $object): array
private function getResourceId(mixed $privateField, object $previousObject): string

Check warning on line 120 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L120

Added line #L120 was not covered by tests
{
$id = $previousObject->{'get'.ucfirst($privateField)}()->getId();
if ($id instanceof \Stringable) {
return (string) $id;

Check warning on line 124 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L122-L124

Added lines #L122 - L124 were not covered by tests
}

return $id;

Check warning on line 127 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L127

Added line #L127 was not covered by tests
}

private function getCollectionIri(string $iri): string

Check warning on line 130 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L130

Added line #L130 was not covered by tests
{
return substr($iri, 0, strrpos($iri, '/'));

Check warning on line 132 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L132

Added line #L132 was not covered by tests
}
Copy link
Member

Choose a reason for hiding this comment

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

This is too hackish we need to find a better way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm all ears, I haven't found one :)


private function getCreatedOrUpdatedPayloads(object $object): array

Check warning on line 135 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L135

Added line #L135 was not covered by tests
{
$iri = $this->iriConverter->getIriFromResource($object);
$subscriptions = $this->getSubscriptionsFromIri($iri);
// Add collection subscriptions
$subscriptions = array_merge(
$this->getSubscriptionsFromIri($this->getCollectionIri($iri)),
$this->getSubscriptionsFromIri($iri)
);

Check warning on line 142 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L139-L142

Added lines #L139 - L142 were not covered by tests

$resourceClass = $this->getObjectClass($object);
$resourceMetadata = $this->resourceMetadataCollectionFactory->create($resourceClass);
$shortName = $resourceMetadata->getOperation()->getShortName();

$mercure = $resourceMetadata->getOperation()->getMercure() ?? false;
$private = $mercure['private'] ?? false;
$privateFieldsConfig = $mercure['private_fields'] ?? [];
$privateFieldData = [];
if ($private && $privateFieldsConfig) {
foreach ($privateFieldsConfig as $privateField) {
$privateFieldData['__private_field_'.$privateField] = $this->getResourceId($privateField, $object);

Check warning on line 154 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L148-L154

Added lines #L148 - L154 were not covered by tests
}
}
Copy link
Member

Choose a reason for hiding this comment

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

I've seen this logic twice, could you use a function to remove a few lines?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A Trait then? This logic is used in 2 different files.


$payloads = [];
foreach ($subscriptions as [$subscriptionId, $subscriptionFields, $subscriptionResult]) {
if ($privateFieldData) {
$fieldDiff = array_intersect_assoc($subscriptionFields, $privateFieldData);
if ($fieldDiff !== $privateFieldData) {
continue;

Check warning on line 163 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L160-L163

Added lines #L160 - L163 were not covered by tests
}
}
$resolverContext = ['fields' => $subscriptionFields, 'is_collection' => false, 'is_mutation' => false, 'is_subscription' => true];
/** @var Operation */
$operation = (new Subscription())->withName('update_subscription')->withShortName($shortName);
$operation = (new Subscription())->withName('mercure_subscription')->withShortName($shortName);

Check warning on line 167 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L167

Added line #L167 was not covered by tests
$data = $this->normalizeProcessor->process($object, $operation, [], $resolverContext);

unset($data['clientSubscriptionId']);
Expand All @@ -96,22 +177,80 @@
return $payloads;
}

/**
* @return array<array>
*/
private function getSubscriptionsFromIri(string $iri): array
private function getDeletePushPayloads(object $object): array

Check warning on line 180 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L180

Added line #L180 was not covered by tests
{
$subscriptionsCacheItem = $this->subscriptionsCache->getItem($this->encodeIriToCacheKey($iri));
$iri = $object->id;
$subscriptions = array_merge(
$this->getSubscriptionsFromIri($iri),
$this->getSubscriptionsFromIri($this->getCollectionIri($iri))
);

Check warning on line 186 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L182-L186

Added lines #L182 - L186 were not covered by tests

$payloads = [];
foreach ($subscriptions as [$subscriptionId, $subscriptionFields, $subscriptionResult]) {
$payloads[] = [$subscriptionId, ['type' => 'delete', 'payload' => $object]];

Check warning on line 190 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L188-L190

Added lines #L188 - L190 were not covered by tests
}
$this->removeItemFromSubscriptionCache($iri);

Check warning on line 192 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L192

Added line #L192 was not covered by tests

return $payloads;

Check warning on line 194 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L194

Added line #L194 was not covered by tests
}

private function updateSubscriptionItemCacheData(

Check warning on line 197 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L197

Added line #L197 was not covered by tests
string $iri,
array $fields,
?array $result,
bool $private,
array $privateFields,
?object $previousObject,
): string {
$subscriptionsCacheItem = $this->subscriptionsCache->getItem($this->encodeIriToCacheKey($iri));
$subscriptions = [];

Check warning on line 206 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L205-L206

Added lines #L205 - L206 were not covered by tests
if ($subscriptionsCacheItem->isHit()) {
return $subscriptionsCacheItem->get();
/*
* @var array<array{string, array<string, string|array>, array<string, string|array>}>
*/
$subscriptions = $subscriptionsCacheItem->get();
foreach ($subscriptions as [$subscriptionId, $subscriptionFields, $subscriptionResult]) {
if ($subscriptionFields === $fields) {
return $subscriptionId;

Check warning on line 214 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L211-L214

Added lines #L211 - L214 were not covered by tests
}
}
}

return [];
$subscriptionId = $this->subscriptionIdentifierGenerator->generateSubscriptionIdentifier($fields);
unset($result['clientSubscriptionId']);
if ($private && $privateFields && $previousObject) {
foreach ($privateFields as $privateField) {
unset($result['__private_field_'.$privateField]);

Check warning on line 223 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L219-L223

Added lines #L219 - L223 were not covered by tests
}
}
$subscriptions[] = [$subscriptionId, $fields, $result];
$subscriptionsCacheItem->set($subscriptions);
$this->subscriptionsCache->save($subscriptionsCacheItem);

Check warning on line 228 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L226-L228

Added lines #L226 - L228 were not covered by tests

return $subscriptionId;

Check warning on line 230 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L230

Added line #L230 was not covered by tests
}

private function encodeIriToCacheKey(string $iri): string
{
return str_replace('/', '_', $iri);
private function updateSubscriptionCollectionCacheData(

Check warning on line 233 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L233

Added line #L233 was not covered by tests
string $iri,
array $fields,
): string {
$subscriptionCollectionCacheItem = $this->subscriptionsCache->getItem(
$this->encodeIriToCacheKey($this->getCollectionIri($iri)),
);
$collectionSubscriptions = [];
if ($subscriptionCollectionCacheItem->isHit()) {
$collectionSubscriptions = $subscriptionCollectionCacheItem->get();
foreach ($collectionSubscriptions as [$subscriptionId, $subscriptionFields]) {
if ($subscriptionFields === $fields) {
return $subscriptionId;

Check warning on line 245 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L237-L245

Added lines #L237 - L245 were not covered by tests
}
}
}
$subscriptionId = $this->subscriptionIdentifierGenerator->generateSubscriptionIdentifier($fields + ['__collection' => true]);
$collectionSubscriptions[] = [$subscriptionId, $fields];
$subscriptionCollectionCacheItem->set($collectionSubscriptions);
$this->subscriptionsCache->save($subscriptionCollectionCacheItem);

Check warning on line 252 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L249-L252

Added lines #L249 - L252 were not covered by tests

return $subscriptionId;

Check warning on line 254 in src/GraphQl/Subscription/SubscriptionManager.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Subscription/SubscriptionManager.php#L254

Added line #L254 was not covered by tests
}
}
2 changes: 1 addition & 1 deletion src/GraphQl/Subscription/SubscriptionManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ interface SubscriptionManagerInterface
{
public function retrieveSubscriptionId(array $context, ?array $result): ?string;

public function getPushPayloads(object $object): array;
public function getPushPayloads(object $object, string $type): array;
Copy link
Member

Choose a reason for hiding this comment

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

this is a public interface, the added argument should be optional to cover the BC layer

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok

}
Loading
Loading