Skip to content

Commit 43dca41

Browse files
author
Valeriy Naida
authored
Merge pull request #3183 from magento-engcom/graphql-develop-prs
[EngCom] Public Pull Requests - GraphQL
2 parents 5f643ef + a633590 commit 43dca41

File tree

13 files changed

+340
-33
lines changed

13 files changed

+340
-33
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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\CatalogGraphQl\Model\Resolver\Product;
9+
10+
use Magento\Catalog\Model\Product;
11+
use Magento\Framework\GraphQl\Config\Element\Field;
12+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
13+
use Magento\Framework\GraphQl\Query\ResolverInterface;
14+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
15+
use Magento\Catalog\Helper\Output as OutputHelper;
16+
17+
/**
18+
* Resolve rendered content for attributes where HTML content is allowed
19+
*/
20+
class ProductHtmlAttribute implements ResolverInterface
21+
{
22+
/**
23+
* @var OutputHelper
24+
*/
25+
private $outputHelper;
26+
27+
/**
28+
* @param OutputHelper $outputHelper
29+
*/
30+
public function __construct(
31+
OutputHelper $outputHelper
32+
) {
33+
$this->outputHelper = $outputHelper;
34+
}
35+
36+
/**
37+
* @inheritdoc
38+
*/
39+
public function resolve(
40+
Field $field,
41+
$context,
42+
ResolveInfo $info,
43+
array $value = null,
44+
array $args = null
45+
) {
46+
if (!isset($value['model'])) {
47+
throw new GraphQlInputException(__('"model" value should be specified'));
48+
}
49+
50+
/* @var $product Product */
51+
$product = $value['model'];
52+
$fieldName = $field->getName();
53+
$renderedValue = $this->outputHelper->productAttribute($product, $product->getData($fieldName), $fieldName);
54+
return $renderedValue;
55+
}
56+
}

app/code/Magento/CatalogGraphQl/etc/schema.graphqls

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,8 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\
248248
id: Int @doc(description: "The ID number assigned to the product") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\EntityIdToId")
249249
name: String @doc(description: "The product name. Customers use this name to identify the product.")
250250
sku: String @doc(description: "A number or code assigned to a product to identify the product, options, price, and manufacturer")
251-
description: String @doc(description: "Detailed information about the product. The value can include simple HTML tags.")
252-
short_description: String @doc(description: "A short description of the product. Its use depends on the theme.")
251+
description: String @doc(description: "Detailed information about the product. The value can include simple HTML tags.") @resolver(class: "\\Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\ProductHtmlAttribute")
252+
short_description: String @doc(description: "A short description of the product. Its use depends on the theme.") @resolver(class: "\\Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\ProductHtmlAttribute")
253253
special_price: Float @doc(description: "The discounted price of the product")
254254
special_from_date: String @doc(description: "The beginning date that a product has a special price")
255255
special_to_date: String @doc(description: "The end date that a product has a special price")
@@ -548,6 +548,6 @@ type SortField {
548548
}
549549

