123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\CustomerImportExport\Model\Import;
- use Magento\Customer\Model\ResourceModel\Address\Attribute\Source\CountryWithWebsites as CountryWithWebsitesSource;
- use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
- use Magento\Framework\App\ObjectManager;
- use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface;
- use Magento\Store\Model\Store;
- use Magento\CustomerImportExport\Model\ResourceModel\Import\Address\Storage as AddressStorage;
- use Magento\ImportExport\Model\Import\AbstractSource;
- /**
- * Customer address import
- *
- * @SuppressWarnings(PHPMD.TooManyFields)
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
- */
- class Address extends AbstractCustomer
- {
- /**#@+
- * Attribute collection name
- */
- const ATTRIBUTE_COLLECTION_NAME = \Magento\Customer\Model\ResourceModel\Address\Attribute\Collection::class;
- /**#@-*/
- /**#@+
- * Permanent column names
- *
- * Names that begins with underscore is not an attribute.
- * This name convention is for to avoid interference with same attribute name.
- */
- const COLUMN_EMAIL = '_email';
- const COLUMN_ADDRESS_ID = '_entity_id';
- /**#@-*/
- /**#@+
- * Required column names
- */
- const COLUMN_REGION = 'region';
- const COLUMN_COUNTRY_ID = 'country_id';
- const COLUMN_POSTCODE = 'postcode';
- /**#@-*/
- /**#@+
- * Particular columns that contains of customer default addresses
- */
- const COLUMN_DEFAULT_BILLING = '_address_default_billing_';
- const COLUMN_DEFAULT_SHIPPING = '_address_default_shipping_';
- /**#@-*/
- /**#@+
- * Error codes
- */
- const ERROR_ADDRESS_ID_IS_EMPTY = 'addressIdIsEmpty';
- const ERROR_ADDRESS_NOT_FOUND = 'addressNotFound';
- const ERROR_INVALID_REGION = 'invalidRegion';
- const ERROR_DUPLICATE_PK = 'duplicateAddressId';
- /**#@-*/
- /**#@-*/
- protected static $_defaultAddressAttributeMapping = [
- self::COLUMN_DEFAULT_BILLING => 'default_billing',
- self::COLUMN_DEFAULT_SHIPPING => 'default_shipping',
- ];
- /**
- * Permanent entity columns
- *
- * @var string[]
- */
- protected $_permanentAttributes = [self::COLUMN_WEBSITE, self::COLUMN_EMAIL, self::COLUMN_ADDRESS_ID];
- /**
- * Attributes with index (not label) value
- *
- * @var string[]
- */
- protected $_indexValueAttributes = [self::COLUMN_COUNTRY_ID];
- /**
- * Customer entity DB table name
- *
- * @var string
- */
- protected $_entityTable;
- /**
- * Region collection instance
- *
- * @var \Magento\Directory\Model\ResourceModel\Region\Collection
- */
- private $_regionCollection;
- /**
- * Countries and regions
- *
- * Example array: array(
- * [country_id_lowercased_1] => array(
- * [region_code_lowercased_1] => region_id_1,
- * [region_default_name_lowercased_1] => region_id_1,
- * ...,
- * [region_code_lowercased_n] => region_id_n,
- * [region_default_name_lowercased_n] => region_id_n
- * ),
- * ...
- * )
- *
- * @var array
- */
- protected $_countryRegions = [];
- /**
- * Region ID to region default name pairs
- *
- * @var array
- */
- protected $_regions = [];
- /**
- * Column names that holds values with particular meaning
- *
- * @var string[]
- */
- protected $_specialAttributes = [
- self::COLUMN_ACTION,
- self::COLUMN_WEBSITE,
- self::COLUMN_EMAIL,
- self::COLUMN_ADDRESS_ID,
- self::COLUMN_DEFAULT_BILLING,
- self::COLUMN_DEFAULT_SHIPPING,
- ];
- /**
- * Customer entity
- *
- * @var \Magento\Customer\Model\Customer
- */
- protected $_customerEntity;
- /**
- * Entity ID incremented value
- *
- * @var int
- */
- protected $_nextEntityId;
- /**
- * Array of region parameters
- *
- * @var array
- */
- protected $_regionParameters;
- /**
- * Address attributes collection
- *
- * @var \Magento\Customer\Model\ResourceModel\Address\Attribute\Collection
- */
- protected $_attributeCollection;
- /**
- * Store imported row primary keys
- *
- * @var array
- */
- protected $_importedRowPks = [];
- /**
- * @var \Magento\ImportExport\Model\ResourceModel\Helper
- */
- protected $_resourceHelper;
- /**
- * @var \Magento\Customer\Model\CustomerFactory
- */
- protected $_customerFactory;
- /**
- * @var \Magento\Eav\Model\Config
- */
- protected $_eavConfig;
- /**
- * @var \Magento\Customer\Model\AddressFactory
- */
- protected $_addressFactory;
- /**
- * @var \Magento\Framework\Stdlib\DateTime
- */
- protected $dateTime;
- /**
- * Customer attributes
- *
- * @var string[]
- */
- protected $_customerAttributes = [];
- /**
- * Valid column names
- *
- * @array
- */
- protected $validColumnNames = [
- "region_id", "vat_is_valid", "vat_request_date", "vat_request_id", "vat_request_success"
- ];
- /**
- * @var \Magento\Customer\Model\Address\Validator\Postcode
- */
- protected $postcodeValidator;
- /**
- * @var CountryWithWebsitesSource
- */
- private $countryWithWebsites;
- /**
- * Options for certain attributes sorted by websites.
- *
- * @var array[][] With path as <attributeCode> => <websiteID> => options[].
- */
- private $optionsByWebsite = [];
- /**
- * @var AddressStorage
- */
- private $addressStorage;
- /**
- * @param \Magento\Framework\Stdlib\StringUtils $string
- * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
- * @param \Magento\ImportExport\Model\ImportFactory $importFactory
- * @param \Magento\ImportExport\Model\ResourceModel\Helper $resourceHelper
- * @param \Magento\Framework\App\ResourceConnection $resource
- * @param ProcessingErrorAggregatorInterface $errorAggregator
- * @param \Magento\Store\Model\StoreManagerInterface $storeManager
- * @param \Magento\ImportExport\Model\Export\Factory $collectionFactory
- * @param \Magento\Eav\Model\Config $eavConfig
- * @param \Magento\CustomerImportExport\Model\ResourceModel\Import\Customer\StorageFactory $storageFactory
- * @param \Magento\Customer\Model\AddressFactory $addressFactory
- * @param \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionColFactory
- * @param \Magento\Customer\Model\CustomerFactory $customerFactory
- * @param \Magento\Customer\Model\ResourceModel\Address\Attribute\CollectionFactory $attributesFactory
- * @param \Magento\Framework\Stdlib\DateTime $dateTime
- * @param \Magento\Customer\Model\Address\Validator\Postcode $postcodeValidator
- * @param array $data
- * @param CountryWithWebsitesSource|null $countryWithWebsites
- * @param AddressStorage|null $addressStorage
- *
- * @SuppressWarnings(PHPMD.NPathComplexity)
- * @SuppressWarnings(PHPMD.ExcessiveParameterList)
- */
- public function __construct(
- \Magento\Framework\Stdlib\StringUtils $string,
- \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
- \Magento\ImportExport\Model\ImportFactory $importFactory,
- \Magento\ImportExport\Model\ResourceModel\Helper $resourceHelper,
- \Magento\Framework\App\ResourceConnection $resource,
- ProcessingErrorAggregatorInterface $errorAggregator,
- \Magento\Store\Model\StoreManagerInterface $storeManager,
- \Magento\ImportExport\Model\Export\Factory $collectionFactory,
- \Magento\Eav\Model\Config $eavConfig,
- \Magento\CustomerImportExport\Model\ResourceModel\Import\Customer\StorageFactory $storageFactory,
- \Magento\Customer\Model\AddressFactory $addressFactory,
- \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionColFactory,
- \Magento\Customer\Model\CustomerFactory $customerFactory,
- \Magento\Customer\Model\ResourceModel\Address\Attribute\CollectionFactory $attributesFactory,
- \Magento\Framework\Stdlib\DateTime $dateTime,
- \Magento\Customer\Model\Address\Validator\Postcode $postcodeValidator,
- array $data = [],
- CountryWithWebsitesSource $countryWithWebsites = null,
- AddressStorage $addressStorage = null
- ) {
- $this->_customerFactory = $customerFactory;
- $this->_addressFactory = $addressFactory;
- $this->_eavConfig = $eavConfig;
- $this->_resourceHelper = $resourceHelper;
- $this->dateTime = $dateTime;
- $this->postcodeValidator = $postcodeValidator;
- $this->countryWithWebsites = $countryWithWebsites ?:
- ObjectManager::getInstance()->get(CountryWithWebsitesSource::class);
- if (!isset($data['attribute_collection'])) {
- /** @var $attributeCollection \Magento\Customer\Model\ResourceModel\Address\Attribute\Collection */
- $attributeCollection = $attributesFactory->create();
- $attributeCollection->addSystemHiddenFilter()->addExcludeHiddenFrontendFilter();
- $data['attribute_collection'] = $attributeCollection;
- }
- parent::__construct(
- $string,
- $scopeConfig,
- $importFactory,
- $resourceHelper,
- $resource,
- $errorAggregator,
- $storeManager,
- $collectionFactory,
- $eavConfig,
- $storageFactory,
- $data
- );
- $this->_entityTable = isset(
- $data['entity_table']
- ) ? $data['entity_table'] : $addressFactory->create()->getResource()->getEntityTable();
- $this->_regionCollection = isset(
- $data['region_collection']
- ) ? $data['region_collection'] : $regionColFactory->create();
- $this->addMessageTemplate(self::ERROR_ADDRESS_ID_IS_EMPTY, __('Customer address id column is not specified'));
- $this->addMessageTemplate(
- self::ERROR_ADDRESS_NOT_FOUND,
- __('We can\'t find that customer address.')
- );
- $this->addMessageTemplate(self::ERROR_INVALID_REGION, __('Please enter a valid region.'));
- $this->addMessageTemplate(
- self::ERROR_DUPLICATE_PK,
- __('We found another row with this email, website and address ID combination.')
- );
- $this->addressStorage = $addressStorage
- ?: ObjectManager::getInstance()->get(AddressStorage::class);
- $this->_initAttributes();
- $this->_initCountryRegions();
- }
- /**
- * @inheritDoc
- */
- public function getAttributeOptions(AbstractAttribute $attribute, array $indexAttributes = [])
- {
- $standardOptions = parent::getAttributeOptions($attribute, $indexAttributes);
- if ($attribute->getAttributeCode() === 'country_id') {
- //If we want to get available options for country field then we have to use alternative source
- // to get actual data for each website.
- $options = $this->countryWithWebsites->getAllOptions();
- //Available country options now will be sorted by websites.
- $code = $attribute->getAttributeCode();
- $websiteOptions = [Store::DEFAULT_STORE_ID => $standardOptions];
- //Sorting options by website.
- foreach ($options as $option) {
- if (array_key_exists('website_ids', $option)) {
- foreach ($option['website_ids'] as $websiteId) {
- if (!array_key_exists($websiteId, $websiteOptions)) {
- $websiteOptions[$websiteId] = [];
- }
- $optionId = mb_strtolower($option['value']);
- $websiteOptions[$websiteId][$optionId] = $option['value'];
- }
- }
- }
- //Storing sorted
- $this->optionsByWebsite[$code] = $websiteOptions;
- }
- return $standardOptions;
- }
- /**
- * Attributes' data may vary depending on website settings,
- * this method adjusts an attribute's data from $this->_attributes to
- * website-specific data.
- *
- * @param array $attributeData Data from $this->_attributes.
- * @param int $websiteId
- *
- * @return array Adjusted data in the same format.
- */
- private function adjustAttributeDataForWebsite(array $attributeData, int $websiteId): array
- {
- if ($attributeData['code'] === 'country_id') {
- $attributeOptions = $this->optionsByWebsite[$attributeData['code']];
- if (array_key_exists($websiteId, $attributeOptions)) {
- $attributeData['options'] = $attributeOptions[$websiteId];
- }
- }
- return $attributeData;
- }
- /**
- * Customer entity getter
- *
- * @return \Magento\Customer\Model\Customer
- */
- protected function _getCustomerEntity()
- {
- if (!$this->_customerEntity) {
- $this->_customerEntity = $this->_customerFactory->create();
- }
- return $this->_customerEntity;
- }
- /**
- * Get next address entity ID
- *
- * @return int
- */
- protected function _getNextEntityId()
- {
- if (!$this->_nextEntityId) {
- /** @var $addressResource \Magento\Customer\Model\ResourceModel\Address */
- $addressResource = $this->_addressFactory->create()->getResource();
- $addressTable = $addressResource->getEntityTable();
- $this->_nextEntityId = $this->_resourceHelper->getNextAutoincrement($addressTable);
- }
- return $this->_nextEntityId++;
- }
- /**
- * Initialize country regions hash for clever recognition
- *
- * @return $this
- */
- protected function _initCountryRegions()
- {
- /** @var $region \Magento\Directory\Model\Region */
- foreach ($this->_regionCollection as $region) {
- $countryNormalized = strtolower($region->getCountryId());
- $regionCode = strtolower($region->getCode());
- $regionName = strtolower($region->getDefaultName());
- $this->_countryRegions[$countryNormalized][$regionCode] = $region->getId();
- $this->_countryRegions[$countryNormalized][$regionName] = $region->getId();
- $this->_regions[$region->getId()] = $region->getDefaultName();
- }
- return $this;
- }
- /**
- * Pre-loading customers for existing customers checks in order
- * to perform mass validation/import efficiently.
- * Also loading existing addresses for requested customers.
- *
- * @param array|AbstractSource $rows Each row must contain data from columns email
- * and website code.
- *
- * @return void
- */
- public function prepareCustomerData($rows): void
- {
- $customersPresent = [];
- foreach ($rows as $rowData) {
- $email = $rowData[static::COLUMN_EMAIL] ?? null;
- $websiteId = isset($rowData[static::COLUMN_WEBSITE])
- ? $this->getWebsiteId($rowData[static::COLUMN_WEBSITE]) : false;
- if ($email && $websiteId !== false) {
- $customersPresent[] = [
- 'email' => $email,
- 'website_id' => $websiteId,
- ];
- }
- }
- $this->getCustomerStorage()->prepareCustomers($customersPresent);
- $ids = [];
- foreach ($customersPresent as $customerData) {
- $id = $this->getCustomerStorage()->getCustomerId(
- $customerData['email'],
- $customerData['website_id']
- );
- if ($id) {
- $ids[] = $id;
- }
- }
- $this->addressStorage->prepareAddresses($ids);
- }
- /**
- * @inheritDoc
- */
- public function validateData()
- {
- $this->prepareCustomerData($this->getSource());
- return parent::validateData();
- }
- /**
- * Import data rows
- *
- * @abstract
- * @return boolean
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- */
- protected function _importData()
- {
- //Preparing data for mass validation/import.
- $rows = [];
- while ($bunch = $this->_dataSourceModel->getNextBunch()) {
- $rows = array_merge($rows, $bunch);
- }
- $this->prepareCustomerData($rows);
- unset($bunch, $rows);
- $this->_dataSourceModel->getIterator()->rewind();
- //Importing
- while ($bunch = $this->_dataSourceModel->getNextBunch()) {
- $newRows = [];
- $updateRows = [];
- $attributes = [];
- $defaults = [];
- // customer default addresses (billing/shipping) data
- $deleteRowIds = [];
- foreach ($bunch as $rowNumber => $rowData) {
- // check row data
- if ($this->_isOptionalAddressEmpty($rowData) || !$this->validateRow($rowData, $rowNumber)) {
- continue;
- }
- if ($this->getErrorAggregator()->hasToBeTerminated()) {
- $this->getErrorAggregator()->addRowToSkip($rowNumber);
- continue;
- }
- if ($this->getBehavior($rowData) == \Magento\ImportExport\Model\Import::BEHAVIOR_ADD_UPDATE) {
- $addUpdateResult = $this->_prepareDataForUpdate($rowData);
- if ($addUpdateResult['entity_row_new']) {
- $newRows[] = $addUpdateResult['entity_row_new'];
- }
- if ($addUpdateResult['entity_row_update']) {
- $updateRows[] = $addUpdateResult['entity_row_update'];
- }
- $attributes = $this->_mergeEntityAttributes($addUpdateResult['attributes'], $attributes);
- $defaults = $this->_mergeEntityAttributes($addUpdateResult['defaults'], $defaults);
- } elseif ($this->getBehavior($rowData) == \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE) {
- $deleteRowIds[] = $rowData[self::COLUMN_ADDRESS_ID];
- }
- }
- $this->updateItemsCounterStats($newRows, $updateRows, $deleteRowIds);
- $this->_saveAddressEntities($newRows, $updateRows)
- ->_saveAddressAttributes($attributes)
- ->_saveCustomerDefaults($defaults);
- $this->_deleteAddressEntities($deleteRowIds);
- }
- return true;
- }
- /**
- * Merge attributes
- *
- * @param array $newAttributes
- * @param array $attributes
- * @return array
- */
- protected function _mergeEntityAttributes(array $newAttributes, array $attributes)
- {
- foreach ($newAttributes as $tableName => $tableData) {
- foreach ($tableData as $entityId => $entityData) {
- foreach ($entityData as $attributeId => $attributeValue) {
- $attributes[$tableName][$entityId][$attributeId] = $attributeValue;
- }
- }
- }
- return $attributes;
- }
- /**
- * Prepare data for add/update action
- *
- * @param array $rowData
- * @return array
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- */
- protected function _prepareDataForUpdate(array $rowData):array
- {
- $multiSeparator = $this->getMultipleValueSeparator();
- $email = strtolower($rowData[self::COLUMN_EMAIL]);
- $customerId = $this->_getCustomerId($email, $rowData[self::COLUMN_WEBSITE]);
- // entity table data
- $entityRowNew = [];
- $entityRowUpdate = [];
- // attribute values
- $attributes = [];
- // customer default addresses
- $defaults = [];
- $newAddress = true;
- // get address id
- if ($rowData[self::COLUMN_ADDRESS_ID]
- && $this->addressStorage->doesExist(
- $rowData[self::COLUMN_ADDRESS_ID],
- (string)$customerId
- )
- ) {
- $newAddress = false;
- $addressId = $rowData[self::COLUMN_ADDRESS_ID];
- } else {
- $addressId = $this->_getNextEntityId();
- }
- $entityRow = [
- 'entity_id' => $addressId,
- 'parent_id' => $customerId,
- 'updated_at' => (new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT),
- ];
- $websiteId = $this->_websiteCodeToId[$rowData[self::COLUMN_WEBSITE]];
- foreach ($this->_attributes as $attributeAlias => $attributeParams) {
- if (array_key_exists($attributeAlias, $rowData)) {
- $attributeParams = $this->adjustAttributeDataForWebsite($attributeParams, $websiteId);
- if (!strlen($rowData[$attributeAlias])) {
- if ($newAddress) {
- $value = null;
- } else {
- continue;
- }
- } elseif ($newAddress && !strlen($rowData[$attributeAlias])) {
- } elseif (in_array($attributeParams['type'], ['select', 'boolean'])) {
- $value = $this->getSelectAttrIdByValue($attributeParams, mb_strtolower($rowData[$attributeAlias]));
- } elseif ('datetime' == $attributeParams['type']) {
- $value = (new \DateTime())->setTimestamp(strtotime($rowData[$attributeAlias]));
- $value = $value->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT);
- } elseif ('multiselect' == $attributeParams['type']) {
- $ids = [];
- foreach (explode($multiSeparator, mb_strtolower($rowData[$attributeAlias])) as $subValue) {
- $ids[] = $this->getSelectAttrIdByValue($attributeParams, $subValue);
- }
- $value = implode(',', $ids);
- } else {
- $value = $rowData[$attributeAlias];
- }
- if ($attributeParams['is_static']) {
- $entityRow[$attributeAlias] = $value;
- } else {
- $attributes[$attributeParams['table']][$addressId][$attributeParams['id']]= $value;
- }
- }
- }
- foreach (self::getDefaultAddressAttributeMapping() as $columnName => $attributeCode) {
- if (!empty($rowData[$columnName])) {
- /** @var $attribute \Magento\Eav\Model\Entity\Attribute\AbstractAttribute */
- $table = $this->_getCustomerEntity()->getResource()->getTable('customer_entity');
- $defaults[$table][$customerId][$attributeCode] = $addressId;
- }
- }
- // let's try to find region ID
- $entityRow['region_id'] = null;
- if (!empty($rowData[self::COLUMN_REGION])) {
- $countryNormalized = strtolower($rowData[self::COLUMN_COUNTRY_ID]);
- $regionNormalized = strtolower($rowData[self::COLUMN_REGION]);
- if (isset($this->_countryRegions[$countryNormalized][$regionNormalized])) {
- $regionId = $this->_countryRegions[$countryNormalized][$regionNormalized];
- $entityRow[self::COLUMN_REGION] = $this->_regions[$regionId];
- $entityRow['region_id'] = $regionId;
- }
- }
- if ($newAddress) {
- $entityRowNew = $entityRow;
- $entityRowNew['created_at'] =
- (new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT);
- } else {
- $entityRowUpdate = $entityRow;
- }
- return [
- 'entity_row_new' => $entityRowNew,
- 'entity_row_update' => $entityRowUpdate,
- 'attributes' => $attributes,
- 'defaults' => $defaults
- ];
- }
- /**
- * Update and insert data in entity table
- *
- * @param array $addRows Rows for insert
- * @param array $updateRows Rows for update
- * @return $this
- */
- protected function _saveAddressEntities(array $addRows, array $updateRows)
- {
- if ($addRows) {
- $this->_connection->insertMultiple($this->_entityTable, $addRows);
- }
- if ($updateRows) {
- //list of updated fields can be different for addresses. We can not use insertOnDuplicate for whole rows.
- foreach ($updateRows as $row) {
- $fields = array_diff(array_keys($row), ['entity_id', 'parent_id', 'created_at']);
- $this->_connection->insertOnDuplicate($this->_entityTable, $row, $fields);
- }
- }
- return $this;
- }
- /**
- * Save custom customer address attributes
- *
- * @param array $attributesData
- * @return $this
- */
- protected function _saveAddressAttributes(array $attributesData)
- {
- foreach ($attributesData as $tableName => $data) {
- $tableData = [];
- foreach ($data as $addressId => $attributeData) {
- foreach ($attributeData as $attributeId => $value) {
- $tableData[] = [
- 'entity_id' => $addressId,
- 'attribute_id' => $attributeId,
- 'value' => $value,
- ];
- }
- }
- $this->_connection->insertOnDuplicate($tableName, $tableData, ['value']);
- }
- return $this;
- }
- /**
- * Save customer default addresses
- *
- * @param array $defaults
- * @return $this
- * @SuppressWarnings(PHPMD.UnusedLocalVariable)
- */
- protected function _saveCustomerDefaults(array $defaults)
- {
- foreach ($defaults as $tableName => $data) {
- foreach ($data as $customerId => $defaultsData) {
- $data = array_merge(
- ['entity_id' => $customerId],
- $defaultsData
- );
- $this->_connection->insertOnDuplicate($tableName, $data, array_keys($defaultsData));
- }
- }
- return $this;
- }
- /**
- * Delete data from entity table
- *
- * @param array $entityRowIds Row IDs for delete
- * @return $this
- */
- protected function _deleteAddressEntities(array $entityRowIds)
- {
- if ($entityRowIds) {
- $this->_connection->delete($this->_entityTable, ['entity_id IN (?)' => $entityRowIds]);
- }
- return $this;
- }
- /**
- * EAV entity type code getter
- *
- * @abstract
- * @return string
- */
- public function getEntityTypeCode()
- {
- return 'customer_address';
- }
- /**
- * Customer default addresses column name to customer attribute mapping array
- *
- * @static
- * @return array
- */
- public static function getDefaultAddressAttributeMapping()
- {
- return self::$_defaultAddressAttributeMapping;
- }
- /**
- * Check if address for import is empty (for customer composite mode)
- *
- * @param array $rowData
- * @return array
- */
- protected function _isOptionalAddressEmpty(array $rowData)
- {
- if (empty($this->_customerAttributes)) {
- return false;
- }
- unset(
- $rowData[Customer::COLUMN_WEBSITE],
- $rowData[Customer::COLUMN_STORE],
- $rowData['_email']
- );
- foreach ($rowData as $key => $value) {
- if (!in_array($key, $this->_customerAttributes) && !empty($value)) {
- return false;
- }
- }
- return true;
- }
- /**
- * Validate row for add/update action
- *
- * @param array $rowData
- * @param int $rowNumber
- * @return void
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- */
- protected function _validateRowForUpdate(array $rowData, $rowNumber)
- {
- $multiSeparator = $this->getMultipleValueSeparator();
- if ($this->_checkUniqueKey($rowData, $rowNumber)) {
- $email = strtolower($rowData[self::COLUMN_EMAIL]);
- $website = $rowData[self::COLUMN_WEBSITE];
- $addressId = $rowData[self::COLUMN_ADDRESS_ID];
- $customerId = $this->_getCustomerId($email, $website);
- if ($customerId === false) {
- $this->addRowError(self::ERROR_CUSTOMER_NOT_FOUND, $rowNumber);
- } else {
- if ($this->_checkRowDuplicate($customerId, $addressId)) {
- $this->addRowError(self::ERROR_DUPLICATE_PK, $rowNumber);
- } else {
- // check simple attributes
- foreach ($this->_attributes as $attributeCode => $attributeParams) {
- $websiteId = $this->_websiteCodeToId[$website];
- $attributeParams = $this->adjustAttributeDataForWebsite($attributeParams, $websiteId);
- if (in_array($attributeCode, $this->_ignoredAttributes)) {
- continue;
- }
- if (isset($rowData[$attributeCode]) && strlen($rowData[$attributeCode])) {
- $this->isAttributeValid(
- $attributeCode,
- $attributeParams,
- $rowData,
- $rowNumber,
- $multiSeparator
- );
- } elseif ($attributeParams['is_required']
- && !$this->addressStorage->doesExist(
- (string)$addressId,
- (string)$customerId
- )
- ) {
- $this->addRowError(self::ERROR_VALUE_IS_REQUIRED, $rowNumber, $attributeCode);
- }
- }
- if (isset($rowData[self::COLUMN_POSTCODE])
- && isset($rowData[self::COLUMN_COUNTRY_ID])
- && !$this->postcodeValidator->isValid(
- $rowData[self::COLUMN_COUNTRY_ID],
- $rowData[self::COLUMN_POSTCODE]
- )
- ) {
- $this->addRowError(self::ERROR_VALUE_IS_REQUIRED, $rowNumber, self::COLUMN_POSTCODE);
- }
- if (isset($rowData[self::COLUMN_COUNTRY_ID]) && isset($rowData[self::COLUMN_REGION])) {
- $countryRegions = isset(
- $this->_countryRegions[strtolower($rowData[self::COLUMN_COUNTRY_ID])]
- ) ? $this->_countryRegions[strtolower(
- $rowData[self::COLUMN_COUNTRY_ID]
- )] : [];
- if (!empty($rowData[self::COLUMN_REGION]) && !empty($countryRegions) && !isset(
- $countryRegions[strtolower($rowData[self::COLUMN_REGION])]
- )
- ) {
- $this->addRowError(self::ERROR_INVALID_REGION, $rowNumber, self::COLUMN_REGION);
- }
- }
- }
- }
- }
- }
- /**
- * Validate row for delete action
- *
- * @param array $rowData
- * @param int $rowNumber
- * @return void
- */
- protected function _validateRowForDelete(array $rowData, $rowNumber)
- {
- if ($this->_checkUniqueKey($rowData, $rowNumber)) {
- $email = strtolower($rowData[self::COLUMN_EMAIL]);
- $website = $rowData[self::COLUMN_WEBSITE];
- $addressId = $rowData[self::COLUMN_ADDRESS_ID];
- $customerId = $this->_getCustomerId($email, $website);
- if ($customerId === false) {
- $this->addRowError(self::ERROR_CUSTOMER_NOT_FOUND, $rowNumber);
- } else {
- if (!strlen($addressId)) {
- $this->addRowError(self::ERROR_ADDRESS_ID_IS_EMPTY, $rowNumber);
- } elseif (!$this->addressStorage->doesExist(
- (string)$addressId,
- (string)$customerId
- )) {
- $this->addRowError(self::ERROR_ADDRESS_NOT_FOUND, $rowNumber);
- }
- }
- }
- }
- /**
- * Check whether row with such address id was already found in import file
- *
- * @param int $customerId
- * @param int $addressId
- * @return bool
- */
- protected function _checkRowDuplicate($customerId, $addressId)
- {
- if ($this->addressStorage->doesExist(
- (string)$addressId,
- (string)$customerId
- )) {
- if (!isset($this->_importedRowPks[$customerId][$addressId])) {
- $this->_importedRowPks[$customerId][$addressId] = true;
- return false;
- } else {
- return true;
- }
- } else {
- return false;
- }
- }
- /**
- * Set customer attributes
- *
- * @param array $customerAttributes
- * @return $this
- */
- public function setCustomerAttributes($customerAttributes)
- {
- $this->_customerAttributes = $customerAttributes;
- return $this;
- }
- }
|