123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Customer\Model\ResourceModel;
- use Magento\Customer\Api\CustomerMetadataInterface;
- use Magento\Customer\Api\Data\CustomerInterface;
- use Magento\Customer\Api\Data\CustomerSearchResultsInterfaceFactory;
- use Magento\Framework\Api\ExtensibleDataObjectConverter;
- use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
- use Magento\Customer\Model\CustomerFactory;
- use Magento\Customer\Model\CustomerRegistry;
- use Magento\Customer\Model\Data\CustomerSecureFactory;
- use Magento\Customer\Model\Customer\NotificationStorage;
- use Magento\Customer\Model\Delegation\Data\NewOperation;
- use Magento\Customer\Api\CustomerRepositoryInterface;
- use Magento\Framework\Api\DataObjectHelper;
- use Magento\Framework\Api\ImageProcessorInterface;
- use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
- use Magento\Framework\Api\SearchCriteriaInterface;
- use Magento\Framework\Api\Search\FilterGroup;
- use Magento\Framework\Event\ManagerInterface;
- use Magento\Customer\Model\Delegation\Storage as DelegatedStorage;
- use Magento\Framework\App\ObjectManager;
- use Magento\Store\Model\StoreManagerInterface;
- /**
- * Customer repository.
- *
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- * @SuppressWarnings(PHPMD.TooManyFields)
- */
- class CustomerRepository implements CustomerRepositoryInterface
- {
- /**
- * @var CustomerFactory
- */
- protected $customerFactory;
- /**
- * @var CustomerSecureFactory
- */
- protected $customerSecureFactory;
- /**
- * @var CustomerRegistry
- */
- protected $customerRegistry;
- /**
- * @var AddressRepository
- */
- protected $addressRepository;
- /**
- * @var Customer
- */
- protected $customerResourceModel;
- /**
- * @var CustomerMetadataInterface
- */
- protected $customerMetadata;
- /**
- * @var CustomerSearchResultsInterfaceFactory
- */
- protected $searchResultsFactory;
- /**
- * @var ManagerInterface
- */
- protected $eventManager;
- /**
- * @var StoreManagerInterface
- */
- protected $storeManager;
- /**
- * @var ExtensibleDataObjectConverter
- */
- protected $extensibleDataObjectConverter;
- /**
- * @var DataObjectHelper
- */
- protected $dataObjectHelper;
- /**
- * @var ImageProcessorInterface
- */
- protected $imageProcessor;
- /**
- * @var JoinProcessorInterface
- */
- protected $extensionAttributesJoinProcessor;
- /**
- * @var CollectionProcessorInterface
- */
- private $collectionProcessor;
- /**
- * @var NotificationStorage
- */
- private $notificationStorage;
- /**
- * @var DelegatedStorage
- */
- private $delegatedStorage;
- /**
- * @param CustomerFactory $customerFactory
- * @param CustomerSecureFactory $customerSecureFactory
- * @param CustomerRegistry $customerRegistry
- * @param AddressRepository $addressRepository
- * @param Customer $customerResourceModel
- * @param CustomerMetadataInterface $customerMetadata
- * @param CustomerSearchResultsInterfaceFactory $searchResultsFactory
- * @param ManagerInterface $eventManager
- * @param StoreManagerInterface $storeManager
- * @param ExtensibleDataObjectConverter $extensibleDataObjectConverter
- * @param DataObjectHelper $dataObjectHelper
- * @param ImageProcessorInterface $imageProcessor
- * @param JoinProcessorInterface $extensionAttributesJoinProcessor
- * @param CollectionProcessorInterface $collectionProcessor
- * @param NotificationStorage $notificationStorage
- * @param DelegatedStorage|null $delegatedStorage
- * @SuppressWarnings(PHPMD.ExcessiveParameterList)
- */
- public function __construct(
- CustomerFactory $customerFactory,
- CustomerSecureFactory $customerSecureFactory,
- CustomerRegistry $customerRegistry,
- AddressRepository $addressRepository,
- Customer $customerResourceModel,
- CustomerMetadataInterface $customerMetadata,
- CustomerSearchResultsInterfaceFactory $searchResultsFactory,
- ManagerInterface $eventManager,
- StoreManagerInterface $storeManager,
- ExtensibleDataObjectConverter $extensibleDataObjectConverter,
- DataObjectHelper $dataObjectHelper,
- ImageProcessorInterface $imageProcessor,
- JoinProcessorInterface $extensionAttributesJoinProcessor,
- CollectionProcessorInterface $collectionProcessor,
- NotificationStorage $notificationStorage,
- DelegatedStorage $delegatedStorage = null
- ) {
- $this->customerFactory = $customerFactory;
- $this->customerSecureFactory = $customerSecureFactory;
- $this->customerRegistry = $customerRegistry;
- $this->addressRepository = $addressRepository;
- $this->customerResourceModel = $customerResourceModel;
- $this->customerMetadata = $customerMetadata;
- $this->searchResultsFactory = $searchResultsFactory;
- $this->eventManager = $eventManager;
- $this->storeManager = $storeManager;
- $this->extensibleDataObjectConverter = $extensibleDataObjectConverter;
- $this->dataObjectHelper = $dataObjectHelper;
- $this->imageProcessor = $imageProcessor;
- $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor;
- $this->collectionProcessor = $collectionProcessor;
- $this->notificationStorage = $notificationStorage;
- $this->delegatedStorage = $delegatedStorage ?? ObjectManager::getInstance()->get(DelegatedStorage::class);
- }
- /**
- * @inheritdoc
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- */
- public function save(CustomerInterface $customer, $passwordHash = null)
- {
- /** @var NewOperation|null $delegatedNewOperation */
- $delegatedNewOperation = !$customer->getId() ? $this->delegatedStorage->consumeNewOperation() : null;
- $prevCustomerData = null;
- $prevCustomerDataArr = null;
- if ($customer->getId()) {
- $prevCustomerData = $this->getById($customer->getId());
- $prevCustomerDataArr = $prevCustomerData->__toArray();
- }
- /** @var $customer \Magento\Customer\Model\Data\Customer */
- $customerArr = $customer->__toArray();
- $customer = $this->imageProcessor->save(
- $customer,
- CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER,
- $prevCustomerData
- );
- $origAddresses = $customer->getAddresses();
- $customer->setAddresses([]);
- $customerData = $this->extensibleDataObjectConverter->toNestedArray($customer, [], CustomerInterface::class);
- $customer->setAddresses($origAddresses);
- /** @var Customer $customerModel */
- $customerModel = $this->customerFactory->create(['data' => $customerData]);
- //Model's actual ID field maybe different than "id" so "id" field from $customerData may be ignored.
- $customerModel->setId($customer->getId());
- $storeId = $customerModel->getStoreId();
- if ($storeId === null) {
- $customerModel->setStoreId($this->storeManager->getStore()->getId());
- }
- // Need to use attribute set or future updates can cause data loss
- if (!$customerModel->getAttributeSetId()) {
- $customerModel->setAttributeSetId(CustomerMetadataInterface::ATTRIBUTE_SET_ID_CUSTOMER);
- }
- $this->populateCustomerWithSecureData($customerModel, $passwordHash);
- // If customer email was changed, reset RpToken info
- if ($prevCustomerData && $prevCustomerData->getEmail() !== $customerModel->getEmail()) {
- $customerModel->setRpToken(null);
- $customerModel->setRpTokenCreatedAt(null);
- }
- if (!array_key_exists('addresses', $customerArr)
- && null !== $prevCustomerDataArr
- && array_key_exists('default_billing', $prevCustomerDataArr)
- ) {
- $customerModel->setDefaultBilling($prevCustomerDataArr['default_billing']);
- }
- if (!array_key_exists('addresses', $customerArr)
- && null !== $prevCustomerDataArr
- && array_key_exists('default_shipping', $prevCustomerDataArr)
- ) {
- $customerModel->setDefaultShipping($prevCustomerDataArr['default_shipping']);
- }
- $this->setValidationFlag($customerArr, $customerModel);
- $customerModel->save();
- $this->customerRegistry->push($customerModel);
- $customerId = $customerModel->getId();
- if (!$customer->getAddresses()
- && $delegatedNewOperation
- && $delegatedNewOperation->getCustomer()->getAddresses()
- ) {
- $customer->setAddresses($delegatedNewOperation->getCustomer()->getAddresses());
- }
- if ($customer->getAddresses() !== null && !$customerModel->getData('ignore_validation_flag')) {
- if ($customer->getId()) {
- $existingAddresses = $this->getById($customer->getId())->getAddresses();
- $getIdFunc = function ($address) {
- return $address->getId();
- };
- $existingAddressIds = array_map($getIdFunc, $existingAddresses);
- } else {
- $existingAddressIds = [];
- }
- $savedAddressIds = [];
- foreach ($customer->getAddresses() as $address) {
- $address->setCustomerId($customerId)
- ->setRegion($address->getRegion());
- $this->addressRepository->save($address);
- if ($address->getId()) {
- $savedAddressIds[] = $address->getId();
- }
- }
- $addressIdsToDelete = array_diff($existingAddressIds, $savedAddressIds);
- foreach ($addressIdsToDelete as $addressId) {
- $this->addressRepository->deleteById($addressId);
- }
- }
- $this->customerRegistry->remove($customerId);
- $savedCustomer = $this->get($customer->getEmail(), $customer->getWebsiteId());
- $this->eventManager->dispatch(
- 'customer_save_after_data_object',
- [
- 'customer_data_object' => $savedCustomer,
- 'orig_customer_data_object' => $prevCustomerData,
- 'delegate_data' => $delegatedNewOperation ? $delegatedNewOperation->getAdditionalData() : [],
- ]
- );
- return $savedCustomer;
- }
- /**
- * Set secure data to customer model
- *
- * @param \Magento\Customer\Model\Customer $customerModel
- * @param string|null $passwordHash
- * @SuppressWarnings(PHPMD.NPathComplexity)
- * @return void
- */
- private function populateCustomerWithSecureData($customerModel, $passwordHash = null)
- {
- if ($customerModel->getId()) {
- $customerSecure = $this->customerRegistry->retrieveSecureData($customerModel->getId());
- $customerModel->setRpToken($passwordHash ? null : $customerSecure->getRpToken());
- $customerModel->setRpTokenCreatedAt($passwordHash ? null : $customerSecure->getRpTokenCreatedAt());
- $customerModel->setPasswordHash($passwordHash ?: $customerSecure->getPasswordHash());
- $customerModel->setFailuresNum($customerSecure->getFailuresNum());
- $customerModel->setFirstFailure($customerSecure->getFirstFailure());
- $customerModel->setLockExpires($customerSecure->getLockExpires());
- } elseif ($passwordHash) {
- $customerModel->setPasswordHash($passwordHash);
- }
- if ($passwordHash && $customerModel->getId()) {
- $this->customerRegistry->remove($customerModel->getId());
- }
- }
- /**
- * @inheritdoc
- */
- public function get($email, $websiteId = null)
- {
- $customerModel = $this->customerRegistry->retrieveByEmail($email, $websiteId);
- return $customerModel->getDataModel();
- }
- /**
- * @inheritdoc
- */
- public function getById($customerId)
- {
- $customerModel = $this->customerRegistry->retrieve($customerId);
- return $customerModel->getDataModel();
- }
- /**
- * @inheritdoc
- */
- public function getList(SearchCriteriaInterface $searchCriteria)
- {
- $searchResults = $this->searchResultsFactory->create();
- $searchResults->setSearchCriteria($searchCriteria);
- /** @var \Magento\Customer\Model\ResourceModel\Customer\Collection $collection */
- $collection = $this->customerFactory->create()->getCollection();
- $this->extensionAttributesJoinProcessor->process(
- $collection,
- CustomerInterface::class
- );
- // This is needed to make sure all the attributes are properly loaded
- foreach ($this->customerMetadata->getAllAttributesMetadata() as $metadata) {
- $collection->addAttributeToSelect($metadata->getAttributeCode());
- }
- // Needed to enable filtering on name as a whole
- $collection->addNameToSelect();
- // Needed to enable filtering based on billing address attributes
- $collection->joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
- ->joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
- ->joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
- ->joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
- ->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left')
- ->joinAttribute('billing_company', 'customer_address/company', 'default_billing', null, 'left');
- $this->collectionProcessor->process($searchCriteria, $collection);
- $searchResults->setTotalCount($collection->getSize());
- $customers = [];
- /** @var \Magento\Customer\Model\Customer $customerModel */
- foreach ($collection as $customerModel) {
- $customers[] = $customerModel->getDataModel();
- }
- $searchResults->setItems($customers);
- return $searchResults;
- }
- /**
- * @inheritdoc
- */
- public function delete(CustomerInterface $customer)
- {
- return $this->deleteById($customer->getId());
- }
- /**
- * @inheritdoc
- */
- public function deleteById($customerId)
- {
- $customerModel = $this->customerRegistry->retrieve($customerId);
- $customerModel->delete();
- $this->customerRegistry->remove($customerId);
- $this->notificationStorage->remove(NotificationStorage::UPDATE_CUSTOMER_SESSION, $customerId);
- return true;
- }
- /**
- * Helper function that adds a FilterGroup to the collection.
- *
- * @deprecated 101.0.0
- * @param FilterGroup $filterGroup
- * @param Collection $collection
- * @return void
- */
- protected function addFilterGroupToCollection(FilterGroup $filterGroup, Collection $collection)
- {
- $fields = [];
- foreach ($filterGroup->getFilters() as $filter) {
- $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq';
- $fields[] = ['attribute' => $filter->getField(), $condition => $filter->getValue()];
- }
- if ($fields) {
- $collection->addFieldToFilter($fields);
- }
- }
- /**
- * Set ignore_validation_flag to skip model validation
- *
- * @param array $customerArray
- * @param Customer $customerModel
- * @return void
- */
- private function setValidationFlag($customerArray, $customerModel)
- {
- if (isset($customerArray['ignore_validation_flag'])) {
- $customerModel->setData('ignore_validation_flag', true);
- }
- }
- }
|