Skip to content

Commit b18ce4a

Browse files
authored
Merge pull request #2361 from magento-honey-badgers/MAGETWO-89292-SDL
[honey] MAGETWO-83853: GraphQL response returns null for website_ids, url_path
2 parents 94ccd58 + 5350d85 commit b18ce4a

File tree

15 files changed

+424
-156
lines changed

15 files changed

+424
-156
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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\Framework\GraphQl\Schema\Type\ResolveInfo;
11+
use Magento\Catalog\Model\Product;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Query\Resolver\Value;
14+
use Magento\Framework\GraphQl\Query\Resolver\ValueFactory;
15+
use Magento\Framework\GraphQl\Query\ResolverInterface;
16+
use Magento\CatalogGraphQl\Model\Resolver\Product\Websites\Collection;
17+
18+
/**
19+
* Retrieves the websites information object
20+
*/
21+
class Websites implements ResolverInterface
22+
{
23+
/**
24+
* @var ValueFactory
25+
*/
26+
private $valueFactory;
27+
28+
/**
29+
* @var Collection
30+
*/
31+
private $productWebsitesCollection;
32+
33+
/**
34+
* @param ValueFactory $valueFactory
35+
* @param Collection $productWebsitesCollection
36+
*/
37+
public function __construct(
38+
ValueFactory $valueFactory,
39+
Collection $productWebsitesCollection
40+
) {
41+
$this->valueFactory = $valueFactory;
42+
$this->productWebsitesCollection = $productWebsitesCollection;
43+
}
44+
45+
/**
46+
* {@inheritDoc}
47+
*/
48+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) : Value
49+
{
50+
if (!isset($value['entity_id'])) {
51+
$result = function () {
52+
return null;
53+
};
54+
return $this->valueFactory->create($result);
55+
}
56+
$this->productWebsitesCollection->addIdFilters((int)$value['entity_id']);
57+
$result = function () use ($value) {
58+
return $this->productWebsitesCollection->getWebsiteForProductId((int)$value['entity_id']);
59+
};
60+
61+
return $this->valueFactory->create($result);
62+
}
63+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
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\Websites;
9+
10+
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
11+
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;
12+
use Magento\Store\Model\ResourceModel\Website\Collection as WebsiteCollection;
13+
use Magento\Store\Model\ResourceModel\Website\CollectionFactory as WebsiteCollectionFactory;
14+
15+
/**
16+
* Collection to fetch websites data at resolution time.
17+
*/
18+
class Collection
19+
{
20+
/**
21+
* @var WebsiteCollection
22+
*/
23+
private $websiteCollection;
24+
25+
/**
26+
* @var ProductCollection
27+
*/
28+
private $productCollection;
29+
30+
/**
31+
* @var int[]
32+
*/
33+
private $productIds = [];
34+
35+
/**
36+
* @var array
37+
*/
38+
private $websites = [];
39+
40+
/**
41+
* @param WebsiteCollectionFactory $websiteCollectionFactory
42+
* @param ProductCollectionFactory $productCollectionFactory
43+
*/
44+
public function __construct(
45+
WebsiteCollectionFactory $websiteCollectionFactory,
46+
ProductCollectionFactory $productCollectionFactory
47+
) {
48+
$this->websiteCollection = $websiteCollectionFactory->create();
49+
$this->productCollection = $productCollectionFactory->create();
50+
}
51+
52+
/**
53+
* Add product and id filter to filter for fetch.
54+
*
55+
* @param int $productId
56+
* @return void
57+
*/
58+
public function addIdFilters(int $productId) : void
59+
{
60+
if (!in_array($productId, $this->productIds)) {
61+
$this->productIds[] = $productId;
62+
}
63+
}
64+
65+
/**
66+
* Retrieve website for passed in product id.
67+
*
68+
* @param int $productId
69+
* @return array
70+
*/
71+
public function getWebsiteForProductId(int $productId) : array
72+
{
73+
$websiteList = $this->fetch();
74+
75+
if (!isset($websiteList[$productId])) {
76+
return [];
77+
}
78+
79+
return $websiteList[$productId];
80+
}
81+
82+
/**
83+
* Fetch website data and return in array format. Keys for links will be their product Ids.
84+
*
85+
* @return array
86+
*/
87+
private function fetch() : array
88+
{
89+
if (empty($this->productIds) || !empty($this->websites)) {
90+
return $this->websites;
91+
}
92+
93+
$selectUnique = $this->productCollection->getConnection()->select()->from(
94+
['product_website' => $this->productCollection->getResource()->getTable('catalog_product_website')]
95+
)->where(
96+
'product_website.product_id IN (?)',
97+
$this->productIds
98+
)->where(
99+
'website_id > ?',
100+
0
101+
)->group('website_id');
102+
103+
$websiteDataUnique = $this->productCollection->getConnection()->fetchAll($selectUnique);
104+
105+
$websiteIds = [];
106+
foreach ($websiteDataUnique as $websiteData) {
107+
$websiteIds[] = $websiteData['website_id'];
108+
}
109+
$this->websiteCollection->addIdFilter($websiteIds);
110+
111+
$siteData = $this->websiteCollection->getItems();
112+
113+
$select = $this->productCollection->getConnection()->select()->from(
114+
['product_website' => $this->productCollection->getResource()->getTable('catalog_product_website')]
115+
)->where(
116+
'product_website.product_id IN (?)',
117+
$this->productIds
118+
)->where(
119+
'website_id > ?',
120+
0
121+
);
122+
123+
foreach ($this->productCollection->getConnection()->fetchAll($select) as $row) {
124+
$website = $siteData[$row['website_id']];
125+
$this->websites[$row['product_id']][$row['website_id']] = [
126+
'id' => $row['website_id'],
127+
'name' => $website->getData('name'),
128+
'code' => $website->getData('code'),
129+
'sort_order' => $website->getData('sort_order'),
130+
'default_group_id' => $website->getData('default_group_id'),
131+
'is_default' => $website->getData('is_default'),
132+
];
133+
}
134+
return $this->websites;
135+
}
136+
}

