PageRenderTime 58ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer/Address.php

https://bitbucket.org/claudiu_marginean/magento-hg-mirror
PHP | 467 lines | 241 code | 39 blank | 187 comment | 28 complexity | 0d73afc578b704f97f6e584f14f4a0ff MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_ImportExport
  23. * @copyright Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Import entity customer address
  28. *
  29. * @category Mage
  30. * @package Mage_ImportExport
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_ImportExport_Model_Import_Entity_Customer_Address extends Mage_ImportExport_Model_Import_Entity_Abstract
  34. {
  35. /**
  36. * Prefix for source file column name, which displays that column contains address data.
  37. */
  38. const COL_NAME_PREFIX = '_address_';
  39. /**
  40. * Particular columns that contains of customer default addresses.
  41. */
  42. const COL_NAME_DEFAULT_BILLING = '_address_default_billing_';
  43. const COL_NAME_DEFAULT_SHIPPING = '_address_default_shipping_';
  44. /**
  45. * Error codes.
  46. */
  47. const ERROR_INVALID_REGION = 'invalidRegion';
  48. /**
  49. * Customer address attributes parameters.
  50. *
  51. * [attr_code_1] => array(
  52. * 'options' => array(),
  53. * 'type' => 'text', 'price', 'textarea', 'select', etc.
  54. * 'id' => ..
  55. * ),
  56. * ...
  57. *
  58. * @var array
  59. */
  60. protected $_attributes = array();
  61. /**
  62. * Countrys and its regions.
  63. *
  64. * array(
  65. * [country_id_lowercased_1] => array(
  66. * [region_code_lowercased_1] => region_id_1,
  67. * [region_default_name_lowercased_1] => region_id_1,
  68. * ...,
  69. * [region_code_lowercased_n] => region_id_n,
  70. * [region_default_name_lowercased_n] => region_id_n
  71. * ),
  72. * ...
  73. * )
  74. *
  75. * @var array
  76. */
  77. protected $_countryRegions = array();
  78. /**
  79. * Customer import entity.
  80. *
  81. * @var Mage_ImportExport_Model_Import_Entity_Customer
  82. */
  83. protected $_customer;
  84. /**
  85. * Default addresses column names to appropriate customer attribute code.
  86. *
  87. * @var array
  88. */
  89. protected static $_defaultAddressAttrMapping = array(
  90. self::COL_NAME_DEFAULT_BILLING => 'default_billing',
  91. self::COL_NAME_DEFAULT_SHIPPING => 'default_shipping'
  92. );
  93. /**
  94. * Customer entity DB table name.
  95. *
  96. * @var string
  97. */
  98. protected $_entityTable;
  99. /**
  100. * Attributes with index (not label) value.
  101. *
  102. * @var array
  103. */
  104. protected $_indexValueAttributes = array('country_id');
  105. /**
  106. * Validation failure message template definitions
  107. *
  108. * @var array
  109. */
  110. protected $_messageTemplates = array(self::ERROR_INVALID_REGION => 'Region is invalid');
  111. /**
  112. * Column names that holds values with particular meaning.
  113. *
  114. * @var array
  115. */
  116. protected $_particularAttributes = array(self::COL_NAME_DEFAULT_BILLING, self::COL_NAME_DEFAULT_SHIPPING);
  117. /**
  118. * Region ID to region default name pairs.
  119. *
  120. * @var array
  121. */
  122. protected $_regions = array();
  123. /**
  124. * Constructor.
  125. *
  126. * @param Mage_ImportExport_Model_Import_Entity_Customer $customer
  127. * @return void
  128. */
  129. public function __construct(Mage_ImportExport_Model_Import_Entity_Customer $customer)
  130. {
  131. parent::__construct();
  132. $this->_initAttributes()->_initCountryRegions();
  133. $this->_entityTable = Mage::getModel('customer/address')->getResource()->getEntityTable();
  134. $this->_customer = $customer;
  135. foreach ($this->_messageTemplates as $errorCode => $message) {
  136. $this->_customer->addMessageTemplate($errorCode, $message);
  137. }
  138. }
  139. /**
  140. * Import data rows.
  141. *
  142. * @return boolean
  143. */
  144. protected function _importData()
  145. {
  146. /** @var $customer Mage_Customer_Model_Customer */
  147. $customer = Mage::getModel('customer/customer');
  148. /** @var $resource Mage_Customer_Model_Address */
  149. $resource = Mage::getModel('customer/address');
  150. $strftimeFormat = Varien_Date::convertZendToStrftime(Varien_Date::DATETIME_INTERNAL_FORMAT, true, true);
  151. $nextEntityId = $this->getNextAutoincrement($resource->getResource()->getEntityTable());
  152. $customerId = null;
  153. $regionColName = self::getColNameForAttrCode('region');
  154. $countryColName = self::getColNameForAttrCode('country_id');
  155. $regionIdAttr = Mage::getSingleton('eav/config')->getAttribute($this->getEntityTypeCode(), 'region_id');
  156. $regionIdTable = $regionIdAttr->getBackend()->getTable();
  157. $regionIdAttrId = $regionIdAttr->getId();
  158. while ($bunch = $this->_dataSourceModel->getNextBunch()) {
  159. $entityRows = array();
  160. $attributes = array();
  161. $defaults = array(); // customer default addresses (billing/shipping) data
  162. foreach ($bunch as $rowNum => $rowData) {
  163. if (!empty($rowData[Mage_ImportExport_Model_Import_Entity_Customer::COL_EMAIL])
  164. && !empty($rowData[Mage_ImportExport_Model_Import_Entity_Customer::COL_WEBSITE])
  165. ) {
  166. $customerId = $this->_customer->getCustomerId(
  167. $rowData[Mage_ImportExport_Model_Import_Entity_Customer::COL_EMAIL],
  168. $rowData[Mage_ImportExport_Model_Import_Entity_Customer::COL_WEBSITE]
  169. );
  170. }
  171. if (!$customerId || !$this->_isRowWithAddress($rowData) || !$this->validateRow($rowData, $rowNum)) {
  172. continue;
  173. }
  174. $entityId = $nextEntityId++;
  175. // entity table data
  176. $entityRows[] = array(
  177. 'entity_id' => $entityId,
  178. 'entity_type_id' => $this->_entityTypeId,
  179. 'parent_id' => $customerId,
  180. 'created_at' => now(),
  181. 'updated_at' => now()
  182. );
  183. // attribute values
  184. foreach ($this->_attributes as $attrAlias => $attrParams) {
  185. if (isset($rowData[$attrAlias]) && strlen($rowData[$attrAlias])) {
  186. if ('select' == $attrParams['type']) {
  187. $value = $attrParams['options'][strtolower($rowData[$attrAlias])];
  188. } elseif ('datetime' == $attrParams['type']) {
  189. $value = gmstrftime($strftimeFormat, strtotime($rowData[$attrAlias]));
  190. } else {
  191. $value = $rowData[$attrAlias];
  192. }
  193. $attributes[$attrParams['table']][$entityId][$attrParams['id']] = $value;
  194. }
  195. }
  196. // customer default addresses
  197. foreach (self::getDefaultAddressAttrMapping() as $colName => $customerAttrCode) {
  198. if (!empty($rowData[$colName])) {
  199. $attribute = $customer->getAttribute($customerAttrCode);
  200. $defaults[$attribute->getBackend()->getTable()][$customerId][$attribute->getId()] = $entityId;
  201. }
  202. }
  203. // let's try to find region ID
  204. if (!empty($rowData[$regionColName])) {
  205. $countryNormalized = strtolower($rowData[$countryColName]);
  206. $regionNormalized = strtolower($rowData[$regionColName]);
  207. if (isset($this->_countryRegions[$countryNormalized][$regionNormalized])) {
  208. $regionId = $this->_countryRegions[$countryNormalized][$regionNormalized];
  209. $attributes[$regionIdTable][$entityId][$regionIdAttrId] = $regionId;
  210. // set 'region' attribute value as default name
  211. $tbl = $this->_attributes[$regionColName]['table'];
  212. $regionColNameId = $this->_attributes[$regionColName]['id'];
  213. $attributes[$tbl][$entityId][$regionColNameId] = $this->_regions[$regionId];
  214. }
  215. }
  216. }
  217. $this->_saveAddressEntity($entityRows)
  218. ->_saveAddressAttributes($attributes)
  219. ->_saveCustomerDefaults($defaults);
  220. }
  221. return true;
  222. }
  223. /**
  224. * Initialize customer address attributes.
  225. *
  226. * @return Mage_ImportExport_Model_Import_Entity_Customer_Address
  227. */
  228. protected function _initAttributes()
  229. {
  230. $addrCollection = Mage::getResourceModel('customer/address_attribute_collection')
  231. ->addSystemHiddenFilter()
  232. ->addExcludeHiddenFrontendFilter();
  233. foreach ($addrCollection as $attribute) {
  234. $this->_attributes[self::getColNameForAttrCode($attribute->getAttributeCode())] = array(
  235. 'id' => $attribute->getId(),
  236. 'code' => $attribute->getAttributeCode(),
  237. 'table' => $attribute->getBackend()->getTable(),
  238. 'is_required' => $attribute->getIsRequired(),
  239. 'rules' => $attribute->getValidateRules() ? unserialize($attribute->getValidateRules()) : null,
  240. 'type' => Mage_ImportExport_Model_Import::getAttributeType($attribute),
  241. 'options' => $this->getAttributeOptions($attribute)
  242. );
  243. }
  244. return $this;
  245. }
  246. /**
  247. * Initialize country regions hash for clever recognition.
  248. *
  249. * @return Mage_ImportExport_Model_Import_Entity_Customer_Address
  250. */
  251. protected function _initCountryRegions()
  252. {
  253. foreach (Mage::getResourceModel('directory/region_collection') as $regionRow) {
  254. $countryNormalized = strtolower($regionRow['country_id']);
  255. $regionCode = strtolower($regionRow['code']);
  256. $regionName = strtolower($regionRow['default_name']);
  257. $this->_countryRegions[$countryNormalized][$regionCode] = $regionRow['region_id'];
  258. $this->_countryRegions[$countryNormalized][$regionName] = $regionRow['region_id'];
  259. $this->_regions[$regionRow['region_id']] = $regionRow['default_name'];
  260. }
  261. return $this;
  262. }
  263. /**
  264. * Check address data availability in row data.
  265. *
  266. * @param array $rowData
  267. * @return bool
  268. */
  269. protected function _isRowWithAddress(array $rowData)
  270. {
  271. foreach (array_keys($this->_attributes) as $colName) {
  272. if (isset($rowData[$colName]) && strlen($rowData[$colName])) {
  273. return true;
  274. }
  275. }
  276. return false;
  277. }
  278. /**
  279. * Save customer address attributes.
  280. *
  281. * @param array $attributesData
  282. * @return Mage_ImportExport_Model_Import_Entity_Customer_Address
  283. */
  284. protected function _saveAddressAttributes(array $attributesData)
  285. {
  286. foreach ($attributesData as $tableName => $data) {
  287. $tableData = array();
  288. foreach ($data as $addressId => $attrData) {
  289. foreach ($attrData as $attributeId => $value) {
  290. $tableData[] = array(
  291. 'entity_id' => $addressId,
  292. 'entity_type_id' => $this->_entityTypeId,
  293. 'attribute_id' => $attributeId,
  294. 'value' => $value
  295. );
  296. }
  297. }
  298. $this->_connection->insertMultiple($tableName, $tableData);
  299. }
  300. return $this;
  301. }
  302. /**
  303. * Update and insert data in entity table.
  304. *
  305. * @param array $entityRows Rows for insert
  306. * @return Mage_ImportExport_Model_Import_Entity_Customer_Address
  307. */
  308. protected function _saveAddressEntity(array $entityRows)
  309. {
  310. if ($entityRows) {
  311. if (Mage_ImportExport_Model_Import::BEHAVIOR_APPEND != $this->_customer->getBehavior()) {
  312. $customersToClean = array();
  313. foreach ($entityRows as $entityData) {
  314. $customersToClean[$entityData['parent_id']] = true;
  315. }
  316. $this->_connection->delete(
  317. $this->_entityTable,
  318. $this->_connection->quoteInto('`parent_id` IN (?)', array_keys($customersToClean))
  319. );
  320. }
  321. $this->_connection->insertMultiple($this->_entityTable, $entityRows);
  322. }
  323. return $this;
  324. }
  325. /**
  326. * Save customer default addresses.
  327. *
  328. * @param array $defaults
  329. * @return Mage_ImportExport_Model_Import_Entity_Customer_Address
  330. */
  331. protected function _saveCustomerDefaults(array $defaults)
  332. {
  333. foreach ($defaults as $tableName => $data) {
  334. $tableData = array();
  335. foreach ($data as $customerId => $attrData) {
  336. foreach ($attrData as $attributeId => $value) {
  337. $tableData[] = array(
  338. 'entity_id' => $customerId,
  339. 'entity_type_id' => $this->_customer->getEntityTypeId(),
  340. 'attribute_id' => $attributeId,
  341. 'value' => $value
  342. );
  343. }
  344. }
  345. $this->_connection->insertOnDuplicate($tableName, $tableData, array('value'));
  346. }
  347. return $this;
  348. }
  349. /**
  350. * Get column name which holds value for attribute with specified code.
  351. *
  352. * @static
  353. * @param string $attrCode
  354. * @return string
  355. */
  356. public static function getColNameForAttrCode($attrCode)
  357. {
  358. return self::COL_NAME_PREFIX . $attrCode;
  359. }
  360. /**
  361. * Customer default addresses column name to customer attribute mapping array.
  362. *
  363. * @static
  364. * @return array
  365. */
  366. public static function getDefaultAddressAttrMapping()
  367. {
  368. return self::$_defaultAddressAttrMapping;
  369. }
  370. /**
  371. * EAV entity type code getter.
  372. *
  373. * @return string
  374. */
  375. public function getEntityTypeCode()
  376. {
  377. return 'customer_address';
  378. }
  379. /**
  380. * Is attribute contains particular data (not plain entity attribute).
  381. *
  382. * @param string $attrCode
  383. * @return bool
  384. */
  385. public function isAttributeParticular($attrCode)
  386. {
  387. return isset($this->_attributes[$attrCode]) || in_array($attrCode, $this->_particularAttributes);
  388. }
  389. /**
  390. * Validate data row.
  391. *
  392. * @param array $rowData
  393. * @param int $rowNum
  394. * @return boolean
  395. */
  396. public function validateRow(array $rowData, $rowNum)
  397. {
  398. $rowIsValid = true;
  399. if ($this->_isRowWithAddress($rowData)) {
  400. foreach ($this->_attributes as $colName => $attrParams) {
  401. if (isset($rowData[$colName]) && strlen($rowData[$colName])) {
  402. $rowIsValid &= $this->_customer->isAttributeValid($colName, $attrParams, $rowData, $rowNum);
  403. } elseif ($attrParams['is_required']) {
  404. $this->_customer->addRowError(
  405. Mage_ImportExport_Model_Import_Entity_Customer::ERROR_VALUE_IS_REQUIRED, $rowNum, $colName
  406. );
  407. $rowIsValid = false;
  408. }
  409. }
  410. // validate region for countries with known region list
  411. if ($rowIsValid) {
  412. $regionColName = self::getColNameForAttrCode('region');
  413. $countryColName = self::getColNameForAttrCode('country_id');
  414. $countryRegions = isset($this->_countryRegions[strtolower($rowData[$countryColName])])
  415. ? $this->_countryRegions[strtolower($rowData[$countryColName])]
  416. : array();
  417. if (!empty($rowData[$regionColName])
  418. && !empty($countryRegions)
  419. && !isset($countryRegions[strtolower($rowData[$regionColName])])
  420. ) {
  421. $this->_customer->addRowError(self::ERROR_INVALID_REGION, $rowNum);
  422. $rowIsValid = false;
  423. }
  424. }
  425. }
  426. return $rowIsValid;
  427. }
  428. }