Skip to content

Commit 88b2115

Browse files
committed
Updating the Wishlist GraphQl implementation
1 parent 878b1c9 commit 88b2115

27 files changed

+1116
-103
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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\Wishlist\Model\Product;
9+
10+
use Magento\Bundle\Helper\Catalog\Product\Configuration;
11+
use Magento\Bundle\Model\Option;
12+
use Magento\Bundle\Model\Product\Type;
13+
use Magento\Catalog\Model\Product;
14+
use Magento\Framework\Exception\LocalizedException;
15+
use Magento\Framework\Pricing\Helper\Data;
16+
use Magento\Framework\Serialize\SerializerInterface;
17+
use Magento\Wishlist\Model\Item;
18+
19+
/**
20+
* Data provider for bundled product options
21+
*/
22+
class BundleOptionDataProvider
23+
{
24+
/**
25+
* @var Data
26+
*/
27+
private $pricingHelper;
28+
29+
/**
30+
* @var SerializerInterface
31+
*/
32+
private $serializer;
33+
34+
/**
35+
* @var Configuration
36+
*/
37+
private $configuration;
38+
39+
/**
40+
* @param Data $pricingHelper
41+
* @param SerializerInterface $serializer
42+
* @param Configuration $configuration
43+
*/
44+
public function __construct(
45+
Data $pricingHelper,
46+
SerializerInterface $serializer,
47+
Configuration $configuration
48+
) {
49+
$this->pricingHelper = $pricingHelper;
50+
$this->serializer = $serializer;
51+
$this->configuration = $configuration;
52+
}
53+
54+
/**
55+
* Extract data for a bundled wishlist item
56+
*
57+
* @param Item $item
58+
*
59+
* @return array
60+
*/
61+
public function getData(Item $item): array
62+
{
63+
$options = [];
64+
$product = $item->getProduct();
65+
$optionsQuoteItemOption = $item->getOptionByCode('bundle_option_ids');
66+
$bundleOptionsIds = $optionsQuoteItemOption
67+
? $this->serializer->unserialize($optionsQuoteItemOption->getValue())
68+
: [];
69+
70+
/** @var Type $typeInstance */
71+
$typeInstance = $product->getTypeInstance();
72+
73+
if ($bundleOptionsIds) {
74+
$selectionsQuoteItemOption = $item->getOptionByCode('bundle_selection_ids');
75+
$optionsCollection = $typeInstance->getOptionsByIds($bundleOptionsIds, $product);
76+
$bundleSelectionIds = $this->serializer->unserialize($selectionsQuoteItemOption->getValue());
77+
78+
if (!empty($bundleSelectionIds)) {
79+
$selectionsCollection = $typeInstance->getSelectionsByIds($bundleSelectionIds, $product);
80+
$bundleOptions = $optionsCollection->appendSelections($selectionsCollection, true);
81+
82+
$options = $this->buildBundleOptions($bundleOptions, $item);
83+
}
84+
}
85+
86+
return $options;
87+
}
88+
89+
/**
90+
* Build bundle product options based on current selection
91+
*
92+
* @param Option[] $bundleOptions
93+
* @param Item $item
94+
*
95+
* @return array
96+
*/
97+
private function buildBundleOptions(array $bundleOptions, Item $item): array
98+
{
99+
$options = [];
100+
foreach ($bundleOptions as $bundleOption) {
101+
if (!$bundleOption->getSelections()) {
102+
continue;
103+
}
104+
105+
$options[] = [
106+
'id' => $bundleOption->getId(),
107+
'label' => $bundleOption->getTitle(),
108+
'type' => $bundleOption->getType(),
109+
'values' => $this->buildBundleOptionValues($bundleOption->getSelections(), $item),
110+
];
111+
}
112+
113+
return $options;
114+
}
115+
116+
/**
117+
* Build bundle product option values based on current selection
118+
*
119+
* @param Product[] $selections
120+
* @param Item $item
121+
*
122+
* @return array
123+
*
124+
* @throws LocalizedException
125+
*/
126+
private function buildBundleOptionValues(array $selections, Item $item): array
127+
{
128+
$product = $item->getProduct();
129+
$values = [];
130+
131+
foreach ($selections as $selection) {
132+
$qty = (float) $this->configuration->getSelectionQty($product, $selection->getSelectionId());
133+
if (!$qty) {
134+
continue;
135+
}
136+
137+
$selectionPrice = $this->configuration->getSelectionFinalPrice($item, $selection);
138+
$values[] = [
139+
'label' => $selection->getName(),
140+
'id' => $selection->getSelectionId(),
141+
'quantity' => $qty,
142+
'price' => $this->pricingHelper->currency($selectionPrice, false, false),
143+
];
144+
}
145+
146+
return $values;
147+
}
148+
}

