From d0dd90f99bc641b5f2c6766a36a25f4cfd6ecf19 Mon Sep 17 00:00:00 2001 From: Lyzun Oleksandr Date: Thu, 13 Sep 2018 14:54:43 +0200 Subject: [PATCH] Refactored Account Mutation --- .../Customer/CustomerDataProvider.php | 108 +----------- .../Resolver/Customer/CustomerDataUpdater.php | 116 +++++++++++++ .../Model/Resolver/CustomerUpdate.php | 15 +- .../Magento/CustomerGraphQl/composer.json | 1 + .../Customer/CustomerAccountEditTest.php | 157 ++++++++++++++++++ 5 files changed, 291 insertions(+), 106 deletions(-) create mode 100644 app/code/Magento/CustomerGraphQl/Model/Resolver/Customer/CustomerDataUpdater.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CustomerAccountEditTest.php diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/Customer/CustomerDataProvider.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/Customer/CustomerDataProvider.php index 6b3c02ea98d41..17f40575ae3eb 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/Customer/CustomerDataProvider.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/Customer/CustomerDataProvider.php @@ -13,11 +13,8 @@ use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\Webapi\ServiceOutputProcessor; use Magento\Customer\Api\Data\CustomerInterface; -use Magento\Newsletter\Model\SubscriberFactory; use Magento\Customer\Model\CustomerRegistry; use Magento\Framework\Encryption\EncryptorInterface as Encryptor; -use Magento\Store\Api\StoreResolverInterface; -use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; /** * Customer field data provider, used for GraphQL request processing. @@ -34,16 +31,6 @@ class CustomerDataProvider */ private $serviceOutputProcessor; - /** - * @var StoreResolverInterface - */ - private $storeResolver; - - /** - * @var \Magento\Newsletter\Model\SubscriberFactory - */ - protected $subscriberFactory; - /** * @var CustomerRegistry */ @@ -68,31 +55,14 @@ public function __construct( CustomerRepositoryInterface $customerRepository, ServiceOutputProcessor $serviceOutputProcessor, SerializerInterface $jsonSerializer, - SubscriberFactory $subscriberFactory, CustomerRegistry $customerRegistry, - Encryptor $encryptor, - StoreResolverInterface $storeResolver + Encryptor $encryptor ) { $this->customerRepository = $customerRepository; $this->serviceOutputProcessor = $serviceOutputProcessor; $this->jsonSerializer = $jsonSerializer; - $this->subscriberFactory = $subscriberFactory; $this->customerRegistry = $customerRegistry; $this->encryptor = $encryptor; - $this->storeResolver = $storeResolver; - } - - /** - * Load customer object - * - * @param int $customerId - * @return CustomerInterface - * @throws LocalizedException - * @throws NoSuchEntityException - */ - public function loadCustomerById(int $customerId): CustomerInterface - { - return $this->customerRepository->getById($customerId); } /** @@ -158,82 +128,14 @@ private function processCustomer(CustomerInterface $customerObject): array } /** - * Check if customer is subscribed to Newsletter - * - * @param int $customerId - * @return bool - */ - public function isSubscribed(int $customerId): bool - { - $checkSubscriber = $this->subscriberFactory->create()->loadByCustomerId($customerId); - return $checkSubscriber->isSubscribed(); - } - - /** - * Manage customer subscription. Subscribe OR unsubscribe if required - * + * @param string $password * @param int $customerId - * @param $newSubscriptionStatus * @return bool - */ - public function manageSubscription(int $customerId, bool $newSubscriptionStatus): bool - { - $checkSubscriber = $this->subscriberFactory->create()->loadByCustomerId($customerId); - $isSubscribed = $this->isSubscribed($customerId); - - if ($newSubscriptionStatus === true && !$isSubscribed) { - $this->subscriberFactory->create()->subscribeCustomerById($customerId); - } elseif ($newSubscriptionStatus === false && $checkSubscriber->isSubscribed()) { - $this->subscriberFactory->create()->unsubscribeCustomerById($customerId); - } - return true; - } - - /** - * @param int $customerId - * @param array $customerData - * @return CustomerInterface - * @throws LocalizedException * @throws NoSuchEntityException - * @throws \Magento\Framework\Exception\InputException - * @throws \Magento\Framework\Exception\State\InputMismatchException */ - public function updateAccountInformation(int $customerId, array $customerData): CustomerInterface + public function isPasswordCorrect(string $password, int $customerId) { - - $customer = $this->loadCustomerById($customerId); - - if (isset($customerData['email']) - && $customer->getEmail() !== $customerData['email'] - && isset($customerData['password'])) { - if ($this->isPasswordCorrect($customerData['password'], $customerId)) { - $customer->setEmail($customerData['email']); - } else { - throw new GraphQlAuthorizationException(__('Invalid current user password.')); - } - } - - if (isset($customerData['firstname'])) { - $customer->setFirstname($customerData['firstname']); - } - if (isset($customerData['lastname'])) { - $customer->setLastname($customerData['lastname']); - } - - $customer->setStoreId($this->storeResolver->getCurrentStoreId()); - $this->customerRepository->save($customer); - - return $customer; - } - - private function isPasswordCorrect(string $password, int $customerId) - { - - $customerSecure = $this->customerRegistry->retrieveSecureData($customerId); - $hash = $customerSecure->getPasswordHash(); - if (!$this->encryptor->validateHash($password, $hash)) { - return false; - } - return true; + $hash = $this->customerRegistry->retrieveSecureData($customerId)->getPasswordHash(); + return $this->encryptor->validateHash($password, $hash); } } diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/Customer/CustomerDataUpdater.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/Customer/CustomerDataUpdater.php new file mode 100644 index 0000000000000..3fec957c163f8 --- /dev/null +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/Customer/CustomerDataUpdater.php @@ -0,0 +1,116 @@ +customerRepository = $customerRepository; + $this->storeResolver = $storeResolver; + $this->customerDataProvider = $customerDataProvider; + $this->subscriberFactory = $subscriberFactory; + } + + /** + * Manage customer subscription. Subscribe OR unsubscribe if required. Return new subscription status + * + * @param int $customerId + * @param $newSubscriptionStatus + * @return bool + */ + public function manageSubscription(int $customerId, bool $newSubscriptionStatus): bool + { + $subscriber = $this->subscriberFactory->create()->loadByCustomerId($customerId); + if ($newSubscriptionStatus === true && !$subscriber->isSubscribed()) { + $this->subscriberFactory->create()->subscribeCustomerById($customerId); + } elseif ($newSubscriptionStatus === false && $subscriber->isSubscribed()) { + $this->subscriberFactory->create()->unsubscribeCustomerById($customerId); + } + /** Load subscribed again to get his new status after update subscription */ + $subscriber = $this->subscriberFactory->create()->loadByCustomerId($customerId); + return $subscriber->isSubscribed(); + } + + /** + * @param int $customerId + * @param array $customerData + * @return CustomerInterface + * @throws GraphQlAuthorizationException + * @throws LocalizedException + * @throws NoSuchEntityException + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\State\InputMismatchException + */ + public function updateAccountInformation(int $customerId, array $customerData): CustomerInterface + { + $customer = $this->customerRepository->getById($customerId); + + if (isset($customerData['email']) + && $customer->getEmail() !== $customerData['email'] + && isset($customerData['password'])) { + if ($this->customerDataProvider->isPasswordCorrect($customerData['password'], $customerId)) { + $customer->setEmail($customerData['email']); + } else { + throw new GraphQlAuthorizationException(__('Invalid current user password.')); + } + } + + if (isset($customerData['firstname'])) { + $customer->setFirstname($customerData['firstname']); + } + if (isset($customerData['lastname'])) { + $customer->setLastname($customerData['lastname']); + } + + $customer->setStoreId($this->storeResolver->getCurrentStoreId()); + $this->customerRepository->save($customer); + + return $customer; + } +} diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/CustomerUpdate.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/CustomerUpdate.php index 51f62a7a8cafd..6c3112632dbe2 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/CustomerUpdate.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/CustomerUpdate.php @@ -10,6 +10,7 @@ use Magento\Authorization\Model\UserContextInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\CustomerGraphQl\Model\Resolver\Customer\CustomerDataProvider; +use Magento\CustomerGraphQl\Model\Resolver\Customer\CustomerDataUpdater; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; @@ -27,6 +28,11 @@ class CustomerUpdate implements ResolverInterface */ private $customerResolver; + /** + * @var CustomerDataUpdater + */ + private $customerUpdater; + /** * @var ValueFactory */ @@ -48,12 +54,14 @@ class CustomerUpdate implements ResolverInterface */ public function __construct( CustomerDataProvider $customerResolver, + CustomerDataUpdater $customerUpdater, ValueFactory $valueFactory, \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory ) { $this->customerResolver = $customerResolver; $this->valueFactory = $valueFactory; $this->subscriberFactory = $subscriberFactory; + $this->customerUpdater = $customerUpdater; } /** @@ -77,13 +85,14 @@ public function resolve( ); } - $this->customerResolver->updateAccountInformation($context->getUserId(), $args); + $customerId = $context->getUserId(); + $this->customerUpdater->updateAccountInformation($customerId, $args); + $data = $this->customerResolver->getCustomerById($customerId); if (isset($args['is_subscribed'])) { - $this->customerResolver->manageSubscription($context->getUserId(), $args['is_subscribed']); + $data['is_subscribed'] = $this->customerUpdater->manageSubscription($customerId, $args['is_subscribed']); } - $data = $args; $result = function () use ($data) { return !empty($data) ? $data : []; }; diff --git a/app/code/Magento/CustomerGraphQl/composer.json b/app/code/Magento/CustomerGraphQl/composer.json index 290d925215ec2..ea9d0613f9737 100644 --- a/app/code/Magento/CustomerGraphQl/composer.json +++ b/app/code/Magento/CustomerGraphQl/composer.json @@ -6,6 +6,7 @@ "php": "~7.1.3||~7.2.0", "magento/module-customer": "*", "magento/module-authorization": "*", + "magento/newsletter": "*", "magento/framework": "*" }, "suggest": { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CustomerAccountEditTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CustomerAccountEditTest.php new file mode 100644 index 0000000000000..7bf46f08c853a --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CustomerAccountEditTest.php @@ -0,0 +1,157 @@ +getChangeAccountInformationQuery($customerNewFirstname, $customerNewLastname); + + $headerMap = $this->getCustomerAuthHeaders($customerEmail, $customerPassword); + $response = $this->graphQlQuery($query, [], '', $headerMap); + + $this->assertEquals($customerNewFirstname, $response['customerUpdate']['firstname']); + $this->assertEquals($customerNewLastname, $response['customerUpdate']['lastname']); + } + + /** + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + */ + public function testCustomerChangeEmail() + { + $customerEmail = 'customer@example.com'; + $customerPassword = 'password'; + $newEmailAddress = 'customer2@example.com'; + + $headerMap = $this->getCustomerAuthHeaders($customerEmail, $customerPassword); + + $query = $this->getChangeEmailQuery($newEmailAddress, $customerPassword); + $response = $this->graphQlQuery($query, [], '', $headerMap); + $this->assertEquals($newEmailAddress, $response['customerUpdate']['email']); + + /** + * Roll back email address to default + */ + $query = $this->getChangeEmailQuery($customerEmail, $customerPassword); + $response = $this->graphQlQuery($query, [], '', $headerMap); + $this->assertEquals($customerEmail, $response['customerUpdate']['email']); + } + + /** + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + */ + public function testCustomerCheckSubscription() + { + $customerEmail = 'customer@example.com'; + $customerPassword = 'password'; + + $isSubscribed = "true"; + + $query = $this->getSubscriptionQuery($isSubscribed); + $headerMap = $this->getCustomerAuthHeaders($customerEmail, $customerPassword); + + $response = $this->graphQlQuery($query, [], '', $headerMap); + + $subscriberModel = ObjectManager::getInstance()->get(Subscriber::class); + $subscriber = $subscriberModel->loadByEmail($customerEmail); + + $this->assertEquals(true, $subscriber->isSubscribed()); + } + private function getSubscriptionQuery($isSubscribed) + { + $query = <<objectManager->create(CustomerTokenServiceInterface::class); + $customerToken = $customerTokenService->createCustomerAccessToken($customerEmail, $customerPassword); + return ['Authorization' => 'Bearer ' . $customerToken]; + } + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->accountManagement = $this->objectManager->get(AccountManagementInterface::class); + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->searchCriteriaBuilder = $objectManager->create( + \Magento\Framework\Api\SearchCriteriaBuilder::class + ); + $this->filterBuilder = $objectManager->get( + \Magento\Framework\Api\FilterBuilder::class + ); + } +} \ No newline at end of file