Skip to content

Commit 1a805d0

Browse files
author
Valeriy Naida
authored
Merge pull request #3470 from magento-engcom/graphql-develop-prs
[EngCom] Public Pull Requests - GraphQL
2 parents 5e17b04 + 1022233 commit 1a805d0

File tree

13 files changed

+495
-4
lines changed

13 files changed

+495
-4
lines changed

app/code/Magento/CatalogGraphQl/Model/Category/Hydrator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ public function hydrateCategory(Category $category, $basicFieldsOnly = false) :
5252
$categoryData = $category->getData();
5353
} else {
5454
$categoryData = $this->dataObjectProcessor->buildOutputDataArray($category, CategoryInterface::class);
55-
$categoryData['product_count'] = $category->getProductCount();
5655
}
5756
$categoryData['id'] = $category->getId();
5857
$categoryData['children'] = [];
5958
$categoryData['available_sort_by'] = $category->getAvailableSortBy();
59+
$categoryData['model'] = $category;
6060
return $this->flattener->flatten($categoryData);
6161
}
6262
}

app/code/Magento/CatalogGraphQl/Model/Resolver/Category/Products.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ public function resolve(
9292
'items' => $searchResult->getProductsSearchResult(),
9393
'page_info' => [
9494
'page_size' => $searchCriteria->getPageSize(),
95-
'current_page' => $currentPage
95+
'current_page' => $currentPage,
96+
'total_pages' => $maxPages
9697
]
9798
];
9899
return $data;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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\Category;
9+
10+
use Magento\Catalog\Model\Category;
11+
use Magento\Catalog\Model\Product\Visibility;
12+
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\StockProcessor;
13+
use Magento\Framework\Api\SearchCriteriaInterface;
14+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
15+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
16+
use Magento\Framework\GraphQl\Config\Element\Field;
17+
use Magento\Framework\GraphQl\Query\ResolverInterface;
18+
19+
/**
20+
* Retrieves products count for a category
21+
*/
22+
class ProductsCount implements ResolverInterface
23+
{
24+
/**
25+
* @var Visibility
26+
*/
27+
private $catalogProductVisibility;
28+
29+
/**
30+
* @var StockProcessor
31+
*/
32+
private $stockProcessor;
33+
34+
/**
35+
* @var SearchCriteriaInterface
36+
*/
37+
private $searchCriteria;
38+
39+
/**
40+
* @param Visibility $catalogProductVisibility
41+
* @param SearchCriteriaInterface $searchCriteria
42+
* @param StockProcessor $stockProcessor
43+
*/
44+
public function __construct(
45+
Visibility $catalogProductVisibility,
46+
SearchCriteriaInterface $searchCriteria,
47+
StockProcessor $stockProcessor
48+
) {
49+
$this->catalogProductVisibility = $catalogProductVisibility;
50+
$this->searchCriteria = $searchCriteria;
51+
$this->stockProcessor = $stockProcessor;
52+
}
53+
54+
/**
55+
* @inheritdoc
56+
*/
57+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
58+
{
59+
if (!isset($value['model'])) {
60+
throw new GraphQlInputException(__('"model" value should be specified'));
61+
}
62+
/** @var Category $category */
63+
$category = $value['model'];
64+
$productsCollection = $category->getProductCollection();
65+
$productsCollection->setVisibility($this->catalogProductVisibility->getVisibleInSiteIds());
66+
$productsCollection = $this->stockProcessor->process($productsCollection, $this->searchCriteria, []);
67+
68+
return $productsCollection->getSize();
69+
}
70+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model
377377
level: Int @doc(description: "Indicates the depth of the category within the tree")
378378
created_at: String @doc(description: "Timestamp indicating when the category was created")
379379
updated_at: String @doc(description: "Timestamp indicating when the category was updated")
380-
product_count: Int @doc(description: "The number of products in the category")
380+
product_count: Int @doc(description: "The number of products in the category") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\ProductsCount")
381381
default_sort_by: String @doc(description: "The attribute to use for sorting")
382382
products(
383383
pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."),
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
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\SendFriendGraphQl\Model\Resolver;
9+
10+
use Magento\Catalog\Api\Data\ProductInterface;
11+
use Magento\Catalog\Api\ProductRepositoryInterface;
12+
use Magento\Framework\DataObjectFactory;
13+
use Magento\Framework\Event\ManagerInterface;
14+
use Magento\Framework\Exception\NoSuchEntityException;
15+
use Magento\Framework\GraphQl\Config\Element\Field;
16+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
17+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
18+
use Magento\Framework\GraphQl\Query\ResolverInterface;
19+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
20+
use Magento\SendFriend\Model\SendFriend;
21+
use Magento\SendFriend\Model\SendFriendFactory;
22+
23+
/**
24+
* @inheritdoc
25+
*/
26+
class SendEmailToFriend implements ResolverInterface
27+
{
28+
/**
29+
* @var SendFriendFactory
30+
*/
31+
private $sendFriendFactory;
32+
33+
/**
34+
* @var ProductRepositoryInterface
35+
*/
36+
private $productRepository;
37+
38+
/**
39+
* @var DataObjectFactory
40+
*/
41+
private $dataObjectFactory;
42+
43+
/**
44+
* @var ManagerInterface
45+
*/
46+
private $eventManager;
47+
48+
/**
49+
* @param SendFriendFactory $sendFriendFactory
50+
* @param ProductRepositoryInterface $productRepository
51+
* @param DataObjectFactory $dataObjectFactory
52+
* @param ManagerInterface $eventManager
53+
*/
54+
public function __construct(
55+
SendFriendFactory $sendFriendFactory,
56+
ProductRepositoryInterface $productRepository,
57+
DataObjectFactory $dataObjectFactory,
58+
ManagerInterface $eventManager
59+
) {
60+
$this->sendFriendFactory = $sendFriendFactory;
61+
$this->productRepository = $productRepository;
62+
$this->dataObjectFactory = $dataObjectFactory;
63+
$this->eventManager = $eventManager;
64+
}
65+
66+
/**
67+
* @inheritdoc
68+
*/
69+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
70+
{
71+
/** @var SendFriend $sendFriend */
72+
$sendFriend = $this->sendFriendFactory->create();
73+
74+
if ($sendFriend->getMaxSendsToFriend() && $sendFriend->isExceedLimit()) {
75+
throw new GraphQlInputException(
76+
__('You can\'t send messages more than %1 times an hour.', $sendFriend->getMaxSendsToFriend())
77+
);
78+
}
79+
80+
$product = $this->getProduct($args['input']['product_id']);
81+
$this->eventManager->dispatch('sendfriend_product', ['product' => $product]);
82+
$sendFriend->setProduct($product);
83+
84+
$senderData = $this->extractSenderData($args);
85+
$sendFriend->setSender($senderData);
86+
87+
$recipientsData = $this->extractRecipientsData($args);
88+
$sendFriend->setRecipients($recipientsData);
89+
90+
$this->validateSendFriendModel($sendFriend, $senderData, $recipientsData);
91+
$sendFriend->send();
92+
93+
return array_merge($senderData, $recipientsData);
94+
}
95+
96+
/**
97+
* Validate send friend model
98+
*
99+
* @param SendFriend $sendFriend
100+
* @param array $senderData
101+
* @param array $recipientsData
102+
* @return void
103+
* @throws GraphQlInputException
104+
*/
105+
private function validateSendFriendModel(SendFriend $sendFriend, array $senderData, array $recipientsData): void
106+
{
107+
$sender = $this->dataObjectFactory->create()->setData($senderData['sender']);
108+
$sendFriend->setData('_sender', $sender);
109+
110+
$emails = array_column($recipientsData['recipients'], 'email');
111+
$recipients = $this->dataObjectFactory->create()->setData('emails', $emails);
112+
$sendFriend->setData('_recipients', $recipients);
113+
114+
$validationResult = $sendFriend->validate();
115+
if ($validationResult !== true) {
116+
throw new GraphQlInputException(__(implode($validationResult)));
117+
}
118+
}
119+
120+
/**
121+
* Get product
122+
*
123+
* @param int $productId
124+
* @return ProductInterface
125+
* @throws GraphQlNoSuchEntityException
126+
*/
127+
private function getProduct(int $productId): ProductInterface
128+
{
129+
try {
130+
$product = $this->productRepository->getById($productId);
131+
if (!$product->isVisibleInCatalog()) {
132+
throw new GraphQlNoSuchEntityException(
133+
__("The product that was requested doesn't exist. Verify the product and try again.")
134+
);
135+
}
136+
} catch (NoSuchEntityException $e) {
137+
throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
138+
}
139+
return $product;
140+
}
141+
142+
/**
143+
* Extract recipients data
144+
*
145+
* @param array $args
146+
* @return array
147+
* @throws GraphQlInputException
148+
*/
149+
private function extractRecipientsData(array $args): array
150+
{
151+
$recipients = [];
152+
foreach ($args['input']['recipients'] as $recipient) {
153+
if (empty($recipient['name'])) {
154+
throw new GraphQlInputException(__('Please provide Name for all of recipients.'));
155+
}
156+
157+
if (empty($recipient['email'])) {
158+
throw new GraphQlInputException(__('Please provide Email for all of recipients.'));
159+
}
160+
161+
$recipients[] = [
162+
'name' => $recipient['name'],
163+
'email' => $recipient['email'],
164+
];
165+
}
166+
return ['recipients' => $recipients];
167+
}
168+
169+
/**
170+
* Extract sender data
171+
*
172+
* @param array $args
173+
* @return array
174+
* @throws GraphQlInputException
175+
*/
176+
private function extractSenderData(array $args): array
177+
{
178+
if (empty($args['input']['sender']['name'])) {
179+
throw new GraphQlInputException(__('Please provide Name of sender.'));
180+
}
181+
182+
if (empty($args['input']['sender']['email'])) {
183+
throw new GraphQlInputException(__('Please provide Email of sender.'));
184+
}
185+
186+
if (empty($args['input']['sender']['message'])) {
187+
throw new GraphQlInputException(__('Please provide Message.'));
188+
}
189+
190+
return [
191+
'sender' => [
192+
'name' => $args['input']['sender']['name'],
193+
'email' => $args['input']['sender']['email'],
194+
'message' => $args['input']['sender']['message'],
195+
],
196+
];
197+
}
198+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# SendFriendGraphQl
2+
3+
**SendFriendGraphQl** provides support of GraphQL for SendFriend functionality.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "magento/module-send-friend-graph-ql",
3+
"description": "N/A",
4+
"type": "magento2-module",
5+
"require": {
6+
"php": "~7.1.3||~7.2.0",
7+
"magento/framework": "*",
8+
"magento/module-catalog": "*",
9+
"magento/module-send-friend": "*"
10+
},
11+
"suggest": {
12+
"magento/module-graph-ql": "*"
13+
},
14+
"license": [
15+
"OSL-3.0",
16+
"AFL-3.0"
17+
],
18+
"autoload": {
19+
"files": [
20+
"registration.php"
21+
],
22+
"psr-4": {
23+
"Magento\\SendFriendGraphQl\\": ""
24+
}
25+
}
26+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
10+
<module name="Magento_SendFriendGraphQl"/>
11+
</config>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright © Magento, Inc. All rights reserved.
2+
# See COPYING.txt for license details.
3+
4+
type Mutation {
5+
sendEmailToFriend (input: SendEmailToFriendSenderInput): SendEmailToFriendOutput @resolver(class: "\\Magento\\SendFriendGraphQl\\Model\\Resolver\\SendEmailToFriend") @doc(description:"Recommends Product by Sending Single/Multiple Email")
6+
}
7+
8+
input SendEmailToFriendSenderInput {
9+
product_id: Int!
10+
sender: Sender!
11+
recipients: [Recipient!]!
12+
}
13+
14+
type Sender {
15+
name: String!
16+
email: String!
17+
message: String!
18+
}
19+
20+
type Recipient {
21+
name: String!
22+
email: String!
23+
}
24+
25+
type SendEmailToFriendOutput {
26+
sender: Sender
27+
recipients: [Recipient]
28+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
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+
use Magento\Framework\Component\ComponentRegistrar;
9+
10+
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_SendFriendGraphQl', __DIR__);

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@
209209
"magento/module-search": "*",
210210
"magento/module-security": "*",
211211
"magento/module-send-friend": "*",
212+
"magento/module-send-friend-graph-ql": "*",
212213
"magento/module-shipping": "*",
213214
"magento/module-signifyd": "*",
214215
"magento/module-sitemap": "*",

0 commit comments

Comments
 (0)