Skip to content

Commit fef1485

Browse files
authored
Merge pull request #1623 from magento-honey-badgers/MAGETWO-81033-Graph-Ql-Get-Simple-Product
[honey] MAGETWO-81033: API for fetching single simple product
2 parents acd713f + f24a929 commit fef1485

39 files changed

+3026
-553
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\GraphQl\Controller;
8+
9+
use GraphQL\Error\FormattedError;
10+
use Magento\Framework\App\FrontControllerInterface;
11+
use Magento\Framework\App\RequestInterface;
12+
use Magento\Framework\App\ResponseInterface;
13+
use Magento\Framework\Webapi\Response;
14+
use Magento\GraphQl\Model\SchemaGeneratorInterface;
15+
16+
/**
17+
* Front controller for web API GraphQL area.
18+
*/
19+
class GraphQl implements FrontControllerInterface
20+
{
21+
/**
22+
* @var Response
23+
*/
24+
private $response;
25+
26+
/**
27+
* @var SchemaGeneratorInterface
28+
*/
29+
private $schemaGenerator;
30+
31+
/**
32+
* Initialize dependencies
33+
*
34+
* @param Response $response
35+
* @param SchemaGeneratorInterface $schemaGenerator
36+
*/
37+
public function __construct(
38+
Response $response,
39+
SchemaGeneratorInterface $schemaGenerator
40+
) {
41+
$this->response = $response;
42+
$this->schemaGenerator = $schemaGenerator;
43+
}
44+
45+
/**
46+
* Handle GraphQL request
47+
*
48+
* @param RequestInterface $request
49+
* @return ResponseInterface
50+
*/
51+
public function dispatch(RequestInterface $request)
52+
{
53+
try {
54+
if ($request->getHeader('Content-Type')
55+
&& strpos($request->getHeader('Content-Type'), 'application/json') !== false
56+
) {
57+
$raw = file_get_contents('php://input') ?: '';
58+
$data = json_decode($raw, true);
59+
} else {
60+
$data = $_REQUEST;
61+
}
62+
$schema = $this->schemaGenerator->generate();
63+
$result = \GraphQL\GraphQL::execute(
64+
$schema,
65+
isset($data['query']) ? $data['query'] : '',
66+
null,
67+
null,
68+
isset($data['variables']) ? $data['variables'] : []
69+
);
70+
} catch (\Exception $error) {
71+
$result['extensions']['exception'] = FormattedError::createFromException($error);
72+
$this->response->setStatusCode(500);
73+
}
74+
$this->response->setBody(json_encode($result))->setHeader('Content-Type', 'application/json');
75+
return $this->response;
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\GraphQl\Model\Resolver;
8+
9+
use Magento\Catalog\Api\ProductAttributeMediaGalleryManagementInterface;
10+
use Magento\Framework\Api\ExtensibleDataInterface;
11+
use Magento\Framework\Exception\NoSuchEntityException;
12+
use Magento\Framework\Webapi\ServiceOutputProcessor;
13+
14+
/**
15+
* Media gallery field resolver, used for GraphQL request processing.
16+
*/
17+
class MediaGalleryEntries
18+
{
19+
/**
20+
* @var ProductAttributeMediaGalleryManagementInterface
21+
*/
22+
private $mediaGalleryManagement;
23+
24+
/**
25+
* @var ServiceOutputProcessor
26+
*/
27+
private $serviceOutputProcessor;
28+
29+
/**
30+
* MediaGalleryEntries constructor.
31+
*
32+
* @param ProductAttributeMediaGalleryManagementInterface $mediaGalleryManagement
33+
* @param ServiceOutputProcessor $serviceOutputProcessor
34+
*/
35+
public function __construct(
36+
ProductAttributeMediaGalleryManagementInterface $mediaGalleryManagement,
37+
ServiceOutputProcessor $serviceOutputProcessor
38+
) {
39+
$this->mediaGalleryManagement = $mediaGalleryManagement;
40+
$this->serviceOutputProcessor = $serviceOutputProcessor;
41+
}
42+
43+
/**
44+
* Get media gallery entries for the specified product.
45+
*
46+
* @param string $sku
47+
* @return array|null
48+
*/
49+
public function getMediaGalleryEntries(string $sku)
50+
{
51+
try {
52+
$mediaGalleryObjectArray = $this->mediaGalleryManagement->getList($sku);
53+
} catch (NoSuchEntityException $e) {
54+
// No error should be thrown, null result should be returned
55+
return null;
56+
}
57+
58+
$mediaGalleryList = $this->serviceOutputProcessor->process(
59+
$mediaGalleryObjectArray,
60+
ProductAttributeMediaGalleryManagementInterface::class,
61+
'getList'
62+
);
63+
64+
foreach ($mediaGalleryList as $key => $mediaGallery) {
65+
if (isset($mediaGallery[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY])
66+
&& isset($mediaGallery[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['video_content'])) {
67+
$mediaGallery = array_merge(
68+
$mediaGallery,
69+
$mediaGallery[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]
70+
);
71+
$mediaGalleryList[$key] = $mediaGallery;
72+
}
73+
}
74+
75+
return $mediaGalleryList;
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\GraphQl\Model\Resolver;
8+
9+
use Magento\Catalog\Api\ProductRepositoryInterface;
10+
use Magento\Framework\Exception\NoSuchEntityException;
11+
use Magento\Framework\Webapi\ServiceOutputProcessor;
12+
13+
/**
14+
* Product field resolver, used for GraphQL request processing.
15+
*/
16+
class Product
17+
{
18+
/**
19+
* @var ProductRepositoryInterface
20+
*/
21+
private $productRepository;
22+
23+
/**
24+
* @var ServiceOutputProcessor
25+
*/
26+
private $serviceOutputProcessor;
27+
28+
/**
29+
* @var MediaGalleryEntries
30+
*/
31+
private $mediaGalleryResolver;
32+
33+
/**
34+
* Initialize dependencies
35+
*
36+
* @param ProductRepositoryInterface $productRepository
37+
* @param ServiceOutputProcessor $serviceOutputProcessor
38+
* @param MediaGalleryEntries $mediaGalleryResolver
39+
*/
40+
public function __construct(
41+
ProductRepositoryInterface $productRepository,
42+
ServiceOutputProcessor $serviceOutputProcessor,
43+
MediaGalleryEntries $mediaGalleryResolver
44+
) {
45+
$this->productRepository = $productRepository;
46+
$this->serviceOutputProcessor = $serviceOutputProcessor;
47+
$this->mediaGalleryResolver = $mediaGalleryResolver;
48+
}
49+
50+
/**
51+
* Resolves product by Sku
52+
*
53+
* @param string $sku
54+
* @return array|null
55+
*/
56+
public function getProduct(string $sku)
57+
{
58+
try {
59+
$productObject = $this->productRepository->get($sku);
60+
} catch (NoSuchEntityException $e) {
61+
// No error should be thrown, null result should be returned
62+
return null;
63+
}
64+
return $this->processProduct($productObject);
65+
}
66+
67+
/**
68+
* Resolves product by Id
69+
*
70+
* @param int $productId
71+
* @return array|null
72+
*/
73+
public function getProductById(int $productId)
74+
{
75+
try {
76+
$productObject = $this->productRepository->getById($productId);
77+
} catch (NoSuchEntityException $e) {
78+
// No error should be thrown, null result should be returned
79+
return null;
80+
}
81+
return $this->processProduct($productObject);
82+
}
83+
84+
/**
85+
* Retrieve single product data in array format
86+
*
87+
* @param \Magento\Catalog\Api\Data\ProductInterface $productObject
88+
* @return array|null
89+
*/
90+
private function processProduct(\Magento\Catalog\Api\Data\ProductInterface $productObject)
91+
{
92+
$product = $this->serviceOutputProcessor->process(
93+
$productObject,
94+
ProductRepositoryInterface::class,
95+
'get'
96+
);
97+
$product = array_merge($product, $product['extension_attributes']);
98+
if (isset($product['custom_attributes'])) {
99+
$customAttributes = [];
100+
foreach ($product['custom_attributes'] as $attribute) {
101+
$isArray = false;
102+
if (is_array($attribute['value'])) {
103+
$isArray = true;
104+
foreach ($attribute['value'] as $attributeValue) {
105+
if (is_array($attributeValue)) {
106+
$customAttributes[$attribute['attribute_code']] = json_encode($attribute['value']);
107+
continue;
108+
}
109+
$customAttributes[$attribute['attribute_code']] = implode(',', $attribute['value']);
110+
continue;
111+
}
112+
}
113+
if ($isArray) {
114+
continue;
115+
}
116+
$customAttributes[$attribute['attribute_code']] = $attribute['value'];
117+
}
118+
}
119+
$product = array_merge($product, $customAttributes);
120+
$product = array_merge($product, $product['product_links']);
121+
$product['media_gallery_entries'] = $this
122+
->mediaGalleryResolver->getMediaGalleryEntries($productObject->getSku());
123+
124+
if (isset($product['configurable_product_links'])) {
125+
$product['configurable_product_links'] = $this
126+
->resolveConfigurableProductLinks($product['configurable_product_links']);
127+
}
128+
129+
return $product;
130+
}
131+
132+
/**
133+
* Resolve links for configurable product into simple products
134+
*
135+
* @param int[]
136+
* @return array
137+
*/
138+
private function resolveConfigurableProductLinks($configurableProductLinks)
139+
{
140+
if (empty($configurableProductLinks)) {
141+
return [];
142+
}
143+
$result = [];
144+
foreach ($configurableProductLinks as $key => $id) {
145+
$result[$key] = $this->getProductById($id);
146+
}
147+
return $result;
148+
}
149+
}

0 commit comments

Comments
 (0)