180 lines
4.3 KiB
PHP
180 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace Nuwave\Lighthouse\Subscriptions;
|
|
|
|
use GraphQL\Language\AST\DocumentNode;
|
|
use GraphQL\Language\AST\NodeList;
|
|
use GraphQL\Type\Definition\ResolveInfo;
|
|
use GraphQL\Utils\AST;
|
|
use Illuminate\Support\Str;
|
|
use Nuwave\Lighthouse\Subscriptions\Contracts\ContextSerializer;
|
|
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
|
use Serializable;
|
|
|
|
class Subscriber implements Serializable
|
|
{
|
|
/**
|
|
* A unique key for the subscriber's channel.
|
|
*
|
|
* This has to be unique for each subscriber, because each of them can send a different
|
|
* query and must receive a response that is specifically tailored towards that.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $channel;
|
|
|
|
/**
|
|
* The topic subscribed to.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $topic;
|
|
|
|
/**
|
|
* The contents of the query.
|
|
*
|
|
* @var \GraphQL\Language\AST\DocumentNode
|
|
*/
|
|
public $query;
|
|
|
|
/**
|
|
* The name of the queried field.
|
|
*
|
|
* Guaranteed be be unique because of
|
|
* @see \GraphQL\Validator\Rules\SingleFieldSubscription
|
|
*
|
|
* @var string
|
|
*/
|
|
public $fieldName;
|
|
|
|
/**
|
|
* The root element of the query.
|
|
*
|
|
* @var mixed Can be anything.
|
|
*/
|
|
public $root;
|
|
|
|
/**
|
|
* The args passed to the subscription query.
|
|
*
|
|
* @var array<string, mixed>
|
|
*/
|
|
public $args;
|
|
|
|
/**
|
|
* The variables passed to the subscription query.
|
|
*
|
|
* @var array<string, mixed>
|
|
*/
|
|
public $variables;
|
|
|
|
/**
|
|
* The context passed to the query.
|
|
*
|
|
* @var \Nuwave\Lighthouse\Support\Contracts\GraphQLContext
|
|
*/
|
|
public $context;
|
|
|
|
/**
|
|
* @param array<string, mixed> $args
|
|
*/
|
|
public function __construct(
|
|
array $args,
|
|
GraphQLContext $context,
|
|
ResolveInfo $resolveInfo
|
|
) {
|
|
$this->fieldName = $resolveInfo->fieldName;
|
|
$this->channel = self::uniqueChannelName();
|
|
$this->args = $args;
|
|
$this->variables = $resolveInfo->variableValues;
|
|
$this->context = $context;
|
|
|
|
/**
|
|
* Must be here, since webonyx/graphql-php validated the subscription.
|
|
*
|
|
* @var \GraphQL\Language\AST\OperationDefinitionNode $operation
|
|
*/
|
|
$operation = $resolveInfo->operation;
|
|
|
|
$this->query = new DocumentNode([
|
|
'definitions' => new NodeList(array_merge(
|
|
$resolveInfo->fragments,
|
|
[$operation]
|
|
)),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Unserialize subscription from a JSON string.
|
|
*
|
|
* @param string $subscription
|
|
*/
|
|
public function unserialize($subscription): void
|
|
{
|
|
$data = \Safe\json_decode($subscription, true);
|
|
|
|
$this->channel = $data['channel'];
|
|
$this->topic = $data['topic'];
|
|
|
|
/**
|
|
* We know the type since it is set during construction and serialized.
|
|
*
|
|
* @var \GraphQL\Language\AST\DocumentNode $documentNode
|
|
*/
|
|
$documentNode = AST::fromArray(
|
|
unserialize($data['query'])
|
|
);
|
|
$this->query = $documentNode;
|
|
$this->fieldName = $data['field_name'];
|
|
$this->args = $data['args'];
|
|
$this->variables = $data['variables'];
|
|
$this->context = $this->contextSerializer()->unserialize(
|
|
$data['context']
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Convert this into a JSON string.
|
|
*/
|
|
public function serialize(): string
|
|
{
|
|
return \Safe\json_encode([
|
|
'channel' => $this->channel,
|
|
'topic' => $this->topic,
|
|
'query' => serialize(
|
|
AST::toArray($this->query)
|
|
),
|
|
'field_name' => $this->fieldName,
|
|
'args' => $this->args,
|
|
'variables' => $this->variables,
|
|
'context' => $this->contextSerializer()->serialize($this->context),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Set root data.
|
|
*
|
|
* @return $this
|
|
* @deprecated set the attribute directly
|
|
*/
|
|
public function setRoot($root): self
|
|
{
|
|
$this->root = $root;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Generate a unique private channel name.
|
|
*/
|
|
public static function uniqueChannelName(): string
|
|
{
|
|
return 'private-lighthouse-'.Str::random(32).'-'.time();
|
|
}
|
|
|
|
protected function contextSerializer(): ContextSerializer
|
|
{
|
|
return app(ContextSerializer::class);
|
|
}
|
|
}
|