550550
type SortFields @doc(description: "SortFields contains a default value for sort fields and all available sort fields") {
551-
default: String @doc(description: "Default value of sort fields")
551+
default: String @doc(description: "Default value of sort fields")
552552
options: [SortField] @doc(description: "Available sort fields")
553553
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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\Resolver\Customer\Account;
9+
10+
use Magento\Framework\Exception\AuthenticationException;
11+
use Magento\Framework\GraphQl\Config\Element\Field;
12+
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
13+
use Magento\Framework\GraphQl\Query\ResolverInterface;
14+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
15+
use Magento\Integration\Api\CustomerTokenServiceInterface;
16+
17+
/**
18+
* Customers Token resolver, used for GraphQL request processing.
19+
*/
20+
class GenerateCustomerToken implements ResolverInterface
21+
{
22+
/**
23+
* @var CustomerTokenServiceInterface
24+
*/
25+
private $customerTokenService;
26+
27+
/**
28+
* @param CustomerTokenServiceInterface $customerTokenService
29+
*/
30+
public function __construct(
31+
CustomerTokenServiceInterface $customerTokenService
32+
) {
33+
$this->customerTokenService = $customerTokenService;
34+
}
35+
36+
/**
37+
* @inheritdoc
38+
*/
39+
public function resolve(
40+
Field $field,
41+
$context,
42+
ResolveInfo $info,
43+
array $value = null,
44+
array $args = null
45+
) {
46+
try {
47+
if (!isset($args['email'])) {
48+
throw new GraphQlInputException(__('"email" value should be specified'));
49+
}
50+
if (!isset($args['password'])) {
51+
throw new GraphQlInputException(__('"password" value should be specified'));
52+
}
53+
$token = $this->customerTokenService->createCustomerAccessToken($args['email'], $args['password']);
54+
return ['token' => $token];
55+
} catch (AuthenticationException $e) {
56+
throw new GraphQlAuthorizationException(
57+
__($e->getMessage())
58+
);
59+
}
60+
}
61+
}

app/code/Magento/CustomerGraphQl/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"php": "~7.1.3||~7.2.0",
77
"magento/module-customer": "*",
88
"magento/module-authorization": "*",
9+
"magento/module-integration": "*",
910
"magento/framework": "*"
1011
},
1112
"suggest": {

app/code/Magento/CustomerGraphQl/etc/schema.graphqls

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ type Query {
55
customer: Customer @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\Customer") @doc(description: "The customer query returns information about a customer account")
66
}
77

8+
type Mutation {
9+
generateCustomerToken(email: String!, password: String!): CustomerToken @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\Customer\\Account\\GenerateCustomerToken") @doc(description:"Retrieve Customer token")
10+
}
11+
12+
type CustomerToken {
13+
token: String @doc(description: "The customer token")
14+
}
15+
816
type Customer @doc(description: "Customer defines the customer name and address and other details") {
917
created_at: String @doc(description: "Timestamp indicating when the account was created")
1018
group_id: Int @doc(description: "The group assigned to the user. Default values are 0 (Not logged in), 1 (General), 2 (Wholesale), and 3 (Retailer)")

app/code/Magento/Quote/Model/MaskedQuoteIdToQuoteId.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
use Magento\Quote\Api\CartRepositoryInterface;
1111
use Magento\Quote\Model\ResourceModel\Quote\QuoteIdMask as QuoteIdMaskResource;
1212

13+
/**
14+
* MaskedQuoteId to QuoteId resolver
15+
*/
1316
class MaskedQuoteIdToQuoteId implements MaskedQuoteIdToQuoteIdInterface
1417
{
1518
/**

app/code/Magento/Quote/Model/QuoteIdToMaskedQuoteId.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,40 @@
88
namespace Magento\Quote\Model;
99

1010
use Magento\Quote\Api\CartRepositoryInterface;
11+
use Magento\Quote\Model\ResourceModel\Quote\QuoteIdMask as QuoteIdMaskResource;
1112

13+
/**
14+
* QuoteId to MaskedQuoteId resolver
15+
*/
1216
class QuoteIdToMaskedQuoteId implements QuoteIdToMaskedQuoteIdInterface
1317
{
1418
/**
1519
* @var QuoteIdMaskFactory
1620
*/
1721
private $quoteIdMaskFactory;
18-
1922
/**
2023
* @var CartRepositoryInterface
2124
*/
2225
private $cartRepository;
2326

27+
/**
28+
* @var QuoteIdMaskResource
29+
*/
30+
private $quoteIdMaskResource;
31+
2432
/**
2533
* @param QuoteIdMaskFactory $quoteIdMaskFactory
2634
* @param CartRepositoryInterface $cartRepository
35+
* @param QuoteIdMaskResource $quoteIdMaskResource
2736
*/
2837
public function __construct(
2938
QuoteIdMaskFactory $quoteIdMaskFactory,
30-
CartRepositoryInterface $cartRepository
39+
CartRepositoryInterface $cartRepository,
40+
QuoteIdMaskResource $quoteIdMaskResource
3141
) {
3242
$this->quoteIdMaskFactory = $quoteIdMaskFactory;
3343
$this->cartRepository = $cartRepository;
44+
$this->quoteIdMaskResource = $quoteIdMaskResource;
3445
}
3546

3647
/**
@@ -42,8 +53,9 @@ public function execute(int $quoteId): string
4253
$this->cartRepository->get($quoteId);
4354

4455
$quoteIdMask = $this->quoteIdMaskFactory->create();
45-
$quoteIdMask->setQuoteId($quoteId)->save();
56+
$this->quoteIdMaskResource->load($quoteIdMask, $quoteId, 'quote_id');
57+
$maskedId = $quoteIdMask->getMaskedId() ?? '';
4658

47-
return $quoteIdMask->getMaskedId();
59+
return $maskedId;
4860
}
4961
}

app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/CreateEmptyCart.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Magento\Quote\Api\CartManagementInterface;
1515
use Magento\Quote\Api\GuestCartManagementInterface;
1616
use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface;
17+
use Magento\Quote\Model\QuoteIdMaskFactory;
1718

1819
/**
1920
* @inheritdoc
@@ -24,7 +25,6 @@ class CreateEmptyCart implements ResolverInterface
2425
* @var CartManagementInterface
2526
*/
2627
private $cartManagement;
27-
2828
/**
2929
* @var GuestCartManagementInterface
3030
*/
@@ -40,22 +40,30 @@ class CreateEmptyCart implements ResolverInterface
4040
*/
4141
private $userContext;
4242

43+
/**
44+
* @var QuoteIdMaskFactory
45+
*/
46+
private $quoteIdMaskFactory;
47+
4348
/**
4449
* @param CartManagementInterface $cartManagement
4550
* @param GuestCartManagementInterface $guestCartManagement
4651
* @param UserContextInterface $userContext
4752
* @param QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedId
53+
* @param QuoteIdMaskFactory $quoteIdMaskFactory
4854
*/
4955
public function __construct(
5056
CartManagementInterface $cartManagement,
5157
GuestCartManagementInterface $guestCartManagement,
5258
UserContextInterface $userContext,
53-
QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedId
59+
QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedId,
60+
QuoteIdMaskFactory $quoteIdMaskFactory
5461
) {
5562
$this->cartManagement = $cartManagement;
5663
$this->guestCartManagement = $guestCartManagement;
5764
$this->userContext = $userContext;
5865
$this->quoteIdToMaskedId = $quoteIdToMaskedId;
66+
$this->quoteIdMaskFactory = $quoteIdMaskFactory;
5967
}
6068

6169
/**
@@ -67,7 +75,13 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
6775

6876
if (0 !== $customerId && null !== $customerId) {
6977
$quoteId = $this->cartManagement->createEmptyCartForCustomer($customerId);
70-
$maskedQuoteId = $this->quoteIdToMaskedId->execute($quoteId);
78+
$maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quoteId);
79+
80+
if (empty($maskedQuoteId)) {
81+
$quoteIdMask = $this->quoteIdMaskFactory->create();
82+
$quoteIdMask->setQuoteId($quoteId)->save();
83+
$maskedQuoteId = $quoteIdMask->getMaskedId();
84+
}
7185
} else {
7286
$maskedQuoteId = $this->guestCartManagement->createEmptyCart();
7387
}

app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public function resolve(
7575
if ($urlRewrite) {
7676
$result = [
7777
'id' => $urlRewrite->getEntityId(),
78-
'canonical_url' => $urlRewrite->getTargetPath(),
78+
'relative_url' => $urlRewrite->getTargetPath(),
7979
'type' => $this->sanitizeType($urlRewrite->getEntityType())
8080
];
8181
}

app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# Copyright © Magento, Inc. All rights reserved.
22
# See COPYING.txt for license details.
33

4-
type EntityUrl @doc(description: "EntityUrl is an output object containing the `id`, `canonical_url`, and `type` attributes") {
4+
type EntityUrl @doc(description: "EntityUrl is an output object containing the `id`, `relative_url`, and `type` attributes") {
55
id: Int @doc(description: "The ID assigned to the object associated with the specified url. This could be a product ID, category ID, or page ID.")
6-
canonical_url: String @doc(description: "The internal relative URL. If the specified url is a redirect, the query returns the redirected URL, not the original.")
6+
relative_url: String @doc(description: "The internal relative URL. If the specified url is a redirect, the query returns the redirected URL, not the original.")
77
type: UrlRewriteEntityTypeEnum @doc(description: "One of PRODUCT, CATEGORY, or CMS_PAGE.")
88
}
99

1010
type Query {
11-
urlResolver(url: String!): EntityUrl @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\UrlRewrite") @doc(description: "The urlResolver query returns the canonical URL for a specified product, category or CMS page")
11+
urlResolver(url: String!): EntityUrl @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\UrlRewrite") @doc(description: "The urlResolver query returns the relative URL for a specified product, category or CMS page")
1212
}
1313

1414
enum UrlRewriteEntityTypeEnum {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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\Catalog;
9+
10+
use Magento\Catalog\Api\Data\ProductInterface;
11+
use Magento\Catalog\Api\ProductRepositoryInterface;
12+
use Magento\TestFramework\ObjectManager;
13+
use Magento\TestFramework\TestCase\GraphQlAbstract;
14+
15+
/**
16+
* Test for checking that product fields with directives allowed are rendered correctly
17+
*/
18+
class ProductWithDescriptionDirectivesTest extends GraphQlAbstract
19+
{
20+
/**
21+
* @var \Magento\TestFramework\ObjectManager
22+
*/
23+
private $objectManager;
24+
25+
protected function setUp()
26+
{
27+
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
28+
}
29+
30+
/**
31+
* @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
32+
* @magentoApiDataFixture Magento/Cms/_files/block.php
33+
*/
34+
public function testHtmlDirectivesRendered()
35+
{
36+
$productSku = 'simple';
37+
$cmsBlockId = 'fixture_block';
38+
$assertionCmsBlockText = 'Fixture Block Title';
39+
40+
/** @var ProductRepositoryInterface $productRepository */
41+
$productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class);
42+
/** @var ProductInterface $product */
43+
$product = $productRepository->get($productSku, false, null, true);
44+
$product->setDescription('Test: {{block id="' . $cmsBlockId . '"}}');
45+
$product->setShortDescription('Test: {{block id="' . $cmsBlockId . '"}}');
46+
$productRepository->save($product);
47+
48+
$query = <<<QUERY
49+
{
50+
products(filter: {sku: {eq: "{$productSku}"}}) {
51+
items {
52+
description
53+
short_description
54+
}
55+
}
56+
}
57+
QUERY;
58+
$response = $this->graphQlQuery($query);
59+
60+
self::assertContains($assertionCmsBlockText, $response['products']['items'][0]['description']);
61+
self::assertNotContains('{{block id', $response['products']['items'][0]['description']);
62+
self::assertContains($assertionCmsBlockText, $response['products']['items'][0]['short_description']);
63+
self::assertNotContains('{{block id', $response['products']['items'][0]['short_description']);
64+
}
65+
}

0 commit comments

Comments
 (0)