Skip to content
This repository has been archived by the owner on Dec 19, 2019. It is now read-only.

My Account > Change account information and Newsletter subscription #162

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CustomerGraphQl\Model\Customer;

use Magento\Newsletter\Model\SubscriberFactory;

/**
* Change subscription status. Subscribe OR unsubscribe if required
*/
class ChangeSubscriptionStatus
{
/**
* @var SubscriberFactory
*/
private $subscriberFactory;

/**
* @param SubscriberFactory $subscriberFactory
*/
public function __construct(
SubscriberFactory $subscriberFactory
) {
$this->subscriberFactory = $subscriberFactory;
}

/**
* Change subscription status. Subscribe OR unsubscribe if required
*
* @param int $customerId
* @param bool $subscriptionStatus
* @return void
*/
public function execute(int $customerId, bool $subscriptionStatus): void
{
$subscriber = $this->subscriberFactory->create()->loadByCustomerId($customerId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not make sense to load records from DB if the next two conditions fail.


if ($subscriptionStatus === true && !$subscriber->isSubscribed()) {
$this->subscriberFactory->create()->subscribeCustomerById($customerId);
} elseif ($subscriptionStatus === false && $subscriber->isSubscribed()) {
$this->subscriberFactory->create()->unsubscribeCustomerById($customerId);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CustomerGraphQl\Model\Customer;

use Magento\Authorization\Model\UserContextInterface;
use Magento\Customer\Api\AccountManagementInterface;
use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Model\AuthenticationInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException;
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;

/**
* Check customer account
*/
class CheckCustomerAccount
{
/**
* @var AuthenticationInterface
*/
private $authentication;

/**
* @var CustomerRepositoryInterface
*/
private $customerRepository;

/**
* @var AccountManagementInterface
*/
private $accountManagement;

/**
* @param AuthenticationInterface $authentication
* @param CustomerRepositoryInterface $customerRepository
* @param AccountManagementInterface $accountManagement
*/
public function __construct(
AuthenticationInterface $authentication,
CustomerRepositoryInterface $customerRepository,
AccountManagementInterface $accountManagement
) {
$this->authentication = $authentication;
$this->customerRepository = $customerRepository;
$this->accountManagement = $accountManagement;
}

/**
* Check customer account
*
* @param int|null $customerId
* @param int|null $customerType
* @return void
* @throws GraphQlAuthorizationException
* @throws GraphQlNoSuchEntityException
* @throws GraphQlAuthenticationException
*/
public function execute(?int $customerId, ?int $customerType): void
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why customer type is needed here? For guests $customerID will be 0.
Also, why these arguments are optional? We can just ask for (int)$customerId

{
if (true === $this->isCustomerGuest($customerId, $customerType)) {
throw new GraphQlAuthorizationException(__('The current customer isn\'t authorized.'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually it is better to use 'is not' instead of 'isn't' in error message.

}

try {
$this->customerRepository->getById($customerId);
} catch (NoSuchEntityException $e) {
throw new GraphQlNoSuchEntityException(
__('Customer with id "%customer_id" does not exist.', ['customer_id' => $customerId]),
$e
);
}

if (true === $this->authentication->isLocked($customerId)) {
throw new GraphQlAuthenticationException(__('The account is locked.'));
}

$confirmationStatus = $this->accountManagement->getConfirmationStatus($customerId);
if ($confirmationStatus === AccountManagementInterface::ACCOUNT_CONFIRMATION_REQUIRED) {
throw new GraphQlAuthenticationException(__("This account isn't confirmed. Verify and try again."));
}
}

/**
* Checking if current customer is guest
*
* @param int|null $customerId
* @param int|null $customerType
* @return bool
*/
private function isCustomerGuest(?int $customerId, ?int $customerType): bool
{
if (null === $customerId || null === $customerType) {
return true;
}
return 0 === (int)$customerId || (int)$customerType === UserContextInterface::USER_TYPE_GUEST;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CustomerGraphQl\Model\Customer;

use Magento\Customer\Model\AuthenticationInterface;
use Magento\Framework\Exception\InvalidEmailOrPasswordException;
use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException;

/**
* Check customer password
*/
class CheckCustomerPassword
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use nouns as class names. Please consider changing it to CustomerPasswordVerifier or CustomerAuthenticator.

Please fix the names of all affected variables which hold this object as well.

{
/**
* @var AuthenticationInterface
*/
private $authentication;

/**
* @param AuthenticationInterface $authentication
*/
public function __construct(
AuthenticationInterface $authentication
) {
$this->authentication = $authentication;
}

/**
* Check customer password
*
* @param string $password
* @param int $customerId
* @throws GraphQlAuthenticationException
*/
public function execute(string $password, int $customerId)
{
try {
$this->authentication->authenticate($customerId, $password);
} catch (InvalidEmailOrPasswordException $e) {
throw new GraphQlAuthenticationException(
__('The password doesn\'t match this account. Verify the password and try again.')
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
*/
declare(strict_types=1);

namespace Magento\CustomerGraphQl\Model\Resolver\Customer;
namespace Magento\CustomerGraphQl\Model\Customer;

use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Framework\Serialize\SerializerInterface;
use Magento\Framework\Webapi\ServiceOutputProcessor;
use Magento\Customer\Api\Data\CustomerInterface;
Expand All @@ -32,21 +33,21 @@ class CustomerDataProvider
/**
* @var SerializerInterface
*/
private $jsonSerializer;
private $serializer;

/**
* @param CustomerRepositoryInterface $customerRepository
* @param ServiceOutputProcessor $serviceOutputProcessor
* @param SerializerInterface $jsonSerializer
* @param SerializerInterface $serializer
*/
public function __construct(
CustomerRepositoryInterface $customerRepository,
ServiceOutputProcessor $serviceOutputProcessor,
SerializerInterface $jsonSerializer
SerializerInterface $serializer
) {
$this->customerRepository = $customerRepository;
$this->serviceOutputProcessor = $serviceOutputProcessor;
$this->jsonSerializer = $jsonSerializer;
$this->serializer = $serializer;
}

/**
Expand All @@ -56,42 +57,44 @@ public function __construct(
* @return array
* @throws NoSuchEntityException|LocalizedException
*/
public function getCustomerById(int $customerId) : array
public function getCustomerById(int $customerId): array
{
try {
$customerObject = $this->customerRepository->getById($customerId);
$customer = $this->customerRepository->getById($customerId);
} catch (NoSuchEntityException $e) {
// No error should be thrown, null result should be returned
return [];
throw new GraphQlNoSuchEntityException(
__('Customer id "%customer_id" does not exist.', ['customer_id' => $customerId]),
$e
);
}
return $this->processCustomer($customerObject);
return $this->processCustomer($customer);
}

/**
* Transform single customer data from object to in array format
*
* @param CustomerInterface $customerObject
* @param CustomerInterface $customer
* @return array
*/
private function processCustomer(CustomerInterface $customerObject) : array
private function processCustomer(CustomerInterface $customer): array
{
$customer = $this->serviceOutputProcessor->process(
$customerObject,
$customerData = $this->serviceOutputProcessor->process(
$customer,
CustomerRepositoryInterface::class,
'get'
);
if (isset($customer['extension_attributes'])) {
$customer = array_merge($customer, $customer['extension_attributes']);
if (isset($customerData['extension_attributes'])) {
$customerData = array_merge($customerData, $customerData['extension_attributes']);
}
$customAttributes = [];
if (isset($customer['custom_attributes'])) {
foreach ($customer['custom_attributes'] as $attribute) {
if (isset($customerData['custom_attributes'])) {
foreach ($customerData['custom_attributes'] as $attribute) {
$isArray = false;
if (is_array($attribute['value'])) {
$isArray = true;
foreach ($attribute['value'] as $attributeValue) {
if (is_array($attributeValue)) {
$customAttributes[$attribute['attribute_code']] = $this->jsonSerializer->serialize(
$customAttributes[$attribute['attribute_code']] = $this->serializer->serialize(
$attribute['value']
);
continue;
Expand All @@ -106,8 +109,8 @@ private function processCustomer(CustomerInterface $customerObject) : array
$customAttributes[$attribute['attribute_code']] = $attribute['value'];
}
}
$customer = array_merge($customer, $customAttributes);
$customerData = array_merge($customerData, $customAttributes);

return $customer;
return $customerData;
}
}
Loading