Skip to content

Commit 3096057

Browse files
committed
magento/graphql-ce#741: Add extension point to set custom parameters to Query Context object
1 parent dffe94d commit 3096057

File tree

14 files changed

+563
-185
lines changed

14 files changed

+563
-185
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Context;
9+
10+
use Magento\Authorization\Model\UserContextInterface;
11+
use Magento\GraphQl\Model\Query\ContextParametersInterface;
12+
use Magento\GraphQl\Model\Query\ContextParametersProcessorInterface;
13+
14+
/**
15+
* @inheritdoc
16+
*/
17+
class AddUserInfoToContext implements ContextParametersProcessorInterface
18+
{
19+
/**
20+
* @var UserContextInterface
21+
*/
22+
private $userContext;
23+
24+
/**
25+
* @var GetCustomer
26+
*/
27+
private $getCustomer;
28+
29+
/**
30+
* @param UserContextInterface $userContext
31+
* @param GetCustomer $getCustomer
32+
*/
33+
public function __construct(
34+
UserContextInterface $userContext,
35+
GetCustomer $getCustomer
36+
) {
37+
$this->userContext = $userContext;
38+
$this->getCustomer = $getCustomer;
39+
}
40+
41+
/**
42+
* @inheritdoc
43+
*/
44+
public function execute(ContextParametersInterface $contextParameters): ContextParametersInterface
45+
{
46+
$currentUserId = $this->userContext->getUserId();
47+
if (null !== $currentUserId) {
48+
$currentUserId = (int)$currentUserId;
49+
}
50+
51+
$currentUserType = $this->userContext->getUserType();
52+
if (null !== $currentUserType) {
53+
$currentUserType = (int)$currentUserType;
54+
}
55+
56+
if (false === $this->isUserGuest($currentUserId, $currentUserType)) {
57+
$customer = $this->getCustomer->execute($currentUserId);
58+
$contextParameters->addExtensionAttribute('customer', $customer);
59+
}
60+
61+
$contextParameters->setUserId($currentUserId);
62+
$contextParameters->setUserType($currentUserType);
63+
return $contextParameters;
64+
}
65+
66+
/**
67+
* Checking if current customer is guest
68+
*
69+
* @param int|null $customerId
70+
* @param int|null $customerType
71+
* @return bool
72+
*/
73+
private function isUserGuest(?int $customerId, ?int $customerType): bool
74+
{
75+
if (null === $customerId || null === $customerType) {
76+
return true;
77+
}
78+
return 0 === (int)$customerId || (int)$customerType === UserContextInterface::USER_TYPE_GUEST;
79+
}
80+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Context;
9+
10+
use Magento\Customer\Api\AccountManagementInterface;
11+
use Magento\Customer\Api\CustomerRepositoryInterface;
12+
use Magento\Customer\Api\Data\CustomerInterface;
13+
use Magento\Customer\Model\AuthenticationInterface;
14+
use Magento\Framework\Exception\LocalizedException;
15+
use Magento\Framework\Exception\NoSuchEntityException;
16+
use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException;
17+
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
18+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
19+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
20+
21+
/**
22+
* Get customer
23+
*/
24+
class GetCustomer
25+
{
26+
/**
27+
* @var AuthenticationInterface
28+
*/
29+
private $authentication;
30+
31+
/**
32+
* @var CustomerRepositoryInterface
33+
*/
34+
private $customerRepository;
35+
36+
/**
37+
* @var AccountManagementInterface
38+
*/
39+
private $accountManagement;
40+
41+
/**
42+
* @param AuthenticationInterface $authentication
43+
* @param CustomerRepositoryInterface $customerRepository
44+
* @param AccountManagementInterface $accountManagement
45+
*/
46+
public function __construct(
47+
AuthenticationInterface $authentication,
48+
CustomerRepositoryInterface $customerRepository,
49+
AccountManagementInterface $accountManagement
50+
) {
51+
$this->authentication = $authentication;
52+
$this->customerRepository = $customerRepository;
53+
$this->accountManagement = $accountManagement;
54+
}
55+
56+
/**
57+
* Get customer
58+
*
59+
* @param int $customerId
60+
* @return void
61+
* @throws GraphQlAuthenticationException
62+
* @throws GraphQlAuthorizationException
63+
* @throws GraphQlInputException
64+
* @throws GraphQlNoSuchEntityException
65+
*/
66+
public function execute(int $customerId): CustomerInterface
67+
{
68+
try {
69+
$customer = $this->customerRepository->getById($customerId);
70+
} catch (NoSuchEntityException $e) {
71+
throw new GraphQlNoSuchEntityException(
72+
__('Customer with id "%customer_id" does not exist.', ['customer_id' => $customerId]),
73+
$e
74+
);
75+
} catch (LocalizedException $e) {
76+
throw new GraphQlInputException(__($e->getMessage()));
77+
}
78+
79+
if (true === $this->authentication->isLocked($customerId)) {
80+
throw new GraphQlAuthenticationException(__('The account is locked.'));
81+
}
82+
83+
try {
84+
$confirmationStatus = $this->accountManagement->getConfirmationStatus($customerId);
85+
} catch (LocalizedException $e) {
86+
throw new GraphQlInputException(__($e->getMessage()));
87+
}
88+
89+
if ($confirmationStatus === AccountManagementInterface::ACCOUNT_CONFIRMATION_REQUIRED) {
90+
throw new GraphQlAuthenticationException(__("This account isn't confirmed. Verify and try again."));
91+
}
92+
return $customer;
93+
}
94+
}

app/code/Magento/CustomerGraphQl/etc/graphql/di.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,11 @@
1313
</argument>
1414
</arguments>
1515
</type>
16+
<type name="Magento\GraphQl\Model\Query\ContextFactory">
17+
<arguments>
18+
<argument name="contextParametersProcessors" xsi:type="array">
19+
<item name="add_customer_to_context" xsi:type="object">Magento\CustomerGraphQl\Model\Context\AddUserInfoToContext</item>
20+
</argument>
21+
</arguments>
22+
</type>
1623
</config>

app/code/Magento/GraphQl/Controller/GraphQl.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
use Magento\Framework\App\ResponseInterface;
1414
use Magento\Framework\GraphQl\Exception\ExceptionFormatter;
1515
use Magento\Framework\GraphQl\Query\QueryProcessor;
16-
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
1716
use Magento\Framework\GraphQl\Schema\SchemaGeneratorInterface;
1817
use Magento\Framework\Serialize\SerializerInterface;
1918
use Magento\Framework\Webapi\Response;
2019
use Magento\Framework\App\Response\Http as HttpResponse;
2120
use Magento\Framework\GraphQl\Query\Fields as QueryFields;
2221
use Magento\Framework\Controller\Result\JsonFactory;
2322
use Magento\Framework\App\ObjectManager;
23+
use Magento\GraphQl\Model\Query\ContextFactoryInterface;
2424

2525
/**
2626
* Front controller for web API GraphQL area.
@@ -57,9 +57,9 @@ class GraphQl implements FrontControllerInterface
5757
private $graphQlError;
5858

5959
/**
60-
* @var ContextInterface
60+
* @var ContextFactoryInterface
6161
*/
62-
private $resolverContext;
62+
private $contextFactory;
6363

6464
/**
6565
* @var HttpRequestProcessor
@@ -87,7 +87,7 @@ class GraphQl implements FrontControllerInterface
8787
* @param SerializerInterface $jsonSerializer
8888
* @param QueryProcessor $queryProcessor
8989
* @param ExceptionFormatter $graphQlError
90-
* @param ContextInterface $resolverContext
90+
* @param ContextFactoryInterface $contextFactory
9191
* @param HttpRequestProcessor $requestProcessor
9292
* @param QueryFields $queryFields
9393
* @param JsonFactory|null $jsonFactory
@@ -100,7 +100,7 @@ public function __construct(
100100
SerializerInterface $jsonSerializer,
101101
QueryProcessor $queryProcessor,
102102
ExceptionFormatter $graphQlError,
103-
ContextInterface $resolverContext,
103+
ContextFactoryInterface $contextFactory,
104104
HttpRequestProcessor $requestProcessor,
105105
QueryFields $queryFields,
106106
JsonFactory $jsonFactory = null,
@@ -111,7 +111,7 @@ public function __construct(
111111
$this->jsonSerializer = $jsonSerializer;
112112
$this->queryProcessor = $queryProcessor;
113113
$this->graphQlError = $graphQlError;
114-
$this->resolverContext = $resolverContext;
114+
$this->contextFactory = $contextFactory;
115115
$this->requestProcessor = $requestProcessor;
116116
$this->queryFields = $queryFields;
117117
$this->jsonFactory = $jsonFactory ?: ObjectManager::getInstance()->get(JsonFactory::class);
@@ -144,7 +144,7 @@ public function dispatch(RequestInterface $request) : ResponseInterface
144144
$result = $this->queryProcessor->process(
145145
$schema,
146146
$query,
147-
$this->resolverContext,
147+
$this->contextFactory->create(),
148148
$data['variables'] ?? []
149149
);
150150
} catch (\Exception $error) {
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\GraphQl\Model\Query;
9+
10+
/**
11+
* Concrete implementation for @see ContextInterface
12+
*
13+
* The purpose for this that GraphQL specification wants to make use of such object where multiple modules can
14+
* participate with data through extension attributes.
15+
*/
16+
class Context implements ContextInterface
17+
{
18+
/**
19+
* @var int|null
20+
*/
21+
private $userType;
22+
23+
/**
24+
* @var int|null
25+
*/
26+
private $userId;
27+
28+
/**
29+
* @var ContextExtensionInterface
30+
*/
31+
private $extensionAttributes;
32+
33+
/**
34+
* @param int|null $userType
35+
* @param int|null $userId
36+
* @param ContextExtensionInterface $extensionAttributes
37+
*/
38+
public function __construct(
39+
?int $userType,
40+
?int $userId,
41+
ContextExtensionInterface $extensionAttributes
42+
) {
43+
$this->userType = $userType;
44+
$this->userId = $userId;
45+
$this->extensionAttributes = $extensionAttributes;
46+
}
47+
48+
49+
/**
50+
* @inheritdoc
51+
*/
52+
public function getUserType(): ?int
53+
{
54+
return $this->userType;
55+
}
56+
57+
/**
58+
* @inheritdoc
59+
*/
60+
public function getUserId(): ?int
61+
{
62+
return $this->userId;
63+
}
64+
65+
/**
66+
* @inheritdoc
67+
*/
68+
public function getExtensionAttributes(): ContextExtensionInterface
69+
{
70+
return $this->extensionAttributes;
71+
}
72+
}

0 commit comments

Comments
 (0)