Skip to content
This repository was archived by the owner on Dec 19, 2019. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 5 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
278 changes: 278 additions & 0 deletions app/code/Magento/CustomerGraphQl/Model/Resolver/Address.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CustomerGraphQl\Model\Resolver;

use Magento\Authorization\Model\UserContextInterface;
use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Api\AddressRepositoryInterface;
use Magento\Customer\Api\AddressMetadataManagementInterface;
use Magento\Customer\Api\Data\AddressInterfaceFactory;
use Magento\Customer\Api\Data\AddressInterface;
use Magento\Framework\Api\DataObjectHelper;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\CustomerGraphQl\Model\Resolver\Address\AddressDataProvider;
use Magento\Eav\Model\Config;
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\Exception\NoSuchEntityException;

/**
* Customers Address, used for GraphQL request processing.
*/
class Address implements ResolverInterface
{
/**
* Mutation Address type
*/
const MUTATION_ADDRESS_CREATE = 'customerAddressCreate';
const MUTATION_ADDRESS_UPDATE = 'customerAddressUpdate';
const MUTATION_ADDRESS_DELETE = 'customerAddressDelete';

/**
* @var AddressRepositoryInterface
*/
private $addressRepositoryInterface;

/**
* @var AddressInterfaceFactory
*/
private $addressInterfaceFactory;

/**
* @var Config
*/
private $eavConfig;

/**
* @var AddressDataProvider
*/
private $addressDataProvider;

/**
* @var DataObjectHelper
*/
private $dataObjectHelper;

/**
* @var array
*/
private $addressAttributes;

/**
* @param AddressRepositoryInterface $addressRepositoryInterface
* @param AddressInterfaceFactory $addressInterfaceFactory
* @param Config $eavConfig
* @param AddressDataProvider $addressDataProvider
* @param DataObjectHelper $dataObjectHelper
*/
public function __construct(
AddressRepositoryInterface $addressRepositoryInterface,
AddressInterfaceFactory $addressInterfaceFactory,
Config $eavConfig,
AddressDataProvider $addressDataProvider,
DataObjectHelper $dataObjectHelper
) {
$this->addressRepositoryInterface = $addressRepositoryInterface;
$this->addressInterfaceFactory = $addressInterfaceFactory;
$this->eavConfig = $eavConfig;
$this->addressDataProvider = $addressDataProvider;
$this->dataObjectHelper = $dataObjectHelper;
$this->addressAttributes = $this->eavConfig->getEntityAttributes(
AddressMetadataManagementInterface::ENTITY_TYPE_ADDRESS
);
}

/**
* @inheritdoc
*/
public function resolve(
Field $field,
$context,
ResolveInfo $info,
array $value = null,
array $args = null
) {
/** @var \Magento\Framework\GraphQl\Query\Resolver\ContextInterface $context */
if ((!$context->getUserId()) || $context->getUserType() == UserContextInterface::USER_TYPE_GUEST) {
throw new GraphQlAuthorizationException(
__(
'Current customer does not have access to the resource "%1"',
[AddressMetadataManagementInterface::ENTITY_TYPE_ADDRESS]
)
);
}
$customerId = $context->getUserId();
switch ($field->getName()) {
case self::MUTATION_ADDRESS_CREATE:
return $this->addressDataProvider->processCustomerAddress(
$this->processCustomerAddressCreate($customerId, $args['input'])
);
case self::MUTATION_ADDRESS_UPDATE:
return $this->addressDataProvider->processCustomerAddress(
$this->processCustomerAddressUpdate($customerId, $args['id'], $args['input'])
);
case self::MUTATION_ADDRESS_DELETE:
return $this->processCustomerAddressDelete($customerId, $args['id']);
default:
return [];
}
}

/**
* Get new address attribute input errors
*
* @param array $addressInput
* @return bool|string
*/
private function getNewAddressInputError(array $addressInput)
{
foreach ($this->addressAttributes as $attributeName => $attributeInfo) {
if ($attributeInfo->getIsRequired()
&& (!isset($addressInput[$attributeName]) || empty($addressInput[$attributeName]))) {
return $attributeName;
}
}
return false;
}

/**
* Get update address attribute input errors
*
* @param array $addressInput
* @return bool|string
*/
private function getUpdateAddressInputError(array $addressInput)
{
foreach ($this->addressAttributes as $attributeName => $attributeInfo) {
if ($attributeInfo->getIsRequired()
&& (isset($addressInput[$attributeName]) && empty($addressInput[$attributeName]))) {
return $attributeName;
}
}
return false;
}

/**
* Add $addressInput array information to a $address object
*
* @param AddressInterface $address
* @param array $addressInput
* @return AddressInterface
*/
private function fillAddress(AddressInterface $address, array $addressInput) : AddressInterface
{
$this->dataObjectHelper->populateWithArray(
$address,
$addressInput,
AddressInterface::class
);
return $address;
}

/**
* Process customer address create
*
* @param int $customerId
* @param array $addressInput
* @return AddressInterface
* @throws GraphQlInputException
*/
private function processCustomerAddressCreate($customerId, array $addressInput) : AddressInterface
{
$errorInput = $this->getNewAddressInputError($addressInput);
if ($errorInput) {
throw new GraphQlInputException(
__('Required parameter %1 is missing', [$errorInput])
);
}
/** @var AddressInterface $newAddress */
$newAddress = $this->fillAddress(
$this->addressInterfaceFactory->create(),
$addressInput
);
$newAddress->setCustomerId($customerId);
return $this->addressRepositoryInterface->save($newAddress);
}

/**
* Process customer address update
*
* @param int $customerId
* @param int $addressId
* @param array $addressInput
* @return AddressInterface
* @throws GraphQlAuthorizationException
* @throws GraphQlNoSuchEntityException
* @throws GraphQlInputException
*/
private function processCustomerAddressUpdate($customerId, $addressId, array $addressInput)
{
try {
/** @var AddressInterface $address */
$address = $this->addressRepositoryInterface->getById($addressId);
} catch (NoSuchEntityException $exception) {
throw new GraphQlNoSuchEntityException(
__('Address id %1 does not exist.', [$addressId])
);
}
if ($address->getCustomerId() != $customerId) {
throw new GraphQlAuthorizationException(
__('Current customer does not have permission to update address id %1', [$addressId])
);
}
$errorInput = $this->getUpdateAddressInputError($addressInput);
if ($errorInput) {
throw new GraphQlInputException(
__('Required parameter %1 is missing', [$errorInput])
);
}
return $this->addressRepositoryInterface->save(
$this->fillAddress($address, $addressInput)
);
}

/**
* Process customer address delete
*
* @param int $customerId
* @param int $addressId
* @return bool
* @throws GraphQlAuthorizationException
* @throws GraphQlNoSuchEntityException
*/
private function processCustomerAddressDelete($customerId, $addressId)
{
try {
/** @var AddressInterface $address */
$address = $this->addressRepositoryInterface->getById($addressId);
} catch (NoSuchEntityException $exception) {
throw new GraphQlNoSuchEntityException(
__('Address id %1 does not exist.', [$addressId])
);
}
if ($customerId != $address->getCustomerId()) {
throw new GraphQlAuthorizationException(
__('Current customer does not have permission to delete address id %1', [$addressId])
);
}
if ($address->isDefaultBilling()) {
throw new GraphQlAuthorizationException(
__('Customer Address %1 is set as default billing address and can not be deleted', [$addressId])
);
}
if ($address->isDefaultShipping()) {
throw new GraphQlAuthorizationException(
__('Customer Address %1 is set as default shipping address and can not be deleted', [$addressId])
);
}
return $this->addressRepositoryInterface->delete($address);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CustomerGraphQl\Model\Resolver\Address;

use Magento\Customer\Api\Data\AddressInterface;
use Magento\Customer\Api\AddressRepositoryInterface;
use Magento\Framework\Webapi\ServiceOutputProcessor;
use Magento\Framework\Serialize\SerializerInterface;

/**
* Customer Address field data provider, used for GraphQL request processing.
*/
class AddressDataProvider
{
/**
* @var ServiceOutputProcessor
*/
private $serviceOutputProcessor;

/**
* @var SerializerInterface
*/
private $jsonSerializer;

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

/**
* Transform single customer address data from object to in array format
*
* @param AddressInterface $addressObject
* @return array
*/
public function processCustomerAddress(AddressInterface $addressObject) : array
{
$address = $this->serviceOutputProcessor->process(
$addressObject,
AddressRepositoryInterface::class,
'getById'
);
if (isset($address['extension_attributes'])) {
$address = array_merge($address, $address['extension_attributes']);
}
$customAttributes = [];
if (isset($address['custom_attributes'])) {
foreach ($address['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(
$attribute['value']
);
continue;
}
$customAttributes[$attribute['attribute_code']] = implode(',', $attribute['value']);
continue;
}
}
if ($isArray) {
continue;
}
$customAttributes[$attribute['attribute_code']] = $attribute['value'];
}
}
$address = array_merge($address, $customAttributes);

return $address;
}
}
1 change: 1 addition & 0 deletions app/code/Magento/CustomerGraphQl/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"magento/module-customer": "*",
"magento/module-authorization": "*",
"magento/module-integration": "*",
"magento/module-eav": "*",
"magento/framework": "*"
},
"suggest": {
Expand Down
1 change: 1 addition & 0 deletions app/code/Magento/CustomerGraphQl/etc/module.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<module name="Magento_Customer"/>
<module name="Magento_Authorization"/>
<module name="Magento_GraphQl"/>
<module name="Magento_Eav"/>
</sequence>
</module>
</config>
Loading