app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/RequiredColumnsProcessor.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ public function process(
3030
$collection->addAttributeToSelect('special_price_from');
3131
$collection->addAttributeToSelect('special_price_to');
3232
$collection->addAttributeToSelect('tax_class_id');
33-
$collection->addWebsiteNamesToResult();
3433

3534
return $collection;
3635
}

app/code/Magento/CatalogGraphQl/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"magento/framework": "*"
1414
},
1515
"suggest": {
16-
"magento/module-graph-ql": "100.0.*"
16+
"magento/module-graph-ql": "*",
17+
"magento/module-store-graph-ql": "*"
1718
},
1819
"license": [
1920
"OSL-3.0",

app/code/Magento/CatalogGraphQl/etc/module.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<module name="Magento_Store"/>
1414
<module name="Magento_Eav"/>
1515
<module name="Magento_GraphQl"/>
16+
<module name="Magento_StoreGraphQl"/>
1617
<module name="Magento_EavGraphQl"/>
1718
</sequence>
1819
</module>

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

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,8 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\
263263
new_from_date: String @doc(description: "The beginning date for new product listings, and determines if the product is featured as a new product") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\NewFromTo")
264264
new_to_date: String @doc(description: "The end date for new product listings") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\NewFromTo")
265265
tier_price: Float @doc(description: "The price when tier pricing is in effect and the items purchased threshold has been reached")
266-
custom_design: String @doc(description: "A theme that can be applied to the product page")
267-
custom_design_from: String @doc(description: "The beginning date when a theme is applied to the product page")
268-
custom_design_to: String @doc(description: "The date at which a theme is no longer applied to the product page")
269266
custom_layout_update: String @doc(description: "XML code that is applied as a layout update to the product page")
270267
custom_layout: String @doc(description: "The name of a custom layout")
271-
page_layout: String @doc(description: "The page layout of the product page. Values are 1column-center, 2columns-left, 2columns-right, and 3columns")
272268
category_ids: [Int] @doc(description: "An array of category IDs the product belongs to")
273269
options_container: String @doc(description: "If the product has multiple options, determines where they appear on the product page")
274270
image_label: String @doc(description: "The label assigned to a product image")
@@ -278,7 +274,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\
278274
updated_at: String @doc(description: "Timestamp indicating when the product was updated")
279275
country_of_manufacture: String @doc(description: "The product's country of origin")
280276
type_id: String @doc(description: "One of simple, virtual, bundle, downloadable, grouped, or configurable")
281-
website_ids: [Int] @doc(description: "An array of website IDs in which the product is available")
277+
websites: [Website] @doc(description: "An array of websites in which the product is available") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Websites")
282278
product_links: [ProductLinksInterface] @doc(description: "An array of ProductLinks objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\ProductLinks")
283279
media_gallery_entries: [MediaGalleryEntry] @doc(description: "An array of MediaGalleryEntry objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\MediaGalleryEntries")
284280
tier_prices: [ProductTierPrices] @doc(description: "An array of ProductTierPrices objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\TierPrices")
@@ -440,14 +436,10 @@ input ProductFilterInput @doc(description: "ProductFilterInput defines the filte
440436
tier_price: FilterTypeInput @doc(description: "The price when tier pricing is in effect and the items purchased threshold has been reached")
441437
news_from_date: FilterTypeInput @doc(description: "The beginning date for new product listings, and determines if the product is featured as a new product")
442438
news_to_date: FilterTypeInput @doc(description: "The end date for new product listings")
443-
custom_design: FilterTypeInput @doc(description: "A theme that can be applied to the product page")
444-
custom_design_from: FilterTypeInput @doc(description: "The beginning date when a theme is applied to the product page")
445-
custom_design_to: FilterTypeInput @doc(description: "The date at which a theme is no longer applied to the product page")
446439
custom_layout_update: FilterTypeInput @doc(description: "XML code that is applied as a layout update to the product page")
447440
min_price: FilterTypeInput @doc(description:"The numeric minimal price of the product. Do not include the currency code.")
448441
max_price: FilterTypeInput @doc(description:"The numeric maximal price of the product. Do not include the currency code.")
449442
special_price: FilterTypeInput @doc(description:"The numeric special price of the product. Do not include the currency code.")
450-
page_layout: FilterTypeInput @doc(description: "The page layout of the product page. Values are 1column-center, 2columns-left, 2columns-right, and 3columns")
451443
category_ids: FilterTypeInput @doc(description: "An array of category IDs the product belongs to")
452444
options_container: FilterTypeInput @doc(description: "If the product has multiple options, determines where they appear on the product page")
453445
required_options: FilterTypeInput @doc(description: "Indicates whether the product has required options")
@@ -498,11 +490,7 @@ input ProductSortInput @doc(description: "ProductSortInput specifies the attrib
498490
tier_price: SortEnum @doc(description: "The price when tier pricing is in effect and the items purchased threshold has been reached")
499491
news_from_date: SortEnum @doc(description: "The beginning date for new product listings, and determines if the product is featured as a new product")
500492
news_to_date: SortEnum @doc(description: "The end date for new product listings")
501-
custom_design: SortEnum @doc(description: "A theme that can be applied to the product page")
502-
custom_design_from: SortEnum @doc(description: "The beginning date when a theme is applied to the product page")
503-
custom_design_to: SortEnum @doc(description: "The date at which a theme is no longer applied to the product page")
504493
custom_layout_update: SortEnum @doc(description: "XML code that is applied as a layout update to the product page")
505-
page_layout: SortEnum @doc(description: "The page layout of the product page. Values are 1column-center, 2columns-left, 2columns-right, and 3columns")
506494
category_ids: SortEnum @doc(description: "An array of category IDs the product belongs to")
507495
options_container: SortEnum @doc(description: "If the product has multiple options, determines where they appear on the product page")
508496
required_options: SortEnum @doc(description: "Indicates whether the product has required options")
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# StoreGraphQl
2+
3+
**StoreGraphQl** provides type information for the GraphQl module
4+
to generate store fields information endpoints.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "magento/module-store-graph-ql",
3+
"description": "N/A",
4+
"type": "magento2-module",
5+
"require": {
6+
"php": "7.0.2|7.0.4|~7.0.6|~7.1.0",
7+
"magento/framework": "*"
8+
},
9+
"suggest": {
10+
"magento/module-graph-ql": "*",
11+
"magento/module-catalog-graph-ql": "*"
12+
},
13+
"license": [
14+
"OSL-3.0",
15+
"AFL-3.0"
16+
],
17+
"autoload": {
18+
"files": [
19+
"registration.php"
20+
],
21+
"psr-4": {
22+
"Magento\\StoreGraphQl\\": ""
23+
}
24+
}
25+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
9+
<module name="Magento_StoreGraphQl">
10+
<sequence>
11+
<module name="Magento_GraphQl"/>
12+
</sequence>
13+
</module>
14+
</config>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright © Magento, Inc. All rights reserved.
2+
# See COPYING.txt for license details.
3+
4+
type Website @doc(description: "The type contains information about a website") {
5+
id : Int @doc(description: "The ID number assigned to the website")
6+
name : String @doc(description: "The website name. Websites use this name to identify it easyer.")
7+
code : String @doc(description: "A code assigned to the website to identify it")
8+
sort_order : Int @doc(description: "The attribute to use for sorting websites")
9+
default_group_id : String @doc(description: "The default group id that the website has")
10+
is_default : Boolean @doc(description: "Specifies if this is the default website")
11+
}

0 commit comments

Comments
 (0)