app/code/Magento/WishlistGraphQl/Model/Resolver/AddProductsToWishlist.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public function resolve(
8383
array $args = null
8484
) {
8585
if (!$this->wishlistConfig->isEnabled()) {
86-
throw new GraphQlInputException(__('The wishlist is not currently available.'));
86+
throw new GraphQlInputException(__('The wishlist configuration is currently disabled.'));
8787
}
8888

8989
$customerId = $context->getUserId();

app/code/Magento/WishlistGraphQl/Model/Resolver/CustomerWishlistResolver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public function resolve(
5454
array $args = null
5555
) {
5656
if (!$this->wishlistConfig->isEnabled()) {
57-
throw new GraphQlInputException(__('The wishlist is not currently available.'));
57+
throw new GraphQlInputException(__('The wishlist configuration is currently disabled.'));
5858
}
5959

6060
if (false === $context->getExtensionAttributes()->getIsCustomer()) {
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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\WishlistGraphQl\Model\Resolver;
9+
10+
use Magento\Framework\GraphQl\Config\Element\Field;
11+
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
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\Wishlist\Model\ResourceModel\Wishlist\Collection as WishlistCollection;
16+
use Magento\Wishlist\Model\ResourceModel\Wishlist\CollectionFactory as WishlistCollectionFactory;
17+
use Magento\Wishlist\Model\Wishlist;
18+
use Magento\Wishlist\Model\Wishlist\Config as WishlistConfig;
19+
use Magento\WishlistGraphQl\Mapper\WishlistDataMapper;
20+
21+
/**
22+
* Fetches customer wishlist list
23+
*/
24+
class CustomerWishlists implements ResolverInterface
25+
{
26+
/**
27+
* @var WishlistDataMapper
28+
*/
29+
private $wishlistDataMapper;
30+
31+
/**
32+
* @var WishlistConfig
33+
*/
34+
private $wishlistConfig;
35+
36+
/**
37+
* @var WishlistCollectionFactory
38+
*/
39+
private $wishlistCollectionFactory;
40+
41+
/**
42+
* @param WishlistDataMapper $wishlistDataMapper
43+
* @param WishlistConfig $wishlistConfig
44+
* @param WishlistCollectionFactory $wishlistCollectionFactory
45+
*/
46+
public function __construct(
47+
WishlistDataMapper $wishlistDataMapper,
48+
WishlistConfig $wishlistConfig,
49+
WishlistCollectionFactory $wishlistCollectionFactory
50+
) {
51+
$this->wishlistDataMapper = $wishlistDataMapper;
52+
$this->wishlistConfig = $wishlistConfig;
53+
$this->wishlistCollectionFactory = $wishlistCollectionFactory;
54+
}
55+
56+
/**
57+
* @inheritdoc
58+
*/
59+
public function resolve(
60+
Field $field,
61+
$context,
62+
ResolveInfo $info,
63+
array $value = null,
64+
array $args = null
65+
) {
66+
if (!$this->wishlistConfig->isEnabled()) {
67+
throw new GraphQlInputException(__('The wishlist configuration is currently disabled.'));
68+
}
69+
70+
$customerId = $context->getUserId();
71+
72+
if (null === $customerId || 0 === $customerId) {
73+
throw new GraphQlAuthorizationException(
74+
__('The current user cannot perform operations on wishlist')
75+
);
76+
}
77+
78+
$currentPage = $args['currentPage'] ?? 1;
79+
$pageSize = $args['pageSize'] ?? 20;
80+
81+
/** @var WishlistCollection $collection */
82+
$collection = $this->wishlistCollectionFactory->create();
83+
$collection->filterByCustomerId($customerId);
84+
85+
if ($currentPage > 0) {
86+
$collection->setCurPage($currentPage);
87+
}
88+
89+
if ($pageSize > 0) {
90+
$collection->setPageSize($pageSize);
91+
}
92+
93+
$wishlists = [];
94+
95+
/** @var Wishlist $wishList */
96+
foreach ($collection->getItems() as $wishList) {
97+
array_push($wishlists, $this->wishlistDataMapper->map($wishList));
98+
}
99+
100+
return $wishlists;
101+
}
102+
}

app/code/Magento/WishlistGraphQl/Model/Resolver/ProductResolver.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace Magento\WishlistGraphQl\Model\Resolver;
99

10+
use Magento\Catalog\Model\Product;
1011
use Magento\CatalogGraphQl\Model\ProductDataProvider;
1112
use Magento\Framework\Exception\LocalizedException;
1213
use Magento\Framework\GraphQl\Config\Element\Field;
@@ -45,9 +46,9 @@ public function resolve(
4546
if (!isset($value['model'])) {
4647
throw new LocalizedException(__('Missing key "model" in Wishlist Item value data'));
4748
}
48-
/** @var Item $wishlistItem */
49-
$wishlistItem = $value['model'];
49+
/** @var Product $product */
50+
$product = $value['model'];
5051

51-
return $this->productDataProvider->getProductDataById((int)$wishlistItem->getProductId());
52+
return $this->productDataProvider->getProductDataById((int) $product->getId());
5253
}
5354
}

app/code/Magento/WishlistGraphQl/Model/Resolver/RemoveProductsFromWishlist.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public function resolve(
8383
array $args = null
8484
) {
8585
if (!$this->wishlistConfig->isEnabled()) {
86-
throw new GraphQlInputException(__('The wishlist is not currently available.'));
86+
throw new GraphQlInputException(__('The wishlist configuration is currently disabled.'));
8787
}
8888

8989
$customerId = $context->getUserId();
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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\WishlistGraphQl\Model\Resolver\Type\Bundle;
9+
10+
use Magento\Wishlist\Model\Product\BundleOptionDataProvider;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Query\ResolverInterface;
14+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
15+
use Magento\Wishlist\Model\Item;
16+
17+
/**
18+
* Fetches the selected bundle options
19+
*/
20+
class BundleOptions implements ResolverInterface
21+
{
22+
/**
23+
* @var BundleOptionDataProvider
24+
*/
25+
private $bundleOptionDataProvider;
26+
27+
/**
28+
* @param BundleOptionDataProvider $bundleOptionDataProvider
29+
*/
30+
public function __construct(
31+
BundleOptionDataProvider $bundleOptionDataProvider
32+
) {
33+
$this->bundleOptionDataProvider = $bundleOptionDataProvider;
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 (!$value['wishlistItemModel'] instanceof Item) {
47+
throw new LocalizedException(__('"wishlistItemModel" should be a "%instance" instance', [
48+
'instance' => Item::class
49+
]));
50+
}
51+
52+
return $this->bundleOptionDataProvider->getData($value['wishlistItemModel']);
53+
}
54+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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\WishlistGraphQl\Model\Resolver\Type\Configurable;
9+
10+
use Magento\Framework\Exception\LocalizedException;
11+
use Magento\Framework\GraphQl\Config\Element\Field;
12+
use Magento\Framework\GraphQl\Query\ResolverInterface;
13+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
14+
use Magento\Wishlist\Model\Item;
15+
16+
/**
17+
* Fetches the simple child sku of configurable product
18+
*/
19+
class ChildSku implements ResolverInterface
20+
{
21+
/**
22+
* @inheritdoc
23+
*/
24+
public function resolve(
25+
Field $field,
26+
$context,
27+
ResolveInfo $info,
28+
array $value = null,
29+
array $args = null
30+
) {
31+
if (!$value['wishlistItemModel'] instanceof Item) {
32+
throw new LocalizedException(__('"wishlistItemModel" should be a "%instance" instance', [
33+
'instance' => Item::class
34+
]));
35+
}
36+
37+
/** @var Item $wishlistItem */
38+
$wishlistItem = $value['wishlistItemModel'];
39+
$optionProduct = $wishlistItem->getProduct()->getCustomOption('simple_product')->getProduct();
40+
41+
return $optionProduct->getSku();
42+
}
43+
}

0 commit comments

Comments
 (0)