Skip to content

Commit

Permalink
Wishlist sharing functionality (#3)
Browse files Browse the repository at this point in the history
* Added support for shared wishlist

* Added creators name

* WIP Added TODOs for MoveWishlistToCart

* upgraded MoveWishlistToCart

* Added wishlist sharing functionality
  • Loading branch information
atravkovs authored Jun 12, 2020
1 parent b76ce65 commit f3e8a08
Show file tree
Hide file tree
Showing 5 changed files with 364 additions and 17 deletions.
56 changes: 43 additions & 13 deletions src/Model/Resolver/MoveWishlistToCart.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Quote\Api\Data\CartInterface;
use Magento\Quote\Api\CartManagementInterface;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Api\GuestCartRepositoryInterface;
use Magento\Quote\Model\Webapi\ParamOverriderCartId;
use Magento\Wishlist\Model\ResourceModel\Wishlist as WishlistResourceModel;
use Magento\Wishlist\Model\Wishlist;
Expand Down Expand Up @@ -57,10 +59,16 @@ class MoveWishlistToCart implements ResolverInterface
*/
protected $wishlistResource;

/**
* @var GuestCartRepositoryInterface
*/
protected $guestCartRepository;

public function __construct(
ParamOverriderCartId $overriderCartId,
CartRepositoryInterface $quoteRepository,
CartManagementInterface $quoteManagement,
GuestCartRepositoryInterface $guestCartRepository,
WishlistFactory $wishlistFactory,
WishlistResourceModel $wishlistResource
) {
Expand All @@ -69,6 +77,7 @@ public function __construct(
$this->quoteManagement = $quoteManagement;
$this->wishlistFactory = $wishlistFactory;
$this->wishlistResource = $wishlistResource;
$this->guestCartRepository = $guestCartRepository;
}

/**
Expand All @@ -77,11 +86,8 @@ public function __construct(
* @param array $wishlistItems
* @return void
*/
protected function addItemsToCart(array $wishlistItems): void
protected function addItemsToCart(array $wishlistItems, CartInterface $quote): void
{
$quoteId = $this->overriderCartId->getOverriddenValue();
$quote = $this->quoteRepository->getActive($quoteId);

foreach ($wishlistItems as $item) {
$product = $item['product'];

Expand Down Expand Up @@ -110,7 +116,7 @@ protected function addItemsToCart(array $wishlistItems): void
* @param Wishlist $wishlist
* @return array
*/
protected function getWishlistItems(Wishlist $wishlist): array
protected function getWishlistItems(Wishlist $wishlist, bool $shouldDeleteItems): array
{
$items = [];
$itemsCollection = $wishlist->getItemCollection();
Expand All @@ -125,7 +131,9 @@ protected function getWishlistItems(Wishlist $wishlist): array
'super_attribute' => $superAttribute,
];

$item->delete();
if ($shouldDeleteItems) {
$item->delete();
}
}

return $items;
Expand All @@ -141,22 +149,29 @@ public function resolve(
array $value = null,
array $args = null
) {
$customerId = $context->getUserId();
if ($customerId === null || $customerId === 0) {
throw new GraphQlAuthorizationException(__('Authorization unsuccessful'));
}
$sharingCode = $args['sharingCode'] ?? null;
$guestCartId = $args['guestCartId'] ?? null;

if (!$guestCartId) {
$customerId = $context->getUserId();
if ($customerId === null || $customerId === 0) {
throw new GraphQlAuthorizationException(__('User not found'));
}

$cart = $this->quoteManagement->getCartForCustomer($customerId);
$cart = $this->quoteManagement->getCartForCustomer($customerId);
} else {
$cart = $this->guestCartRepository->get($guestCartId);
}

/** @var Wishlist $wishlist */
$wishlist = $this->wishlistFactory->create();
$this->wishlistResource->load($wishlist, $customerId, 'customer_id');
$this->loadWishlist($wishlist, $sharingCode, $context);

if (!$wishlist->getId() || $wishlist->getItemsCount() <= 0) {
return true;
}

$wishlistItems = $this->getWishlistItems($wishlist);
$wishlistItems = $this->getWishlistItems($wishlist, !!$sharingCode);
$cartItems = $cart->getItems();

foreach ($cartItems as $item) {
Expand Down Expand Up @@ -184,4 +199,19 @@ public function resolve(

return true;
}

private function loadWishlist(Wishlist $wishlist, $sharingCode, $context): void
{
if (!$sharingCode) {
$customerId = $context->getUserId();
$this->wishlistResource->load($wishlist, $customerId, 'customer_id');
return;
}

$this->wishlistResource->load($wishlist, $sharingCode, 'sharing_code');

if (!$wishlist->getShared()) {
throw new GraphQlNoSuchEntityException(__('Shared wishlist with provided sharing code does not exist'));
}
}
}
222 changes: 222 additions & 0 deletions src/Model/Resolver/ShareWishlist.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
<?php
/**
* ScandiPWA - Progressive Web App for Magento
*
* Copyright © Scandiweb, Inc. All rights reserved.
* See LICENSE for license details.
*
* @license OSL-3.0 (Open Software License ("OSL") v. 3.0)
* @package scandipwa/wishlist-graphql
* @link https://github.com/scandipwa/wishlist-graphql
*/

declare(strict_types=1);

namespace ScandiPWA\WishlistGraphQl\Model\Resolver;

use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Customer\Model\ResourceModel\CustomerRepository;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Escaper;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\UrlInterface;
use Magento\Framework\View\LayoutFactory;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Wishlist\Model\WishlistFactory;
use ScandiPWA\WishlistGraphQl\Model\Resolver\WishlistResolver;

class ShareWishlist implements ResolverInterface
{
/**
* @var CustomerRepository
*/
protected $customerRepository;
/**
* @var Escaper
*/
protected $escaper;
/**
* @var WishlistFactory
*/
protected $wishlistFactory;
/**
* @var WishlistResolver
*/
protected $wishlistResolver;
/**
* @var TransportBuilder
*/
protected $transportBuilder;
/**
* @var ScopeConfigInterface
*/
protected $scopeConfig;
/**
* @var StoreManagerInterface
*/
protected $storeManager;
/**
* @var UrlInterface
*/
protected $url;
/**
* @var LayoutFactory
*/
protected $layoutFactory;

/**
* @param Escaper $escaper
* @param UrlInterface $url
* @param LayoutFactory $layoutFactory
* @param WishlistFactory $wishlistFactory
* @param ScopeConfigInterface $scopeConfig
* @param WishlistResolver $wishlistResolver
* @param TransportBuilder $transportBuilder
* @param StoreManagerInterface $storeManager
* @param CustomerRepository $customerRepository
*/
public function __construct(
Escaper $escaper,
UrlInterface $url,
LayoutFactory $layoutFactory,
WishlistFactory $wishlistFactory,
ScopeConfigInterface $scopeConfig,
WishlistResolver $wishlistResolver,
TransportBuilder $transportBuilder,
StoreManagerInterface $storeManager,
CustomerRepository $customerRepository
) {
$this->url = $url;
$this->escaper = $escaper;
$this->scopeConfig = $scopeConfig;
$this->storeManager = $storeManager;
$this->layoutFactory = $layoutFactory;
$this->wishlistFactory = $wishlistFactory;
$this->wishlistResolver = $wishlistResolver;
$this->transportBuilder = $transportBuilder;
$this->customerRepository = $customerRepository;
}

/**
* @inheritDoc
*/
public function resolve(
Field $field,
$context,
ResolveInfo $info,
array $value = null,
array $args = null
) {
$customerId = $context->getUserId();
if (!$customerId) {
throw new GraphQlAuthorizationException(__('Authorization unsuccessful'));
}

$emails = $args['input']['emails'] ?? null;
$message = $args['input']['message'] ?? '';

$wishlist = $this->wishlistFactory->create();
$this->wishlistResolver->loadWishlist($wishlist, null, $context);

$message = nl2br($this->escaper->escapeHtml($message));

/** @var CustomerInterface */
$customer = $this->customerRepository->getById($customerId);

$firstName = $customer->getFirstname();
$lastName = $customer->getLastname();

$sent = 0;
$customerName = "$firstName $lastName";
$sharingCode = $wishlist->getSharingCode();

try {
$sentEmails = [];

foreach ($emails as $email) {
$email = trim($email);

if (in_array($email, $sentEmails)) {
continue;
}

if (!\Zend_Validate::is($email, \Magento\Framework\Validator\EmailAddress::class)) {
throw new GraphQlInputException(__('Provided emails are not valid'));
}

$transport = $this->transportBuilder->setTemplateIdentifier(
$this->scopeConfig->getValue(
'wishlist/email/email_template',
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
)
)->setTemplateOptions(
[
'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
'store' => $this->storeManager->getStore()->getStoreId(),
]
)->setTemplateVars(
[
'customer' => $customer,
'customerName' => $customerName,
'salable' => $wishlist->isSalable() ? 'yes' : '',
'items' => $this->getWishlistItems(),
'viewOnSiteLink' => $this->getWebsiteLink($sharingCode),
'message' => $message,
'store' => $this->storeManager->getStore(),
]
)->setFromByScope(
[
'name' => $customerName,
'email' => $customer->getEmail(),
],
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
)->addTo(
$email
)->getTransport();

$transport->sendMessage();

$sent++;
$sentEmails[] = $email;
}
} catch (\Exception $e) {
$wishlist->setShared($wishlist->getShared() + $sent);
$wishlist->save();
throw $e;
}

$wishlist->setShared($wishlist->getShared() + $sent);
$wishlist->save();

return true;
}

/**
* Retrieve wishlist items content (html)
*
* @return string
*/
protected function getWishlistItems()
{

$layout = $this->layoutFactory->create();
$layout->getUpdate()->load(['wishlist_email_items']);
$layout->generateXml();
$layout->generateElements();

$block = $layout->getBlock('wishlist.email.items');

return $block ? $block->getHtml() : '';
}

protected function getWebsiteLink(string $sharingCode): string
{
$baseUrl = $this->url->getBaseUrl();
return $baseUrl . "wishlist/shared/$sharingCode";
}
}
Loading

0 comments on commit f3e8a08

Please sign in to comment.