PageRenderTime 53ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/shopimporter/shopimporter.php

https://bitbucket.org/marcenuc/prestashop
PHP | 1506 lines | 1363 code | 72 blank | 71 comment | 229 complexity | bc544b36d103f7b97e4833eb6be5685b MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0
  1. <?php
  2. /*
  3. * 2007-2012 PrestaShop
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Academic Free License (AFL 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/afl-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-2012 PrestaShop SA
  23. * @version Release: $Revision$
  24. * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
  25. * International Registered Trademark & Property of PrestaShop SA
  26. */
  27. if (!defined('_PS_VERSION_'))
  28. exit;
  29. class shopimporter extends ImportModule
  30. {
  31. public $supportedImports = array();
  32. public function __construct()
  33. {
  34. $this->name = 'shopimporter';
  35. $this->tab = 'migration_tools';
  36. $this->version = '1.0';
  37. $this->author = 'PrestaShop';
  38. $this->need_instance = 0;
  39. $this->is_configurable = 1;
  40. parent::__construct ();
  41. $this->displayName = $this->l('Shop Importer');
  42. $this->description = $this->l('This module allows you to import your shop from another system into Prestashop.');
  43. $this->supportedImports = array(
  44. 'language' => array('methodName' => 'getLangagues',
  45. 'name' => $this->l('Language'),
  46. 'className' => 'Language',
  47. 'label' => $this->l('Import Languages'),
  48. 'table' => 'lang',
  49. 'identifier' => 'id_lang',
  50. 'alterTable' => array('id_lang' => 'int(10)'),
  51. 'info' => $this->l('New languages will automatically add translations.'),
  52. 'defaultId' => 'PS_LANG_DEFAULT'
  53. ),
  54. 'currency' => array('methodName' => 'getCurrencies',
  55. 'name' => $this->l('Currency'),
  56. 'className' => 'Currency',
  57. 'label' => $this->l('Import Currencies'),
  58. 'table' => 'currency',
  59. 'identifier' => 'id_currency',
  60. 'alterTable' => array('id_currency' => 'int(10)'),
  61. 'delete' => true,
  62. 'defaultId' => 'PS_CURRENCY_DEFAULT'
  63. ),
  64. /*
  65. 'tax' => array('methodName' => 'getTaxes',
  66. 'name' => $this->l('Taxes'),
  67. 'className' => 'Tax',
  68. 'label' => $this->l('Import Taxes'),
  69. 'table' => 'tax',
  70. 'identifier' => 'id_tax',
  71. 'alterTable' => array('id_tax' => 'int(10)'),
  72. 'delete' => true
  73. ),
  74. 'tax_rule' => array('methodName' => 'getTaxes rules',
  75. 'name' => $this->l('Taxes rules'),
  76. 'className' => 'TaxRule',
  77. 'label' => $this->l('Import Taxes Rules'),
  78. 'table' => 'tax_rules_group',
  79. 'identifier' => 'id_tax',
  80. 'alterTable' => array('id_tax_rules_group' => 'int(10)'),
  81. 'delete' => true
  82. ),
  83. */
  84. 'zone' => array('methodName' => 'getZones',
  85. 'name' => $this->l('Zone'),
  86. 'className' => 'Zone',
  87. 'label' => $this->l('Import Zones'),
  88. 'table' => 'zone',
  89. 'identifier' => 'id_zone',
  90. 'alterTable' => array('id_zone' => 'int(10)'),
  91. 'delete' => true
  92. ),
  93. 'country' => array('methodName' => 'getCountries',
  94. 'name' => $this->l('Country'),
  95. 'className' => 'Country',
  96. 'label' => $this->l('Import Countries'),
  97. 'table' => 'country',
  98. 'identifier' => 'id_country',
  99. 'foreign_key' => array('id_zone', 'id_currency'),
  100. 'alterTable' => array('id_country' => 'int(10)'),
  101. 'delete' => true,
  102. 'defaultId' => 'PS_COUNTRY_DEFAULT'
  103. ),
  104. 'state' => array('methodName' => 'getStates',
  105. 'name' => $this->l('State'),
  106. 'className' => 'State',
  107. 'label' => $this->l('Import States'),
  108. 'table' => 'state',
  109. 'identifier' => 'id_state',
  110. 'foreign_key' => array('id_zone', 'id_country'),
  111. 'alterTable' => array('id_state' => 'int(10)'),
  112. 'delete' => true
  113. ),
  114. 'group' => array('methodName' => 'getGroups',
  115. 'name' => $this->l('Group'),
  116. 'className' => 'Group',
  117. 'label' => $this->l('Import Groups'),
  118. 'table' => 'group',
  119. 'identifier' => 'id_group',
  120. 'alterTable' => array('id_group' => 'int(10)'),
  121. 'delete' => true,
  122. ),
  123. 'customer' => array('methodName' => 'getCustomers',
  124. 'name' => $this->l('Customer'),
  125. 'className' => 'Customer',
  126. 'label' => $this->l('Import Customers'),
  127. 'table' => 'customer',
  128. 'identifier' => 'id_customer',
  129. 'foreign_key' => array('id_group'),
  130. 'alterTable' => array('id_customer' => 'int(10)', 'passwd' => 'varchar(100)'),
  131. 'delete' => true,
  132. 'association' => array(
  133. array(
  134. 'table' => 'customer_group',
  135. 'fields' => array('id_customer', 'id_group'),
  136. 'matchTable' => array('customer', 'group'),
  137. )
  138. )
  139. ),
  140. 'address' => array('methodName' => 'getAddresses',
  141. 'name' => $this->l('Address'),
  142. 'className' => 'Address',
  143. 'label' => $this->l('Import Addresses'),
  144. 'table' => 'address',
  145. 'identifier' => 'id_address',
  146. 'foreign_key' => array('id_country', 'id_state', 'id_customer'),
  147. 'alterTable' => array('id_address' => 'int(10)'),
  148. 'delete' => true
  149. ),
  150. 'manufacturer' => array('methodName' => 'getManufacturers',
  151. 'name' => $this->l('Manufacturer'),
  152. 'className' => 'Manufacturer',
  153. 'label' => $this->l('Import Manufacturers'),
  154. 'table' => 'manufacturer',
  155. 'identifier' => 'id_manufacturer',
  156. 'delete' => true,
  157. 'alterTable' => array('id_manufacturer' => 'int(10)'),
  158. 'hasImage' => true
  159. ),
  160. 'supplier' => array('methodName' => 'getSuppliers',
  161. 'name' => $this->l('Supplier'),
  162. 'className' => 'Supplier',
  163. 'label' => $this->l('Import Suppliers'),
  164. 'table' => 'supplier',
  165. 'identifier' => 'id_supplier',
  166. 'delete' => true,
  167. 'alterTable' => array('id_supplier' => 'int(10)'),
  168. 'hasImage' => true
  169. ),
  170. 'category' => array('methodName' => 'getCategories',
  171. 'name' => $this->l('Category'),
  172. 'className' => 'Category',
  173. 'label' => $this->l('Import Categories'),
  174. 'table' => 'category',
  175. 'identifier' => 'id_category',
  176. 'alterTable' => array('id_category' => 'int(10)'),
  177. 'delete' => true,
  178. 'hasImage' => true,
  179. ),
  180. 'attributegroup' => array('methodName' => 'getAttributesGroups',
  181. 'name' => $this->l('AttributeGroup'),
  182. 'className' => 'AttributeGroup',
  183. 'label' => $this->l('Import Attributes Groups'),
  184. 'table' => 'attribute_group',
  185. 'identifier' => 'id_attribute_group',
  186. 'alterTable' => array('id_attribute_group' => 'int(10)'),
  187. 'delete' => true
  188. ),
  189. 'attribute' => array('methodName' => 'getAttributes',
  190. 'name' => $this->l('Attribute'),
  191. 'className' => 'Attribute',
  192. 'label' => $this->l('Import Attributes'),
  193. 'table' => 'attribute',
  194. 'identifier' => 'id_attribute',
  195. 'alterTable' => array('id_attribute' => 'int(10)'),
  196. 'foreign_key' => array('id_attribute_group'),
  197. 'delete' => true
  198. ),
  199. 'product' => array('methodName' => 'getProducts',
  200. 'name' => $this->l('Product'),
  201. 'className' => 'Product',
  202. 'label' => $this->l('Import Products'),
  203. 'table' => 'product',
  204. 'identifier' => 'id_product',
  205. 'alterTable' => array('id_product' => 'int(10)'),
  206. 'foreign_key' => array('id_category', 'id_manufacturer'),
  207. 'delete' => true,
  208. 'association' => array(
  209. array(
  210. 'table' => 'category_product',
  211. 'fields' => array('id_category', 'id_product'),
  212. 'matchTable' => array('category', 'product')
  213. )
  214. ),
  215. 'hasImage' => true
  216. ),
  217. 'combination' => array('methodName' => 'getProductsCombination',
  218. 'name' => $this->l('Combination'),
  219. 'className' => 'Combination',
  220. 'label' => $this->l('Import Products Combinations'),
  221. 'table' => 'product_attribute',
  222. 'identifier' => 'id_product_attribute',
  223. 'alterTable' => array('id_product_attribute' => 'int(10)', 'id_product' => 'int(10)'),
  224. 'foreign_key' => array('id_product'),
  225. 'delete' => false,
  226. 'association' => array(
  227. array(
  228. 'table' => 'product_attribute_combination',
  229. 'fields' => array('id_attribute', 'id_product_attribute'),
  230. 'matchTable' => array('attribute', 'product_attribute')
  231. )
  232. )
  233. ),
  234. 'orderstate' => array('methodName' => 'getOrdersStates',
  235. 'name' => $this->l('Orders States'),
  236. 'className' => 'OrderState',
  237. 'label' => $this->l('Import Orders States'),
  238. 'table' => 'order_state',
  239. 'identifier' => 'id_order_state',
  240. 'alterTable' => array('id_order_state' => 'int(10)')
  241. ),
  242. 'cart' => array('methodName' => 'getOrders',
  243. 'name' => $this->l('Order'),
  244. 'className' => 'Cart',
  245. 'label' => $this->l('Import Orders'),
  246. 'table' => 'cart',
  247. 'identifier' => 'id_cart',
  248. 'foreign_key' => array('id_address_delivery', 'id_address_invoice', 'id_customer'),
  249. 'alterTable' => array('id_cart' => 'int(10)')
  250. ),
  251. 'orderhistory' => array('methodName' => 'getOrdersHistory',
  252. 'name' => $this->l('Order history'),
  253. 'className' => 'Order history',
  254. 'label' => $this->l('Import Order History'),
  255. 'table' => 'order_history',
  256. 'identifier' => 'id_order_history',
  257. 'foreign_key' => array('id_order', 'id_order_state'),
  258. 'alterTable' => array('id_order_history' => 'int(10)'),
  259. 'hidden' => true
  260. ),
  261. 'order' => array('methodName' => 'getOrders',
  262. 'name' => $this->l('Order'),
  263. 'className' => 'Order',
  264. 'label' => $this->l('Import Order History'),
  265. 'table' => 'orders',
  266. 'identifier' => 'id_order',
  267. 'alterTable' => array('id_order' => 'int(10)'),
  268. 'hidden' => true
  269. )
  270. );
  271. }
  272. public function install()
  273. {
  274. return parent::install();
  275. }
  276. public function uninstall()
  277. {
  278. return parent::uninstall();
  279. }
  280. public function getContent()
  281. {
  282. $exportModules = parent::getImportModulesOnDisk();
  283. //get installed module only
  284. foreach($exportModules as $key => $module)
  285. if ($module->name == $this->name || !(bool)$module->id)
  286. unset($exportModules[$key]);
  287. $html = '<script type="text/javascript">var globalAjaxShopImporterToken = "'.sha1(_COOKIE_KEY_.'ajaxShopImporter').'";</script>
  288. <script type="text/javascript" src="../modules/shopimporter/shopimporter.js"></script>
  289. <script src="'._PS_JS_DIR_.'jquery/jquery.scrollTo-1.4.2-min.js"></script>
  290. <script type="text/javascript">
  291. var conf = new Array(); ';
  292. $i = 0;
  293. foreach($this->supportedImports as $import)
  294. {
  295. if(!array_key_exists('hidden', $import))
  296. $html .= 'conf['.$i.'] = new Array(\''.addslashes($import['methodName']).'\', \''.addslashes($import['label']).'\', \''.addslashes($import['className']).'\', \''.addslashes($import['name']).'\');';
  297. $i++;
  298. }
  299. $html .= ' var notExist = "'.$this->l('is not available in this module').'";
  300. var databaseOk = "'.$this->l('Connection to the database OK').'";
  301. var wsOk = "'.$this->l('Connection to the web service OK').'";
  302. var showErrors = "'.$this->l('Show errors').'";
  303. var testImport = "'.$this->l('Test import process').'";
  304. var runImport = "'.$this->l('Run Import').'";
  305. var importHasErrors = "'.$this->l('Errors occurred during import. For more details click on "Show errors".').'"
  306. var importFinish = "'.$this->l('Import is complete.').'"
  307. var truncateTable = "'.$this->l('Remove data').'"
  308. var oneThing = "'.$this->l('Please choose one thing to import').'"
  309. </script>
  310. <style>
  311. .margin-form{padding: 0px 0px 1em 120px;width:300px;}
  312. label{width: 170px;}
  313. .import{background-color: #CCCCCC;border: 1px solid gray;margin: 0px 0px 10px;padding: 10px 15px;line-height: 20px;}
  314. </style>
  315. <fieldset><legend><img src="'.$this->_path.'logo.gif" alt="" />'.$this->l('Import from another system').'</legend>
  316. <div class="warn" ><img src="../img/admin/warn2.png">
  317. '.$this->l('Before starting the import please backup your database. ').'
  318. <a href="index.php?tab=AdminBackup&token='.Tools::getAdminToken('AdminBackup'.(int)Tab::getIdFromClassName('AdminBackup').(int)$this->context->employee->id).'"">'.$this->l(' Click here to backup').'</a>
  319. </div>
  320. <br>
  321. <div style="float:right;width:450px" id="steps"></div>';
  322. if (sizeof($exportModules))
  323. {
  324. $html .= '
  325. <label>'.$this->l('Choose your import').' : </label>
  326. <div class="margin-form">
  327. <select name="import_module_name" id="import_module_name">
  328. <option value="0">---</option>';
  329. foreach($exportModules as $key => $module)
  330. (($module->name != $this->name AND $module->id) ? $html .= '<option value="'.$module->name.'">'.$module->displayName.'</option>' : '' );
  331. $html .= '</select><input type="submit" class="button" id="choose_module_name" value="'.$this->l('Choose').'">
  332. </div>';
  333. }
  334. else
  335. $html .= '<div class="warn" ><img src="../img/admin/warn2.png">'.$this->l('No import module installed').'</div>';
  336. $html .= '
  337. <div style="display:none;" class="error" id="connectionInformation"></div>
  338. <div id="config_connector"></div>
  339. <div class="margin-form">
  340. <input type="submit" name="displayOptions" id="displayOptions" class="button" value="'.$this->l('Next Step').'">
  341. </div>
  342. <hr>
  343. <div style="display:none" id="importOptions">
  344. <h2>'.$this->l('Import Options').'</h2>
  345. <div id="importOptionsYesNo">';
  346. foreach($this->supportedImports as $key => $import)
  347. {
  348. if(!array_key_exists('hidden', $import))
  349. $html .= '<label>'.$import['name'].' : </label>
  350. <div class="margin-form">
  351. <label class="t" for="'.$import['identifier'].'_on'.'"><img src="../img/admin/enabled.gif" alt="Yes" title="Yes"></label>
  352. <input type="radio" id="'.$import['identifier'].'_on'.'" name="'.$import['methodName'].'" class="'.$key.'" value="1" checked="checked">
  353. <label class="t" for="'.$import['identifier'].'_off'.'"><img src="../img/admin/disabled.gif" alt="No" title="No" style="margin-left: 10px;"></label>
  354. <input type="radio" id="'.$import['identifier'].'_off'.'" name="'.$import['methodName'].'" class="'.$key.'" value="0">
  355. '.(array_key_exists('delete', $import) ? '
  356. <label class="t"><img src="../img/admin/delete.gif" alt="Delete" title="Delete"></label>
  357. <input type="checkbox" class="truncateTable" id="'.$key.'" name="delete_'.$import['className'].'">' : '' ).
  358. (array_key_exists('hasImage', $import) ? '
  359. <label class="t"><img src="../img/admin/picture.gif" alt="Images" title="Images"></label>
  360. <input type="checkbox" class="importImages" id="'.$key.'" name="images_'.$import['className'].'">' : '' ).
  361. (array_key_exists('info', $import) ? '<p>'.$import['info'].'</p>' : '').'
  362. </div>';
  363. }
  364. $html .= '</div><hr>
  365. <h2>'.$this->l('Advanced Options').'</h2>
  366. <div class="warn" id="warnSkip" style="display:none"><img src="../img/admin/warn2.png">
  367. '.$this->l('This mode is dangerous').'
  368. </div>
  369. <label>'.$this->l('Import for every').' : </label>
  370. <div class="margin-form">
  371. <select name="nbr_import" id="nbr_import">
  372. <option value="10">10</option>
  373. <option value="50">50</option>
  374. <option value="100" selected="selected">100</option>
  375. <option value="200">200</option>
  376. </select>
  377. <p>'.$this->l('Select the number of occurrences for each query to import').'</p>
  378. </div>
  379. <label>'.$this->l('If errors occur').' : </label>
  380. <div class="margin-form">
  381. <label class="t"><img src="'.$this->_path.'img/stop.png"></label>
  382. <input type="radio" name="hasErrors" id="hasErrors" value="0" checked="checked">
  383. <label class="t">'.$this->l('Stop').'</label>
  384. <label class="t"><img src="'.$this->_path.'img/skip.png" style="margin-left: 10px;"></label>
  385. <input type="radio" name="hasErrors" id="hasErrors" value="1">
  386. <label class="t">'.$this->l('Skip').'</label>
  387. <label class="t"><img src="'.$this->_path.'img/force.gif" style="margin-left: 10px;"></label>
  388. <input type="radio" name="hasErrors" id="hasErrors" value="2">
  389. <label class="t">'.$this->l('Force').'</label>
  390. <p>'.$this->l('Stop: if there are errors with the data, import will not run.').'</p>
  391. <p>'.$this->l('Skip: if there are errors with the data, import will skip incorrect data.').'</p>
  392. <p>'.$this->l('Force: if there are errors with the data, import will replace incorrect data by generic data.').'</p>
  393. </div>
  394. <hr>
  395. <div style="display:none" id="specificOptions">
  396. <h2>'.$this->l('Specific Options').'</h2>
  397. <div style="display:none" class="error" id="specificOptionsErrors"></div>
  398. <div id="specificOptionsContent">
  399. </div>
  400. </div>
  401. <hr>
  402. <div class="margin-form">
  403. <input type="submit" class="button" name="checkAndSaveConfig" id="checkAndSaveConfig" value="'.$this->l('Next Step').'">
  404. </div>
  405. </div>
  406. </fieldset>';
  407. return $html;
  408. }
  409. public function genericImport($className, $fields, $save = false)
  410. {
  411. $return = '';
  412. $json = array();
  413. $errors = array();
  414. $json['hasError'] = false;
  415. $json['datas'] = array_values($fields);
  416. $languages = array();
  417. $defaultLanguage = '';
  418. $table = $this->supportedImports[strtolower($className)]['table'];
  419. $object = new $className();
  420. $rules = call_user_func(array($className, 'getValidationRules'), $className);
  421. if ((sizeof($rules['requiredLang']) || sizeof($rules['sizeLang']) || sizeof($rules['validateLang']) || Tools::isSubmit('syncLang') || Tools::isSubmit('syncCurrency')))
  422. {
  423. $moduleName = Tools::getValue('moduleName');
  424. if (Validate::isModuleName($moduleName) && Validate::file_exists('../../modules/'.$moduleName.'/'.$moduleName.'.php'))
  425. {
  426. require_once('../../modules/'.$moduleName.'/'.$moduleName.'.php');
  427. $importModule = new $moduleName();
  428. $importModule->server = Tools::getValue('server');
  429. $importModule->user = Tools::getValue('user');
  430. $importModule->passwd = Tools::getValue('password');
  431. $importModule->database = Tools::getValue('database');
  432. $importModule->prefix = Tools::getValue('prefix');
  433. $defaultLanguage = new Language((int)Configuration::get('PS_LANG_DEFAULT'));
  434. $languages = $importModule->getLangagues(0);
  435. if (Tools::isSubmit('syncLang') || Tools::isSubmit('syncLangWS'))
  436. {
  437. $defaultIdLand = $importModule->getDefaultIdLang();
  438. $defaultLanguageImport = new Language(Language::getIdByIso($languages[$defaultIdLand]['iso_code']));
  439. if ($defaultLanguage->iso_code != $defaultLanguageImport->iso_code)
  440. $errors[] = $this->l('Default language doesn\'t match : ').'<br>'.Configuration::get('PS_SHOP_NAME').' : '.$defaultLanguage->name.' ?
  441. '.$importModule->displayName.' : '.$defaultLanguageImport->name.'<br>'.$this->l('Please change default language in your configuration');
  442. }
  443. if (Tools::isSubmit('syncCurrency') || Tools::isSubmit('syncCurrencyWS'))
  444. {
  445. $defaultIdCurrency = $importModule->getDefaultIdCurrency();
  446. $currencies = $importModule->getCurrencies(0);
  447. if(!empty($currencies[$defaultIdCurrency]['iso_code']))
  448. $defaultCurrencyImport = new Currency((int)Currency::getIdByIsoCode($currencies[$defaultIdCurrency]['iso_code']));
  449. else
  450. $defaultCurrencyImport = new Currency((int)Currency::getIdByIsoCodeNum($currencies[$defaultIdCurrency]['iso_code_num']));
  451. $defaultCurrency = new Currency((int)Configuration::get('PS_CURRENCY_DEFAULT'));
  452. if ($defaultCurrency->iso_code != $defaultCurrencyImport->iso_code)
  453. $errors[] = $this->l('Default currency doesn\'t match : ').'<br>'.Configuration::get('PS_SHOP_NAME').' : '.$defaultCurrency->name.' ? '.$importModule->displayName.' : '.$defaultCurrencyImport->name.'<br>'.$this->l('Please change default currency in your configuration');
  454. }
  455. if (!empty($errors))
  456. die('{"hasError" : true, "error" : '.Tools::jsonEncode($errors).'}');
  457. }
  458. else
  459. die('{"hasError" : true, "error" : ["FATAL ERROR"], "datas" : []}');
  460. }
  461. foreach($fields as $key => $field)
  462. {
  463. $id = $this->supportedImports[strtolower($className)]['identifier'];
  464. //remove wrong fields (ex : id_toto in Customer)
  465. foreach($field as $name => $value)
  466. if (!array_key_exists($name, get_object_vars($object)) AND ($name != $id) AND ($name != 'association') AND ($name != 'images') AND (strtolower($className) != 'cart'))
  467. unset($field[$name]);
  468. $return = $this->validateRules($rules, $field, $className, $languages, $defaultLanguage);
  469. $fields[$key] = $field;
  470. if (!empty($return))
  471. {
  472. //skip mode
  473. if (Tools::getValue('hasErrors') == 1)
  474. unset($fields[$key]);
  475. $errors[] = $return;
  476. array_unshift($errors[sizeof($errors)-1], $field[$id]);
  477. }
  478. }
  479. if (sizeof($errors) > 0)
  480. {
  481. $json['hasError'] = true;
  482. $json['error'] = $errors;
  483. }
  484. if ($save || Tools::isSubmit('syncLang') || Tools::isSubmit('syncLangWS'))
  485. {
  486. //add language if not exist in prestashop
  487. if ($className == 'Language')
  488. {
  489. if (Tools::isSubmit('syncLang') || Tools::isSubmit('syncLangWS'))
  490. $add = true;
  491. else
  492. $add = false;
  493. $errors = $this->checkAndAddLang($fields, $add);
  494. }
  495. elseif ($className == 'Cart')
  496. {
  497. $this->saveOrders($fields);
  498. }
  499. else
  500. {
  501. $return = $this->saveObject($className, $fields);
  502. $this->cleanPositions($table);
  503. //insert association
  504. if (array_key_exists('association', $this->supportedImports[strtolower($className)]))
  505. $this->insertAssociation(strtolower($className), $fields);
  506. if (!empty($return))
  507. {
  508. $json['hasError'] = true;
  509. $json['error'] = $return;
  510. }
  511. }
  512. if ($className == 'Category' AND (sizeof($fields) != (int)Tools::getValue('nbr_import')))
  513. $this->updateCat();
  514. }
  515. if (sizeof($errors) > 0 AND is_array($errors))
  516. {
  517. $json['hasError'] = true;
  518. $json['error'] = $errors;
  519. }
  520. die(Tools::jsonEncode($json));
  521. }
  522. public function genericImportWS($className, $fields, $save = false)
  523. {
  524. $return = '';
  525. $json = array();
  526. $errors = array();
  527. $json['hasError'] = false;
  528. $json['datas'] = array_values($fields);
  529. $languages = array();
  530. $defaultLanguage = '';
  531. $table = $this->supportedImports[strtolower($className)]['table'];
  532. $object = new $className();
  533. $rules = call_user_func(array($className, 'getValidationRules'), $className);
  534. if ((sizeof($rules['requiredLang']) || sizeof($rules['sizeLang']) || sizeof($rules['validateLang']) || Tools::isSubmit('syncLangWS') || Tools::isSubmit('syncCurrency')))
  535. {
  536. $moduleName = Tools::getValue('moduleName');
  537. if (Validate::isModuleName($moduleName) && file_exists('../../modules/'.$moduleName.'/'.$moduleName.'.php'))
  538. {
  539. require_once('../../modules/'.$moduleName.'/'.$moduleName.'.php');
  540. $importModule = new $moduleName();
  541. $defaultLanguage = new Language((int)Configuration::get('PS_LANG_DEFAULT'));
  542. $languages = $importModule->getLangagues();
  543. if (Tools::isSubmit('syncLangWS'))
  544. {
  545. $defaultIdLand = $importModule->getDefaultIdLang();
  546. $defaultLanguageImport = new Language(Language::getIdByIso($languages[$defaultIdLand]['iso_code']));
  547. if ($defaultLanguage->iso_code != $defaultLanguageImport->iso_code)
  548. $errors[] = $this->l('Default language doesn\'t match : ').'<br>'.Configuration::get('PS_SHOP_NAME').' : '.$defaultLanguage->name.' ?
  549. '.$importModule->displayName.' : '.$defaultLanguageImport->name.'<br>'.$this->l('Please change default language in your configuration');
  550. }
  551. if (Tools::isSubmit('syncCurrency'))
  552. {
  553. $defaultIdCurrency = $importModule->getDefaultIdCurrency();
  554. $currencies = $importModule->getCurrencies();
  555. if (!empty($currencies[$defaultIdCurrency]['iso_code']))
  556. $defaultCurrencyImport = new Currency((int)Currency::getIdByIsoCode($currencies[$defaultIdCurrency]['iso_code']));
  557. else
  558. $defaultCurrencyImport = new Currency((int)Currency::getIdByIsoCodeNum($currencies[$defaultIdCurrency]['iso_code_num']));
  559. $defaultCurrency = new Currency((int)Configuration::get('PS_CURRENCY_DEFAULT'));
  560. if ($defaultCurrency->iso_code != $defaultCurrencyImport->iso_code)
  561. $errors[] = $this->l('Default currency doesn\'t match : ').'<br>'.Configuration::get('PS_SHOP_NAME').' : '.$defaultCurrency->name.' ? '.$importModule->displayName.' : '.$defaultCurrencyImport->name.'<br>'.$this->l('Please change default currency in your configuration');
  562. }
  563. if (!empty($errors))
  564. die('{"hasError" : true, "error" : '.Tools::jsonEncode($errors).'}');
  565. }
  566. else
  567. die('{"hasError" : true, "error" : ["FATAL ERROR"], "datas" : []}');
  568. }
  569. foreach($fields as $key => $field)
  570. {
  571. $id = $this->supportedImports[strtolower($className)]['identifier'];
  572. //remove wrong fields (ex : id_toto in Customer)
  573. foreach($field as $name => $value)
  574. if (!array_key_exists($name, get_object_vars($object)) AND ($name != $id) AND ($name != 'association') AND ($name != 'images') AND (strtolower($className) != 'cart'))
  575. unset($field[$name]);
  576. $return = $this->validateRules($rules, $field, $className, $languages, $defaultLanguage);
  577. $fields[$key] = $field;
  578. if (!empty($return))
  579. {
  580. //skip mode
  581. if (Tools::getValue('hasErrors') == 1)
  582. unset($fields[$key]);
  583. $errors[] = $return;
  584. array_unshift($errors[sizeof($errors)-1], $field[$id]);
  585. }
  586. }
  587. if (sizeof($errors) > 0)
  588. {
  589. $json['hasError'] = true;
  590. $json['error'] = $errors;
  591. }
  592. if ($save || Tools::isSubmit('syncLang') || Tools::isSubmit('syncLangWS'))
  593. {
  594. //add language if not exist in prestashop
  595. if ($className == 'Language')
  596. {
  597. if (Tools::isSubmit('syncLang') || Tools::isSubmit('syncLangWS'))
  598. $add = true;
  599. else
  600. $add = false;
  601. $errors = $this->checkAndAddLang($fields, $add);
  602. }
  603. elseif ($className == 'Cart')
  604. {
  605. $this->saveOrders($fields);
  606. }
  607. else
  608. {
  609. $return = $this->saveObject($className, $fields);
  610. $this->cleanPositions($table);
  611. //insert association
  612. if (array_key_exists('association', $this->supportedImports[strtolower($className)]))
  613. $this->insertAssociation(strtolower($className), $fields);
  614. if (!empty($return))
  615. {
  616. $json['hasError'] = true;
  617. $json['error'] = $return;
  618. }
  619. }
  620. if ($className == 'Category' AND (sizeof($fields) != (int)Tools::getValue('nbr_import')))
  621. $this->updateCat();
  622. }
  623. if (sizeof($errors) > 0 AND is_array($errors))
  624. {
  625. $json['hasError'] = true;
  626. $json['error'] = $errors;
  627. }
  628. die(Tools::jsonEncode($json));
  629. }
  630. private function saveObject($className, $items)
  631. {
  632. $return = array();
  633. $table = $this->supportedImports[strtolower($className)]['table'];
  634. //creating temporary fields for identifiers matching and password
  635. if (array_key_exists('alterTable', $this->supportedImports[strtolower($className)]))
  636. $this->alterTable(strtolower($className));
  637. $matchIdLang = $this->getMatchIdLang(1);
  638. foreach($items as $item)
  639. {
  640. $object = new $className;
  641. $id = $item[$this->supportedImports[strtolower($className)]['identifier']];
  642. if (array_key_exists('foreign_key', $this->supportedImports[strtolower($className)]))
  643. $this->replaceForeignKey($item, $table);
  644. foreach($item as $key => $val)
  645. {
  646. if ($key == 'passwd')
  647. {
  648. $password = $val;
  649. $val = '------';
  650. }
  651. if (is_array($val) AND $key != 'images')
  652. {
  653. $tmp = array();
  654. foreach($matchIdLang as $k => $v)
  655. {
  656. if (array_key_exists($k, $val))
  657. {
  658. $tmp[$v] = $val[$k];
  659. }
  660. }
  661. $object->$key = $tmp;
  662. }
  663. else
  664. $object->$key = $val;
  665. }
  666. if (!$object->save(false, false))
  667. $return[] = array($item[$this->supportedImports[strtolower($className)]['identifier']], $this->l('An error occurred when adding the object'));
  668. else
  669. {
  670. $this->saveMatchId(strtolower($className), (int)$object->id, (int)$id);
  671. if ($className == 'Customer')
  672. Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'customer SET `passwd_'.bqSQL(Tools::getValue('moduleName')).'` = \''.pSQL($password).'\' WHERE id_customer = '.(int)$object->id);
  673. if (array_key_exists('hasImage', $this->supportedImports[strtolower($className)]) AND Tools::isSubmit('images_'.$className))
  674. $this->copyImg($item, $className);
  675. }
  676. }
  677. return $return;
  678. }
  679. private function saveOrders($items)
  680. {
  681. $this->saveObject('cart', $items);
  682. //import cart product
  683. $foreignKey = $this->getForeignKey('Cart', array('id_cart', 'id_product', 'id_product_attribute', 'id_customer','id_address_invoice', 'id_address_delivery'));
  684. foreach($items as &$item)
  685. {
  686. foreach($item['cart_products'] as $k => $cart_products)
  687. {
  688. foreach($cart_products as $key => $val)
  689. if (array_key_exists($key, $foreignKey))
  690. if (array_key_exists($val, $foreignKey[$key]))
  691. $item['cart_products'][$k][$key] = $foreignKey[$key][$val];
  692. else
  693. $item['cart_products'][$k][$key] = 0;
  694. Db::getInstance()->insert('cart_product', $item['cart_products'][$k]);
  695. }
  696. foreach($item['order_products'] as $k => $order_products)
  697. {
  698. foreach($order_products as $key => $val)
  699. if (array_key_exists($key, $foreignKey) || $key == 'product_id')
  700. //patch to correct a mistake naming column in the database
  701. if ($key == 'product_id')
  702. $item['order_products'][$k]['product_id'] = $foreignKey['id_product'][$val];
  703. elseif (array_key_exists($val, $foreignKey[$key]))
  704. $item['order_products'][$k][$key] = $foreignKey[$key][$val];
  705. else
  706. $item['order_products'][$k][$key] = 0;
  707. }
  708. }
  709. //cart to order
  710. $this->cartToOrder($items, $foreignKey);
  711. $foreignKey = array_merge($this->getForeignKey('Cart', array('id_order', 'id_order_state')), $foreignKey);
  712. foreach($items as &$item)
  713. {
  714. //insert product in order detail
  715. foreach($item['order_products'] as $k => $order_products)
  716. {
  717. foreach($order_products as $key => $val)
  718. if (array_key_exists($key, $foreignKey))
  719. if (array_key_exists($val, $foreignKey[$key]))
  720. $item['order_products'][$k][$key] = $foreignKey[$key][$val];
  721. else
  722. $item['order_products'][$k][$key] = 0;
  723. Db::getInstance()->insert('order_detail', $item['order_products'][$k]);
  724. }
  725. //save order history
  726. foreach($item['order_history'] as $k => $order_history)
  727. {
  728. foreach($order_history as $key => $val)
  729. if (array_key_exists($key, $foreignKey))
  730. if (array_key_exists($val, $foreignKey[$key]))
  731. $item['order_history'][$k][$key] = $foreignKey[$key][$val];
  732. else
  733. $item['order_history'][$k][$key] = 0;
  734. Db::getInstance()->insert('order_history', $item['order_history'][$k]);
  735. }
  736. }
  737. }
  738. private function insertAssociation($table, $items)
  739. {
  740. foreach($this->supportedImports[$table]['association'] AS $association)
  741. {
  742. $associatFields = '';
  743. $associatFieldsName = implode('`, `', $association['fields']);
  744. $tableAssociation = $association['table'];
  745. $matchTable = $association['matchTable'];
  746. if (!empty($items))
  747. {
  748. $match = array();
  749. foreach($matchTable as $mTable)
  750. {
  751. $tmp = $this->getForeignKey($mTable, array('id_'.$mTable));
  752. if (array_key_exists('id_'.$mTable, $tmp))
  753. $match['id_'.$mTable] = $tmp['id_'.$mTable];
  754. else
  755. $match['id_'.$mTable] = $this->getDefaultId($table);
  756. }
  757. foreach($items AS $item)
  758. foreach($item AS $key => $val)
  759. if ($key == 'association' AND !empty($key))
  760. foreach($val[$tableAssociation] AS $k => $v)
  761. {
  762. $associatFields .= ' ('.((array_key_exists($k, $match[$association['fields'][0]])) ? (int)$match[$association['fields'][0]][$k] : '1').', ';
  763. $associatFields .= (int)$match[$association['fields'][1]][$v].'), ';
  764. }
  765. if ($associatFields != '')
  766. Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.bqSQL($tableAssociation).'` (`'.$associatFieldsName.'`) VALUES '.rtrim($associatFields, ', '));
  767. }
  768. }
  769. }
  770. private function saveMatchId($className, $psId, $matchId)
  771. {
  772. $table = $this->supportedImports[$className]['table'];
  773. $moduleName = Tools::getValue('moduleName');
  774. $identifier = $this->supportedImports[$className]['identifier'];
  775. Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.bqSQL($table).'` SET `'.bqSQL($identifier).'_'.bqSQL($moduleName).'` = '.(int)$matchId.' WHERE `'.bqSQL($identifier).'` = '.(int)$psId);
  776. }
  777. private function getMatchId($className)
  778. {
  779. $table = $this->supportedImports[$className]['table'];
  780. $moduleName = Tools::getValue('moduleName');
  781. $identifier = $this->supportedImports[$className]['identifier'];
  782. $returns = Db::getInstance()->executeS('SELECT `'.bqSQL($identifier).'_'.bqSQL($moduleName).'`, `'.bqSQL($identifier).'` FROM `'._DB_PREFIX_.bqSQL($table).'` WHERE `'.bqSQL($identifier).'_'.bqSQL($moduleName).'` != 0 ');
  783. $match = array();
  784. foreach($returns as $return)
  785. $match[$return[$identifier.'_'.$moduleName]] = $return[$identifier];
  786. return $match;
  787. }
  788. private function getDefaultId($table)
  789. {
  790. $defaultId = 1;
  791. if (array_key_exists('defaultId', $this->supportedImports[strtolower($table)]))
  792. $defaultId = Configuration::get($this->supportedImports[strtolower($table)]['defaultId']);
  793. return $defaultId;
  794. }
  795. private function copyImg($item, $className)
  796. {
  797. require_once('../../images.inc.php');
  798. $identifier = $this->supportedImports[strtolower($className)]['identifier'];
  799. $matchId = $this->getMatchId(strtolower($className));
  800. $matchIdLang = $this->getMatchIdLang();
  801. switch($className)
  802. {
  803. default:
  804. case 'Product':
  805. $path = _PS_PROD_IMG_DIR_;
  806. $type = 'products';
  807. break;
  808. case 'Category':
  809. $path = _PS_CAT_IMG_DIR_;
  810. $type = 'categories';
  811. break;
  812. case 'Manufacturer':
  813. $path = _PS_MANU_IMG_DIR_;
  814. $type = 'manufacturers';
  815. break;
  816. case 'Supplier':
  817. $path = _PS_SUPP_IMG_DIR_;
  818. $type = 'suppliers';
  819. break;
  820. }
  821. $cover = 1;
  822. if (array_key_exists($item[$identifier], $matchId))
  823. if(array_key_exists('images', $item) && !is_null($item['images']))
  824. foreach($item['images'] as $key => $image)
  825. {
  826. $tmpfile = tempnam(_PS_TMP_IMG_DIR_, 'import');
  827. if (@copy(str_replace(' ', '%20', $image), $tmpfile))
  828. {
  829. $imagesTypes = ImageType::getImagesTypes($type);
  830. ImageManager::resize($tmpfile, $path.(int)$matchId[$item[$identifier]].'.jpg');
  831. if ($className == 'Product')
  832. {
  833. $image = new Image();
  834. $image->id_product = (int)($matchId[$item[$identifier]]);
  835. $image->cover = $cover;
  836. $image->position = Image::getHighestPosition((int)$matchId[$item[$identifier]]) + 1;
  837. $legend = array();
  838. foreach($item['name'] as $key => $val)
  839. if (array_key_exists($key, $matchIdLang))
  840. $legend[$matchIdLang[$key]] = Tools::link_rewrite($val);
  841. else
  842. $legend[Configuration::get('PS_LANG_DEFAULT')] = Tools::link_rewrite($val);
  843. $image->legend = $legend;
  844. $image->add();
  845. ImageManager::resize($tmpfile, $path.(int)$matchId[$item[$identifier]].'-'.(int)$image->id.'.jpg');
  846. foreach ($imagesTypes AS $k => $imageType)
  847. ImageManager::resize($tmpfile, $path.(int)$matchId[$item[$identifier]].'-'.(int)$image->id.'-'.stripslashes($imageType['name']).'.jpg', $imageType['width'], $imageType['height']);
  848. }
  849. else
  850. foreach ($imagesTypes as $imageType)
  851. ImageManager::resize($tmpfile, $path.(int)$matchId[$item[$identifier]].'-'.stripslashes($imageType['name']).'.jpg', $imageType['width'], $imageType['height']);
  852. }
  853. else
  854. @unlink($tmpfile);
  855. @unlink($tmpfile);
  856. $cover = 0;
  857. }
  858. }
  859. private function replaceForeignKey(&$item, $table)
  860. {
  861. if ($table == 'product_attribute')
  862. $table2 = 'combination';
  863. else
  864. $table2 = $table;
  865. $foreingKey = $this->supportedImports[$table2]['foreign_key'];
  866. $foreingKeyValue = $this->getForeignKey($table, $foreingKey);
  867. foreach($foreingKey as $key)
  868. {
  869. if ($table == 'product' AND $key == 'id_category')
  870. $key2 = 'id_category_default';
  871. else if ($table == 'customer' AND $key == 'id_group')
  872. $key2 = 'id_default_group';
  873. else
  874. $key2 = $key;
  875. if (array_key_exists($key, $foreingKeyValue) && $item[$key2] != 0)
  876. $item[$key2] = (array_key_exists($item[$key2], $foreingKeyValue[$key]) ? $item[$key2] = $foreingKeyValue[$key][$item[$key2]] : $item[$key2] = 0);
  877. else
  878. $item[$key2] = $this->getDefaultId($table);
  879. }
  880. }
  881. private function alterTable($className)
  882. {
  883. $query ='';
  884. $queryTmp = '';
  885. $from = $this->supportedImports[$className]['table'];
  886. $result = array();
  887. $result = Db::getInstance()->getRow('SELECT * FROM `'._DB_PREFIX_.bqSQL($from).'`');
  888. if (!$result)
  889. $result = array();
  890. foreach ($this->supportedImports[$className]['alterTable'] AS $name => $type)
  891. {
  892. $moduleName = Tools::getValue('moduleName');
  893. Db::getInstance()->executeS("SHOW COLUMNS FROM `"._DB_PREFIX_.bqSQL($from)."` LIKE '".pSQL($name).'_'.pSQL($moduleName)."'");
  894. if (!Db::getInstance()->numRows() AND !array_key_exists($name.'_'.$moduleName, $result))
  895. $queryTmp .= ' ADD `'.$name.'_'.$moduleName.'` '.$type.' NOT NULL,';
  896. }
  897. if (!empty($queryTmp))
  898. {
  899. $query = 'ALTER TABLE `'._DB_PREFIX_.bqSQL($from).'` ';
  900. $query .= rtrim($queryTmp, ',');
  901. Db::getInstance()->execute($query);
  902. }
  903. }
  904. private function updateCat()
  905. {
  906. $moduleName = Tools::getValue('moduleName');
  907. Db::getInstance()->execute('UPDATE
  908. '._DB_PREFIX_.'category c
  909. INNER JOIN
  910. '._DB_PREFIX_.'category c2
  911. ON
  912. c.id_parent = c2.`id_category_'.bqSQL($moduleName).'`
  913. SET
  914. c.id_parent = c2.id_category
  915. WHERE c.`id_category_'.bqSQL($moduleName).'` != 0');
  916. $category = new Category();
  917. $cats = $category->getSimpleCategories((int)Configuration::get('PS_LANG_DEFAULT'));
  918. foreach($cats as $cat)
  919. {
  920. $cat = new Category((int)$cat['id_category']);
  921. $cat->level_depth = $cat->calcLevelDepth();
  922. $cat->update();
  923. }
  924. }
  925. private function getForeignKey($className, $foreign_key = null)
  926. {
  927. $moduleName = Tools::getValue('moduleName');
  928. if (is_null($foreign_key))
  929. $foreign_key = $this->supportedImports[$className]['foreign_key'];
  930. $match = array();
  931. foreach($foreign_key AS $key)
  932. {
  933. if (in_array($key , array('id_address_invoice', 'id_address_delivery')))
  934. $key2 = 'id_address';
  935. elseif (in_array($key , array('id_category_default')))
  936. $key2 = 'id_category';
  937. else
  938. $key2 = $key;
  939. foreach($this->supportedImports AS $table => $conf)
  940. if ($conf['identifier'] == $key2)
  941. $from = $this->supportedImports[$table]['table'];
  942. $return = Db::getInstance()->executeS('SELECT `'.bqSQL($key2).'_'.bqSQL($moduleName).'`, `'.bqSQL($key2).'` FROM `'._DB_PREFIX_.bqSQL($from).'` WHERE `'.bqSQL($key2).'_'.bqSQL($moduleName).'` != 0');
  943. if (!empty($return))
  944. foreach($return AS $name => $val)
  945. $match[$key][$val[$key2.'_'.$moduleName]] = $val[$key2];
  946. }
  947. return $match;
  948. }
  949. private function getForeignKeyLang($table)
  950. {
  951. $id = $this->supportedImports[$table]['identifier'];
  952. $moduleName = Tools::getValue('moduleName');
  953. $return = Db::getInstance()->executeS('SELECT `'.bqSQL($id).'_'.bqSQL($moduleName).'`, `'.bqSQL($id).'` FROM `'._DB_PREFIX_.bqSQL($table).'` WHERE `'.bqSQL($id).'_'.bqSQL($moduleName).'` != 0');
  954. $match = array();
  955. foreach($return AS $name => $val)
  956. $match[$val[$id.'_'.$moduleName]] = $val[$id];
  957. return $match;
  958. }
  959. private function getMatchIdLang($order = 1)
  960. {
  961. $moduleName = Tools::getValue('moduleName');
  962. $return = Db::getInstance()->executeS('SELECT `id_lang`, `id_lang_'.bqSQL($moduleName).'` FROM `'._DB_PREFIX_.'lang'.'` WHERE `id_lang_'.bqSQL($moduleName).'` != 0');
  963. $match = array();
  964. foreach($return AS $name => $val)
  965. if ((bool)$order)
  966. $match[$val['id_lang_'.$moduleName]] = $val['id_lang'];
  967. else
  968. $match[$val['id_lang']] = $val['id_lang_'.$moduleName];
  969. return $match;
  970. }
  971. private function validateRules($rules, &$fields, $className, $languages, $defaultLanguage)
  972. {
  973. $returnErrors = array();
  974. $hasErrors = Tools::getValue('hasErrors');
  975. /* Checking for required fields */
  976. foreach ($rules['required'] AS $field)
  977. if (($value = $fields[$field]) == false AND (string)$value != '0')
  978. if ($hasErrors == 2)
  979. {
  980. if (array_key_exists($field, $rules['size']))
  981. $size = $rules['size'][$field];
  982. else
  983. $size = 1;
  984. $fields[$field] = $this->generateData($size, $rules['validate'][$field]);
  985. }
  986. else
  987. $returnErrors[] = sprintf(
  988. $this->l('The field %s is required.'),
  989. call_user_func(array($className, 'displayFieldName'), $field, $className)
  990. );
  991. /* Checking for maximum fields sizes */
  992. foreach ($rules['size'] AS $field => $maxLength)
  993. if (array_key_exists($field, $fields) AND $field != 'passwd')
  994. if ($fields[$field] !== false AND Tools::strlen($fields[$field]) > $maxLength)
  995. if ($hasErrors == 2)
  996. $fields[$field] = substr($fields[$field], 0, $maxLength);
  997. else
  998. $returnErrors[] = sprintf(
  999. $this->l('The field %1$s is too long (%2$d chars max).'),
  1000. call_user_func(array($className, 'displayFieldName'), $field, $className),
  1001. $maxLength
  1002. );
  1003. /* Checking for fields validity */
  1004. foreach ($rules['validate'] AS $field => $function)
  1005. if (array_key_exists($field, $fields))
  1006. if (($value = $fields[$field]) !== false AND ($field != 'passwd'))
  1007. if (!Validate::$function($value))
  1008. if ($hasErrors == 2)
  1009. {
  1010. if (array_key_exists($field, $rules['size']))
  1011. $size = $rules['size'][$field];
  1012. else
  1013. $size = 1;
  1014. $fields[$field] = $this->generateData($size, $rules['validate'][$field]);
  1015. }
  1016. else
  1017. $returnErrors[] = sprintf(
  1018. $this->l('The field %s is invalid.'),
  1019. call_user_func(array($className, 'displayFieldName'), $field, $className)
  1020. );
  1021. if ((sizeof($rules['requiredLang']) || sizeof($rules['sizeLang']) || sizeof($rules['validateLang'])))
  1022. {
  1023. $matchIdLang = $this->getMatchIdLang(0);
  1024. /* Checking for multilingual required fields */
  1025. foreach ($rules['requiredLang'] AS $fieldLang)
  1026. {
  1027. if (($empty = $fields[$fieldLang][$matchIdLang[$defaultLanguage->id]]) === false || empty($empty))
  1028. if ($hasErrors == 2)
  1029. {
  1030. if (array_key_exists($fieldLang, $rules['sizeLang']))
  1031. $size = $rules['sizeLang'][$fieldLang];
  1032. else
  1033. $size = 1;
  1034. $fields[$fieldLang][$matchIdLang[$defaultLanguage->id]] = $this->generateData($size, $rules['validateLang'][$fieldLang]);
  1035. }
  1036. else
  1037. $returnErrors[] = sprintf(
  1038. $this->l('This field %1$s is required at least in %2$s'),
  1039. call_user_func(array($className, 'displayFieldName'), $fieldLang, $className),
  1040. $defaultLanguage->name
  1041. );
  1042. }
  1043. /* Checking for maximum multilingual fields size */
  1044. foreach ($rules['sizeLang'] AS $fieldLang => $maxLength)
  1045. foreach ($languages AS $language)
  1046. if (isset($fields[$fieldLang][$language['id_lang']]) && $fields[$fieldLang] !== false AND Tools::strlen($fields[$fieldLang][$language['id_lang']]) > $maxLength)
  1047. if ($hasErrors == 2)
  1048. $fields[$fieldLang] = substr($fields[$fieldLang], 0, $maxLength);
  1049. else
  1050. $returnErrors[] = sprintf(
  1051. $this->l('This field %1$s (%2$s) is too long: %3$d chars max.'),
  1052. call_user_func(array($className, 'displayFieldName'), $fieldLang, $className),
  1053. $language['name'],
  1054. $maxLength
  1055. );
  1056. foreach ($rules['validateLang'] AS $fieldLang => $function)
  1057. {
  1058. foreach ($languages AS $language)
  1059. {
  1060. if (array_key_exists($fieldLang, $fields) AND array_key_exists($language['id_lang'], $fields[$fieldLang]) AND ($value = $fields[$fieldLang][$language['id_lang']]) !== false AND !empty($value))
  1061. {
  1062. if (!Validate::$function($value))
  1063. if ($hasErrors == 2)
  1064. {
  1065. if (array_key_exists($fieldLang, $rules['sizeLang']))
  1066. $size = $rules['sizeLang'][$fieldLang];
  1067. else
  1068. $size = 1;
  1069. $fields[$fieldLang][$language['id_lang']] = $this->generateData($size, $rules['validateLang'][$fieldLang]);
  1070. }
  1071. else
  1072. $returnErrors[] = sprintf(
  1073. $this->l('The field %1$s (%2$s) is invalid.'),
  1074. call_user_func(array($className, 'displayFieldName'), $fieldLang, $className),
  1075. $language['name']
  1076. );
  1077. }
  1078. }
  1079. }
  1080. }
  1081. return $returnErrors;
  1082. }
  1083. private function validateRulesWS($rules, &$fields, $className, $languages, $defaultLanguage)
  1084. {
  1085. $returnErrors = array();
  1086. $hasErrors = Tools::getValue('hasErrors');
  1087. /* Checking for required fields */
  1088. foreach ($rules['required'] AS $field)
  1089. if (($value = $fields[$field]) == false AND (string)$value != '0')
  1090. if ($hasErrors == 2)
  1091. {
  1092. if (array_key_exists($field, $rules['size']))
  1093. $size = $rules['size'][$field];
  1094. else
  1095. $size = 1;
  1096. $fields[$field] = $this->generateData($size, $rules['validate'][$field]);
  1097. }
  1098. else
  1099. $returnErrors[] = sprintf(
  1100. $this->l('The field %s is required.'),
  1101. call_user_func(array($className, 'displayFieldName'), $field, $className)
  1102. );
  1103. /* Checking for maximum fields sizes */
  1104. foreach ($rules['size'] AS $field => $maxLength)
  1105. if (array_key_exists($field, $fields) AND $field != 'passwd')
  1106. if ($fields[$field] !== false AND Tools::strlen($fields[$field]) > $maxLength)
  1107. if ($hasErrors == 2)
  1108. $fields[$field] = substr($fields[$field], 0, $maxLength);
  1109. else
  1110. $returnErrors[] = sprintf(
  1111. $this->l('The field %1$s is too long (%2$d chars max).'),
  1112. call_user_func(array($className, 'displayFieldName'), $field, $className),
  1113. $maxLength
  1114. );
  1115. /* Checking for fields validity */
  1116. foreach ($rules['validate'] AS $field => $function)
  1117. if (array_key_exists($field, $fields))
  1118. if (($value = $fields[$field]) !== false AND ($field != 'passwd'))
  1119. if (!Validate::$function($value))
  1120. if ($hasErrors == 2)
  1121. {
  1122. if (array_key_exists($field, $rules['size']))
  1123. $size = $rules['size'][$field];
  1124. else
  1125. $size = 1;
  1126. $fields[$field] = $this->generateData($size, $rules['validate'][$field]);
  1127. }
  1128. else
  1129. $returnErrors[] = sprintf(
  1130. $this->l('The field %s is invalid.'),
  1131. call_user_func(array($className, 'displayFieldName'), $field, $className)
  1132. );
  1133. return $returnErrors;
  1134. }
  1135. public function checkAndAddLang ($languages, $add = true)
  1136. {
  1137. $errors = '';
  1138. $moduleName = Tools::getValue('moduleName');
  1139. $this->alterTable('language');
  1140. foreach($languages as $language)
  1141. {
  1142. $iso = $language['iso_code'];
  1143. if (!Language::isInstalled($iso))
  1144. {
  1145. if ($add)
  1146. {
  1147. if (@fsockopen('www.prestashop.com', 80))
  1148. {
  1149. if ($lang_pack = Tools::jsonDecode(Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='._PS_VERSION_.'&iso_lang='.$iso)))
  1150. {
  1151. if ($content = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/gzip/'.$lang_pack->version.'/'.$iso.'.gzip'))
  1152. {
  1153. $file = _PS_TRANSLATIONS_DIR_.$iso.'.gzip';
  1154. if (file_put_contents($file, $content))
  1155. {
  1156. require_once('../../tools/tar/Archive_Tar.php');
  1157. $gz = new Archive_Tar($file, true);
  1158. if ($gz->extract(_PS_TRANSLATIONS_DIR_.'../', false))
  1159. {
  1160. if (!Language::checkAndAddLanguage($iso))
  1161. $errors[] = $this->l('Archive cannot be extracted.');
  1162. else
  1163. {
  1164. $newId = Language::getIdByIso($iso);
  1165. Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'lang`
  1166. SET `id_lang_'.bqSQL($moduleName).'` = '.(int)$language['id_lang'].'
  1167. WHERE `id_lang` = '.(int)$newId);
  1168. }
  1169. }
  1170. $errors[] = $this->l('Archive cannot be extracted.');
  1171. }
  1172. else
  1173. $errors[] = $this->l('Server does not have permissions for writing.');
  1174. }
  1175. else
  1176. $errors[] = $this->l('Language not found');
  1177. }
  1178. else
  1179. $errors[] = $this->l('archive cannot be downloaded from prestashop.com.');
  1180. }
  1181. else
  1182. $errors[] = $this->l('archive cannot be downloaded from prestashop.com.');
  1183. }
  1184. }
  1185. else
  1186. {
  1187. $newId = Language::getIdByIso($iso);
  1188. Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'lang`
  1189. SET `id_lang_'.bqSQL($moduleName).'` = '.(int)$language['id_lang'].'
  1190. WHERE `id_lang` = '.(int)$newId);
  1191. }
  1192. }
  1193. }
  1194. public function truncateTable($table)
  1195. {
  1196. switch ($table)
  1197. {
  1198. case 'customer' :
  1199. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customer');
  1200. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customer_group');
  1201. break;
  1202. case 'address' :
  1203. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'address');
  1204. break;
  1205. case 'country' :
  1206. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'state');
  1207. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'country');
  1208. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'country_lang');
  1209. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'country');
  1210. case 'group' :
  1211. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customer_group');
  1212. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'group_lang');
  1213. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'group');
  1214. break;
  1215. case 'combination' :
  1216. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute');
  1217. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_shop');
  1218. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_combination');
  1219. break;
  1220. case 'category' :
  1221. Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'category` WHERE id_category != 1');
  1222. Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'category_lang` WHERE id_category != 1');
  1223. Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'category` AUTO_INCREMENT = 2 ');
  1224. foreach (scandir(_PS_CAT_IMG_DIR_) AS $d)
  1225. if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d))
  1226. unlink(_PS_CAT_IMG_DIR_.$d);
  1227. Image::clearTmpDir();
  1228. break;
  1229. case 'product' :
  1230. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product');
  1231. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_shop');
  1232. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'feature_product');
  1233. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_lang');
  1234. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'category_product');
  1235. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_tag');
  1236. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'image');
  1237. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'image_lang');
  1238. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute');
  1239. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_shop');
  1240. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_combination');
  1241. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'specific_price');
  1242. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'specific_price_priority');
  1243. Image::deleteAllImages(_PS_PROD_IMG_DIR_);
  1244. Image::clearTmpDir();
  1245. @mkdir(_PS_PROD_IMG_DIR_);
  1246. break;
  1247. case 'manufacturer' :
  1248. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'manufacturer');
  1249. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'manufacturer_lang');
  1250. foreach (scandir(_PS_MANU_IMG_DIR_) AS $d)
  1251. if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d))
  1252. unlink(_PS_MANU_IMG_DIR_.$d);
  1253. Image::clearTmpDir();
  1254. break;
  1255. case 'Suppliers' :
  1256. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supplier');
  1257. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supplier_lang');
  1258. foreach (scandir(_PS_SUPP_IMG_DIR_) AS $d)
  1259. if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d))
  1260. unlink(_PS_SUPP_IMG_DIR_.$d);
  1261. Image::clearTmpDir();
  1262. break;
  1263. case 'attribute' :
  1264. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute');
  1265. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_lang');
  1266. break;
  1267. case 'attributegroup' :
  1268. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_group');
  1269. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_group_lang');
  1270. break;
  1271. case 'currency' :
  1272. case 'customer' :
  1273. case 'zone' :
  1274. case 'state' :
  1275. Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.bqSQL($table).'`');
  1276. break;
  1277. }
  1278. return true;
  1279. }
  1280. public function cleanPositions($table, $shopList = null)
  1281. {
  1282. if ($table == 'category')
  1283. {
  1284. //clean category position
  1285. $cat = Category::getCategories(1, false, false);
  1286. foreach($cat AS $i => $categ)
  1287. Category::cleanPositions((int)($categ['id_category']));
  1288. }
  1289. if ($table == 'product')
  1290. {
  1291. //clean products position
  1292. $cat = Category::getCategories(1, false, false);
  1293. foreach($cat AS $i => $categ)
  1294. Product::cleanPositions((int)($categ['id_category']));
  1295. }
  1296. }
  1297. public function getDefaultIdLang()
  1298. {
  1299. return;
  1300. }
  1301. private function generateData($size = 1, $type)
  1302. {
  1303. $type = str_replace('is', '', $type);
  1304. $dom = array('com', 'net', 'org', 'biz', 'info');
  1305. $alphaNum = '0123456789abcdefghijklmnopqrstuvwxyz';
  1306. $alpha = 'abcdefghijklmnopqrstuvwxyz';
  1307. $num = '0123456789';
  1308. $return = '';
  1309. switch($type)
  1310. {
  1311. case 'CityName':
  1312. case 'Name':
  1313. case 'GenericName':
  1314. case 'CatalogName':
  1315. case 'Address':
  1316. case 'LinkRewrite':
  1317. case 'String':
  1318. $a = mt_rand($size/2, $size);
  1319. for ($i = 1; $i <= $a; $i++)
  1320. $return .= substr($alpha, mt_rand(0, strlen($alpha)), 1);
  1321. break;
  1322. case 'LanguageIsoCode':
  1323. for ($i = 1; $i <= 2; $i++)
  1324. $return .= substr($alpha, mt_rand(0, strlen($alpha)), 1);
  1325. break;
  1326. case 'LanguageCode':
  1327. for ($i = 1; $i <= 2; $i++)
  1328. $return .= substr($alphaNum, mt_rand(0, strlen($alphaNum)), 1);
  1329. $return .= '-';
  1330. for ($i = 1; $i <= 2; $i++)
  1331. $return .= substr($alphaNum, mt_rand(0, strlen($alphaNum)), 1);
  1332. break;
  1333. case 'Bool':
  1334. $return .= mt_rand(0,1);
  1335. break;
  1336. case 'Int':
  1337. case 'UnsignedId':
  1338. case 'NumericIsoCode':
  1339. case 'PhoneNumber':
  1340. case 'PostCode':
  1341. $a = mt_rand($size/2, $size);
  1342. for ($i = 1; $i <= $a; $i++)
  1343. $return .= substr($num, mt_rand(0, strlen($num)), 1);
  1344. break;
  1345. case 'Price':
  1346. case 'Float':
  1347. $a = mt_rand(4, 10);
  1348. $b = mt_rand(4, 10);
  1349. for ($i = 1; $i <= $a; $i++)
  1350. $return .= substr($alphaNum, mt_rand(0, strlen($alphaNum)), 1);
  1351. $return .= '-';
  1352. for ($i = 1; $i <= $b; $i++)
  1353. $return .= substr($alphaNum, mt_rand(0, strlen($alphaNum)), 1);
  1354. $return .= '.'.$dom[mt_rand(0, (sizeof($dom)-1))];
  1355. break;
  1356. case 'ZipCodeFormat';
  1357. $str = 'NLC -';
  1358. $a = mt_rand($size/2, $size);
  1359. for ($i = 1; $i <= $a; $i++)
  1360. $return .= substr($str, mt_rand(0, strlen($str)), 1);
  1361. break;
  1362. case 'StateIsoCode';
  1363. break;
  1364. case 'Email':
  1365. $a = mt_rand(4, 10);
  1366. $b = mt_rand(4, 10);
  1367. for ($i = 1; $i <= $a; $i++)
  1368. $return .= substr($alphaNum, mt_rand(0, strlen($alphaNum)), 1);
  1369. $return .= '@';
  1370. for ($i = 1; $i <= $b; $i++)
  1371. $return .= substr($alphaNum, mt_rand(0, strlen($alphaNum)), 1);
  1372. $return .= '.'.$dom[mt_rand(0, (sizeof($dom)-1))];
  1373. break;
  1374. case 'Passwd':
  1375. $a = mt_rand($size/2, $size);
  1376. for ($i = 1; $i <= $a; $i++)
  1377. $return .= substr($alphaNum, mt_rand(0, strlen($alphaNum)), 1);
  1378. break;
  1379. case 'BirthDate':
  1380. $return .= '1970-01-01 00:00:00';
  1381. break;
  1382. }
  1383. return $return;
  1384. }
  1385. private function cartToOrder($items, $foreignKey)
  1386. {
  1387. $this->alterTable('order');
  1388. foreach($items as $item)
  1389. {
  1390. $order = new Order();
  1391. $order->id_carrier = (int)$item['id_carrier'];
  1392. $order->id_customer = (int)$foreignKey['id_customer'][$item['id_customer']];
  1393. $order->id_address_invoice = (int)$foreignKey['id_address_invoice'][$item['id_address_invoice']];
  1394. $order->id_address_delivery = (int)$foreignKey['id_address_delivery'][$item['id_address_delivery']];
  1395. $vat_address = new Address((int)$foreignKey['id_address_delivery'][$item['id_address_delivery']]);
  1396. $id_zone = Address::getZoneById((int)$vat_address->id);
  1397. $order->id_currency = (int)$item['id_currency'];
  1398. $order->id_lang = (int)$item['id_lang'];
  1399. $order->id_cart = (int)$foreignKey['id_cart'][$item['id_cart']];
  1400. $customer = new Customer((int)$order->id_customer);
  1401. $order->secure_key = pSQL($customer->secure_key);
  1402. if (!strlen(trim($item['payment'])))
  1403. $order->payment = 'payment'.Tools::getValue('moduleName');
  1404. else
  1405. $order->payment = utf8_encode(html_entity_decode(strip_tags(Tools::substr($item['payment'], 0, 32))));
  1406. if (isset($this->name))
  1407. $order->module = $this->name;
  1408. $carrier = new Carrier((int)$item['id_carrier']);
  1409. $currency = new Currency($order->id_currency);
  1410. $order->conversion_rate = !empty($currency->conversion_rate) ? $currency->conversion_rate : 1;
  1411. $order->total_products = (float)$item['total_products'];
  1412. $order->total_products_wt = (float)$item['total_products_wt'];
  1413. $order->total_discounts = (float)$item['total_discounts'];
  1414. $order->total_shipping = (float)$item['total_shipping'];
  1415. $order->carrier_tax_rate = (float)$carrier->getTaxesRate(new Address((int)$item[Configuration::get('PS_TAX_ADDRESS_TYPE')]));
  1416. $order->total_wrapping = (float)$item['total_wrapping'];
  1417. $order->total_paid = (float)$item['total_paid'];
  1418. $order->total_paid_real = (float)$item['total_paid_real'];
  1419. $order->invoice_date = '0000-00-00 00:00:00';
  1420. $order->delivery_date = '0000-00-00 00:00:00';
  1421. if(array_key_exists('date_add', $item))
  1422. $order->date_add = $item['date_add'];
  1423. if(array_key_exists('date_upd', $item))
  1424. $order->date_upd = $item['date_upd'];
  1425. //test valid paid
  1426. if($item['total_paid'] == $item['total_paid_real'])
  1427. $order->valid = 1;
  1428. else
  1429. $order->valid = 0;
  1430. $order->save(false, false);
  1431. $this->saveMatchId('order', (int)$order->id, (int)$item['id_cart']);
  1432. }
  1433. }
  1434. }