Advertisement
Guest User

Untitled

a guest
May 5th, 2016
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.52 KB | None | 0 0
  1. <?php
  2.  
  3. define('BUNCH_SIZE_TO_INSERT', 20);
  4.  
  5. $magentoRootPath = './public';
  6. require_once $magentoRootPath . '/shell/abstract.php';
  7.  
  8. class CustomerImportFromCsv extends Mage_Shell_Abstract
  9. {
  10. protected $_headerArray = array();
  11. protected $_attributes = array();
  12. protected $_attributeRows = array();
  13. protected $_customFieldNamesEqualsTo;
  14. protected $_nextEntityId;
  15. protected $_entityTypeId;
  16. protected $_passId;
  17. protected $_passTable;
  18. protected $_connection;
  19. protected $_resource;
  20. protected $_table;
  21. protected $_indexValueAttributes = array('group_id');
  22.  
  23. protected $_defaultValuesForBuiltInImport = array(
  24. '_website' => 'uk',
  25. 'group_id' => 1,
  26. 'firstname' => ' ',
  27. 'middlename' => ' ',
  28. 'lastname' => ' ',
  29. 'email' => 'default@email.com',
  30. 'reward_update_notification' => '1',
  31. 'reward_warning_notification' => '1',
  32. );
  33.  
  34. protected $_defaultValuesForCustomImport = array(
  35. 'group_id' => '1',
  36. 'store_id' => '1',
  37. 'entity_type_id' => '1',
  38. 'attribute_set_id' => '0',
  39. 'website_id' => '1',
  40. 'is_active' => '1',
  41. 'email' => 'default@email.com',
  42. );
  43.  
  44. public function __construct()
  45. {
  46. parent::__construct();
  47.  
  48. Mage::setIsDeveloperMode(true);
  49. ini_set('display_errors', 1);
  50. echo "\n";
  51.  
  52. $entityType = Mage::getSingleton('eav/config')->getEntityType('customer');
  53. $this->_entityTypeId = $entityType->getEntityTypeId();
  54. $this->_connection = Mage::getSingleton('core/resource')->getConnection('write');
  55. $this->_resource = Mage::getModel('customer/customer');
  56. $this->_table = $this->_resource->getResource()->getEntityTable();
  57.  
  58. $this->_initAttributes();
  59.  
  60. if ($this->getArg('h') || $this->getArg('help') || count($this->_args) == 0) {
  61. echo $this->usageHelp();
  62. return 1;
  63. }
  64.  
  65. $this->behavior = ($this->getArg('b') ? $this->getArg('b') : ($this->getArg('behavior') ? $this->getArg('behavior') : 'replace'));
  66. $this->behavior === true ? $this->behavior = 'replace': '';
  67. $this->_customFieldNamesEqualsTo = $this->getFieldMappings();
  68. }
  69.  
  70. public function run()
  71. {
  72. if ($filename = $this->getCustomersSourceFile()) {
  73. $files = $this->splitFile($filename, ($this->getArg('l') ? $this->getArg('l') : ($this->getArg('linecount') ? $this->getArg('linecount') : true)));
  74.  
  75. echo "Start customers '$this->behavior' action from $filename\n";
  76. Mage::log("Start customers '$this->behavior' action from $filename", Zend_Log::DEBUG);
  77.  
  78. $count = 0;
  79. $files_ = array();
  80. foreach ($files as $file) {
  81. if (empty($this->_customFieldNamesEqualsTo)) {
  82. $count += $this->_importWithBuiltInFunctionality($file);
  83. } else {
  84. $count += $this->_importFromCustomFormattedCsv($file);
  85. }
  86. }
  87.  
  88. $this->unlinkFiles($files);
  89. $this->unlinkFiles($files_);
  90. echo "\nDone (processed rows count: " . $count . ")\n";
  91. }
  92. }
  93.  
  94. protected function _initAttributes()
  95. {
  96. $collection = Mage::getResourceModel('customer/attribute_collection')->addSystemHiddenFilterWithPasswordHash();
  97. foreach ($collection as $attribute) {
  98. $this->_attributes[$attribute->getAttributeCode()] = array(
  99. 'id' => $attribute->getId(),
  100. 'is_required' => $attribute->getIsRequired(),
  101. 'is_static' => $attribute->isStatic(),
  102. 'rules' => $attribute->getValidateRules() ? unserialize($attribute->getValidateRules()) : null,
  103. 'type' => Mage_ImportExport_Model_Import::getAttributeType($attribute),
  104. 'options' => $this->getAttributeOptions($attribute)
  105. );
  106. }
  107. return $this;
  108. }
  109.  
  110. public function getCustomersSourceFile()
  111. {
  112. $option1 = $this->getArg('f');
  113. $option2 = $this->getArg('filename');
  114. if ($option1 || $option2) {
  115. if ($option1 && $option1 != 1) {
  116. if (file_exists($option1)) {
  117. return $option1;
  118. } else {
  119. echo "Skipping customers source file $option1\n";
  120. }
  121. }
  122. if ($option2 && $option2 != 1) {
  123. if (file_exists($option2)) {
  124. return $option2;
  125. } else {
  126. echo "Skipping customers source file $option2\n";
  127. }
  128. }
  129. if ($default = 'customers.csv') {
  130. if (file_exists($default)) {
  131. return $default;
  132. } else {
  133. echo "Skipping default customers source file $default\n";
  134. }
  135. } else {
  136. echo "No default customers source file found in config.xml\n";
  137. }
  138. }
  139. }
  140.  
  141. public function getFieldMappings()
  142. {
  143. $mappings = array();
  144. $option1 = $this->getArg('m');
  145. $option2 = $this->getArg('map');
  146.  
  147. if ($option1 || $option2) {
  148. if ($option1 && $option1 != 1) {
  149. parse_str(str_replace(array(',', ' '), array('&', ''), trim($option1)), $mappings);
  150. }
  151. if ($option2 && $option2 != 1) {
  152. parse_str(str_replace(array(',', ' '), array('&', ''), trim($option2)), $mappings);
  153. }
  154. }
  155. return $mappings;
  156. }
  157.  
  158. public function initCustomersImportModel()
  159. {
  160. $customersimport = Mage::getModel('importexport/import');
  161. $customersimport->setEntity('customer');
  162. $customersimport->setBehavior($this->behavior);
  163.  
  164. return $customersimport;
  165. }
  166.  
  167. public function usageHelp()
  168. {
  169. $tmpFolder = substr(
  170. Mage::getConfig()->getOptions()->getTmpDir(),
  171. strlen(Mage::getConfig()->getOptions()->getBaseDir()) + 1
  172. );
  173.  
  174. return <<<HELP
  175. SYNOPSIS
  176. php -f customerImportFromCsv.php
  177. php -f customerImportFromCsv.php [-- [OPTIONS...]]
  178.  
  179. DESCRIPTION
  180. This can import customers from CSV file.
  181.  
  182. Imports:
  183. file.csv: multiple-row csv files, supports multiselect fields
  184. Multiselect fields:
  185. Use commas to separate values, but make sure not to put asterisks in column header, ie:
  186. sku ,*_category ,color
  187. TEST,"CAT1/CAT2,CAT3","red,yellow"
  188.  
  189. OPTIONS
  190. -h
  191. -help
  192. print this usage and exit
  193.  
  194. -b
  195. -behavior
  196. set import behavior for csv file: append|delete|replace (default)
  197.  
  198. -f [file]
  199. -filename [file]
  200. import customers from csv file, if source file not specified or not found uses defined in config.xml
  201.  
  202. -l <n>
  203. -linecount <n>
  204. split import file into pieces of n lines length ($tmpFolder must be writable)
  205.  
  206. -m
  207. -map
  208. set custom fields' mapping when you use custom formatted CSV file
  209.  
  210. EXAMPLES
  211. php -f customerImportFromCsv.php -- -f customers.csv
  212. php -f customerImportFromCsv.php -- -f customers.csv -m "u_email_address=email, u_first_name=firstname, u_last_name=lastname"
  213.  
  214. HELP;
  215. }
  216.  
  217. public function splitFile($filename, $linecount)
  218. {
  219. $extension = pathinfo($filename, PATHINFO_EXTENSION);
  220. $count = 0;
  221. $i = 0;
  222. $j = 0;
  223. $files = array();
  224. $h = fopen($filename, 'r');
  225. $header = fgets($h);
  226.  
  227. $defaultValueIndex = array();
  228. $this->_headerArray = explode(',', trim($header));
  229.  
  230. foreach (array_keys($this->_defaultValuesForBuiltInImport) as $requiredField) {
  231. if (FALSE !== $indexInHeader = array_search($requiredField, $this->_headerArray)) {
  232. $defaultValueIndex[$requiredField] = $indexInHeader;
  233. } else {
  234. $defaultValueIndex[$requiredField] = count($this->_headerArray);
  235. $this->_headerArray[] = $requiredField;
  236. }
  237. }
  238. $header = implode(',', $this->_headerArray) . "\n";
  239.  
  240. while ($line = fgets($h)) {
  241. // first iteration / no "attr-only" line / line count has been reached
  242. if ($i == 0 || (substr($line, 0 ,1) != ',' && substr($line, 0 ,2) != '""' && substr($line, 0 ,2) != "''" && $i >= $linecount && !($linecount === true))) {
  243. if (defined('t')) {
  244. fclose($t);
  245. }
  246. $files[] = Mage::getConfig()->getOptions()->getTmpDir() . DS . pathinfo($filename, PATHINFO_FILENAME) . '.tmp.' . $j . '.' . $extension;
  247. $t = fopen($files[$j++], 'w');
  248. fwrite($t, $header);
  249. $i = 0;
  250. }
  251. $line = $this->_convertCsvLineToValid($line, $this->_headerArray) . "\n";
  252. fwrite($t, $line);
  253. $count++;
  254. $i++;
  255. }
  256. fclose($h);
  257. if (defined('t')) {
  258. fclose($t);
  259. }
  260.  
  261. return $files;
  262. }
  263.  
  264. public function unlinkFiles($files)
  265. {
  266. foreach ($files as $file) {
  267. unlink($file);
  268. }
  269. }
  270.  
  271. private function _convertCsvLineToValid($line, $headerArray)
  272. {
  273. $lineArray = explode(',', trim($line));
  274. foreach ($this->_defaultValuesForBuiltInImport as $requiredField => $defaultValue) {
  275. $requiredFieldIndex = array_search($requiredField, $headerArray);
  276. if (empty($lineArray[$requiredFieldIndex])) {
  277. $lineArray[$requiredFieldIndex] = $defaultValue;
  278. }
  279. }
  280. return implode(',', $lineArray);
  281. }
  282.  
  283. private function _importWithBuiltInFunctionality($file)
  284. {
  285. $count = 0;
  286. $customersimport = $this->initCustomersImportModel();
  287. $validationResult = $customersimport->validateSource($file);
  288. $processedRowsCount = $customersimport->getProcessedRowsCount();
  289.  
  290. if ($processedRowsCount > 0) {
  291. // get only one field each time to prevent disruption because some line errors
  292. while (!$validationResult) {
  293. echo "\n";
  294. $errorLines = array();
  295. foreach ($customersimport->getErrors() as $type => $lines) {
  296. echo ":::: " . $type . " in line(s) " . implode(", ", $lines) . " ::::\n";
  297. $errorLines = array_merge($errorLines, $lines);
  298. }
  299. echo "\n";
  300. $file_ = str_replace('tmp.', 'tmp._', $file);
  301. $files_[] = $file_;
  302. $h = fopen($file, 'r');
  303. $t = fopen($file_, 'w');
  304. $i = 0;
  305. $error = false;
  306. while ($line = fgets($h)) {
  307. if ((substr($line, 0 ,1) != ',' && substr($line, 0 ,2) != '""' && substr($line, 0 ,2) != "''")) {
  308. $error = false;
  309. }
  310. if (!$error) {
  311. if (!in_array($i, $errorLines)) {
  312. fwrite($t, $line);
  313. } else {
  314. echo ":: Line " . $i . " :: " . $line;
  315. $error = true;
  316. }
  317. }
  318. $i++;
  319. }
  320. fclose($h);
  321. fclose($t);
  322.  
  323. $customersimport = $this->initCustomersImportModel();
  324. $validationResult = $customersimport->validateSource($file_);
  325. $processedRowsCount = $customersimport->getProcessedRowsCount();
  326. $file = $file_;
  327. }
  328.  
  329. $count += $processedRowsCount;
  330. $customersimport->importSource();
  331. }
  332.  
  333. return $count;
  334. }
  335.  
  336. private function _importFromCustomFormattedCsv($filePath)
  337. {
  338. $count = 0;
  339. $entityRows = $this->_attributeRows = array();
  340. $this->_nextEntityId = Mage::getResourceHelper('importexport')->getNextAutoincrement($this->_table);
  341. $this->_passId = $this->_resource->getAttribute('password_hash')->getId();
  342. $this->_passTable = $this->_resource->getAttribute('password_hash')->getBackend()->getTable();
  343.  
  344. $file = fopen($filePath, 'r');
  345. $header = fgets($file);
  346. $error = false;
  347. while ($line = fgets($file)) {
  348. if ((substr($line, 0 ,1) != ',' && substr($line, 0 ,2) != '""' && substr($line, 0 ,2) != "''")) {
  349. $error = false;
  350. }
  351. if (!$error) {
  352. $count++;
  353. $entityRows[] = $this->_createEntityArrayFromKnownFields($line);
  354. $this->_loadAttributesFromKnownFields($line);
  355. }
  356.  
  357. if ($count > 0 && $count % BUNCH_SIZE_TO_INSERT == 0) {
  358. $this->_connection->insertMultiple($this->_table, $entityRows);
  359. $this->_saveCustomerAttributes($this->_attributeRows);
  360. $entityRows = array();
  361. $this->_attributeRows = array();
  362. }
  363. }
  364. fclose($file);
  365.  
  366. if ($count > 0 && ! empty($entityRows)) {
  367. $this->_connection->insertMultiple($this->_table, $entityRows);
  368. $this->_saveCustomerAttributes($this->_attributeRows);
  369. }
  370.  
  371. return $count;
  372. }
  373.  
  374. protected function _saveCustomerAttributes(array $attributesData)
  375. {
  376. foreach ($attributesData as $tableName => $data) {
  377. $tableData = array();
  378.  
  379. foreach ($data as $customerId => $attrData) {
  380. foreach ($attrData as $attributeId => $value) {
  381. $tableData[] = array(
  382. 'entity_id' => $customerId,
  383. 'entity_type_id' => $this->_entityTypeId,
  384. 'attribute_id' => $attributeId,
  385. 'value' => $value
  386. );
  387. }
  388. }
  389. $this->_connection->insertOnDuplicate($tableName, $tableData, array('value'));
  390. }
  391. return $this;
  392. }
  393.  
  394. private function _createEntityArrayFromKnownFields($line)
  395. {
  396. $row = $tmpRow = array();
  397. $lineArray = explode(',', trim($line));
  398. foreach ($this->_customFieldNamesEqualsTo as $customFieldName => $correspondingFieldName) {
  399. $customFieldIndex = array_search($customFieldName, $this->_headerArray);
  400. $tmpRow[$correspondingFieldName] = $lineArray[$customFieldIndex];
  401. }
  402.  
  403. foreach ($this->_defaultValuesForCustomImport as $fieldName => $defaultValue) {
  404. $row[$fieldName] = (empty($tmpRow[$fieldName]) || $tmpRow[$fieldName] === "NULL")
  405. ? $defaultValue
  406. : $tmpRow[$fieldName];
  407. }
  408.  
  409. return $row;
  410. }
  411.  
  412. private function _loadAttributesFromKnownFields($line)
  413. {
  414. $row = $tmpRow = array();
  415. $entityId = $this->_nextEntityId++;
  416. $lineArray = explode(',', trim($line));
  417. foreach ($this->_customFieldNamesEqualsTo as $customFieldName => $correspondingFieldName) {
  418. $customFieldIndex = array_search($customFieldName, $this->_headerArray);
  419. $tmpRow[$correspondingFieldName] = $lineArray[$customFieldIndex];
  420. }
  421.  
  422. foreach (array_merge($this->_headerArray, array_keys($tmpRow)) as $index => $fieldName) {
  423. if (empty($lineArray[$index])) {
  424. $lineArray[$index] = '';
  425. }
  426. $row[$fieldName] = empty($tmpRow[$fieldName]) ? $lineArray[$index] : $tmpRow[$fieldName];
  427. if ($row[$fieldName] == 'NULL' && array_key_exists($fieldName, $this->_defaultValuesForBuiltInImport)) {
  428. $row[$fieldName] = $this->_defaultValuesForBuiltInImport[$fieldName];
  429. }
  430. }
  431.  
  432. // attribute values
  433. foreach (array_intersect_key($row, $this->_attributes) as $attrCode => $value) {
  434. if (!$this->_attributes[$attrCode]['is_static'] && strlen($value)) {
  435. /** @var $attribute Mage_Customer_Model_Attribute */
  436. $attribute = $this->_resource->getAttribute($attrCode);
  437. $backModel = $attribute->getBackendModel();
  438. $attrParams = $this->_attributes[$attrCode];
  439.  
  440. if ('select' == $attrParams['type']) {
  441. $value = $attrParams['options'][strtolower($value)];
  442. } elseif ('datetime' == $attrParams['type']) {
  443. $value = gmstrftime($strftimeFormat, strtotime($value));
  444. } elseif ($backModel) {
  445. $attribute->getBackend()->beforeSave($this->_resource->setData($attrCode, $value));
  446. $value = $this->_resource->getData($attrCode);
  447. }
  448. $this->_attributeRows[$attribute->getBackend()->getTable()][$entityId][$attrParams['id']] = $value;
  449.  
  450. // restore 'backend_model' to avoid default setting
  451. $attribute->setBackendModel($backModel);
  452. }
  453. }
  454. // password change/set
  455. if (isset($row['password']) && strlen($row['password'])) {
  456. $this->_attributeRows[$this->_passTable][$entityId][$this->_passId] = $this->_resource->hashPassword($row['password']);
  457. }
  458. }
  459.  
  460. public function getAttributeOptions(Mage_Eav_Model_Entity_Attribute_Abstract $attribute, $indexValAttrs = array())
  461. {
  462. $options = array();
  463.  
  464. if ($attribute->usesSource()) {
  465. // merge global entity index value attributes
  466. $indexValAttrs = array_merge($indexValAttrs, $this->_indexValueAttributes);
  467.  
  468. // should attribute has index (option value) instead of a label?
  469. $index = in_array($attribute->getAttributeCode(), $indexValAttrs) ? 'value' : 'label';
  470.  
  471. // only default (admin) store values used
  472. $attribute->setStoreId(Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID);
  473.  
  474. try {
  475. foreach ($attribute->getSource()->getAllOptions(false) as $option) {
  476. $value = is_array($option['value']) ? $option['value'] : array($option);
  477. foreach ($value as $innerOption) {
  478. if (strlen($innerOption['value'])) { // skip ' -- Please Select -- ' option
  479. $options[strtolower($innerOption[$index])] = $innerOption['value'];
  480. }
  481. }
  482. }
  483. } catch (Exception $e) {
  484. // ignore exceptions connected with source models
  485. }
  486. }
  487. return $options;
  488. }
  489. }
  490.  
  491. $main = new CustomerImportFromCsv();
  492. $main->run();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement