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

/controllers/admin/AdminImportController.php

https://github.com/netplayer/PrestaShop
PHP | 3415 lines | 2935 code | 298 blank | 182 comment | 730 complexity | e89c6481b6852a6dce33350b71f75a3c MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, LGPL-3.0
  1. <?php
  2. /*
  3. * 2007-2014 PrestaShop
  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@prestashop.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 PrestaShop to newer
  18. * versions in the future. If you wish to customize PrestaShop for your
  19. * needs please refer to http://www.prestashop.com for more information.
  20. *
  21. * @author PrestaShop SA <contact@prestashop.com>
  22. * @copyright 2007-2014 PrestaShop SA
  23. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  24. * International Registered Trademark & Property of PrestaShop SA
  25. */
  26. @ini_set('max_execution_time', 0);
  27. /** No max line limit since the lines can be more than 4096. Performance impact is not significant. */
  28. define('MAX_LINE_SIZE', 0);
  29. /** Used for validatefields diying without user friendly error or not */
  30. define('UNFRIENDLY_ERROR', false);
  31. /** this value set the number of columns visible on each page */
  32. define('MAX_COLUMNS', 6);
  33. /** correct Mac error on eof */
  34. @ini_set('auto_detect_line_endings', '1');
  35. class AdminImportControllerCore extends AdminController
  36. {
  37. public static $column_mask;
  38. public $entities = array();
  39. public $available_fields = array();
  40. public $required_fields = array();
  41. public $cache_image_deleted = array();
  42. public static $default_values = array();
  43. public static $validators = array(
  44. 'active' => array('AdminImportController', 'getBoolean'),
  45. 'tax_rate' => array('AdminImportController', 'getPrice'),
  46. /** Tax excluded */
  47. 'price_tex' => array('AdminImportController', 'getPrice'),
  48. /** Tax included */
  49. 'price_tin' => array('AdminImportController', 'getPrice'),
  50. 'reduction_price' => array('AdminImportController', 'getPrice'),
  51. 'reduction_percent' => array('AdminImportController', 'getPrice'),
  52. 'wholesale_price' => array('AdminImportController', 'getPrice'),
  53. 'ecotax' => array('AdminImportController', 'getPrice'),
  54. 'name' => array('AdminImportController', 'createMultiLangField'),
  55. 'description' => array('AdminImportController', 'createMultiLangField'),
  56. 'description_short' => array('AdminImportController', 'createMultiLangField'),
  57. 'meta_title' => array('AdminImportController', 'createMultiLangField'),
  58. 'meta_keywords' => array('AdminImportController', 'createMultiLangField'),
  59. 'meta_description' => array('AdminImportController', 'createMultiLangField'),
  60. 'link_rewrite' => array('AdminImportController', 'createMultiLangField'),
  61. 'available_now' => array('AdminImportController', 'createMultiLangField'),
  62. 'available_later' => array('AdminImportController', 'createMultiLangField'),
  63. 'category' => array('AdminImportController', 'split'),
  64. 'online_only' => array('AdminImportController', 'getBoolean')
  65. );
  66. public $separator;
  67. public $multiple_value_separator;
  68. public function __construct()
  69. {
  70. $this->bootstrap = true;
  71. $this->entities = array(
  72. $this->l('Categories'),
  73. $this->l('Products'),
  74. $this->l('Combinations'),
  75. $this->l('Customers'),
  76. $this->l('Addresses'),
  77. $this->l('Manufacturers'),
  78. $this->l('Suppliers'),
  79. $this->l('Alias'),
  80. );
  81. // @since 1.5.0
  82. if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
  83. {
  84. $this->entities = array_merge(
  85. $this->entities,
  86. array(
  87. $this->l('Supply Orders'),
  88. $this->l('Supply Order Details'),
  89. )
  90. );
  91. }
  92. $this->entities = array_flip($this->entities);
  93. switch ((int)Tools::getValue('entity'))
  94. {
  95. case $this->entities[$this->l('Combinations')]:
  96. $this->required_fields = array(
  97. 'id_product',
  98. 'group',
  99. 'attribute'
  100. );
  101. $this->available_fields = array(
  102. 'no' => array('label' => $this->l('Ignore this column')),
  103. 'id_product' => array('label' => $this->l('Product ID').'*'),
  104. 'group' => array(
  105. 'label' => $this->l('Attribute (Name:Type:Position)').'*'
  106. ),
  107. 'attribute' => array(
  108. 'label' => $this->l('Value (Value:Position)').'*'
  109. ),
  110. 'supplier_reference' => array('label' => $this->l('Supplier reference')),
  111. 'reference' => array('label' => $this->l('Reference')),
  112. 'ean13' => array('label' => $this->l('EAN13')),
  113. 'upc' => array('label' => $this->l('UPC')),
  114. 'wholesale_price' => array('label' => $this->l('Wholesale price')),
  115. 'price' => array('label' => $this->l('Impact on price')),
  116. 'ecotax' => array('label' => $this->l('Ecotax')),
  117. 'quantity' => array('label' => $this->l('Quantity')),
  118. 'minimal_quantity' => array('label' => $this->l('Minimal quantity')),
  119. 'weight' => array('label' => $this->l('Impact on weight')),
  120. 'default_on' => array('label' => $this->l('Default (0 = No, 1 = Yes)')),
  121. 'image_position' => array(
  122. 'label' => $this->l('Image position')
  123. ),
  124. 'image_url' => array('label' => $this->l('Image URL')),
  125. 'delete_existing_images' => array(
  126. 'label' => $this->l('Delete existing images (0 = No, 1 = Yes).')
  127. ),
  128. 'shop' => array(
  129. 'label' => $this->l('ID / Name of shop'),
  130. 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
  131. ),
  132. 'advanced_stock_management' => array(
  133. 'label' => $this->l('Advanced Stock Management'),
  134. 'help' => $this->l('Enable Advanced Stock Management on product (0 = No, 1 = Yes)')
  135. ),
  136. 'depends_on_stock' => array(
  137. 'label' => $this->l('Depends on stock'),
  138. 'help' => $this->l('0 = Use quantity set in product, 1 = Use quantity from warehouse.')
  139. ),
  140. 'warehouse' => array(
  141. 'label' => $this->l('Warehouse'),
  142. 'help' => $this->l('ID of the warehouse to set as storage.')
  143. ),
  144. );
  145. self::$default_values = array(
  146. 'reference' => '',
  147. 'supplier_reference' => '',
  148. 'ean13' => '',
  149. 'upc' => '',
  150. 'wholesale_price' => 0,
  151. 'price' => 0,
  152. 'ecotax' => 0,
  153. 'quantity' => 0,
  154. 'minimal_quantity' => 1,
  155. 'weight' => 0,
  156. 'default_on' => 0,
  157. 'advanced_stock_management' => 0,
  158. 'depends_on_stock' => 0,
  159. );
  160. break;
  161. case $this->entities[$this->l('Categories')]:
  162. $this->available_fields = array(
  163. 'no' => array('label' => $this->l('Ignore this column')),
  164. 'id' => array('label' => $this->l('ID')),
  165. 'active' => array('label' => $this->l('Active (0/1)')),
  166. 'name' => array('label' => $this->l('Name')),
  167. 'parent' => array('label' => $this->l('Parent category')),
  168. 'is_root_category' => array(
  169. 'label' => $this->l('Root category (0/1)'),
  170. 'help' => $this->l('A category root is where a category tree can begin. This is used with multistore.')
  171. ),
  172. 'description' => array('label' => $this->l('Description')),
  173. 'meta_title' => array('label' => $this->l('Meta title')),
  174. 'meta_keywords' => array('label' => $this->l('Meta keywords')),
  175. 'meta_description' => array('label' => $this->l('Meta description')),
  176. 'link_rewrite' => array('label' => $this->l('URL rewritten')),
  177. 'image' => array('label' => $this->l('Image URL')),
  178. 'shop' => array(
  179. 'label' => $this->l('ID / Name of shop'),
  180. 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
  181. ),
  182. );
  183. self::$default_values = array(
  184. 'active' => '1',
  185. 'parent' => Configuration::get('PS_HOME_CATEGORY'),
  186. 'link_rewrite' => ''
  187. );
  188. break;
  189. case $this->entities[$this->l('Products')]:
  190. self::$validators['image'] = array(
  191. 'AdminImportController',
  192. 'split'
  193. );
  194. $this->available_fields = array(
  195. 'no' => array('label' => $this->l('Ignore this column')),
  196. 'id' => array('label' => $this->l('ID')),
  197. 'active' => array('label' => $this->l('Active (0/1)')),
  198. 'name' => array('label' => $this->l('Name')),
  199. 'category' => array('label' => $this->l('Categories (x,y,z...)')),
  200. 'price_tex' => array('label' => $this->l('Price tax excluded')),
  201. 'price_tin' => array('label' => $this->l('Price tax included')),
  202. 'id_tax_rules_group' => array('label' => $this->l('Tax rules ID')),
  203. 'wholesale_price' => array('label' => $this->l('Wholesale price')),
  204. 'on_sale' => array('label' => $this->l('On sale (0/1)')),
  205. 'reduction_price' => array('label' => $this->l('Discount amount')),
  206. 'reduction_percent' => array('label' => $this->l('Discount percent')),
  207. 'reduction_from' => array('label' => $this->l('Discount from (yyyy-mm-dd)')),
  208. 'reduction_to' => array('label' => $this->l('Discount to (yyyy-mm-dd)')),
  209. 'reference' => array('label' => $this->l('Reference #')),
  210. 'supplier_reference' => array('label' => $this->l('Supplier reference #')),
  211. 'supplier' => array('label' => $this->l('Supplier')),
  212. 'manufacturer' => array('label' => $this->l('Manufacturer')),
  213. 'ean13' => array('label' => $this->l('EAN13')),
  214. 'upc' => array('label' => $this->l('UPC')),
  215. 'ecotax' => array('label' => $this->l('Ecotax')),
  216. 'width' => array('label' => $this->l('Width')),
  217. 'height' => array('label' => $this->l('Height')),
  218. 'depth' => array('label' => $this->l('Depth')),
  219. 'weight' => array('label' => $this->l('Weight')),
  220. 'quantity' => array('label' => $this->l('Quantity')),
  221. 'minimal_quantity' => array('label' => $this->l('Minimal quantity')),
  222. 'visibility' => array('label' => $this->l('Visibility')),
  223. 'additional_shipping_cost' => array('label' => $this->l('Additional shipping cost')),
  224. 'unity' => array('label' => $this->l('Unit for the unit price')),
  225. 'unit_price' => array('label' => $this->l('Unit price')),
  226. 'description_short' => array('label' => $this->l('Short description')),
  227. 'description' => array('label' => $this->l('Description')),
  228. 'tags' => array('label' => $this->l('Tags (x,y,z...)')),
  229. 'meta_title' => array('label' => $this->l('Meta title')),
  230. 'meta_keywords' => array('label' => $this->l('Meta keywords')),
  231. 'meta_description' => array('label' => $this->l('Meta description')),
  232. 'link_rewrite' => array('label' => $this->l('URL rewritten')),
  233. 'available_now' => array('label' => $this->l('Text when in stock')),
  234. 'available_later' => array('label' => $this->l('Text when backorder allowed')),
  235. 'available_for_order' => array('label' => $this->l('Available for order (0 = No, 1 = Yes)')),
  236. 'available_date' => array('label' => $this->l('Product available date')),
  237. 'date_add' => array('label' => $this->l('Product creation date')),
  238. 'show_price' => array('label' => $this->l('Show price (0 = No, 1 = Yes)')),
  239. 'image' => array('label' => $this->l('Image URLs (x,y,z...)')),
  240. 'delete_existing_images' => array(
  241. 'label' => $this->l('Delete existing images (0 = No, 1 = Yes)')
  242. ),
  243. 'features' => array('label' => $this->l('Feature (Name:Value:Position:Customized)')),
  244. 'online_only' => array('label' => $this->l('Available online only (0 = No, 1 = Yes)')),
  245. 'condition' => array('label' => $this->l('Condition')),
  246. 'customizable' => array('label' => $this->l('Customizable (0 = No, 1 = Yes)')),
  247. 'uploadable_files' => array('label' => $this->l('Uploadable files (0 = No, 1 = Yes)')),
  248. 'text_fields' => array('label' => $this->l('Text fields (0 = No, 1 = Yes)')),
  249. 'out_of_stock' => array('label' => $this->l('Action when out of stock')),
  250. 'shop' => array(
  251. 'label' => $this->l('ID / Name of shop'),
  252. 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
  253. ),
  254. 'advanced_stock_management' => array(
  255. 'label' => $this->l('Advanced Stock Management'),
  256. 'help' => $this->l('Enable Advanced Stock Management on product (0 = No, 1 = Yes).')
  257. ),
  258. 'depends_on_stock' => array(
  259. 'label' => $this->l('Depends on stock'),
  260. 'help' => $this->l('0 = Use quantity set in product, 1 = Use quantity from warehouse.')
  261. ),
  262. 'warehouse' => array(
  263. 'label' => $this->l('Warehouse'),
  264. 'help' => $this->l('ID of the warehouse to set as storage.')
  265. ),
  266. );
  267. self::$default_values = array(
  268. 'id_category' => array((int)Configuration::get('PS_HOME_CATEGORY')),
  269. 'id_category_default' => (int)Configuration::get('PS_HOME_CATEGORY'),
  270. 'active' => '1',
  271. 'width' => 0.000000,
  272. 'height' => 0.000000,
  273. 'depth' => 0.000000,
  274. 'weight' => 0.000000,
  275. 'visibility' => 'both',
  276. 'additional_shipping_cost' => 0.00,
  277. 'unit_price' => 0,
  278. 'quantity' => 0,
  279. 'minimal_quantity' => 1,
  280. 'price' => 0,
  281. 'id_tax_rules_group' => 0,
  282. 'description_short' => array((int)Configuration::get('PS_LANG_DEFAULT') => ''),
  283. 'link_rewrite' => array((int)Configuration::get('PS_LANG_DEFAULT') => ''),
  284. 'online_only' => 0,
  285. 'condition' => 'new',
  286. 'available_date' => date('Y-m-d'),
  287. 'date_add' => date('Y-m-d H:i:s'),
  288. 'customizable' => 0,
  289. 'uploadable_files' => 0,
  290. 'text_fields' => 0,
  291. 'out_of_stock' => '2',
  292. 'advanced_stock_management' => 0,
  293. 'depends_on_stock' => 0,
  294. );
  295. break;
  296. case $this->entities[$this->l('Customers')]:
  297. //Overwrite required_fields AS only email is required whereas other entities
  298. $this->required_fields = array('email', 'passwd', 'lastname', 'firstname');
  299. $this->available_fields = array(
  300. 'no' => array('label' => $this->l('Ignore this column')),
  301. 'id' => array('label' => $this->l('ID')),
  302. 'active' => array('label' => $this->l('Active (0/1)')),
  303. 'id_gender' => array('label' => $this->l('Titles ID (Mr = 1, Ms = 2, else 0)')),
  304. 'email' => array('label' => $this->l('Email *')),
  305. 'passwd' => array('label' => $this->l('Password *')),
  306. 'birthday' => array('label' => $this->l('Birthday (yyyy-mm-dd)')),
  307. 'lastname' => array('label' => $this->l('Last Name *')),
  308. 'firstname' => array('label' => $this->l('First Name *')),
  309. 'newsletter' => array('label' => $this->l('Newsletter (0/1)')),
  310. 'optin' => array('label' => $this->l('Opt-in (0/1)')),
  311. 'group' => array('label' => $this->l('Groups (x,y,z...)')),
  312. 'id_default_group' => array('label' => $this->l('Default group ID')),
  313. 'id_shop' => array(
  314. 'label' => $this->l('ID / Name of shop'),
  315. 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
  316. ),
  317. );
  318. self::$default_values = array(
  319. 'active' => '1',
  320. 'id_shop' => Configuration::get('PS_SHOP_DEFAULT'),
  321. );
  322. break;
  323. case $this->entities[$this->l('Addresses')]:
  324. //Overwrite required_fields
  325. $this->required_fields = array(
  326. 'alias',
  327. 'lastname',
  328. 'firstname',
  329. 'address1',
  330. 'postcode',
  331. 'country',
  332. 'customer_email',
  333. 'city'
  334. );
  335. $this->available_fields = array(
  336. 'no' => array('label' => $this->l('Ignore this column')),
  337. 'id' => array('label' => $this->l('ID')),
  338. 'alias' => array('label' => $this->l('Alias *')),
  339. 'active' => array('label' => $this->l('Active (0/1)')),
  340. 'customer_email' => array('label' => $this->l('Customer email *')),
  341. 'id_customer' => array('label' => $this->l('Customer ID')),
  342. 'manufacturer' => array('label' => $this->l('Manufacturer')),
  343. 'supplier' => array('label' => $this->l('Supplier')),
  344. 'company' => array('label' => $this->l('Company')),
  345. 'lastname' => array('label' => $this->l('Last Name *')),
  346. 'firstname' => array('label' => $this->l('First Name *')),
  347. 'address1' => array('label' => $this->l('Address 1 *')),
  348. 'address2' => array('label' => $this->l('Address 2')),
  349. 'postcode' => array('label' => $this->l('Zip/postal code *')),
  350. 'city' => array('label' => $this->l('City *')),
  351. 'country' => array('label' => $this->l('Country *')),
  352. 'state' => array('label' => $this->l('State')),
  353. 'other' => array('label' => $this->l('Other')),
  354. 'phone' => array('label' => $this->l('Phone')),
  355. 'phone_mobile' => array('label' => $this->l('Mobile Phone')),
  356. 'vat_number' => array('label' => $this->l('VAT number')),
  357. );
  358. self::$default_values = array(
  359. 'alias' => 'Alias',
  360. 'postcode' => 'X'
  361. );
  362. break;
  363. case $this->entities[$this->l('Manufacturers')]:
  364. case $this->entities[$this->l('Suppliers')]:
  365. //Overwrite validators AS name is not MultiLangField
  366. self::$validators = array(
  367. 'description' => array('AdminImportController', 'createMultiLangField'),
  368. 'short_description' => array('AdminImportController', 'createMultiLangField'),
  369. 'meta_title' => array('AdminImportController', 'createMultiLangField'),
  370. 'meta_keywords' => array('AdminImportController', 'createMultiLangField'),
  371. 'meta_description' => array('AdminImportController', 'createMultiLangField'),
  372. );
  373. $this->available_fields = array(
  374. 'no' => array('label' => $this->l('Ignore this column')),
  375. 'id' => array('label' => $this->l('ID')),
  376. 'active' => array('label' => $this->l('Active (0/1)')),
  377. 'name' => array('label' => $this->l('Name')),
  378. 'description' => array('label' => $this->l('Description')),
  379. 'short_description' => array('label' => $this->l('Short description')),
  380. 'meta_title' => array('label' => $this->l('Meta title')),
  381. 'meta_keywords' => array('label' => $this->l('Meta keywords')),
  382. 'meta_description' => array('label' => $this->l('Meta description')),
  383. 'image' => array('label' => $this->l('Image URL')),
  384. 'shop' => array(
  385. 'label' => $this->l('ID / Name of group shop'),
  386. 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
  387. ),
  388. );
  389. self::$default_values = array(
  390. 'shop' => Shop::getGroupFromShop(Configuration::get('PS_SHOP_DEFAULT')),
  391. );
  392. break;
  393. case $this->entities[$this->l('Alias')]:
  394. //Overwrite required_fields
  395. $this->required_fields = array(
  396. 'alias',
  397. 'search',
  398. );
  399. $this->available_fields = array(
  400. 'no' => array('label' => $this->l('Ignore this column')),
  401. 'id' => array('label' => $this->l('ID')),
  402. 'alias' => array('label' => $this->l('Alias *')),
  403. 'search' => array('label' => $this->l('Search *')),
  404. 'active' => array('label' => $this->l('Active')),
  405. );
  406. self::$default_values = array(
  407. 'active' => '1',
  408. );
  409. break;
  410. }
  411. // @since 1.5.0
  412. if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
  413. switch ((int)Tools::getValue('entity'))
  414. {
  415. case $this->entities[$this->l('Supply Orders')]:
  416. // required fields
  417. $this->required_fields = array(
  418. 'id_supplier',
  419. 'id_warehouse',
  420. 'reference',
  421. 'date_delivery_expected',
  422. );
  423. // available fields
  424. $this->available_fields = array(
  425. 'no' => array('label' => $this->l('Ignore this column')),
  426. 'id' => array('label' => $this->l('ID')),
  427. 'id_supplier' => array('label' => $this->l('Supplier ID *')),
  428. 'id_lang' => array('label' => $this->l('Lang ID')),
  429. 'id_warehouse' => array('label' => $this->l('Warehouse ID *')),
  430. 'id_currency' => array('label' => $this->l('Currency ID *')),
  431. 'reference' => array('label' => $this->l('Supply Order Reference *')),
  432. 'date_delivery_expected' => array('label' => $this->l('Delivery Date (Y-M-D)*')),
  433. 'discount_rate' => array('label' => $this->l('Discount Rate')),
  434. 'is_template' => array('label' => $this->l('Template')),
  435. );
  436. // default values
  437. self::$default_values = array(
  438. 'id_lang' => (int)Configuration::get('PS_LANG_DEFAULT'),
  439. 'id_currency' => Currency::getDefaultCurrency()->id,
  440. 'discount_rate' => '0',
  441. 'is_template' => '0',
  442. );
  443. break;
  444. case $this->entities[$this->l('Supply Order Details')]:
  445. // required fields
  446. $this->required_fields = array(
  447. 'supply_order_reference',
  448. 'id_product',
  449. 'unit_price_te',
  450. 'quantity_expected',
  451. );
  452. // available fields
  453. $this->available_fields = array(
  454. 'no' => array('label' => $this->l('Ignore this column')),
  455. 'supply_order_reference' => array('label' => $this->l('Supply Order Reference *')),
  456. 'id_product' => array('label' => $this->l('Product ID *')),
  457. 'id_product_attribute' => array('label' => $this->l('Product Attribute ID')),
  458. 'unit_price_te' => array('label' => $this->l('Unit Price (tax excl.)*')),
  459. 'quantity_expected' => array('label' => $this->l('Quantity Expected *')),
  460. 'discount_rate' => array('label' => $this->l('Discount Rate')),
  461. 'tax_rate' => array('label' => $this->l('Tax Rate')),
  462. );
  463. // default values
  464. self::$default_values = array(
  465. 'discount_rate' => '0',
  466. 'tax_rate' => '0',
  467. );
  468. break;
  469. }
  470. $this->separator = ($separator = Tools::substr(strval(trim(Tools::getValue('separator'))), 0, 1)) ? $separator : ';';
  471. $this->multiple_value_separator = ($separator = Tools::substr(strval(trim(Tools::getValue('multiple_value_separator'))), 0, 1)) ? $separator : ',';
  472. parent::__construct();
  473. }
  474. public function setMedia()
  475. {
  476. $bo_theme = ((Validate::isLoadedObject($this->context->employee)
  477. && $this->context->employee->bo_theme) ? $this->context->employee->bo_theme : 'default');
  478. if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR
  479. .'template'))
  480. $bo_theme = 'default';
  481. // We need to set parent media first, so that jQuery is loaded before the dependant plugins
  482. parent::setMedia();
  483. $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.iframe-transport.js');
  484. $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload.js');
  485. $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload-process.js');
  486. $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload-validate.js');
  487. $this->addJs(__PS_BASE_URI__.'js/vendor/spin.js');
  488. $this->addJs(__PS_BASE_URI__.'js/vendor/ladda.js');
  489. }
  490. public function renderForm()
  491. {
  492. if (!is_dir(AdminImportController::getPath()))
  493. return !($this->errors[] = Tools::displayError('The import directory does not exist.'));
  494. if (!is_writable(AdminImportController::getPath()))
  495. $this->displayWarning($this->l('The import directory must be writable (CHMOD 755 / 777).'));
  496. if (isset($this->warnings) && count($this->warnings))
  497. {
  498. $warnings = array();
  499. foreach ($this->warnings as $warning)
  500. $warnings[] = $warning;
  501. }
  502. $files_to_import = scandir(AdminImportController::getPath());
  503. uasort($files_to_import, array('AdminImportController', 'usortFiles'));
  504. foreach ($files_to_import as $k => &$filename)
  505. //exclude . .. .svn and index.php and all hidden files
  506. if (preg_match('/^\..*|index\.php/i', $filename))
  507. unset($files_to_import[$k]);
  508. unset($filename);
  509. $this->fields_form = array('');
  510. $this->toolbar_scroll = false;
  511. $this->toolbar_btn = array();
  512. // adds fancybox
  513. $this->addJqueryPlugin(array('fancybox'));
  514. $entity_selected = 0;
  515. if (isset($this->entities[$this->l(Tools::ucfirst(Tools::getValue('import_type')))]))
  516. {
  517. $entity_selected = $this->entities[$this->l(Tools::ucfirst(Tools::getValue('import_type')))];
  518. $this->context->cookie->entity_selected = (int)$entity_selected;
  519. }
  520. elseif (isset($this->context->cookie->entity_selected))
  521. $entity_selected = (int)$this->context->cookie->entity_selected;
  522. $csv_selected = '';
  523. if (isset($this->context->cookie->csv_selected) && @filemtime(AdminImportController::getPath(
  524. urldecode($this->context->cookie->csv_selected))))
  525. $csv_selected = urldecode($this->context->cookie->csv_selected);
  526. else
  527. $this->context->cookie->csv_selected = $csv_selected;
  528. $id_lang_selected = '';
  529. if (isset($this->context->cookie->iso_lang_selected) && $this->context->cookie->iso_lang_selected)
  530. $id_lang_selected = (int)Language::getIdByIso(urldecode($this->context->cookie->iso_lang_selected));
  531. $separator_selected = $this->separator;
  532. if (isset($this->context->cookie->separator_selected) && $this->context->cookie->separator_selected)
  533. $separator_selected = urldecode($this->context->cookie->separator_selected);
  534. $multiple_value_separator_selected = $this->multiple_value_separator;
  535. if (isset($this->context->cookie->multiple_value_separator_selected) && $this->context->cookie->multiple_value_separator_selected)
  536. $multiple_value_separator_selected = urldecode($this->context->cookie->multiple_value_separator_selected);
  537. //get post max size
  538. $post_max_size = ini_get('post_max_size');
  539. $bytes = trim($post_max_size);
  540. $last = strtolower($post_max_size[strlen($post_max_size) - 1]);
  541. switch ($last)
  542. {
  543. case 'g': $bytes *= 1024;
  544. case 'm': $bytes *= 1024;
  545. case 'k': $bytes *= 1024;
  546. }
  547. if (!isset($bytes) || $bytes == '')
  548. $bytes = 20971520; // 20Mb
  549. $this->tpl_form_vars = array(
  550. 'post_max_size' => (int)$bytes,
  551. 'module_confirmation' => Tools::isSubmit('import') && (isset($this->warnings) && !count($this->warnings)),
  552. 'path_import' => AdminImportController::getPath(),
  553. 'entities' => $this->entities,
  554. 'entity_selected' => $entity_selected,
  555. 'csv_selected' => $csv_selected,
  556. 'separator_selected' => $separator_selected,
  557. 'multiple_value_separator_selected' => $multiple_value_separator_selected,
  558. 'files_to_import' => $files_to_import,
  559. 'languages' => Language::getLanguages(false),
  560. 'id_language' => ($id_lang_selected) ? $id_lang_selected : $this->context->language->id,
  561. 'available_fields' => $this->getAvailableFields(),
  562. 'truncateAuthorized' => (Shop::isFeatureActive() && $this->context->employee->isSuperAdmin()) || !Shop::isFeatureActive(),
  563. 'PS_ADVANCED_STOCK_MANAGEMENT' => Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'),
  564. );
  565. return parent::renderForm();
  566. }
  567. public function ajaxProcessuploadCsv()
  568. {
  569. $filename_prefix = date('YmdHis').'-';
  570. if (isset($_FILES['file']) && !empty($_FILES['file']['error']))
  571. {
  572. switch ($_FILES['file']['error'])
  573. {
  574. case UPLOAD_ERR_INI_SIZE:
  575. $_FILES['file']['error'] = Tools::displayError('The uploaded file exceeds the upload_max_filesize directive in php.ini. If your server configuration allows it, you may add a directive in your .htaccess.');
  576. break;
  577. case UPLOAD_ERR_FORM_SIZE:
  578. $_FILES['file']['error'] = Tools::displayError('The uploaded file exceeds the post_max_size directive in php.ini.
  579. If your server configuration allows it, you may add a directive in your .htaccess, for example:')
  580. .'<br/><a href="'.$this->context->link->getAdminLink('AdminMeta').'" >
  581. <code>php_value post_max_size 20M</code> '.
  582. Tools::displayError('(click to open "Generators" page)').'</a>';
  583. break;
  584. break;
  585. case UPLOAD_ERR_PARTIAL:
  586. $_FILES['file']['error'] = Tools::displayError('The uploaded file was only partially uploaded.');
  587. break;
  588. break;
  589. case UPLOAD_ERR_NO_FILE:
  590. $_FILES['file']['error'] = Tools::displayError('No file was uploaded.');
  591. break;
  592. break;
  593. }
  594. }
  595. elseif (!preg_match('/.*\.csv$/i', $_FILES['file']['name']))
  596. $_FILES['file']['error'] = Tools::displayError('The extension of your file should be .csv.');
  597. elseif (!@filemtime($_FILES['file']['tmp_name']) ||
  598. !@move_uploaded_file($_FILES['file']['tmp_name'], AdminImportController::getPath().$filename_prefix.str_replace("\0", '', $_FILES['file']['name'])))
  599. $_FILES['file']['error'] = $this->l('An error occurred while uploading / copying the file.');
  600. else
  601. {
  602. @chmod(AdminImportController::getPath().$filename_prefix.$_FILES['file']['name'], 0664);
  603. $_FILES['file']['filename'] = $filename_prefix.str_replace('\0', '', $_FILES['file']['name']);
  604. }
  605. die(Tools::jsonEncode($_FILES));
  606. }
  607. public function renderView()
  608. {
  609. $this->addJS(_PS_JS_DIR_.'adminImport.js');
  610. $handle = $this->openCsvFile();
  611. $nb_column = $this->getNbrColumn($handle, $this->separator);
  612. $nb_table = ceil($nb_column / MAX_COLUMNS);
  613. $res = array();
  614. foreach ($this->required_fields as $elem)
  615. $res[] = '\''.$elem.'\'';
  616. $data = array();
  617. for ($i = 0; $i < $nb_table; $i++)
  618. $data[$i] = $this->generateContentTable($i, $nb_column, $handle, $this->separator);
  619. $this->context->cookie->entity_selected = (int)Tools::getValue('entity');
  620. $this->context->cookie->iso_lang_selected = urlencode(Tools::getValue('iso_lang'));
  621. $this->context->cookie->separator_selected = urlencode($this->separator);
  622. $this->context->cookie->multiple_value_separator_selected = urlencode($this->multiple_value_separator);
  623. $this->context->cookie->csv_selected = urlencode(Tools::getValue('csv'));
  624. $this->tpl_view_vars = array(
  625. 'import_matchs' => Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'import_match'),
  626. 'fields_value' => array(
  627. 'csv' => Tools::getValue('csv'),
  628. 'convert' => Tools::getValue('convert'),
  629. 'entity' => (int)Tools::getValue('entity'),
  630. 'iso_lang' => Tools::getValue('iso_lang'),
  631. 'truncate' => Tools::getValue('truncate'),
  632. 'forceIDs' => Tools::getValue('forceIDs'),
  633. 'regenerate' => Tools::getValue('regenerate'),
  634. 'match_ref' => Tools::getValue('match_ref'),
  635. 'separator' => $this->separator,
  636. 'multiple_value_separator' => $this->multiple_value_separator
  637. ),
  638. 'nb_table' => $nb_table,
  639. 'nb_column' => $nb_column,
  640. 'res' => implode(',', $res),
  641. 'max_columns' => MAX_COLUMNS,
  642. 'no_pre_select' => array('price_tin', 'feature'),
  643. 'available_fields' => $this->available_fields,
  644. 'data' => $data
  645. );
  646. return parent::renderView();
  647. }
  648. public function initToolbar()
  649. {
  650. switch ($this->display)
  651. {
  652. case 'import':
  653. // Default cancel button - like old back link
  654. $back = Tools::safeOutput(Tools::getValue('back', ''));
  655. if (empty($back))
  656. $back = self::$currentIndex.'&token='.$this->token;
  657. $this->toolbar_btn['cancel'] = array(
  658. 'href' => $back,
  659. 'desc' => $this->l('Cancel')
  660. );
  661. // Default save button - action dynamically handled in javascript
  662. $this->toolbar_btn['save-import'] = array(
  663. 'href' => '#',
  664. 'desc' => $this->l('Import .CSV data')
  665. );
  666. break;
  667. }
  668. }
  669. protected function generateContentTable($current_table, $nb_column, $handle, $glue)
  670. {
  671. $html = '<table id="table'.$current_table.'" style="display: none;" class="table table-bordered"><thead><tr>';
  672. // Header
  673. for ($i = 0; $i < $nb_column; $i++)
  674. if (MAX_COLUMNS * (int)$current_table <= $i && (int)$i < MAX_COLUMNS * ((int)$current_table + 1))
  675. $html .= '<th>
  676. <select id="type_value['.$i.']"
  677. name="type_value['.$i.']"
  678. class="type_value">
  679. '.$this->getTypeValuesOptions($i).'
  680. </select>
  681. </th>';
  682. $html .= '</tr></thead><tbody>';
  683. AdminImportController::setLocale();
  684. for ($current_line = 0; $current_line < 10 && $line = fgetcsv($handle, MAX_LINE_SIZE, $glue); $current_line++)
  685. {
  686. /* UTF-8 conversion */
  687. if (Tools::getValue('convert'))
  688. $line = $this->utf8EncodeArray($line);
  689. $html .= '<tr id="table_'.$current_table.'_line_'.$current_line.'">';
  690. foreach ($line as $nb_c => $column)
  691. if ((MAX_COLUMNS * (int)$current_table <= $nb_c) && ((int)$nb_c < MAX_COLUMNS * ((int)$current_table + 1)))
  692. $html .= '<td>'.htmlentities(Tools::substr($column, 0, 200), ENT_QUOTES, 'UTF-8').'</td>';
  693. $html .= '</tr>';
  694. }
  695. $html .= '</tbody></table>';
  696. AdminImportController::rewindBomAware($handle);
  697. return $html;
  698. }
  699. public function init()
  700. {
  701. parent::init();
  702. if (Tools::isSubmit('submitImportFile'))
  703. $this->display = 'import';
  704. }
  705. public function initContent()
  706. {
  707. $this->initTabModuleList();
  708. // toolbar (save, cancel, new, ..)
  709. $this->initToolbar();
  710. $this->initPageHeaderToolbar();
  711. if ($this->display == 'import')
  712. {
  713. if (Tools::getValue('csv'))
  714. $this->content .= $this->renderView();
  715. else
  716. {
  717. $this->errors[] = $this->l('You must upload a file in order to proceed to the next step');
  718. $this->content .= $this->renderForm();
  719. }
  720. }
  721. else
  722. $this->content .= $this->renderForm();
  723. $this->context->smarty->assign(array(
  724. 'content' => $this->content,
  725. 'url_post' => self::$currentIndex.'&token='.$this->token,
  726. 'show_page_header_toolbar' => $this->show_page_header_toolbar,
  727. 'page_header_toolbar_title' => $this->page_header_toolbar_title,
  728. 'page_header_toolbar_btn' => $this->page_header_toolbar_btn
  729. ));
  730. }
  731. protected static function rewindBomAware($handle)
  732. {
  733. // A rewind wrapper that skips BOM signature wrongly
  734. if (!is_resource($handle))
  735. return false;
  736. rewind($handle);
  737. if (($bom = fread($handle, 3)) != "\xEF\xBB\xBF")
  738. rewind($handle);
  739. }
  740. protected static function getBoolean($field)
  741. {
  742. return (boolean)$field;
  743. }
  744. protected static function getPrice($field)
  745. {
  746. $field = ((float)str_replace(',', '.', $field));
  747. $field = ((float)str_replace('%', '', $field));
  748. return $field;
  749. }
  750. protected static function split($field)
  751. {
  752. if (empty($field))
  753. return array();
  754. $separator = Tools::getValue('multiple_value_separator');
  755. if (is_null($separator) || trim($separator) == '')
  756. $separator = ',';
  757. do $uniqid_path = _PS_UPLOAD_DIR_.uniqid(); while (file_exists($uniqid_path));
  758. file_put_contents($uniqid_path, $field);
  759. $tab = '';
  760. if (!empty($uniqid_path))
  761. {
  762. $fd = fopen($uniqid_path, 'r');
  763. $tab = fgetcsv($fd, MAX_LINE_SIZE, $separator);
  764. fclose($fd);
  765. if (file_exists($uniqid_path))
  766. @unlink($uniqid_path);
  767. }
  768. if (empty($tab) || (!is_array($tab)))
  769. return array();
  770. return $tab;
  771. }
  772. protected static function createMultiLangField($field)
  773. {
  774. $languages = Language::getLanguages(false);
  775. $res = array();
  776. foreach ($languages as $lang)
  777. $res[$lang['id_lang']] = $field;
  778. return $res;
  779. }
  780. protected function getTypeValuesOptions($nb_c)
  781. {
  782. $i = 0;
  783. $no_pre_select = array('price_tin', 'feature');
  784. $options = '';
  785. foreach ($this->available_fields as $k => $field)
  786. {
  787. $options .= '<option value="'.$k.'"';
  788. if ($k === 'price_tin')
  789. ++$nb_c;
  790. if ($i === ($nb_c + 1) && (!in_array($k, $no_pre_select)))
  791. $options .= ' selected="selected"';
  792. $options .= '>'.$field['label'].'</option>';
  793. ++$i;
  794. }
  795. return $options;
  796. }
  797. /*
  798. * Return fields to be display AS piece of advise
  799. *
  800. * @param $in_array boolean
  801. * @return string or return array
  802. */
  803. public function getAvailableFields($in_array = false)
  804. {
  805. $i = 0;
  806. $fields = array();
  807. $keys = array_keys($this->available_fields);
  808. array_shift($keys);
  809. foreach ($this->available_fields as $k => $field)
  810. {
  811. if ($k === 'no')
  812. continue;
  813. if ($k === 'price_tin')
  814. $fields[$i - 1] = '<div>'.$this->available_fields[$keys[$i - 1]]['label'].' '.$this->l('or').' '.$field['label'].'</div>';
  815. else
  816. {
  817. if (isset($field['help']))
  818. $html = '&nbsp;<a href="#" class="help-tooltip" data-toggle="tooltip" title="'.$field['help'].'"><i class="icon-info-sign"></i></a>';
  819. else
  820. $html = '';
  821. $fields[] = '<div>'.$field['label'].$html.'</div>';
  822. }
  823. ++$i;
  824. }
  825. if ($in_array)
  826. return $fields;
  827. else
  828. return implode("\n\r", $fields);
  829. }
  830. protected function receiveTab()
  831. {
  832. $type_value = Tools::getValue('type_value') ? Tools::getValue('type_value') : array();
  833. foreach ($type_value as $nb => $type)
  834. if ($type != 'no')
  835. self::$column_mask[$type] = $nb;
  836. }
  837. public static function getMaskedRow($row)
  838. {
  839. $res = array();
  840. if (is_array(self::$column_mask))
  841. foreach (self::$column_mask as $type => $nb)
  842. $res[$type] = isset($row[$nb]) ? $row[$nb] : null;
  843. return $res;
  844. }
  845. protected static function setDefaultValues(&$info)
  846. {
  847. foreach (self::$default_values as $k => $v)
  848. if (!isset($info[$k]) || $info[$k] == '')
  849. $info[$k] = $v;
  850. }
  851. protected static function setEntityDefaultValues(&$entity)
  852. {
  853. $members = get_object_vars($entity);
  854. foreach (self::$default_values as $k => $v)
  855. if ((array_key_exists($k, $members) && $entity->$k === null) || !array_key_exists($k, $members))
  856. $entity->$k = $v;
  857. }
  858. protected static function fillInfo($infos, $key, &$entity)
  859. {
  860. $infos = trim($infos);
  861. if (isset(self::$validators[$key][1]) && self::$validators[$key][1] == 'createMultiLangField' && Tools::getValue('iso_lang'))
  862. {
  863. $id_lang = Language::getIdByIso(Tools::getValue('iso_lang'));
  864. $tmp = call_user_func(self::$validators[$key], $infos);
  865. foreach ($tmp as $id_lang_tmp => $value)
  866. if (empty($entity->{$key}[$id_lang_tmp]) || $id_lang_tmp == $id_lang)
  867. $entity->{$key}[$id_lang_tmp] = $value;
  868. }
  869. else
  870. if (!empty($infos) || $infos == '0') // ($infos == '0') => if you want to disable a product by using "0" in active because empty('0') return true
  871. $entity->{$key} = isset(self::$validators[$key]) ? call_user_func(self::$validators[$key], $infos) : $infos;
  872. return true;
  873. }
  874. /**
  875. * @param $array
  876. * @param $funcname
  877. * @param mixed $user_data
  878. * @return bool
  879. */
  880. public static function arrayWalk(&$array, $funcname, &$user_data = false)
  881. {
  882. if (!is_callable($funcname)) return false;
  883. foreach ($array as $k => $row)
  884. if (!call_user_func_array($funcname, array($row, $k, $user_data)))
  885. return false;
  886. return true;
  887. }
  888. /**
  889. * copyImg copy an image located in $url and save it in a path
  890. * according to $entity->$id_entity .
  891. * $id_image is used if we need to add a watermark
  892. *
  893. * @param int $id_entity id of product or category (set in entity)
  894. * @param int $id_image (default null) id of the image if watermark enabled.
  895. * @param string $url path or url to use
  896. * @param string entity 'products' or 'categories'
  897. * @return boolean
  898. */
  899. protected static function copyImg($id_entity, $id_image = null, $url, $entity = 'products', $regenerate = true)
  900. {
  901. $tmpfile = tempnam(_PS_TMP_IMG_DIR_, 'ps_import');
  902. $watermark_types = explode(',', Configuration::get('WATERMARK_TYPES'));
  903. switch ($entity)
  904. {
  905. default:
  906. case 'products':
  907. $image_obj = new Image($id_image);
  908. $path = $image_obj->getPathForCreation();
  909. break;
  910. case 'categories':
  911. $path = _PS_CAT_IMG_DIR_.(int)$id_entity;
  912. break;
  913. case 'manufacturers':
  914. $path = _PS_MANU_IMG_DIR_.(int)$id_entity;
  915. break;
  916. case 'suppliers':
  917. $path = _PS_SUPP_IMG_DIR_.(int)$id_entity;
  918. break;
  919. }
  920. $url = str_replace(' ', '%20', trim($url));
  921. // Evaluate the memory required to resize the image: if it's too much, you can't resize it.
  922. if (!ImageManager::checkImageMemoryLimit($url))
  923. return false;
  924. // 'file_exists' doesn't work on distant file, and getimagesize makes the import slower.
  925. // Just hide the warning, the processing will be the same.
  926. if (Tools::copy($url, $tmpfile))
  927. {
  928. ImageManager::resize($tmpfile, $path.'.jpg');
  929. $images_types = ImageType::getImagesTypes($entity);
  930. if ($regenerate)
  931. foreach ($images_types as $image_type)
  932. {
  933. ImageManager::resize($tmpfile, $path.'-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], $image_type['height']);
  934. if (in_array($image_type['id_image_type'], $watermark_types))
  935. Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_entity));
  936. }
  937. }
  938. else
  939. {
  940. unlink($tmpfile);
  941. return false;
  942. }
  943. unlink($tmpfile);
  944. return true;
  945. }
  946. public function categoryImport()
  947. {
  948. $cat_moved = array();
  949. $this->receiveTab();
  950. $handle = $this->openCsvFile();
  951. $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT');
  952. $id_lang = Language::getIdByIso(Tools::getValue('iso_lang'));
  953. if (!Validate::isUnsignedId($id_lang))
  954. $id_lang = $default_language_id;
  955. AdminImportController::setLocale();
  956. for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++)
  957. {
  958. if (Tools::getValue('convert'))
  959. $line = $this->utf8EncodeArray($line);
  960. $info = AdminImportController::getMaskedRow($line);
  961. $tab_categ = array(Configuration::get('PS_HOME_CATEGORY'), Configuration::get('PS_ROOT_CATEGORY'));
  962. if (isset($info['id']) && in_array((int)$info['id'], $tab_categ))
  963. {
  964. $this->errors[] = Tools::displayError('The category ID cannot be the same as the Root category ID or the Home category ID.');
  965. continue;
  966. }
  967. AdminImportController::setDefaultValues($info);
  968. if (Tools::getValue('forceIDs') && isset($info['id']) && (int)$info['id'])
  969. $category = new Category((int)$info['id']);
  970. else
  971. {
  972. if (isset($info['id']) && (int)$info['id'] && Category::existsInDatabase((int)$info['id'], 'category'))
  973. $category = new Category((int)$info['id']);
  974. else
  975. $category = new Category();
  976. }
  977. AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $category);
  978. if (isset($category->parent) && is_numeric($category->parent))
  979. {
  980. if (isset($cat_moved[$category->parent]))
  981. $category->parent = $cat_moved[$category->parent];
  982. $category->id_parent = $category->parent;
  983. }
  984. elseif (isset($category->parent) && is_string($category->parent))
  985. {
  986. $category_parent = Category::searchByName($id_lang, $category->parent, true);
  987. if ($category_parent['id_category'])
  988. {
  989. $category->id_parent = (int)$category_parent['id_category'];
  990. $category->level_depth = (int)$category_parent['level_depth'] + 1;
  991. }
  992. else
  993. {
  994. $category_to_create = new Category();
  995. $category_to_create->name = AdminImportController::createMultiLangField($category->parent);
  996. $category_to_create->active = 1;
  997. $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$id_lang]);
  998. $category_to_create->link_rewrite = AdminImportController::createMultiLangField($category_link_rewrite);
  999. $category_to_create->id_parent = Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create
  1000. if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  1001. ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $category_to_create->add())
  1002. $category->id_parent = $category_to_create->id;
  1003. else
  1004. {
  1005. $this->errors[] = sprintf(
  1006. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  1007. $category_to_create->name[$id_lang],
  1008. (isset($category_to_create->id) && !empty($category_to_create->id))? $category_to_create->id : 'null'
  1009. );
  1010. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  1011. Db::getInstance()->getMsgError();
  1012. }
  1013. }
  1014. }
  1015. if (isset($category->link_rewrite) && !empty($category->link_rewrite[$default_language_id]))
  1016. $valid_link = Validate::isLinkRewrite($category->link_rewrite[$default_language_id]);
  1017. else
  1018. $valid_link = false;
  1019. if (!Shop::isFeatureActive())
  1020. $category->id_shop_default = 1;
  1021. else
  1022. $category->id_shop_default = (int)Context::getContext()->shop->id;
  1023. $bak = $category->link_rewrite[$default_language_id];
  1024. if ((isset($category->link_rewrite) && empty($category->link_rewrite[$default_language_id])) || !$valid_link)
  1025. {
  1026. $category->link_rewrite = Tools::link_rewrite($category->name[$default_language_id]);
  1027. if ($category->link_rewrite == '')
  1028. {
  1029. $category->link_rewrite = 'friendly-url-autogeneration-failed';
  1030. $this->warnings[] = sprintf(Tools::displayError('URL rewriting failed to auto-generate a friendly URL for: %s'), $category->name[$default_language_id]);
  1031. }
  1032. $category->link_rewrite = AdminImportController::createMultiLangField($category->link_rewrite);
  1033. }
  1034. if (!$valid_link)
  1035. $this->warnings[] = sprintf(
  1036. Tools::displayError('Rewrite link for %1$s (ID: %2$s) was re-written as %3$s.'),
  1037. $bak,
  1038. (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null',
  1039. $category->link_rewrite[$default_language_id]
  1040. );
  1041. $res = false;
  1042. if (($field_error = $category->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  1043. ($lang_field_error = $category->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && empty($this->errors))
  1044. {
  1045. $category_already_created = Category::searchByNameAndParentCategoryId(
  1046. $id_lang,
  1047. $category->name[$id_lang],
  1048. $category->id_parent
  1049. );
  1050. // If category already in base, get id category back
  1051. if ($category_already_created['id_category'])
  1052. {
  1053. $cat_moved[$category->id] = (int)$category_already_created['id_category'];
  1054. $category->id = (int)$category_already_created['id_category'];
  1055. }
  1056. if ($category->id && $category->id == $category->id_parent)
  1057. {
  1058. $this->errors[] = Tools::displayError('A category cannot be its own parent');
  1059. continue;
  1060. }
  1061. /* No automatic nTree regeneration for import */
  1062. $category->doNotRegenerateNTree = true;
  1063. // If id category AND id category already in base, trying to update
  1064. $categories_home_root = array(Configuration::get('PS_ROOT_CATEGORY'), Configuration::get('PS_HOME_CATEGORY'));
  1065. if ($category->id && $category->categoryExists($category->id) && !in_array($category->id, $categories_home_root))
  1066. $res = $category->update();
  1067. if ($category->id == Configuration::get('PS_ROOT_CATEGORY'))
  1068. $this->errors[] = Tools::displayError('The root category cannot be modified.');
  1069. // If no id_category or update failed
  1070. $category->force_id = (bool)Tools::getValue('forceIDs');
  1071. if (!$res)
  1072. $res = $category->add();
  1073. }
  1074. //copying images of categories
  1075. if (isset($category->image) && !empty($category->image))
  1076. if (!(AdminImportController::copyImg($category->id, null, $category->image, 'categories', !Tools::getValue('regenerate'))))
  1077. $this->warnings[] = $category->image.' '.Tools::displayError('cannot be copied.');
  1078. // If both failed, mysql error
  1079. if (!$res)
  1080. {
  1081. $this->errors[] = sprintf(
  1082. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  1083. (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name',
  1084. (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID'
  1085. );
  1086. $error_tmp = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').Db::getInstance()->getMsgError();
  1087. if ($error_tmp != '')
  1088. $this->errors[] = $error_tmp;
  1089. }
  1090. else
  1091. {
  1092. // Associate category to shop
  1093. if (Shop::isFeatureActive())
  1094. {
  1095. Db::getInstance()->execute('
  1096. DELETE FROM '._DB_PREFIX_.'category_shop
  1097. WHERE id_category = '.(int)$category->id
  1098. );
  1099. if (!Shop::isFeatureActive())
  1100. $info['shop'] = 1;
  1101. elseif (!isset($info['shop']) || empty($info['shop']))
  1102. $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID());
  1103. // Get shops for each attributes
  1104. $info['shop'] = explode($this->multiple_value_separator, $info['shop']);
  1105. foreach ($info['shop'] as $shop)
  1106. if (!empty($shop) && !is_numeric($shop))
  1107. $category->addShop(Shop::getIdByName($shop));
  1108. elseif (!empty($shop))
  1109. $category->addShop($shop);
  1110. }
  1111. }
  1112. }
  1113. /* Import has finished, we can regenerate the categories nested tree */
  1114. Category::regenerateEntireNtree();
  1115. $this->closeCsvFile($handle);
  1116. }
  1117. public function productImport()
  1118. {
  1119. $this->receiveTab();
  1120. $handle = $this->openCsvFile();
  1121. $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT');
  1122. $id_lang = Language::getIdByIso(Tools::getValue('iso_lang'));
  1123. if (!Validate::isUnsignedId($id_lang))
  1124. $id_lang = $default_language_id;
  1125. AdminImportController::setLocale();
  1126. $shop_ids = Shop::getCompleteListOfShopsID();
  1127. for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++)
  1128. {
  1129. if (Tools::getValue('convert'))
  1130. $line = $this->utf8EncodeArray($line);
  1131. $info = AdminImportController::getMaskedRow($line);
  1132. if (Tools::getValue('forceIDs') && isset($info['id']) && (int)$info['id'])
  1133. $product = new Product((int)$info['id']);
  1134. elseif (Tools::getValue('match_ref') && array_key_exists('reference', $info))
  1135. {
  1136. $datas = Db::getInstance()->getRow('
  1137. SELECT p.`id_product`
  1138. FROM `'._DB_PREFIX_.'product` p
  1139. '.Shop::addSqlAssociation('product', 'p').'
  1140. WHERE p.`reference` = "'.pSQL($info['reference']).'"
  1141. ');
  1142. if (isset($datas['id_product']) && $datas['id_product'])
  1143. $product = new Product((int)$datas['id_product']);
  1144. else
  1145. $product = new Product();
  1146. }
  1147. elseif (array_key_exists('id', $info) && (int)$info['id'] && Product::existsInDatabase((int)$info['id'], 'product'))
  1148. $product = new Product((int)$info['id']);
  1149. else
  1150. $product = new Product();
  1151. if (isset($product->id) && $product->id && Product::existsInDatabase((int)$product->id, 'product'))
  1152. {
  1153. $product->loadStockData();
  1154. $category_data = Product::getProductCategories((int)$product->id);
  1155. foreach ($category_data as $tmp)
  1156. $product->category[] = $tmp;
  1157. }
  1158. AdminImportController::setEntityDefaultValues($product);
  1159. AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $product);
  1160. if (!Shop::isFeatureActive())
  1161. $product->shop = 1;
  1162. elseif (!isset($product->shop) || empty($product->shop))
  1163. $product->shop = implode($this->multiple_value_separator, Shop::getContextListShopID());
  1164. if (!Shop::isFeatureActive())
  1165. $product->id_shop_default = 1;
  1166. else
  1167. $product->id_shop_default = (int)Context::getContext()->shop->id;
  1168. // link product to shops
  1169. $product->id_shop_list = array();
  1170. foreach (explode($this->multiple_value_separator, $product->shop) as $shop)
  1171. if (!empty($shop) && !is_numeric($shop))
  1172. $product->id_shop_list[] = Shop::getIdByName($shop);
  1173. elseif (!empty($shop))
  1174. $product->id_shop_list[] = $shop;
  1175. if ((int)$product->id_tax_rules_group != 0)
  1176. {
  1177. if (Validate::isLoadedObject(new TaxRulesGroup($product->id_tax_rules_group)))
  1178. {
  1179. $address = $this->context->shop->getAddress();
  1180. $tax_manager = TaxManagerFactory::getManager($address, $product->id_tax_rules_group);
  1181. $product_tax_calculator = $tax_manager->getTaxCalculator();
  1182. $product->tax_rate = $product_tax_calculator->getTotalRate();
  1183. }
  1184. else
  1185. $this->addProductWarning(
  1186. 'id_tax_rules_group',
  1187. $product->id_tax_rules_group,
  1188. Tools::displayError('Invalid tax rule group ID. You first need to create a group with this ID.')
  1189. );
  1190. }
  1191. if (isset($product->manufacturer) && is_numeric($product->manufacturer) && Manufacturer::manufacturerExists((int)$product->manufacturer))
  1192. $product->id_manufacturer = (int)$product->manufacturer;
  1193. else if (isset($product->manufacturer) && is_string($product->manufacturer) && !empty($product->manufacturer))
  1194. {
  1195. if ($manufacturer = Manufacturer::getIdByName($product->manufacturer))
  1196. $product->id_manufacturer = (int)$manufacturer;
  1197. else
  1198. {
  1199. $manufacturer = new Manufacturer();
  1200. $manufacturer->name = $product->manufacturer;
  1201. if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  1202. ($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $manufacturer->add())
  1203. $product->id_manufacturer = (int)$manufacturer->id;
  1204. else
  1205. {
  1206. $this->errors[] = sprintf(
  1207. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  1208. $manufacturer->name,
  1209. (isset($manufacturer->id) && !empty($manufacturer->id))? $manufacturer->id : 'null'
  1210. );
  1211. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  1212. Db::getInstance()->getMsgError();
  1213. }
  1214. }
  1215. }
  1216. if (isset($product->supplier) && is_numeric($product->supplier) && Supplier::supplierExists((int)$product->supplier))
  1217. $product->id_supplier = (int)$product->supplier;
  1218. else if (isset($product->supplier) && is_string($product->supplier) && !empty($product->supplier))
  1219. {
  1220. if ($supplier = Supplier::getIdByName($product->supplier))
  1221. $product->id_supplier = (int)$supplier;
  1222. else
  1223. {
  1224. $supplier = new Supplier();
  1225. $supplier->name = $product->supplier;
  1226. $supplier->active = true;
  1227. if (($field_error = $supplier->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  1228. ($lang_field_error = $supplier->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $supplier->add())
  1229. {
  1230. $product->id_supplier = (int)$supplier->id;
  1231. $supplier->associateTo($product->id_shop_list);
  1232. }
  1233. else
  1234. {
  1235. $this->errors[] = sprintf(
  1236. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  1237. $supplier->name,
  1238. (isset($supplier->id) && !empty($supplier->id))? $supplier->id : 'null'
  1239. );
  1240. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  1241. Db::getInstance()->getMsgError();
  1242. }
  1243. }
  1244. }
  1245. if (isset($product->price_tex) && !isset($product->price_tin))
  1246. $product->price = $product->price_tex;
  1247. else if (isset($product->price_tin) && !isset($product->price_tex))
  1248. {
  1249. $product->price = $product->price_tin;
  1250. // If a tax is already included in price, withdraw it from price
  1251. if ($product->tax_rate)
  1252. $product->price = (float)number_format($product->price / (1 + $product->tax_rate / 100), 6, '.', '');
  1253. }
  1254. else if (isset($product->price_tin) && isset($product->price_tex))
  1255. $product->price = $product->price_tex;
  1256. if (isset($product->category) && is_array($product->category) && count($product->category))
  1257. {
  1258. $product->id_category = array(); // Reset default values array
  1259. foreach ($product->category as $value)
  1260. {
  1261. if (is_numeric($value))
  1262. {
  1263. if (Category::categoryExists((int)$value))
  1264. $product->id_category[] = (int)$value;
  1265. else
  1266. {
  1267. $this->errors[] = sprintf(
  1268. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  1269. $category_to_create->name[$default_language_id],
  1270. (isset($category_to_create->id) && !empty($category_to_create->id))? $category_to_create->id : 'null'
  1271. );
  1272. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  1273. Db::getInstance()->getMsgError();
  1274. $category_to_create = new Category();
  1275. $category_to_create->id = (int)$value;
  1276. $category_to_create->name = AdminImportController::createMultiLangField($value);
  1277. $category_to_create->active = 1;
  1278. $category_to_create->id_parent = Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create
  1279. $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$default_language_id]);
  1280. $category_to_create->link_rewrite = AdminImportController::createMultiLangField($category_link_rewrite);
  1281. if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  1282. ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $category_to_create->add())
  1283. $product->id_category[] = (int)$category_to_create->id;
  1284. else
  1285. {
  1286. $this->errors[] = sprintf(
  1287. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  1288. $category_to_create->name[$default_language_id],
  1289. (isset($category_to_create->id) && !empty($category_to_create->id))? $category_to_create->id : 'null'
  1290. );
  1291. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  1292. Db::getInstance()->getMsgError();
  1293. }
  1294. }
  1295. }
  1296. else if (is_string($value) && !empty($value))
  1297. {
  1298. $category = Category::searchByPath($default_language_id, trim($value), $this, 'productImportCreateCat');
  1299. if ($category['id_category'])
  1300. $product->id_category[] = (int)$category['id_category'];
  1301. else
  1302. $this->errors[] = sprintf(Tools::displayError('%1$s cannot be saved'), trim($value));
  1303. }
  1304. }
  1305. }
  1306. $product->id_category_default = isset($product->id_category[0]) ? (int)$product->id_category[0] : '';
  1307. $link_rewrite = (is_array($product->link_rewrite) && isset($product->link_rewrite[$id_lang])) ? trim($product->link_rewrite[$id_lang]) : '';
  1308. $valid_link = Validate::isLinkRewrite($link_rewrite);
  1309. if ((isset($product->link_rewrite[$id_lang]) && empty($product->link_rewrite[$id_lang])) || !$valid_link)
  1310. {
  1311. $link_rewrite = Tools::link_rewrite($product->name[$id_lang]);
  1312. if ($link_rewrite == '')
  1313. $link_rewrite = 'friendly-url-autogeneration-failed';
  1314. }
  1315. if (!$valid_link)
  1316. $this->warnings[] = sprintf(
  1317. Tools::displayError('Rewrite link for %1$s (ID: %2$s) was re-written as %3$s.'),
  1318. $product->name[$id_lang],
  1319. (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null',
  1320. $link_rewrite
  1321. );
  1322. if (!Tools::getValue('match_ref') || !(is_array($product->link_rewrite) && count($product->link_rewrite) && !empty($product->link_rewrite[$id_lang])))
  1323. $product->link_rewrite = AdminImportController::createMultiLangField($link_rewrite);
  1324. // replace the value of separator by coma
  1325. if ($this->multiple_value_separator != ',')
  1326. if (is_array($product->meta_keywords))
  1327. foreach ($product->meta_keywords as &$meta_keyword)
  1328. if (!empty($meta_keyword))
  1329. $meta_keyword = str_replace($this->multiple_value_separator, ',', $meta_keyword);
  1330. // Convert comma into dot for all floating values
  1331. foreach (Product::$definition['fields'] as $key => $array)
  1332. if ($array['type'] == Product::TYPE_FLOAT)
  1333. $product->{$key} = str_replace(',', '.', $product->{$key});
  1334. // Indexation is already 0 if it's a new product, but not if it's an update
  1335. $product->indexed = 0;
  1336. $res = false;
  1337. $field_error = $product->validateFields(UNFRIENDLY_ERROR, true);
  1338. $lang_field_error = $product->validateFieldsLang(UNFRIENDLY_ERROR, true);
  1339. if ($field_error === true && $lang_field_error === true)
  1340. {
  1341. // check quantity
  1342. if ($product->quantity == null)
  1343. $product->quantity = 0;
  1344. // If match ref is specified && ref product && ref product already in base, trying to update
  1345. if (Tools::getValue('match_ref') == 1 && $product->reference && $product->existsRefInDatabase($product->reference))
  1346. {
  1347. $datas = Db::getInstance()->getRow('
  1348. SELECT product_shop.`date_add`, p.`id_product`
  1349. FROM `'._DB_PREFIX_.'product` p
  1350. '.Shop::addSqlAssociation('product', 'p').'
  1351. WHERE p.`reference` = "'.pSQL($product->reference).'"
  1352. ');
  1353. $product->id = (int)$datas['id_product'];
  1354. $product->date_add = pSQL($datas['date_add']);
  1355. $res = $product->update();
  1356. } // Else If id product && id product already in base, trying to update
  1357. else if ($product->id && Product::existsInDatabase((int)$product->id, 'product'))
  1358. {
  1359. $datas = Db::getInstance()->getRow('
  1360. SELECT product_shop.`date_add`
  1361. FROM `'._DB_PREFIX_.'product` p
  1362. '.Shop::addSqlAssociation('product', 'p').'
  1363. WHERE p.`id_product` = '.(int)$product->id);
  1364. $product->date_add = pSQL($datas['date_add']);
  1365. $res = $product->update();
  1366. }
  1367. // If no id_product or update failed
  1368. $product->force_id = (bool)Tools::getValue('forceIDs');
  1369. if (!$res)
  1370. {
  1371. if (isset($product->date_add) && $product->date_add != '')
  1372. $res = $product->add(false);
  1373. else
  1374. $res = $product->add();
  1375. }
  1376. }
  1377. $shops = array();
  1378. $product_shop = explode($this->multiple_value_separator, $product->shop);
  1379. foreach ($product_shop as $shop)
  1380. {
  1381. if (empty($shop))
  1382. continue;
  1383. $shop = trim($shop);
  1384. if (!empty($shop) && !is_numeric($shop))
  1385. $shop = Shop::getIdByName($shop);
  1386. if (in_array($shop, $shop_ids))
  1387. $shops[] = $shop;
  1388. else
  1389. $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Shop is not valid'));
  1390. }
  1391. if (empty($shops))
  1392. $shops = Shop::getContextListShopID();
  1393. // If both failed, mysql error
  1394. if (!$res)
  1395. {
  1396. $this->errors[] = sprintf(
  1397. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  1398. (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name',
  1399. (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID'
  1400. );
  1401. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  1402. Db::getInstance()->getMsgError();
  1403. }
  1404. else
  1405. {
  1406. // Product supplier
  1407. if (isset($product->id) && $product->id && isset($product->id_supplier) && property_exists($product, 'supplier_reference'))
  1408. {
  1409. $id_product_supplier = (int)ProductSupplier::getIdByProductAndSupplier((int)$product->id, 0, (int)$product->id_supplier);
  1410. if ($id_product_supplier)
  1411. $product_supplier = new ProductSupplier($id_product_supplier);
  1412. else
  1413. $product_supplier = new ProductSupplier();
  1414. $product_supplier->id_product = (int)$product->id;
  1415. $product_supplier->id_product_attribute = 0;
  1416. $product_supplier->id_supplier = (int)$product->id_supplier;
  1417. $product_supplier->product_supplier_price_te = $product->wholesale_price;
  1418. $product_supplier->product_supplier_reference = $product->supplier_reference;
  1419. $product_supplier->save();
  1420. }
  1421. // SpecificPrice (only the basic reduction feature is supported by the import)
  1422. if (!Shop::isFeatureActive())
  1423. $info['shop'] = 1;
  1424. elseif (!isset($info['shop']) || empty($info['shop']))
  1425. $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID());
  1426. // Get shops for each attributes
  1427. $info['shop'] = explode($this->multiple_value_separator, $info['shop']);
  1428. $id_shop_list = array();
  1429. foreach ($info['shop'] as $shop)
  1430. if (!empty($shop) && !is_numeric($shop))
  1431. $id_shop_list[] = (int)Shop::getIdByName($shop);
  1432. elseif (!empty($shop))
  1433. $id_shop_list[] = $shop;
  1434. if ((isset($info['reduction_price']) && $info['reduction_price'] > 0) || (isset($info['reduction_percent']) && $info['reduction_percent'] > 0))
  1435. foreach($id_shop_list as $id_shop)
  1436. {
  1437. $specific_price = SpecificPrice::getSpecificPrice($product->id, $id_shop, 0, 0, 0, 1, 0, 0, 0, 0);
  1438. if (is_array($specific_price) && isset($specific_price['id_specific_price']))
  1439. $specific_price = new SpecificPrice((int)$specific_price['id_specific_price']);
  1440. else
  1441. $specific_price = new SpecificPrice();
  1442. $specific_price->id_product = (int)$product->id;
  1443. $specific_price->id_specific_price_rule = 0;
  1444. $specific_price->id_shop = $id_shop;
  1445. $specific_price->id_currency = 0;
  1446. $specific_price->id_country = 0;
  1447. $specific_price->id_group = 0;
  1448. $specific_price->price = -1;
  1449. $specific_price->id_customer = 0;
  1450. $specific_price->from_quantity = 1;
  1451. $specific_price->reduction = (isset($info['reduction_price']) && $info['reduction_price']) ? $info['reduction_price'] : $info['reduction_percent'] / 100;
  1452. $specific_price->reduction_type = (isset($info['reduction_price']) && $info['reduction_price']) ? 'amount' : 'percentage';
  1453. $specific_price->from = (isset($info['reduction_from']) && Validate::isDate($info['reduction_from'])) ? $info['reduction_from'] : '0000-00-00 00:00:00';
  1454. $specific_price->to = (isset($info['reduction_to']) && Validate::isDate($info['reduction_to'])) ? $info['reduction_to'] : '0000-00-00 00:00:00';
  1455. if (!$specific_price->save())
  1456. $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Discount is invalid'));
  1457. }
  1458. if (isset($product->tags) && !empty($product->tags))
  1459. {
  1460. if (isset($product->id) && $product->id)
  1461. {
  1462. $tags = Tag::getProductTags($product->id);
  1463. if (is_array($tags) && count($tags))
  1464. {
  1465. if (!empty($product->tags))
  1466. $product->tags = explode($this->multiple_value_separator, $product->tags);
  1467. if (is_array($product->tags) && count($product->tags))
  1468. {
  1469. foreach ($product->tags as $key => $tag)
  1470. if (!empty($tag))
  1471. $product->tags[$key] = trim($tag);
  1472. $tags[$id_lang] = $product->tags;
  1473. $product->tags = $tags;
  1474. }
  1475. }
  1476. }
  1477. // Delete tags for this id product, for no duplicating error
  1478. Tag::deleteTagsForProduct($product->id);
  1479. if (!is_array($product->tags) && !empty($product->tags))
  1480. {
  1481. $product->tags = AdminImportController::createMultiLangField($product->tags);
  1482. foreach ($product->tags as $key => $tags)
  1483. {
  1484. $is_tag_added = Tag::addTags($key, $product->id, $tags, $this->multiple_value_separator);
  1485. if (!$is_tag_added)
  1486. {
  1487. $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Tags list is invalid'));
  1488. break;
  1489. }
  1490. }
  1491. }
  1492. else
  1493. {
  1494. foreach ($product->tags as $key => $tags)
  1495. {
  1496. $str = '';
  1497. foreach ($tags as $one_tag)
  1498. $str .= $one_tag.$this->multiple_value_separator;
  1499. $str = rtrim($str, $this->multiple_value_separator);
  1500. $is_tag_added = Tag::addTags($key, $product->id, $str, $this->multiple_value_separator);
  1501. if (!$is_tag_added)
  1502. {
  1503. $this->addProductWarning(Tools::safeOutput($info['name']), (int)$product->id, 'Invalid tag(s) ('.$str.')');
  1504. break;
  1505. }
  1506. }
  1507. }
  1508. }
  1509. //delete existing images if "delete_existing_images" is set to 1
  1510. if (isset($product->delete_existing_images))
  1511. if ((bool)$product->delete_existing_images)
  1512. $product->deleteImages();
  1513. else if (isset($product->image) && is_array($product->image) && count($product->image))
  1514. $product->deleteImages();
  1515. if (isset($product->image) && is_array($product->image) && count($product->image))
  1516. {
  1517. $product_has_images = (bool)Image::getImages($this->context->language->id, (int)$product->id);
  1518. foreach ($product->image as $key => $url)
  1519. {
  1520. $url = trim($url);
  1521. $error = false;
  1522. if (!empty($url))
  1523. {
  1524. $url = str_replace(' ', '%20', $url);
  1525. $image = new Image();
  1526. $image->id_product = (int)$product->id;
  1527. $image->position = Image::getHighestPosition($product->id) + 1;
  1528. $image->cover = (!$key && !$product_has_images) ? true : false;
  1529. // file_exists doesn't work with HTTP protocol
  1530. if (($field_error = $image->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  1531. ($lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $image->add())
  1532. {
  1533. // associate image to selected shops
  1534. $image->associateTo($shops);
  1535. if (!AdminImportController::copyImg($product->id, $image->id, $url, 'products', !Tools::getValue('regenerate')))
  1536. {
  1537. $image->delete();
  1538. $this->warnings[] = sprintf(Tools::displayError('Error copying image: %s'), $url);
  1539. }
  1540. }
  1541. else
  1542. $error = true;
  1543. }
  1544. else
  1545. $error = true;
  1546. if ($error)
  1547. $this->warnings[] = sprintf(Tools::displayError('Product #%1$d: the picture (%2$s) cannot be saved.'), $image->id_product, $url);
  1548. }
  1549. }
  1550. if (isset($product->id_category))
  1551. $product->updateCategories(array_map('intval', $product->id_category));
  1552. $product->checkDefaultAttributes();
  1553. if (!$product->cache_default_attribute)
  1554. Product::updateDefaultAttribute($product->id);
  1555. // Features import
  1556. $features = get_object_vars($product);
  1557. if (isset($features['features']) && !empty($features['features']))
  1558. foreach (explode($this->multiple_value_separator, $features['features']) as $single_feature)
  1559. {
  1560. if (empty($single_feature))
  1561. continue;
  1562. $tab_feature = explode(':', $single_feature);
  1563. $feature_name = isset($tab_feature[0]) ? trim($tab_feature[0]) : '';
  1564. $feature_value = isset($tab_feature[1]) ? trim($tab_feature[1]) : '';
  1565. $position = isset($tab_feature[2]) ? (int)$tab_feature[2] - 1 : false;
  1566. $custom = isset($tab_feature[3]) ? (int)$tab_feature[3] : false;
  1567. if(!empty($feature_name) && !empty($feature_value))
  1568. {
  1569. $id_feature = (int)Feature::addFeatureImport($feature_name, $position);
  1570. $id_product = null;
  1571. if (Tools::getValue('forceIDs') || Tools::getValue('match_ref'))
  1572. $id_product = (int)$product->id;
  1573. $id_feature_value = (int)FeatureValue::addFeatureValueImport($id_feature, $feature_value, $id_product, $id_lang, $custom);
  1574. Product::addFeatureProductImport($product->id, $id_feature, $id_feature_value);
  1575. }
  1576. }
  1577. // clean feature positions to avoid conflict
  1578. Feature::cleanPositions();
  1579. // set advanced stock managment
  1580. if (isset($product->advanced_stock_management))
  1581. {
  1582. if ($product->advanced_stock_management != 1 && $product->advanced_stock_management != 0)
  1583. $this->warnings[] = sprintf(Tools::displayError('Advanced stock management has incorrect value. Not set for product %1$s '),$product->name[$default_language_id]);
  1584. elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management == 1)
  1585. $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, can not enable on product %1$s '),$product->name[$default_language_id]);
  1586. else
  1587. $product->setAdvancedStockManagement($product->advanced_stock_management);
  1588. // automaticly disable depends on stock, if a_s_m set to disabled
  1589. if (StockAvailable::dependsOnStock($product->id) == 1 && $product->advanced_stock_management == 0)
  1590. StockAvailable::setProductDependsOnStock($product->id, 0);
  1591. }
  1592. // Check if warehouse exists
  1593. if (isset($product->warehouse) && $product->warehouse)
  1594. {
  1595. if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
  1596. $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, warehouse not set on product %1$s '),$product->name[$default_language_id]);
  1597. else
  1598. {
  1599. if (Warehouse::exists($product->warehouse))
  1600. {
  1601. // Get already associated warehouses
  1602. $associated_warehouses_collection = WarehouseProductLocation::getCollection($product->id);
  1603. // Delete any entry in warehouse for this product
  1604. foreach ($associated_warehouses_collection as $awc)
  1605. $awc->delete();
  1606. $warehouse_location_entity = new WarehouseProductLocation();
  1607. $warehouse_location_entity->id_product = $product->id;
  1608. $warehouse_location_entity->id_product_attribute = 0;
  1609. $warehouse_location_entity->id_warehouse = $product->warehouse;
  1610. if (WarehouseProductLocation::getProductLocation($product->id, 0, $product->warehouse) !== false)
  1611. $warehouse_location_entity->update();
  1612. else
  1613. $warehouse_location_entity->save();
  1614. StockAvailable::synchronize($product->id);
  1615. }
  1616. else
  1617. $this->warnings[] = sprintf(Tools::displayError('Warehouse did not exist, can not set on product %1$s.'),$product->name[$default_language_id]);
  1618. }
  1619. }
  1620. // stock available
  1621. if (isset($product->depends_on_stock))
  1622. {
  1623. if ($product->depends_on_stock != 0 && $product->depends_on_stock != 1)
  1624. $this->warnings[] = sprintf(Tools::displayError('Incorrect value for "depends on stock" for product %1$s '),$product->name[$default_language_id]);
  1625. elseif ((!$product->advanced_stock_management || $product->advanced_stock_management == 0) && $product->depends_on_stock == 1)
  1626. $this->warnings[] = sprintf(Tools::displayError('Advanced stock management not enabled, can not set "depends on stock" for product %1$s '),$product->name[$default_language_id]);
  1627. else
  1628. StockAvailable::setProductDependsOnStock($product->id, $product->depends_on_stock);
  1629. // This code allows us to set qty and disable depends on stock
  1630. if (isset($product->quantity) && $product->depends_on_stock == 0)
  1631. {
  1632. if (Shop::isFeatureActive())
  1633. foreach ($shops as $shop)
  1634. StockAvailable::setQuantity((int)$product->id, 0, $product->quantity, (int)$shop);
  1635. else
  1636. StockAvailable::setQuantity((int)$product->id, 0, $product->quantity, $this->context->shop->id);
  1637. }
  1638. // elseif enable depends on stock and quantity, add quantity to stock
  1639. elseif (isset($product->quantity) && $product->depends_on_stock == 1)
  1640. {
  1641. // add stock
  1642. $stock_manager = StockManagerFactory::getManager();
  1643. $price = str_replace(',', '.', $product->wholesale_price);
  1644. if ($price == 0)
  1645. $price = 0.000001;
  1646. $price = round(floatval($price), 6);
  1647. $warehouse = new Warehouse($product->warehouse);
  1648. if ($stock_manager->addProduct((int)$product->id, 0, $warehouse, $product->quantity, 1, $price, true))
  1649. StockAvailable::synchronize((int)$product->id);
  1650. }
  1651. }
  1652. else // if not depends_on_stock set, use normal qty
  1653. {
  1654. if (Shop::isFeatureActive())
  1655. foreach ($shops as $shop)
  1656. StockAvailable::setQuantity((int)$product->id, 0, $product->quantity, (int)$shop);
  1657. else
  1658. StockAvailable::setQuantity((int)$product->id, 0, $product->quantity, $this->context->shop->id);
  1659. }
  1660. }
  1661. }
  1662. $this->closeCsvFile($handle);
  1663. }
  1664. public function productImportCreateCat($default_language_id, $category_name, $id_parent_category=null)
  1665. {
  1666. $category_to_create = new Category();
  1667. if (!Shop::isFeatureActive())
  1668. $category_to_create->id_shop_default = 1;
  1669. else
  1670. $category_to_create->id_shop_default = (int)Context::getContext()->shop->id;
  1671. $category_to_create->name = AdminImportController::createMultiLangField(trim($category_name));
  1672. $category_to_create->active = 1;
  1673. $category_to_create->id_parent = (int)Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create
  1674. $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$default_language_id]);
  1675. $category_to_create->link_rewrite = AdminImportController::createMultiLangField($category_link_rewrite);
  1676. if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  1677. ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $category_to_create->add())
  1678. $product->id_category[] = (int)$category_to_create->id;
  1679. else
  1680. {
  1681. $this->errors[] = sprintf(
  1682. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  1683. $category_to_create->name[$default_language_id],
  1684. (isset($category_to_create->id) && !empty($category_to_create->id))? $category_to_create->id : 'null'
  1685. );
  1686. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  1687. Db::getInstance()->getMsgError();
  1688. }
  1689. }
  1690. public function attributeImport()
  1691. {
  1692. $default_language = Configuration::get('PS_LANG_DEFAULT');
  1693. $groups = array();
  1694. foreach (AttributeGroup::getAttributesGroups($default_language) as $group)
  1695. $groups[$group['name']] = (int)$group['id_attribute_group'];
  1696. $attributes = array();
  1697. foreach (Attribute::getAttributes($default_language) as $attribute)
  1698. $attributes[$attribute['attribute_group'].'_'.$attribute['name']] = (int)$attribute['id_attribute'];
  1699. $this->receiveTab();
  1700. $handle = $this->openCsvFile();
  1701. AdminImportController::setLocale();
  1702. for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++)
  1703. {
  1704. if (count($line) == 1 && empty($line[0]))
  1705. continue;
  1706. if (Tools::getValue('convert'))
  1707. $line = $this->utf8EncodeArray($line);
  1708. $info = AdminImportController::getMaskedRow($line);
  1709. $info = array_map('trim', $info);
  1710. AdminImportController::setDefaultValues($info);
  1711. if (!Shop::isFeatureActive())
  1712. $info['shop'] = 1;
  1713. elseif (!isset($info['shop']) || empty($info['shop']))
  1714. $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID());
  1715. // Get shops for each attributes
  1716. $info['shop'] = explode($this->multiple_value_separator, $info['shop']);
  1717. $id_shop_list = array();
  1718. if (is_array($info['shop']) && count($info['shop']))
  1719. foreach ($info['shop'] as $shop)
  1720. if (!empty($shop) && !is_numeric($shop))
  1721. $id_shop_list[] = Shop::getIdByName($shop);
  1722. elseif (!empty($shop))
  1723. $id_shop_list[] = $shop;
  1724. if(isset($info['id_product']))
  1725. $product = new Product((int)$info['id_product'], false, $default_language);
  1726. else
  1727. continue;
  1728. $id_image = null;
  1729. //delete existing images if "delete_existing_images" is set to 1
  1730. if (array_key_exists('delete_existing_images', $info) && $info['delete_existing_images'] && !isset($this->cache_image_deleted[(int)$product->id]))
  1731. {
  1732. $product->deleteImages();
  1733. $this->cache_image_deleted[(int)$product->id] = true;
  1734. }
  1735. if (isset($info['image_url']) && $info['image_url'])
  1736. {
  1737. $product_has_images = (bool)Image::getImages($this->context->language->id, $product->id);
  1738. $url = $info['image_url'];
  1739. $image = new Image();
  1740. $image->id_product = (int)$product->id;
  1741. $image->position = Image::getHighestPosition($product->id) + 1;
  1742. $image->cover = (!$product_has_images) ? true : false;
  1743. $field_error = $image->validateFields(UNFRIENDLY_ERROR, true);
  1744. $lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true);
  1745. if ($field_error === true && $lang_field_error === true && $image->add())
  1746. {
  1747. $image->associateTo($id_shop_list);
  1748. if (!AdminImportController::copyImg($product->id, $image->id, $url, 'products', !Tools::getValue('regenerate')))
  1749. {
  1750. $this->warnings[] = sprintf(Tools::displayError('Error copying image: %s'), $url);
  1751. $image->delete();
  1752. }
  1753. else
  1754. $id_image = array($image->id);
  1755. }
  1756. else
  1757. {
  1758. $this->warnings[] = sprintf(
  1759. Tools::displayError('%s cannot be saved'),
  1760. (isset($image->id_product) ? ' ('.$image->id_product.')' : '')
  1761. );
  1762. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').mysql_error();
  1763. }
  1764. }
  1765. elseif (isset($info['image_position']) && $info['image_position'])
  1766. {
  1767. $images = $product->getImages($default_language);
  1768. if ($images)
  1769. foreach ($images as $row)
  1770. if ($row['position'] == (int)$info['image_position'])
  1771. {
  1772. $id_image = array($row['id_image']);
  1773. break;
  1774. }
  1775. if (!$id_image)
  1776. $this->warnings[] = sprintf(
  1777. Tools::displayError('No image was found for combination with id_product = %s and image position = %s.'),
  1778. $product->id,
  1779. (int)$info['image_position']
  1780. );
  1781. }
  1782. $id_attribute_group = 0;
  1783. // groups
  1784. $groups_attributes = array();
  1785. if(isset($info['group']))
  1786. foreach (explode($this->multiple_value_separator, $info['group']) as $key => $group)
  1787. {
  1788. if (empty($group))
  1789. continue;
  1790. $tab_group = explode(':', $group);
  1791. $group = trim($tab_group[0]);
  1792. if (!isset($tab_group[1]))
  1793. $type = 'select';
  1794. else
  1795. $type = trim($tab_group[1]);
  1796. // sets group
  1797. $groups_attributes[$key]['group'] = $group;
  1798. // if position is filled
  1799. if (isset($tab_group[2]))
  1800. $position = trim($tab_group[2]);
  1801. else
  1802. $position = false;
  1803. if (!isset($groups[$group]))
  1804. {
  1805. $obj = new AttributeGroup();
  1806. $obj->is_color_group = false;
  1807. $obj->group_type = pSQL($type);
  1808. $obj->name[$default_language] = $group;
  1809. $obj->public_name[$default_language] = $group;
  1810. $obj->position = (!$position) ? AttributeGroup::getHigherPosition() + 1 : $position;
  1811. if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  1812. ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true)
  1813. {
  1814. $obj->add();
  1815. $obj->associateTo($id_shop_list);
  1816. $groups[$group] = $obj->id;
  1817. }
  1818. else
  1819. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '');
  1820. // fills groups attributes
  1821. $id_attribute_group = $obj->id;
  1822. $groups_attributes[$key]['id'] = $id_attribute_group;
  1823. }
  1824. else // already exists
  1825. {
  1826. $id_attribute_group = $groups[$group];
  1827. $groups_attributes[$key]['id'] = $id_attribute_group;
  1828. }
  1829. }
  1830. // inits attribute
  1831. $id_product_attribute = 0;
  1832. $id_product_attribute_update = false;
  1833. $attributes_to_add = array();
  1834. // for each attribute
  1835. if(isset($info['attribute']))
  1836. foreach (explode($this->multiple_value_separator, $info['attribute']) as $key => $attribute)
  1837. {
  1838. if (empty($attribute))
  1839. continue;
  1840. $tab_attribute = explode(':', $attribute);
  1841. $attribute = trim($tab_attribute[0]);
  1842. // if position is filled
  1843. if (isset($tab_attribute[1]))
  1844. $position = trim($tab_attribute[1]);
  1845. else
  1846. $position = false;
  1847. if (isset($groups_attributes[$key]))
  1848. {
  1849. $group = $groups_attributes[$key]['group'];
  1850. if (!isset($attributes[$group.'_'.$attribute]) && count($groups_attributes[$key]) == 2)
  1851. {
  1852. $id_attribute_group = $groups_attributes[$key]['id'];
  1853. $obj = new Attribute();
  1854. // sets the proper id (corresponding to the right key)
  1855. $obj->id_attribute_group = $groups_attributes[$key]['id'];
  1856. $obj->name[$default_language] = str_replace('\n', '', str_replace('\r', '', $attribute));
  1857. $obj->position = (!$position && isset($groups[$group])) ? Attribute::getHigherPosition($groups[$group]) + 1 : $position;
  1858. if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  1859. ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true)
  1860. {
  1861. $obj->add();
  1862. $obj->associateTo($id_shop_list);
  1863. $attributes[$group.'_'.$attribute] = $obj->id;
  1864. }
  1865. else
  1866. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '');
  1867. }
  1868. $info['minimal_quantity'] = isset($info['minimal_quantity']) && $info['minimal_quantity'] ? (int)$info['minimal_quantity'] : 1;
  1869. $info['wholesale_price'] = str_replace(',', '.', $info['wholesale_price']);
  1870. $info['price'] = str_replace(',', '.', $info['price']);
  1871. $info['ecotax'] = str_replace(',', '.', $info['ecotax']);
  1872. $info['weight'] = str_replace(',', '.', $info['weight']);
  1873. // if a reference is specified for this product, get the associate id_product_attribute to UPDATE
  1874. if (isset($info['reference']) && !empty($info['reference']))
  1875. {
  1876. $id_product_attribute = Combination::getIdByReference($product->id, strval($info['reference']));
  1877. // updates the attribute
  1878. if ($id_product_attribute)
  1879. {
  1880. // gets all the combinations of this product
  1881. $attribute_combinations = $product->getAttributeCombinations($default_language);
  1882. foreach ($attribute_combinations as $attribute_combination)
  1883. {
  1884. if ($id_product_attribute && in_array($id_product_attribute, $attribute_combination))
  1885. {
  1886. $product->updateAttribute(
  1887. $id_product_attribute,
  1888. (float)$info['wholesale_price'],
  1889. (float)$info['price'],
  1890. (float)$info['weight'],
  1891. 0,
  1892. (float)$info['ecotax'],
  1893. $id_image,
  1894. strval($info['reference']),
  1895. strval($info['ean13']),
  1896. (int)$info['default_on'],
  1897. 0,
  1898. strval($info['upc']),
  1899. (int)$info['minimal_quantity'],
  1900. 0,
  1901. null,
  1902. $id_shop_list
  1903. );
  1904. $id_product_attribute_update = true;
  1905. if (isset($info['supplier_reference']) && !empty($info['supplier_reference']))
  1906. $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']);
  1907. }
  1908. }
  1909. }
  1910. }
  1911. // if no attribute reference is specified, creates a new one
  1912. if (!$id_product_attribute)
  1913. {
  1914. $id_product_attribute = $product->addCombinationEntity(
  1915. (float)$info['wholesale_price'],
  1916. (float)$info['price'],
  1917. (float)$info['weight'],
  1918. 0,
  1919. (float)$info['ecotax'],
  1920. (int)$info['quantity'],
  1921. $id_image,
  1922. strval($info['reference']),
  1923. 0,
  1924. strval($info['ean13']),
  1925. (int)$info['default_on'],
  1926. 0,
  1927. strval($info['upc']),
  1928. (int)$info['minimal_quantity'],
  1929. $id_shop_list
  1930. );
  1931. if (isset($info['supplier_reference']) && !empty($info['supplier_reference']))
  1932. $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']);
  1933. }
  1934. // fills our attributes array, in order to add the attributes to the product_attribute afterwards
  1935. if(isset($attributes[$group.'_'.$attribute]))
  1936. $attributes_to_add[] = (int)$attributes[$group.'_'.$attribute];
  1937. // after insertion, we clean attribute position and group attribute position
  1938. $obj = new Attribute();
  1939. $obj->cleanPositions((int)$id_attribute_group, false);
  1940. AttributeGroup::cleanPositions();
  1941. }
  1942. }
  1943. $product->checkDefaultAttributes();
  1944. if (!$product->cache_default_attribute)
  1945. Product::updateDefaultAttribute($product->id);
  1946. if ($id_product_attribute)
  1947. {
  1948. // now adds the attributes in the attribute_combination table
  1949. if ($id_product_attribute_update)
  1950. {
  1951. Db::getInstance()->execute('
  1952. DELETE FROM '._DB_PREFIX_.'product_attribute_combination
  1953. WHERE id_product_attribute = '.(int)$id_product_attribute);
  1954. }
  1955. foreach ($attributes_to_add as $attribute_to_add)
  1956. {
  1957. Db::getInstance()->execute('
  1958. INSERT IGNORE INTO '._DB_PREFIX_.'product_attribute_combination (id_attribute, id_product_attribute)
  1959. VALUES ('.(int)$attribute_to_add.','.(int)$id_product_attribute.')');
  1960. }
  1961. // set advanced stock managment
  1962. if (isset($info['advanced_stock_management']))
  1963. {
  1964. if ($info['advanced_stock_management'] != 1 && $info['advanced_stock_management'] != 0)
  1965. $this->warnings[] = sprintf(Tools::displayError('Advanced stock management has incorrect value. Not set for product with id %s.'),$product->id);
  1966. elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $info['advanced_stock_management'] == 1)
  1967. $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, can not enable on product with id %s.'),$product->id);
  1968. else
  1969. $product->setAdvancedStockManagement($info['advanced_stock_management']);
  1970. // automaticly disable depends on stock, if a_s_m set to disabled
  1971. if (StockAvailable::dependsOnStock($product->id) == 1 && $info['advanced_stock_management'] == 0)
  1972. StockAvailable::setProductDependsOnStock($product->id, 0,null,$id_product_attribute);
  1973. }
  1974. // Check if warehouse exists
  1975. if (isset($info['warehouse']) && $info['warehouse'])
  1976. {
  1977. if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
  1978. $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, warehouse is not set on product with id %s.'),$product->id);
  1979. else
  1980. {
  1981. if (Warehouse::exists($info['warehouse']))
  1982. {
  1983. $warehouse_location_entity = new WarehouseProductLocation();
  1984. $warehouse_location_entity->id_product = $product->id;
  1985. $warehouse_location_entity->id_product_attribute = $id_product_attribute;
  1986. $warehouse_location_entity->id_warehouse = $info['warehouse'];
  1987. if (WarehouseProductLocation::getProductLocation($product->id, $id_product_attribute, $info['warehouse']) !== false)
  1988. $warehouse_location_entity->update();
  1989. else
  1990. $warehouse_location_entity->save();
  1991. StockAvailable::synchronize($product->id);
  1992. }
  1993. else
  1994. $this->warnings[] = sprintf(Tools::displayError('Warehouse did not exist, cannot set on product %1$s.'),$product->name[$default_language_id]);
  1995. }
  1996. }
  1997. // stock available
  1998. if (isset($info['depends_on_stock']))
  1999. {
  2000. if ($info['depends_on_stock'] != 0 && $info['depends_on_stock'] != 1)
  2001. $this->warnings[] = sprintf(Tools::displayError('Incorrect value for depends on stock for product %1$s '),$product->name[$default_language_id]);
  2002. elseif ((!$info['advanced_stock_management'] || $info['advanced_stock_management'] == 0) && $info['depends_on_stock'] == 1)
  2003. $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, cannot set depends on stock %1$s '),$product->name[$default_language_id]);
  2004. else
  2005. StockAvailable::setProductDependsOnStock($product->id, $info['depends_on_stock'],null,$id_product_attribute);
  2006. // This code allows us to set qty and disable depends on stock
  2007. if (isset($info['quantity']) && $info['depends_on_stock'] == 0)
  2008. {
  2009. if (Shop::isFeatureActive())
  2010. foreach ($shops as $shop)
  2011. StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], (int)$shop);
  2012. else
  2013. StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], $this->context->shop->id);
  2014. }
  2015. // elseif enable depends on stock and quantity, add quantity to stock
  2016. elseif (isset($info['quantity']) && $info['depends_on_stock'] == 1)
  2017. {
  2018. // add stock
  2019. $stock_manager = StockManagerFactory::getManager();
  2020. $price = str_replace(',', '.', $info['wholesale_price']);
  2021. if ($price == 0)
  2022. $price = 0.000001;
  2023. $price = round(floatval($price), 6);
  2024. $warehouse = new Warehouse($info['warehouse']);
  2025. if ($stock_manager->addProduct((int)$product->id, $id_product_attribute, $warehouse, (int)$info['quantity'], 1, $price, true))
  2026. StockAvailable::synchronize((int)$product->id);
  2027. }
  2028. }
  2029. // if not depends_on_stock set, use normal qty
  2030. else
  2031. {
  2032. if (Shop::isFeatureActive())
  2033. foreach ($shops as $shop)
  2034. StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], (int)$shop);
  2035. else
  2036. StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], $this->context->shop->id);
  2037. }
  2038. }
  2039. }
  2040. $this->closeCsvFile($handle);
  2041. }
  2042. public function customerImport()
  2043. {
  2044. $customer_exist = false;
  2045. $this->receiveTab();
  2046. $handle = $this->openCsvFile();
  2047. $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT');
  2048. $id_lang = Language::getIdByIso(Tools::getValue('iso_lang'));
  2049. if (!Validate::isUnsignedId($id_lang))
  2050. $id_lang = $default_language_id;
  2051. AdminImportController::setLocale();
  2052. for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++)
  2053. {
  2054. if (Tools::getValue('convert'))
  2055. $line = $this->utf8EncodeArray($line);
  2056. $info = AdminImportController::getMaskedRow($line);
  2057. AdminImportController::setDefaultValues($info);
  2058. if (Tools::getValue('forceIDs') && isset($info['id']) && (int)$info['id'])
  2059. $customer = new Customer((int)$info['id']);
  2060. else
  2061. {
  2062. if (array_key_exists('id', $info) && (int)$info['id'] && Customer::customerIdExistsStatic((int)$info['id']))
  2063. $customer = new Customer((int)$info['id']);
  2064. else
  2065. $customer = new Customer();
  2066. }
  2067. if (array_key_exists('id', $info) && (int)$info['id'] && Customer::customerIdExistsStatic((int)$info['id']))
  2068. {
  2069. $current_id_customer = $customer->id;
  2070. $current_id_shop = $customer->id_shop;
  2071. $current_id_shop_group = $customer->id_shop_group;
  2072. $customer_exist = true;
  2073. $customer_groups = $customer->getGroups();
  2074. $addresses = $customer->getAddresses((int)Configuration::get('PS_LANG_DEFAULT'));
  2075. }
  2076. // Group Importation
  2077. if (isset($info['group']) && !empty($info['group']))
  2078. {
  2079. foreach (explode($this->multiple_value_separator, $info['group']) as $key => $group)
  2080. {
  2081. $group = trim($group);
  2082. if(empty($group))
  2083. continue;
  2084. $id_group = false;
  2085. if (is_numeric($group) && $group)
  2086. {
  2087. $myGroup = new Group((int)$group);
  2088. if (Validate::isLoadedObject($myGroup))
  2089. $customer_groups[] = (int)$group;
  2090. continue;
  2091. }
  2092. $myGroup = Group::searchByName($group);
  2093. if (isset($myGroup['id_group']) && $myGroup['id_group'])
  2094. $id_group = (int)$myGroup['id_group'];
  2095. if (!$id_group)
  2096. {
  2097. $myGroup = new Group();
  2098. $myGroup->name = Array($id_lang => $group);
  2099. if ($id_lang != $default_language_id)
  2100. $myGroup->name = $myGroup->name + array($default_language_id => $group);
  2101. $myGroup->price_display_method = 1;
  2102. $myGroup->add();
  2103. if (Validate::isLoadedObject($myGroup))
  2104. $id_group = (int)$myGroup->id;
  2105. }
  2106. if ($id_group)
  2107. $customer_groups[] = (int)$id_group;
  2108. }
  2109. }
  2110. elseif(empty($info['group']) && isset($customer->id) && $customer->id)
  2111. $customer_groups = array(0 => Configuration::get('PS_CUSTOMER_GROUP'));
  2112. AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $customer);
  2113. if ($customer->passwd)
  2114. $customer->passwd = Tools::encrypt($customer->passwd);
  2115. $id_shop_list = explode($this->multiple_value_separator, $customer->id_shop);
  2116. $customers_shop = array();
  2117. $customers_shop['shared'] = array();
  2118. $default_shop = new Shop((int)Configuration::get('PS_SHOP_DEFAULT'));
  2119. if (Shop::isFeatureActive() && $id_shop_list)
  2120. {
  2121. foreach ($id_shop_list as $id_shop)
  2122. {
  2123. if (empty($id_shop))
  2124. continue;
  2125. $shop = new Shop((int)$id_shop);
  2126. $group_shop = $shop->getGroup();
  2127. if ($group_shop->share_customer)
  2128. {
  2129. if (!in_array($group_shop->id, $customers_shop['shared']))
  2130. $customers_shop['shared'][(int)$id_shop] = $group_shop->id;
  2131. }
  2132. else
  2133. $customers_shop[(int)$id_shop] = $group_shop->id;
  2134. }
  2135. }
  2136. else
  2137. {
  2138. $default_shop = new Shop((int)Configuration::get('PS_SHOP_DEFAULT'));
  2139. $default_shop->getGroup();
  2140. $customers_shop[$default_shop->id] = $default_shop->getGroup()->id;
  2141. }
  2142. //set temporally for validate field
  2143. $customer->id_shop = $default_shop->id;
  2144. $customer->id_shop_group = $default_shop->getGroup()->id;
  2145. if (isset($info['id_default_group']) && !empty($info['id_default_group']) && !is_numeric($info['id_default_group']))
  2146. {
  2147. $info['id_default_group'] = trim($info['id_default_group']);
  2148. $myGroup = Group::searchByName($info['id_default_group']);
  2149. if (isset($myGroup['id_group']) && $myGroup['id_group'])
  2150. $info['id_default_group'] = (int)$myGroup['id_group'];
  2151. }
  2152. $myGroup = new Group($customer->id_default_group);
  2153. if (!Validate::isLoadedObject($myGroup))
  2154. $customer->id_default_group = (int)Configuration::get('PS_CUSTOMER_GROUP');
  2155. $customer_groups[] = (int)$customer->id_default_group;
  2156. $customer_groups = array_flip(array_flip($customer_groups));
  2157. $res = true;
  2158. if (($field_error = $customer->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  2159. ($lang_field_error = $customer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true)
  2160. {
  2161. foreach ($customers_shop as $id_shop => $id_group)
  2162. {
  2163. $customer->force_id = (bool)Tools::getValue('forceIDs');
  2164. if ($id_shop == 'shared')
  2165. {
  2166. foreach ($id_group as $key => $id)
  2167. {
  2168. $customer->id_shop = (int)$key;
  2169. $customer->id_shop_group = (int)$id;
  2170. if ($customer_exist && ($current_id_shop_group == $id || in_array($current_id_shop, ShopGroup::getShopsFromGroup($id))))
  2171. {
  2172. $customer->id = $current_id_customer;
  2173. $res &= $customer->update();
  2174. }
  2175. else
  2176. {
  2177. $res &= $customer->add();
  2178. if (isset($addresses))
  2179. foreach ($addresses as $address)
  2180. {
  2181. $address['id_customer'] = $customer->id;
  2182. unset($address['country'], $address['state'], $address['state_iso'], $address['id_address'] );
  2183. Db::getInstance()->insert('address', $address);
  2184. }
  2185. }
  2186. if ($res && isset($customer_groups))
  2187. $customer->updateGroup($customer_groups);
  2188. }
  2189. }
  2190. else
  2191. {
  2192. $customer->id_shop = $id_shop;
  2193. $customer->id_shop_group = $id_group;
  2194. if ($customer_exist && $id_shop == $current_id_shop)
  2195. {
  2196. $customer->id = $current_id_customer;
  2197. $res &= $customer->update();
  2198. }
  2199. else
  2200. {
  2201. $res &= $customer->add();
  2202. if (isset($addresses))
  2203. foreach ($addresses as $address)
  2204. {
  2205. $address['id_customer'] = $customer->id;
  2206. unset($address['country'], $address['state'], $address['state_iso'], $address['id_address']);
  2207. Db::getInstance()->insert('address', $address);
  2208. }
  2209. }
  2210. if ($res && isset($customer_groups))
  2211. $customer->updateGroup($customer_groups);
  2212. }
  2213. }
  2214. }
  2215. unset($customer_groups);
  2216. $customer_exist = false;
  2217. if (!$res)
  2218. {
  2219. $this->errors[] = sprintf(
  2220. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  2221. $info['email'],
  2222. (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null'
  2223. );
  2224. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  2225. Db::getInstance()->getMsgError();
  2226. }
  2227. }
  2228. $this->closeCsvFile($handle);
  2229. }
  2230. public function addressImport()
  2231. {
  2232. $this->receiveTab();
  2233. $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT');
  2234. $handle = $this->openCsvFile();
  2235. AdminImportController::setLocale();
  2236. for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++)
  2237. {
  2238. if (Tools::getValue('convert'))
  2239. $line = $this->utf8EncodeArray($line);
  2240. $info = AdminImportController::getMaskedRow($line);
  2241. AdminImportController::setDefaultValues($info);
  2242. $address = new Address();
  2243. AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $address);
  2244. if (isset($address->country) && is_numeric($address->country))
  2245. {
  2246. if (Country::getNameById(Configuration::get('PS_LANG_DEFAULT'), (int)$address->country))
  2247. $address->id_country = (int)$address->country;
  2248. }
  2249. else if (isset($address->country) && is_string($address->country) && !empty($address->country))
  2250. {
  2251. if ($id_country = Country::getIdByName(null, $address->country))
  2252. $address->id_country = (int)$id_country;
  2253. else
  2254. {
  2255. $country = new Country();
  2256. $country->active = 1;
  2257. $country->name = AdminImportController::createMultiLangField($address->country);
  2258. $country->id_zone = 0; // Default zone for country to create
  2259. $country->iso_code = Tools::strtoupper(Tools::substr($address->country, 0, 2)); // Default iso for country to create
  2260. $country->contains_states = 0; // Default value for country to create
  2261. $lang_field_error = $country->validateFieldsLang(UNFRIENDLY_ERROR, true);
  2262. if (($field_error = $country->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  2263. ($lang_field_error = $country->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $country->add())
  2264. $address->id_country = (int)$country->id;
  2265. else
  2266. {
  2267. $this->errors[] = sprintf(Tools::displayError('%s cannot be saved'), $country->name[$default_language_id]);
  2268. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  2269. Db::getInstance()->getMsgError();
  2270. }
  2271. }
  2272. }
  2273. if (isset($address->state) && is_numeric($address->state))
  2274. {
  2275. if (State::getNameById((int)$address->state))
  2276. $address->id_state = (int)$address->state;
  2277. }
  2278. else if (isset($address->state) && is_string($address->state) && !empty($address->state))
  2279. {
  2280. if ($id_state = State::getIdByName($address->state))
  2281. $address->id_state = (int)$id_state;
  2282. else
  2283. {
  2284. $state = new State();
  2285. $state->active = 1;
  2286. $state->name = $address->state;
  2287. $state->id_country = isset($country->id) ? (int)$country->id : 0;
  2288. $state->id_zone = 0; // Default zone for state to create
  2289. $state->iso_code = Tools::strtoupper(Tools::substr($address->state, 0, 2)); // Default iso for state to create
  2290. $state->tax_behavior = 0;
  2291. if (($field_error = $state->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  2292. ($lang_field_error = $state->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $state->add())
  2293. $address->id_state = (int)$state->id;
  2294. else
  2295. {
  2296. $this->errors[] = sprintf(Tools::displayError('%s cannot be saved'), $state->name);
  2297. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  2298. Db::getInstance()->getMsgError();
  2299. }
  2300. }
  2301. }
  2302. if (isset($address->customer_email) && !empty($address->customer_email))
  2303. {
  2304. if (Validate::isEmail($address->customer_email))
  2305. {
  2306. // a customer could exists in different shop
  2307. $customer_list = Customer::getCustomersByEmail($address->customer_email);
  2308. if (count($customer_list) == 0)
  2309. $this->errors[] = sprintf(
  2310. Tools::displayError('%1$s does not exist in database %2$s (ID: %3$s), and therefore cannot be saved.'),
  2311. Db::getInstance()->getMsgError(),
  2312. $address->customer_email,
  2313. (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null'
  2314. );
  2315. }
  2316. else
  2317. {
  2318. $this->errors[] = sprintf(Tools::displayError('"%s" is not a valid email address.'), $address->customer_email);
  2319. continue;
  2320. }
  2321. }
  2322. elseif (isset($address->id_customer) && !empty($address->id_customer))
  2323. {
  2324. if (Customer::customerIdExistsStatic((int)$address->id_customer))
  2325. {
  2326. $customer = new Customer((int)$address->id_customer);
  2327. // a customer could exists in different shop
  2328. $customer_list = Customer::getCustomersByEmail($customer->email);
  2329. if (count($customer_list) == 0)
  2330. $this->errors[] = sprintf(
  2331. Tools::displayError('%1$s does not exist in database %2$s (ID: %3$s), and therefore cannot be saved.'),
  2332. Db::getInstance()->getMsgError(),
  2333. $customer->email,
  2334. (int)$address->id_customer
  2335. );
  2336. }
  2337. else
  2338. $this->errors[] = sprintf(Tools::displayError('The customer ID #%d does not exist in the database, and therefore cannot be saved.'), $address->id_customer);
  2339. }
  2340. else
  2341. {
  2342. $customer_list = array();
  2343. $address->id_customer = 0;
  2344. }
  2345. if (isset($address->manufacturer) && is_numeric($address->manufacturer) && Manufacturer::manufacturerExists((int)$address->manufacturer))
  2346. $address->id_manufacturer = (int)$address->manufacturer;
  2347. else if (isset($address->manufacturer) && is_string($address->manufacturer) && !empty($address->manufacturer))
  2348. {
  2349. $manufacturer = new Manufacturer();
  2350. $manufacturer->name = $address->manufacturer;
  2351. if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  2352. ($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $manufacturer->add())
  2353. $address->id_manufacturer = (int)$manufacturer->id;
  2354. else
  2355. {
  2356. $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf(
  2357. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  2358. $manufacturer->name,
  2359. (isset($manufacturer->id) && !empty($manufacturer->id))? $manufacturer->id : 'null'
  2360. );
  2361. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  2362. Db::getInstance()->getMsgError();
  2363. }
  2364. }
  2365. if (isset($address->supplier) && is_numeric($address->supplier) && Supplier::supplierExists((int)$address->supplier))
  2366. $address->id_supplier = (int)$address->supplier;
  2367. else if (isset($address->supplier) && is_string($address->supplier) && !empty($address->supplier))
  2368. {
  2369. $supplier = new Supplier();
  2370. $supplier->name = $address->supplier;
  2371. if (($field_error = $supplier->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  2372. ($lang_field_error = $supplier->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $supplier->add())
  2373. $address->id_supplier = (int)$supplier->id;
  2374. else
  2375. {
  2376. $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf(
  2377. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  2378. $supplier->name,
  2379. (isset($supplier->id) && !empty($supplier->id))? $supplier->id : 'null'
  2380. );
  2381. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  2382. Db::getInstance()->getMsgError();
  2383. }
  2384. }
  2385. $res = false;
  2386. if (($field_error = $address->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  2387. ($lang_field_error = $address->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true)
  2388. {
  2389. if (isset($customer_list) && count($customer_list) > 0)
  2390. {
  2391. $filter_list = array();
  2392. foreach ($customer_list as $customer)
  2393. {
  2394. if (in_array($customer['id_customer'], $filter_list))
  2395. continue;
  2396. $filter_list[] = $customer['id_customer'];
  2397. unset($address->id);
  2398. $address->id_customer = $customer['id_customer'];
  2399. $res = $address->add();
  2400. if (!$res)
  2401. $this->errors[] = sprintf(
  2402. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  2403. $info['alias'],
  2404. (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null'
  2405. );
  2406. }
  2407. }
  2408. else
  2409. {
  2410. $address->force_id = (bool)Tools::getValue('forceIDs');
  2411. if ($address->id && $address->addressExists($address->id))
  2412. $res = $address->update();
  2413. if (!$res)
  2414. $res = $address->add();
  2415. }
  2416. }
  2417. if (!$res)
  2418. {
  2419. $this->errors[] = sprintf(
  2420. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  2421. $info['alias'],
  2422. (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null'
  2423. );
  2424. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  2425. Db::getInstance()->getMsgError();
  2426. }
  2427. }
  2428. $this->closeCsvFile($handle);
  2429. }
  2430. public function manufacturerImport()
  2431. {
  2432. $this->receiveTab();
  2433. $handle = $this->openCsvFile();
  2434. AdminImportController::setLocale();
  2435. for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++)
  2436. {
  2437. if (Tools::getValue('convert'))
  2438. $line = $this->utf8EncodeArray($line);
  2439. $info = AdminImportController::getMaskedRow($line);
  2440. AdminImportController::setDefaultValues($info);
  2441. if (Tools::getValue('forceIDs') && isset($info['id']) && (int)$info['id'])
  2442. $manufacturer = new Manufacturer((int)$info['id']);
  2443. else
  2444. {
  2445. if (array_key_exists('id', $info) && (int)$info['id'] && Manufacturer::existsInDatabase((int)$info['id'], 'manufacturer'))
  2446. $manufacturer = new Manufacturer((int)$info['id']);
  2447. else
  2448. $manufacturer = new Manufacturer();
  2449. }
  2450. AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $manufacturer);
  2451. $res = false;
  2452. if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  2453. ($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true)
  2454. {
  2455. if ($manufacturer->id && $manufacturer->manufacturerExists($manufacturer->id))
  2456. $res = $manufacturer->update();
  2457. $manufacturer->force_id = (bool)Tools::getValue('forceIDs');
  2458. if (!$res)
  2459. $res = $manufacturer->add();
  2460. //copying images of manufacturer
  2461. if (isset($manufacturer->image) && !empty($manufacturer->image))
  2462. if (!AdminImportController::copyImg($manufacturer->id, null, $manufacturer->image, 'manufacturers', !Tools::getValue('regenerate')))
  2463. $this->warnings[] = $manufacturer->image.' '.Tools::displayError('cannot be copied.');
  2464. if ($res)
  2465. {
  2466. // Associate supplier to group shop
  2467. if (Shop::isFeatureActive() && $manufacturer->shop)
  2468. {
  2469. Db::getInstance()->execute('
  2470. DELETE FROM '._DB_PREFIX_.'manufacturer_shop
  2471. WHERE id_manufacturer = '.(int)$manufacturer->id
  2472. );
  2473. $manufacturer->shop = explode($this->multiple_value_separator, $manufacturer->shop);
  2474. $shops = array();
  2475. foreach ($manufacturer->shop as $shop)
  2476. {
  2477. if (empty($shop))
  2478. continue;
  2479. $shop = trim($shop);
  2480. if (!is_numeric($shop))
  2481. $shop = ShopGroup::getIdByName($shop);
  2482. $shops[] = $shop;
  2483. }
  2484. $manufacturer->associateTo($shops);
  2485. }
  2486. }
  2487. }
  2488. if (!$res)
  2489. {
  2490. $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf(
  2491. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  2492. (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name',
  2493. (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID'
  2494. );
  2495. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').
  2496. Db::getInstance()->getMsgError();
  2497. }
  2498. }
  2499. $this->closeCsvFile($handle);
  2500. }
  2501. public function supplierImport()
  2502. {
  2503. $this->receiveTab();
  2504. $handle = $this->openCsvFile();
  2505. AdminImportController::setLocale();
  2506. for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++)
  2507. {
  2508. if (Tools::getValue('convert'))
  2509. $line = $this->utf8EncodeArray($line);
  2510. $info = AdminImportController::getMaskedRow($line);
  2511. AdminImportController::setDefaultValues($info);
  2512. if (Tools::getValue('forceIDs') && isset($info['id']) && (int)$info['id'])
  2513. $supplier = new Supplier((int)$info['id']);
  2514. else
  2515. {
  2516. if (array_key_exists('id', $info) && (int)$info['id'] && Supplier::existsInDatabase((int)$info['id'], 'supplier'))
  2517. $supplier = new Supplier((int)$info['id']);
  2518. else
  2519. $supplier = new Supplier();
  2520. }
  2521. AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $supplier);
  2522. if (($field_error = $supplier->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  2523. ($lang_field_error = $supplier->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true)
  2524. {
  2525. $res = false;
  2526. if ($supplier->id && $supplier->supplierExists($supplier->id))
  2527. $res = $supplier->update();
  2528. $supplier->force_id = (bool)Tools::getValue('forceIDs');
  2529. if (!$res)
  2530. $res = $supplier->add();
  2531. //copying images of suppliers
  2532. if (isset($supplier->image) && !empty($supplier->image))
  2533. if (!AdminImportController::copyImg($supplier->id, null, $supplier->image, 'suppliers', !Tools::getValue('regenerate')))
  2534. $this->warnings[] = $supplier->image.' '.Tools::displayError('cannot be copied.');
  2535. if (!$res)
  2536. $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf(
  2537. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  2538. (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name',
  2539. (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID'
  2540. );
  2541. else
  2542. {
  2543. // Associate supplier to group shop
  2544. if (Shop::isFeatureActive() && $supplier->shop)
  2545. {
  2546. Db::getInstance()->execute('
  2547. DELETE FROM '._DB_PREFIX_.'supplier_shop
  2548. WHERE id_supplier = '.(int)$supplier->id
  2549. );
  2550. $supplier->shop = explode($this->multiple_value_separator, $supplier->shop);
  2551. $shops = array();
  2552. foreach ($supplier->shop as $shop)
  2553. {
  2554. if (empty($shop))
  2555. continue;
  2556. $shop = trim($shop);
  2557. if (!is_numeric($shop))
  2558. $shop = ShopGroup::getIdByName($shop);
  2559. $shops[] = $shop;
  2560. }
  2561. $supplier->associateTo($shops);
  2562. }
  2563. }
  2564. }
  2565. else
  2566. {
  2567. $this->errors[] = $this->l('Supplier is invalid').' ('.$supplier->name.')';
  2568. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '');
  2569. }
  2570. }
  2571. $this->closeCsvFile($handle);
  2572. }
  2573. public function aliasImport()
  2574. {
  2575. $this->receiveTab();
  2576. $handle = $this->openCsvFile();
  2577. AdminImportController::setLocale();
  2578. for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++)
  2579. {
  2580. if (Tools::getValue('convert'))
  2581. $line = $this->utf8EncodeArray($line);
  2582. $info = AdminImportController::getMaskedRow($line);
  2583. AdminImportController::setDefaultValues($info);
  2584. if (Tools::getValue('forceIDs') && isset($info['id']) && (int)$info['id'])
  2585. $alias = new Alias((int)$info['id']);
  2586. else
  2587. {
  2588. if (array_key_exists('id', $info) && (int)$info['id'] && Alias::existsInDatabase((int)$info['id'], 'alias'))
  2589. $alias = new Alias((int)$info['id']);
  2590. else
  2591. $alias = new Alias();
  2592. }
  2593. AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $alias);
  2594. $res = false;
  2595. if (($field_error = $alias->validateFields(UNFRIENDLY_ERROR, true)) === true &&
  2596. ($lang_field_error = $alias->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true)
  2597. {
  2598. if ($alias->id && $alias->aliasExists($alias->id))
  2599. $res = $alias->update();
  2600. $alias->force_id = (bool)Tools::getValue('forceIDs');
  2601. if (!$res)
  2602. $res = $alias->add();
  2603. if (!$res)
  2604. $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf(
  2605. Tools::displayError('%1$s (ID: %2$s) cannot be saved'),
  2606. $info['name'],
  2607. (isset($info['id']) ? $info['id'] : 'null')
  2608. );
  2609. }
  2610. else
  2611. {
  2612. $this->errors[] = $this->l('Alias is invalid').' ('.$alias->name.')';
  2613. $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '');
  2614. }
  2615. }
  2616. $this->closeCsvFile($handle);
  2617. }
  2618. /**
  2619. * @since 1.5.0
  2620. */
  2621. public function supplyOrdersImport()
  2622. {
  2623. // opens CSV & sets locale
  2624. $this->receiveTab();
  2625. $handle = $this->openCsvFile();
  2626. AdminImportController::setLocale();
  2627. // main loop, for each supply orders to import
  2628. for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); ++$current_line)
  2629. {
  2630. // if convert requested
  2631. if (Tools::getValue('convert'))
  2632. $line = $this->utf8EncodeArray($line);
  2633. $info = AdminImportController::getMaskedRow($line);
  2634. // sets default values if needed
  2635. AdminImportController::setDefaultValues($info);
  2636. // if an id is set, instanciates a supply order with this id if possible
  2637. if (array_key_exists('id', $info) && (int)$info['id'] && SupplyOrder::exists((int)$info['id']))
  2638. $supply_order = new SupplyOrder((int)$info['id']);
  2639. // if a reference is set, instanciates a supply order with this reference if possible
  2640. else if (array_key_exists('reference', $info) && $info['reference'] && SupplyOrder::exists(pSQL($info['reference'])))
  2641. $supply_order = SupplyOrder::getSupplyOrderByReference(pSQL($info['reference']));
  2642. else // new supply order
  2643. $supply_order = new SupplyOrder();
  2644. // gets parameters
  2645. $id_supplier = (int)$info['id_supplier'];
  2646. $id_lang = (int)$info['id_lang'];
  2647. $id_warehouse = (int)$info['id_warehouse'];
  2648. $id_currency = (int)$info['id_currency'];
  2649. $reference = pSQL($info['reference']);
  2650. $date_delivery_expected = pSQL($info['date_delivery_expected']);
  2651. $discount_rate = (float)$info['discount_rate'];
  2652. $is_template = (bool)$info['is_template'];
  2653. $error = '';
  2654. // checks parameters
  2655. if (!Supplier::supplierExists($id_supplier))
  2656. $error = sprintf($this->l('Supplier ID (%d) is not valid (at line %d).'), $id_supplier, $current_line + 1);
  2657. if (!Language::getLanguage($id_lang))
  2658. $error = sprintf($this->l('Lang ID (%d) is not valid (at line %d).'), $id_lang, $current_line + 1);
  2659. if (!Warehouse::exists($id_warehouse))
  2660. $error = sprintf($this->l('Warehouse ID (%d) is not valid (at line %d).'), $id_warehouse, $current_line + 1);
  2661. if (!Currency::getCurrency($id_currency))
  2662. $error = sprintf($this->l('Currency ID (%d) is not valid (at line %d).'), $id_currency, $current_line + 1);
  2663. if (empty($supply_order->reference) && SupplyOrder::exists($reference))
  2664. $error = sprintf($this->l('Reference (%s) already exists (at line %d).'), $reference, $current_line + 1);
  2665. if (!empty($supply_order->reference) && ($supply_order->reference != $reference && SupplyOrder::exists($reference)))
  2666. $error = sprintf($this->l('Reference (%s) already exists (at line %d).'), $reference, $current_line + 1);
  2667. if (!Validate::isDateFormat($date_delivery_expected))
  2668. $error = sprintf($this->l('Date (%s) is not valid (at line %d). Format: %s.'), $date_delivery_expected, $current_line + 1, $this->l('YYYY-MM-DD'));
  2669. else if (new DateTime($date_delivery_expected) <= new DateTime('yesterday'))
  2670. $error = sprintf($this->l('Date (%s) cannot be in the past (at line %d). Format: %s.'), $date_delivery_expected, $current_line + 1, $this->l('YYYY-MM-DD'));
  2671. if ($discount_rate < 0 || $discount_rate > 100)
  2672. $error = sprintf($this->l('Discount rate (%d) is not valid (at line %d). %s.'), $discount_rate, $current_line + 1, $this->l('Format: Between 0 and 100'));
  2673. if ($supply_order->id > 0 && !$supply_order->isEditable())
  2674. $error = sprintf($this->l('Supply Order (%d) is not editable (at line %d).'), $supply_order->id, $current_line + 1);
  2675. // if no errors, sets supply order
  2676. if (empty($error))
  2677. {
  2678. // adds parameters
  2679. $info['id_ref_currency'] = (int)Currency::getDefaultCurrency()->id;
  2680. $info['supplier_name'] = pSQL(Supplier::getNameById($id_supplier));
  2681. if ($supply_order->id > 0)
  2682. {
  2683. $info['id_supply_order_state'] = (int)$supply_order->id_supply_order_state;
  2684. $info['id'] = (int)$supply_order->id;
  2685. }
  2686. else
  2687. $info['id_supply_order_state'] = 1;
  2688. // sets parameters
  2689. AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $supply_order);
  2690. // updatesd($supply_order);
  2691. $res = true;
  2692. if ((int)$supply_order->id && ($supply_order->exists((int)$supply_order->id) || $supply_order->exists($supply_order->reference)))
  2693. $res &= $supply_order->update();
  2694. else
  2695. {
  2696. $supply_order->force_id = (bool)Tools::getValue('forceIDs');
  2697. $res &= $supply_order->add();
  2698. }
  2699. // errors
  2700. if (!$res)
  2701. $this->errors[] = sprintf($this->l('Supply Order could not be saved (at line %d).'), $current_line + 1);
  2702. }
  2703. else
  2704. $this->errors[] = $error;
  2705. }
  2706. // closes
  2707. $this->closeCsvFile($handle);
  2708. }
  2709. public function supplyOrdersDetailsImport()
  2710. {
  2711. // opens CSV & sets locale
  2712. $this->receiveTab();
  2713. $handle = $this->openCsvFile();
  2714. AdminImportController::setLocale();
  2715. $products = array();
  2716. $reset = true;
  2717. // main loop, for each supply orders details to import
  2718. for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); ++$current_line)
  2719. {
  2720. // if convert requested
  2721. if (Tools::getValue('convert'))
  2722. $line = $this->utf8EncodeArray($line);
  2723. $info = AdminImportController::getMaskedRow($line);
  2724. // sets default values if needed
  2725. AdminImportController::setDefaultValues($info);
  2726. // gets the supply order
  2727. if (array_key_exists('supply_order_reference', $info) && pSQL($info['supply_order_reference']) && SupplyOrder::exists(pSQL($info['supply_order_reference'])))
  2728. $supply_order = SupplyOrder::getSupplyOrderByReference(pSQL($info['supply_order_reference']));
  2729. else
  2730. $this->errors[] = sprintf($this->l('Supply Order (%s) could not be loaded (at line %d).'), (int)$info['supply_order_reference'], $current_line + 1);
  2731. if (empty($this->errors))
  2732. {
  2733. // sets parameters
  2734. $id_product = (int)$info['id_product'];
  2735. if (!$info['id_product_attribute'])
  2736. $info['id_product_attribute'] = 0;
  2737. $id_product_attribute = (int)$info['id_product_attribute'];
  2738. $unit_price_te = (float)$info['unit_price_te'];
  2739. $quantity_expected = (int)$info['quantity_expected'];
  2740. $discount_rate = (float)$info['discount_rate'];
  2741. $tax_rate = (float)$info['tax_rate'];
  2742. // checks if one product/attribute is there only once
  2743. if (isset($products[$id_product][$id_product_attribute]))
  2744. $this->errors[] = sprintf($this->l('Product/Attribute (%d/%d) cannot be added twice (at line %d).'), $id_product,
  2745. $id_product_attribute, $current_line + 1);
  2746. else
  2747. $products[$id_product][$id_product_attribute] = $quantity_expected;
  2748. // checks parameters
  2749. if (false === ($supplier_reference = ProductSupplier::getProductSupplierReference($id_product, $id_product_attribute, $supply_order->id_supplier)))
  2750. $this->errors[] = sprintf($this->l('Product (%d/%d) is not available for this order (at line %d).'), $id_product,
  2751. $id_product_attribute, $current_line + 1);
  2752. if ($unit_price_te < 0)
  2753. $this->errors[] = sprintf($this->l('Unit Price (tax excl.) (%d) is not valid (at line %d).'), $unit_price_te, $current_line + 1);
  2754. if ($quantity_expected < 0)
  2755. $this->errors[] = sprintf($this->l('Quantity Expected (%d) is not valid (at line %d).'), $quantity_expected, $current_line + 1);
  2756. if ($discount_rate < 0 || $discount_rate > 100)
  2757. $this->errors[] = sprintf($this->l('Discount rate (%d) is not valid (at line %d). %s.'), $discount_rate,
  2758. $current_line + 1, $this->l('Format: Between 0 and 100'));
  2759. if ($tax_rate < 0 || $tax_rate > 100)
  2760. $this->errors[] = sprintf($this->l('Quantity Expected (%d) is not valid (at line %d).'), $tax_rate,
  2761. $current_line + 1, $this->l('Format: Between 0 and 100'));
  2762. // if no errors, sets supply order details
  2763. if (empty($this->errors))
  2764. {
  2765. // resets order if needed
  2766. if ($reset)
  2767. {
  2768. $supply_order->resetProducts();
  2769. $reset = false;
  2770. }
  2771. // creates new product
  2772. $supply_order_detail = new SupplyOrderDetail();
  2773. AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $supply_order_detail);
  2774. // sets parameters
  2775. $supply_order_detail->id_supply_order = $supply_order->id;
  2776. $currency = new Currency($supply_order->id_ref_currency);
  2777. $supply_order_detail->id_currency = $currency->id;
  2778. $supply_order_detail->exchange_rate = $currency->conversion_rate;
  2779. $supply_order_detail->supplier_reference = $supplier_reference;
  2780. $supply_order_detail->name = Product::getProductName($id_product, $id_product_attribute, $supply_order->id_lang);
  2781. // gets ean13 / ref / upc
  2782. $query = new DbQuery();
  2783. $query->select('
  2784. IFNULL(pa.reference, IFNULL(p.reference, \'\')) as reference,
  2785. IFNULL(pa.ean13, IFNULL(p.ean13, \'\')) as ean13,
  2786. IFNULL(pa.upc, IFNULL(p.upc, \'\')) as upc
  2787. ');
  2788. $query->from('product', 'p');
  2789. $query->leftJoin('product_attribute', 'pa', 'pa.id_product = p.id_product AND id_product_attribute = '.(int)$id_product_attribute);
  2790. $query->where('p.id_product = '.(int)$id_product);
  2791. $query->where('p.is_virtual = 0 AND p.cache_is_pack = 0');
  2792. $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query);
  2793. $product_infos = $res['0'];
  2794. $supply_order_detail->reference = $product_infos['reference'];
  2795. $supply_order_detail->ean13 = $product_infos['ean13'];
  2796. $supply_order_detail->upc = $product_infos['upc'];
  2797. $supply_order_detail->force_id = (bool)Tools::getValue('forceIDs');
  2798. $supply_order_detail->add();
  2799. $supply_order->update();
  2800. unset($supply_order_detail);
  2801. }
  2802. }
  2803. }
  2804. // closes
  2805. $this->closeCsvFile($handle);
  2806. }
  2807. public function utf8EncodeArray($array)
  2808. {
  2809. return (is_array($array) ? array_map('utf8_encode', $array) : utf8_encode($array));
  2810. }
  2811. protected function getNbrColumn($handle, $glue)
  2812. {
  2813. if (!is_resource($handle))
  2814. return false;
  2815. $tmp = fgetcsv($handle, MAX_LINE_SIZE, $glue);
  2816. AdminImportController::rewindBomAware($handle);
  2817. return count($tmp);
  2818. }
  2819. protected static function usortFiles($a, $b)
  2820. {
  2821. if ($a == $b)
  2822. return 0;
  2823. return ($b < $a) ? 1 : -1;
  2824. }
  2825. protected function openCsvFile()
  2826. {
  2827. $file = AdminImportController::getPath(strval(preg_replace('/\.{2,}/', '.', Tools::getValue('csv'))));
  2828. $handle = false;
  2829. if (is_file($file) && is_readable($file))
  2830. $handle = fopen($file, 'r');
  2831. if (!$handle)
  2832. $this->errors[] = Tools::displayError('Cannot read the .CSV file');
  2833. AdminImportController::rewindBomAware($handle);
  2834. for ($i = 0; $i < (int)Tools::getValue('skip'); ++$i)
  2835. $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator);
  2836. return $handle;
  2837. }
  2838. protected function closeCsvFile($handle)
  2839. {
  2840. fclose($handle);
  2841. }
  2842. protected function truncateTables($case)
  2843. {
  2844. switch ((int)$case)
  2845. {
  2846. case $this->entities[$this->l('Categories')]:
  2847. Db::getInstance()->execute('
  2848. DELETE FROM `'._DB_PREFIX_.'category`
  2849. WHERE id_category NOT IN ('.(int)Configuration::get('PS_HOME_CATEGORY').
  2850. ', '.(int)Configuration::get('PS_ROOT_CATEGORY').')');
  2851. Db::getInstance()->execute('
  2852. DELETE FROM `'._DB_PREFIX_.'category_lang`
  2853. WHERE id_category NOT IN ('.(int)Configuration::get('PS_HOME_CATEGORY').
  2854. ', '.(int)Configuration::get('PS_ROOT_CATEGORY').')');
  2855. Db::getInstance()->execute('
  2856. DELETE FROM `'._DB_PREFIX_.'category_shop`
  2857. WHERE `id_category` NOT IN ('.(int)Configuration::get('PS_HOME_CATEGORY').
  2858. ', '.(int)Configuration::get('PS_ROOT_CATEGORY').')');
  2859. Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'category` AUTO_INCREMENT = 3');
  2860. foreach (scandir(_PS_CAT_IMG_DIR_) as $d)
  2861. if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d))
  2862. unlink(_PS_CAT_IMG_DIR_.$d);
  2863. break;
  2864. case $this->entities[$this->l('Products')]:
  2865. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product`');
  2866. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_shop`');
  2867. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'feature_product`');
  2868. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_lang`');
  2869. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'category_product`');
  2870. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_tag`');
  2871. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'image`');
  2872. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'image_lang`');
  2873. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'image_shop`');
  2874. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'specific_price`');
  2875. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'specific_price_priority`');
  2876. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_carrier`');
  2877. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'cart_product`');
  2878. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'compare_product`');
  2879. if (count(Db::getInstance()->executeS('SHOW TABLES LIKE \''._DB_PREFIX_.'favorite_product\' '))) //check if table exist
  2880. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'favorite_product`');
  2881. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attachment`');
  2882. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_country_tax`');
  2883. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_download`');
  2884. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_group_reduction_cache`');
  2885. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_sale`');
  2886. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_supplier`');
  2887. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'scene_products`');
  2888. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'warehouse_product_location`');
  2889. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'stock`');
  2890. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'stock_available`');
  2891. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'stock_mvt`');
  2892. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customization`');
  2893. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customization_field`');
  2894. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supply_order_detail`');
  2895. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_impact`');
  2896. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute`');
  2897. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_shop`');
  2898. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_combination`');
  2899. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_image`');
  2900. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'pack`');
  2901. Image::deleteAllImages(_PS_PROD_IMG_DIR_);
  2902. if (!file_exists(_PS_PROD_IMG_DIR_))
  2903. mkdir(_PS_PROD_IMG_DIR_);
  2904. break;
  2905. case $this->entities[$this->l('Combinations')]:
  2906. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute`');
  2907. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_impact`');
  2908. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_lang`');
  2909. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_group`');
  2910. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_group_lang`');
  2911. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_group_shop`');
  2912. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_shop`');
  2913. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute`');
  2914. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_shop`');
  2915. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_combination`');
  2916. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_image`');
  2917. Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'stock_available` WHERE id_product_attribute != 0');
  2918. break;
  2919. case $this->entities[$this->l('Customers')]:
  2920. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customer`');
  2921. break;
  2922. case $this->entities[$this->l('Addresses')]:
  2923. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'address`');
  2924. break;
  2925. case $this->entities[$this->l('Manufacturers')]:
  2926. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'manufacturer`');
  2927. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'manufacturer_lang`');
  2928. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'manufacturer_shop`');
  2929. foreach (scandir(_PS_MANU_IMG_DIR_) as $d)
  2930. if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d))
  2931. unlink(_PS_MANU_IMG_DIR_.$d);
  2932. break;
  2933. case $this->entities[$this->l('Suppliers')]:
  2934. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supplier`');
  2935. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supplier_lang`');
  2936. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supplier_shop`');
  2937. foreach (scandir(_PS_SUPP_IMG_DIR_) as $d)
  2938. if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d))
  2939. unlink(_PS_SUPP_IMG_DIR_.$d);
  2940. break;
  2941. case $this->entities[$this->l('Alias')]:
  2942. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'alias`');
  2943. break;
  2944. }
  2945. Image::clearTmpDir();
  2946. return true;
  2947. }
  2948. public function clearSmartyCache()
  2949. {
  2950. Tools::enableCache();
  2951. Tools::clearCache($this->context->smarty);
  2952. Tools::restoreCacheSettings();
  2953. }
  2954. public function postProcess()
  2955. {
  2956. /* PrestaShop demo mode */
  2957. if (_PS_MODE_DEMO_)
  2958. {
  2959. $this->errors[] = Tools::displayError('This functionality has been disabled.');
  2960. return;
  2961. }
  2962. if (Tools::isSubmit('import'))
  2963. {
  2964. // Check if the CSV file exist
  2965. if (Tools::getValue('csv'))
  2966. {
  2967. // If i am a superadmin, i can truncate table
  2968. if (((Shop::isFeatureActive() && $this->context->employee->isSuperAdmin()) || !Shop::isFeatureActive()) && Tools::getValue('truncate'))
  2969. $this->truncateTables((int)Tools::getValue('entity'));
  2970. $import_type = false;
  2971. switch ((int)Tools::getValue('entity'))
  2972. {
  2973. case $this->entities[$import_type = $this->l('Categories')]:
  2974. $this->categoryImport();
  2975. $this->clearSmartyCache();
  2976. break;
  2977. case $this->entities[$import_type = $this->l('Products')]:
  2978. $this->productImport();
  2979. $this->clearSmartyCache();
  2980. break;
  2981. case $this->entities[$import_type = $this->l('Customers')]:
  2982. $this->customerImport();
  2983. break;
  2984. case $this->entities[$import_type = $this->l('Addresses')]:
  2985. $this->addressImport();
  2986. break;
  2987. case $this->entities[$import_type = $this->l('Combinations')]:
  2988. $this->attributeImport();
  2989. $this->clearSmartyCache();
  2990. break;
  2991. case $this->entities[$import_type = $this->l('Manufacturers')]:
  2992. $this->manufacturerImport();
  2993. $this->clearSmartyCache();
  2994. break;
  2995. case $this->entities[$import_type = $this->l('Suppliers')]:
  2996. $this->supplierImport();
  2997. $this->clearSmartyCache();
  2998. break;
  2999. case $this->entities[$import_type = $this->l('Alias')]:
  3000. $this->aliasImport();
  3001. break;
  3002. }
  3003. // @since 1.5.0
  3004. if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
  3005. switch ((int)Tools::getValue('entity'))
  3006. {
  3007. case $this->entities[$import_type = $this->l('Supply Orders')]:
  3008. if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
  3009. $this->supplyOrdersImport();
  3010. break;
  3011. case $this->entities[$import_type = $this->l('Supply Order Details')]:
  3012. if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
  3013. $this->supplyOrdersDetailsImport();
  3014. break;
  3015. }
  3016. if ($import_type !== false)
  3017. {
  3018. $log_message = sprintf($this->l('%s import', 'AdminTab', false, false), $import_type);
  3019. if (Tools::getValue('truncate'))
  3020. $log_message .= ' '.$this->l('with truncate', 'AdminTab', false, false);
  3021. PrestaShopLogger::addLog($log_message, 1, null, $import_type, null, true, (int)$this->context->employee->id);
  3022. }
  3023. }
  3024. else
  3025. $this->errors[] = $this->l('You must upload a file in order to proceed to the next step');
  3026. }
  3027. elseif ($filename = Tools::getValue('csvfilename'))
  3028. {
  3029. $filename = urldecode($filename);
  3030. $file = AdminImportController::getPath(basename($filename));
  3031. if (realpath(dirname($file)) != realpath(AdminImportController::getPath()))
  3032. exit();
  3033. if (!empty($filename))
  3034. {
  3035. $bName = basename($filename);
  3036. if (Tools::getValue('delete') && file_exists($file))
  3037. @unlink($file);
  3038. elseif (file_exists($file))
  3039. {
  3040. $bName = explode('.', $bName);
  3041. $bName = strtolower($bName[count($bName) - 1]);
  3042. $mimeTypes = array('csv' => 'text/csv');
  3043. if (isset($mimeTypes[$bName]))
  3044. $mimeType = $mimeTypes[$bName];
  3045. else
  3046. $mimeType = 'application/octet-stream';
  3047. if (ob_get_level() && ob_get_length() > 0)
  3048. ob_end_clean();
  3049. header('Content-Transfer-Encoding: binary');
  3050. header('Content-Type: '.$mimeType);
  3051. header('Content-Length: '.filesize($file));
  3052. header('Content-Disposition: attachment; filename="'.$filename.'"');
  3053. $fp = fopen($file, 'rb');
  3054. while (is_resource($fp) && !feof($fp))
  3055. echo fgets($fp, 16384);
  3056. exit;
  3057. }
  3058. }
  3059. }
  3060. return parent::postProcess();
  3061. }
  3062. public static function setLocale()
  3063. {
  3064. $iso_lang = trim(Tools::getValue('iso_lang'));
  3065. setlocale(LC_COLLATE, strtolower($iso_lang).'_'.strtoupper($iso_lang).'.UTF-8');
  3066. setlocale(LC_CTYPE, strtolower($iso_lang).'_'.strtoupper($iso_lang).'.UTF-8');
  3067. }
  3068. protected function addProductWarning($product_name, $product_id = null, $message = '')
  3069. {
  3070. $this->warnings[] = $product_name.(isset($product_id) ? ' (ID '.$product_id.')' : '').' '
  3071. .Tools::displayError($message);
  3072. }
  3073. public function ajaxProcessSaveImportMatchs()
  3074. {
  3075. if ($this->tabAccess['edit'] === '1')
  3076. {
  3077. $match = implode('|', Tools::getValue('type_value'));
  3078. Db::getInstance()->execute('INSERT IGNORE INTO `'._DB_PREFIX_.'import_match` (
  3079. `id_import_match` ,
  3080. `name` ,
  3081. `match`,
  3082. `skip`
  3083. )
  3084. VALUES (
  3085. NULL ,
  3086. \''.pSQL(Tools::getValue('newImportMatchs')).'\',
  3087. \''.pSQL($match).'\',
  3088. \''.pSQL(Tools::getValue('skip')).'\'
  3089. )');
  3090. die('{"id" : "'.Db::getInstance()->Insert_ID().'"}');
  3091. }
  3092. }
  3093. public function ajaxProcessLoadImportMatchs()
  3094. {
  3095. if ($this->tabAccess['edit'] === '1')
  3096. {
  3097. $return = Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'import_match` WHERE `id_import_match` = '
  3098. .(int)Tools::getValue('idImportMatchs'));
  3099. die('{"id" : "'.$return[0]['id_import_match'].'", "matchs" : "'.$return[0]['match'].'", "skip" : "'
  3100. .$return[0]['skip'].'"}');
  3101. }
  3102. }
  3103. public function ajaxProcessDeleteImportMatchs()
  3104. {
  3105. if ($this->tabAccess['edit'] === '1')
  3106. {
  3107. Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'import_match` WHERE `id_import_match` = '
  3108. .(int)Tools::getValue('idImportMatchs'));
  3109. die;
  3110. }
  3111. }
  3112. public static function getPath($file = '')
  3113. {
  3114. return (defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).DIRECTORY_SEPARATOR.'import'
  3115. .DIRECTORY_SEPARATOR.$file;
  3116. }
  3117. }