1051 lines
41 KiB
PHP
1051 lines
41 KiB
PHP
<?php
|
|
|
|
/**
|
|
* File from http://PrestaShow.pl
|
|
*
|
|
* DISCLAIMER
|
|
* Do not edit or add to this file if you wish to upgrade this module to newer
|
|
* versions in the future.
|
|
*
|
|
* @authors PrestaShow.pl <kontakt@prestashow.pl>
|
|
* @copyright 2015 PrestaShow.pl
|
|
* @license http://PrestaShow.pl/license
|
|
*/
|
|
class PShow_Import
|
|
{
|
|
|
|
public $id_shop;
|
|
public $filepath;
|
|
public $filename;
|
|
protected $import_status;
|
|
protected $lang;
|
|
protected $langs;
|
|
public static $file_config;
|
|
public static $file_path;
|
|
public static $imported_ref = false;
|
|
public static $imported_id = false;
|
|
public static $objects_instances = array();
|
|
public static $objects = array();
|
|
public static $objects_ = array();
|
|
public static $LOG = array();
|
|
protected static $instance = null;
|
|
public $maintenance_mode_enabled = false;
|
|
public static $shopsToImport = array();
|
|
|
|
/** @var int */
|
|
public $current_row_number;
|
|
|
|
public function isSomethingToImport()
|
|
{
|
|
if (!file_exists(_IMPORT_STATUS_PATH_ . "actual_row")) {
|
|
return false;
|
|
}
|
|
|
|
$rowsCount = PShow_Config::get('rowsCount');
|
|
$actualRow = (int) PShow_File::file_get_contents(_IMPORT_STATUS_PATH_ . "actual_row");
|
|
|
|
return (($rowsCount - $actualRow) > 0);
|
|
}
|
|
|
|
public static function debug_backtrace($limit)
|
|
{
|
|
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
|
|
return debug_backtrace(0, $limit);
|
|
}
|
|
|
|
return debug_backtrace();
|
|
}
|
|
|
|
public static function getInstanceOfRunningImport()
|
|
{
|
|
if (self::$instance) {
|
|
return self::$instance;
|
|
}
|
|
|
|
$path = _IMPORT_STATUS_PATH_ . "filename";
|
|
$filename = (file_exists($path) ? file_get_contents($path) : false);
|
|
|
|
if (!$filename) {
|
|
return false;
|
|
}
|
|
|
|
return PShow_Import::getInstance($filename);
|
|
}
|
|
|
|
/**
|
|
* Get singleton instance
|
|
*
|
|
* @param string|null $fileToImport
|
|
* @return boolean|PShow_Import
|
|
*/
|
|
public static function getInstance($fileToImport = null)
|
|
{
|
|
if (self::$instance === null || $fileToImport !== null) {
|
|
if ($fileToImport === null || !count(glob(_MODULE_UPLOAD_PATH_ . $fileToImport . '*'))) {
|
|
return false;
|
|
}
|
|
self::$instance = new PShow_Import();
|
|
self::$instance->init($fileToImport);
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Refresh import status
|
|
*/
|
|
public function refreshStatus()
|
|
{
|
|
$this->status = array(
|
|
"actual_row" => (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "actual_row"),
|
|
"counter_imported_rows" => (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "counter_imported_rows"),
|
|
"counter_error_rows" => (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "counter_error_rows"),
|
|
"counter_skipped_rows" => (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "counter_skipped_rows"),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Prepare import
|
|
*
|
|
* @param string $fileToImport
|
|
*/
|
|
public function prepareImport($fileToImport)
|
|
{
|
|
$this->clearStatus();
|
|
|
|
$this->filename = $fileToImport;
|
|
$this->filepath = $this->getFilePathByFileName($this->filename);
|
|
|
|
$this->refreshConfig();
|
|
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "actual_row", 0);
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "error_rows", "");
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "filename", $fileToImport);
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "counter_imported_rows", "0");
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "counter_error_rows", "0");
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "counter_skipped_rows", "0");
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "imported_references", "");
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "imported_ids", "");
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "cached_from_file", "0");
|
|
file_put_contents(_IMPORT_CONFIG_PATH_ . $fileToImport . '/lastimport', time());
|
|
|
|
if (PShow_Config::isChecked('updateWithDownload')) {
|
|
$url = PShow_File::file_get_contents(str_replace(pathinfo($this->filepath, PATHINFO_EXTENSION), "txt", $this->filepath));
|
|
PShow_File::updateFileFromURL($this->filepath, $url);
|
|
}
|
|
|
|
// count rows count
|
|
$parser = PShow_Xml_Parser::getInstance($this->filepath);
|
|
$this->config[0]['rowsCount'] = $parser->countElementsByPath($this->config[1]['objectTag']);
|
|
PShow_Config::saveFileConfig($this->filename, array('primary' => $this->config[0]));
|
|
|
|
PShow_Log::add(_IMPORT_LOG_PATH_ . $this->filename . ".log", PShow_Log::IMPORT_START);
|
|
}
|
|
|
|
public function clearStatus()
|
|
{
|
|
array_map("unlink", glob(_IMPORT_STATUS_PATH_ . "*"));
|
|
|
|
if (file_exists(getModulePath(__FILE__) . "direct_import_now")) {
|
|
unlink(getModulePath(__FILE__) . "direct_import_now");
|
|
}
|
|
}
|
|
|
|
public function getFilePathByFileName($filename)
|
|
{
|
|
$filepath = _MODULE_UPLOAD_PATH_ . $filename . '.xml';
|
|
|
|
if (!file_exists($filepath)) {
|
|
throw new PrestaShopException("File to import not found: " . _MODULE_UPLOAD_PATH_ . $filename . ".*");
|
|
}
|
|
|
|
return $filepath;
|
|
}
|
|
|
|
public function refreshConfig()
|
|
{
|
|
$config = PShow_Config::getFileConfig($this->filename);
|
|
|
|
$this->config = array(
|
|
$config['primary'],
|
|
$config['matched'],
|
|
(array_key_exists('matched_categories', $config) ? $config['matched_categories'] : false),
|
|
(array_key_exists('skipped_manufacturers', $config) ? $config['skipped_manufacturers'] : false),
|
|
'file' => (array_key_exists('file', $config) ? $config['file'] : false),
|
|
);
|
|
|
|
if (!array_key_exists('firstLine', $this->config[0])) {
|
|
$this->config[0]['firstLine'] = 1;
|
|
}
|
|
}
|
|
|
|
public function init($fileToImport = null)
|
|
{
|
|
// check is import prepared
|
|
if (!file_exists(_IMPORT_STATUS_PATH_ . 'filename')) {
|
|
// prepare new import
|
|
if ($fileToImport !== null) {
|
|
$this->prepareImport($fileToImport);
|
|
} else {
|
|
throw new PrestaShopException("Import not started");
|
|
}
|
|
}
|
|
|
|
// find file path
|
|
$this->filename = file_get_contents(_IMPORT_STATUS_PATH_ . 'filename');
|
|
$this->filepath = $this->getFilePathByFileName($this->filename);
|
|
|
|
// get config
|
|
$this->refreshConfig();
|
|
|
|
// get status
|
|
$this->refreshStatus();
|
|
|
|
$this->fileext = Tools::strtolower(pathinfo($this->filepath, PATHINFO_EXTENSION));
|
|
|
|
$lang = (int) $this->config[0]['lang'];
|
|
|
|
$this->matched_categories = (isset($this->config[2]) ? $this->config[2] : array());
|
|
|
|
if ($lang == 0) {
|
|
$this->langs = Language::getLanguages(true);
|
|
} else {
|
|
$this->langs = array(array('id_lang' => $lang));
|
|
}
|
|
|
|
if (array_key_exists('unique_data', $this->config[0]) && $this->config[0]['unique_data'] == 'reference') {
|
|
$imported = Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "imported_references");
|
|
self::$imported_ref = (!empty($imported)) ? explode(';', $imported) : array();
|
|
}
|
|
|
|
if (array_key_exists('unique_data', $this->config[0]) && $this->config[0]['unique_data'] == 'id') {
|
|
$imported = Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "imported_ids");
|
|
self::$imported_id = (!empty($imported)) ? explode(';', $imported) : array();
|
|
}
|
|
|
|
$this->context = Context::getContext();
|
|
|
|
require_once _MODULE_CLASS_PATH_ . 'PShow_' . ucfirst($this->fileext) . '.php';
|
|
}
|
|
|
|
public function getFileRow($row)
|
|
{
|
|
PShow_Log::addImportLog("get next file row/object");
|
|
|
|
$classname = 'PShow_' . ucfirst($this->fileext);
|
|
|
|
return $classname::getRows($this->filepath, $this->config, $row, 1);
|
|
}
|
|
|
|
public function getNextFileRow()
|
|
{
|
|
return $this->getFileRow(( $this->status["actual_row"] + 1));
|
|
}
|
|
|
|
/**
|
|
* Create categories from path
|
|
* eg.: category1/category2/category3
|
|
*
|
|
* @param string $value_
|
|
* @param string $separator
|
|
* @return \Category
|
|
*/
|
|
public function createCategoriesFromPath($value_, $separator)
|
|
{
|
|
$value = str_replace(' / ', '|slash|', implode($separator, $value_));
|
|
$path = explode($separator, $value);
|
|
|
|
PShow_Log::addImportLog("create categories from path");
|
|
|
|
$parent_id = 2;
|
|
$level_depth = 2;
|
|
|
|
foreach ($path as $value) {
|
|
$category = false;
|
|
|
|
$value = str_replace('|slash|', ' / ', $value);
|
|
|
|
$value = strip_tags($value);
|
|
|
|
if (empty($value)) {
|
|
continue;
|
|
}
|
|
|
|
$lang_tmp = $this->langs;
|
|
if (is_array($lang_tmp)) {
|
|
$lang_tmp = reset($lang_tmp);
|
|
}
|
|
|
|
$category = Category::searchByNameAndParentCategoryId($lang_tmp, $value, $parent_id);
|
|
|
|
if (!$category) {
|
|
$category = new Category();
|
|
|
|
foreach ($this->langs as $lang) {
|
|
$category->name[$lang['id_lang']] = $value;
|
|
$category->link_rewrite[$lang['id_lang']] = Tools::link_rewrite($value);
|
|
$category->meta_keywords[$lang['id_lang']] = implode(',', explode(' ', $value));
|
|
}
|
|
|
|
$category->active = true;
|
|
$category->is_root_category = 0;
|
|
$category->position = 0;
|
|
$category->id_parent = $parent_id;
|
|
$category->level_depth = $level_depth;
|
|
|
|
try {
|
|
$category->add();
|
|
} catch (PrestaShopException $e) {
|
|
PShow_Log::addExceptionLog($e);
|
|
}
|
|
|
|
$parent_id = $category->id;
|
|
} else {
|
|
$parent_id = $category['id_category'];
|
|
}
|
|
|
|
$level_depth += 1;
|
|
}
|
|
|
|
if (is_array($category)) {
|
|
$category = new Category($category['id_category']);
|
|
}
|
|
|
|
return $category;
|
|
}
|
|
|
|
public function updateActualRow()
|
|
{
|
|
if ((int) $this->config[0]['number_of_threads'] > 1) {
|
|
return;
|
|
}
|
|
|
|
self::_updateActualRow();
|
|
}
|
|
|
|
public static function _updateActualRow()
|
|
{
|
|
PShow_Import::getInstance()->current_row_number = (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "actual_row") + 1;
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "actual_row", PShow_Import::getInstance()->current_row_number);
|
|
}
|
|
|
|
public function updateSkippedRowsCounter()
|
|
{
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "counter_skipped_rows", (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "counter_skipped_rows") + 1);
|
|
}
|
|
|
|
public function updateImportedRowsCounter()
|
|
{
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "counter_imported_rows", (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "counter_imported_rows") + 1);
|
|
}
|
|
|
|
public function updateErrorsCounter()
|
|
{
|
|
self::_updateErrorsCounter();
|
|
}
|
|
|
|
public static function _updateErrorsCounter()
|
|
{
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "counter_error_rows", (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "counter_error_rows") + 1);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $row
|
|
* @param bool|string $error
|
|
*/
|
|
public function addImportError($row, $error = false)
|
|
{
|
|
$errors = file(_IMPORT_STATUS_PATH_ . "error_rows");
|
|
|
|
if (!$errors || count($errors) == 0 || $errors === null) {
|
|
$errors = array();
|
|
}
|
|
|
|
if ($error) {
|
|
$row .= ': ' . $error;
|
|
}
|
|
|
|
array_push($errors, "\n" . $row);
|
|
$new_contents = implode("", $errors);
|
|
file_put_contents(_IMPORT_STATUS_PATH_ . "error_rows", $new_contents);
|
|
}
|
|
|
|
/**
|
|
* Push some required value to object
|
|
*
|
|
* @param object $object
|
|
* @param string $key
|
|
* @param array $info
|
|
* @param bool $force
|
|
* @return object
|
|
*/
|
|
public static function pushRequiredValue($object, $key, $info, $force = false)
|
|
{
|
|
if ((!array_key_exists('required', $info) || !$info['required'] || !empty($object->{$key}) || is_array($object->{$key})) && !$force) {
|
|
return $object;
|
|
}
|
|
|
|
if (empty($object->{$key}) || $force) {
|
|
$object->{$key} = null;
|
|
}
|
|
|
|
switch ($info['type']) {
|
|
case 1: //int
|
|
$value = 0;
|
|
break;
|
|
|
|
case 2: //bool
|
|
$value = false;
|
|
break;
|
|
|
|
case 4: //float
|
|
$value = (float) 0.0;
|
|
break;
|
|
|
|
case 5: //date
|
|
$value = '0000-00-00';
|
|
break;
|
|
|
|
case 6: //html
|
|
case 8: //sql
|
|
case 7: //nothing
|
|
case 3: //string
|
|
$value = 'not-defined-but-required';
|
|
break;
|
|
}
|
|
|
|
if (array_key_exists('lang', $info) && $info['lang']) {
|
|
foreach (Language::getLanguages(true, false, true) as $lang) {
|
|
$object->{$key}[$lang] = $value;
|
|
}
|
|
} else {
|
|
$object->$key = $value;
|
|
}
|
|
|
|
return $object;
|
|
}
|
|
|
|
public function importToDatabase()
|
|
{
|
|
//xdebug_start_trace(_IMPORT_STATUS_PATH_.'xdebug_trace', XDEBUG_TRACE_COMPUTERIZED);// XDEBUG_TRACE_HTML);
|
|
// init timer
|
|
PShow_Timer::getInstance()->start();
|
|
|
|
$delay = (int) PShow_Settings::getInstance(__FILE__)->get('import_delay');
|
|
if ($delay > 0) {
|
|
PShow_Log::addImportLog("wait " . $delay . "s");
|
|
sleep($delay);
|
|
PShow_Log::addImportLog("continue import");
|
|
}
|
|
|
|
// enable maintenance mode
|
|
if ((bool) Configuration::get('pshowimporter_maintenance_mode') && (bool) Configuration::get('PS_SHOP_ENABLE')) {
|
|
Configuration::updateValue('PS_SHOP_ENABLE', '0');
|
|
$this->maintenance_mode_enabled = true;
|
|
PShow_Log::addImportLog("enabled maintenance mode");
|
|
}
|
|
|
|
$row_ = 1 + (int) file_get_contents(_IMPORT_STATUS_PATH_ . "actual_row");
|
|
if ((int) (int) $this->config[0]['number_of_threads'] > 1) {
|
|
self::_updateActualRow();
|
|
}
|
|
|
|
PShow_Log::addImportLog("*** Importing object from line " . $row_ . " ***");
|
|
|
|
$filepath = $this->filepath;
|
|
set_error_handler(function($errno, $errstr, $errfile, $errline) use ($filepath) {
|
|
// skip some errors
|
|
if (in_array($errno, array(E_WARNING, E_NOTICE)))
|
|
return;
|
|
|
|
PShow_Log::add(pathinfo($filepath, PATHINFO_FILENAME) . ".log", "Error in " . $errfile . " [" . $errline . "]: \n" . $errstr);
|
|
|
|
$status = $this->status;
|
|
$config = $this->config;
|
|
|
|
if (Tools::getValue('ajax')) {
|
|
$data = Tools::jsonEncode(array(
|
|
'filename' => pathinfo($filepath, PATHINFO_FILENAME),
|
|
'actual_row' => $status['actual_row'],
|
|
'first_line' => 0,
|
|
'counter_imported_rows' => $status['counter_imported_rows'],
|
|
'counter_error_rows' => $status['counter_error_rows'],
|
|
'counter_skipped_rows' => $status['counter_skipped_rows'],
|
|
'isSomethingToImport' => (bool) PShowImporterImportController::isSomethingToImport(),
|
|
'error' => array($errstr),
|
|
'importedThisTime' => 0,
|
|
'time' => 0,
|
|
));
|
|
die($data);
|
|
}
|
|
|
|
global $smarty;
|
|
|
|
$smarty->assign('filename', pathinfo($filepath, PATHINFO_FILENAME));
|
|
$smarty->assign('importStatus', $status);
|
|
$smarty->assign('first_line', $config[0]['firstLine']);
|
|
|
|
if (file_exists(_IMPORT_LOG_PATH_ . pathinfo($filepath, PATHINFO_FILENAME) . '.log'))
|
|
$smarty->assign('log_content', file_get_contents(_IMPORT_LOG_PATH_ . pathinfo($filepath, PATHINFO_FILENAME) . '.log'));
|
|
else
|
|
$smarty->assign('log_content', "empty log...");
|
|
|
|
|
|
|
|
$smarty->assign('rowsCount', $config[0]['rowsCount']);
|
|
});
|
|
|
|
$classname = 'PShow_' . ucfirst($this->fileext);
|
|
|
|
PShow_Xml_Parser::getInstance($this->filepath);
|
|
|
|
$file_row = ($row_);
|
|
|
|
$this->data = $classname::compareFileRowWithMatchedFields(
|
|
$file_row, $this->config, _IMPORT_CONFIG_PATH_ . pathinfo($this->filepath, PATHINFO_FILENAME) . '/'
|
|
);
|
|
|
|
if (isset($this->data['product']) && PShow_Config::isChecked('updateOnce') && self::$imported_ref !== false && PShow_Config::get('unique_data') == 'reference' && in_array($this->data['product']['reference'][0], self::$imported_ref)) {
|
|
PShow_Log::addImportLog("Skipped because imported before with code '" . $this->data['product']['reference'][0] . "'");
|
|
$this->updateActualRow();
|
|
$this->updateSkippedRowsCounter();
|
|
return true;
|
|
}
|
|
|
|
if (isset($this->data['product']) && PShow_Config::isChecked('updateOnce') && self::$imported_id !== false && PShow_Config::get('unique_data') == 'id_product' && in_array($this->data['product']['id_product'][0], self::$imported_id)) {
|
|
PShow_Log::addImportLog("Skipped because imported before with id '" . $this->data['product']['id_product'][0] . "'");
|
|
$this->updateActualRow();
|
|
$this->updateSkippedRowsCounter();
|
|
return true;
|
|
}
|
|
|
|
if (PShow_Addon::exists('Multistore')) {
|
|
$shopsToImport = PShow_Import_Object_Multistore::getShopsIdToImport();
|
|
} else {
|
|
$shops = Shop::getShops(true, null, true);
|
|
asort($shops);
|
|
$shopsToImport = array(reset($shops));
|
|
}
|
|
|
|
self::$shopsToImport = $shopsToImport;
|
|
|
|
$shops_ = array(reset($shopsToImport));
|
|
|
|
if (!in_array(PShow_Config::get('what_import'), array('all', 'not_exists'))) {
|
|
$shops_ = $shopsToImport;
|
|
}
|
|
|
|
foreach ($shops_ as $shopToImport) {
|
|
|
|
if (PShow_Addon::exists('Multistore')) {
|
|
PShow_Import_Object_Multistore::initShopToImport($shopToImport);
|
|
} else {
|
|
Shop::initialize($shopToImport);
|
|
}
|
|
|
|
PShow_Import::getInstance()->id_shop = $shopToImport;
|
|
Context::getContext()->shop = new Shop($shopToImport);
|
|
|
|
PShow_Log::addImportLog("selected shop: #" . $shopToImport);
|
|
|
|
self::$objects = array();
|
|
self::$objects_instances = array();
|
|
|
|
foreach ($this->data as $object_name => $matches) {
|
|
switch ($object_name) {
|
|
case 'attributegroup':
|
|
$classname = 'AttributeGroup';
|
|
break;
|
|
default:
|
|
$classname = ucfirst($object_name);
|
|
break;
|
|
}
|
|
|
|
if (!array_key_exists($classname, self::$objects)) {
|
|
$_class = 'PShow_Import_' . $classname;
|
|
|
|
if (!class_exists($_class)) {
|
|
continue;
|
|
}
|
|
|
|
$importer = new $_class();
|
|
|
|
$merge = PShow_Ini::read(_IMPORT_CONFIG_PATH_ . pathinfo($this->filepath, PATHINFO_FILENAME) . '/merge.ini');
|
|
|
|
$importer->importLangs = $this->langs;
|
|
|
|
if (!$importer->setData($matches, (($merge) ? $merge : array()))) {
|
|
continue;
|
|
}
|
|
|
|
if (!$importer->checkConditions()) {
|
|
continue;
|
|
}
|
|
|
|
if (PShow_Config::get('file_contains') == 'data_category' && array_key_exists('category_path', $matches)) {
|
|
self::$objects_ = $this->createCategoriesFromPath(
|
|
$matches['category_path'], PShow_Config::get('category_separator', null, true)
|
|
);
|
|
}
|
|
else {
|
|
self::$objects_ = $importer->getNewObject();
|
|
}
|
|
|
|
if (!is_object(self::$objects_) && !is_array(self::$objects_)) {
|
|
$row_ = 1 + (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "actual_row");
|
|
|
|
$price = 0;
|
|
if (array_key_exists('price', $this->data)) {
|
|
$price = $this->data['price'][0];
|
|
} elseif (array_key_exists('price_brutto', $this->data)) {
|
|
$price = $this->data['price_brutto'][0];
|
|
}
|
|
|
|
switch (self::$objects_) {
|
|
case 0:
|
|
|
|
break;
|
|
case 1:
|
|
PShow_Log::addImportLog("Skipped because product manufacturer: '" . $importer->data['manufacturer'][0] . "'");
|
|
break;
|
|
case 2:
|
|
$cat = '?';
|
|
if (array_key_exists('category', $importer->data)) {
|
|
$cat = $importer->data['category'][0];
|
|
} elseif (array_key_exists('category_path', $importer->data)) {
|
|
$cat = $importer->data['category_path'][0];
|
|
}
|
|
PShow_Log::addImportLog("Skipped because product category: '" . $cat . "'");
|
|
break;
|
|
case 4:
|
|
PShow_Log::addImportLog("Skipped because product price is equal or lower than " . $this->config[0]['productskipp_price_el']);
|
|
break;
|
|
case 5:
|
|
PShow_Log::addImportLog("Skipped because product price is greater than " . $this->config[0]['productskipp_price_eg']);
|
|
break;
|
|
case 6:
|
|
PShow_Log::addImportLog("Skipped because not exists with code: '" . $importer->data['reference'][0] . "'");
|
|
break;
|
|
case 7:
|
|
PShow_Log::addImportLog("Skipped because exists with code: '" . $importer->data['reference'][0] . "'");
|
|
break;
|
|
case 8:
|
|
PShow_Log::addImportLog("Skipped because product quantity is greater than " . $this->config[0]['productskipp_quantity_eg']);
|
|
break;
|
|
case 9:
|
|
PShow_Log::addImportLog("Skipped because product quantity is equal or lower than " . $this->config[0]['productskipp_quantity_el']);
|
|
break;
|
|
case 10:
|
|
PShow_Log::addImportLog("Skipped because price from file (" . $price . ") is lower than product net price");
|
|
break;
|
|
case 11:
|
|
PShow_Log::addImportLog("Skipped because price from file (" . $price . ") is lower than product gross price");
|
|
break;
|
|
case 12:
|
|
// no message
|
|
break;
|
|
default:
|
|
PShow_Log::addImportLog("Skipped because not found with code: '" . $importer->data['reference'][0] . "'");
|
|
break;
|
|
}
|
|
|
|
$this->updateSkippedRowsCounter();
|
|
$this->refreshStatus();
|
|
continue;
|
|
}
|
|
|
|
if (is_array(self::$objects_)) {
|
|
foreach (self::$objects_ as $object) {
|
|
self::$objects[$classname] = $object;
|
|
self::$objects_instances[] = $object;
|
|
|
|
$importer->import();
|
|
}
|
|
} else {
|
|
self::$objects[$classname] = self::$objects_;
|
|
self::$objects_instances[] = self::$objects_;
|
|
|
|
$importer->import();
|
|
}
|
|
} else {
|
|
$importer->import();
|
|
}
|
|
}
|
|
|
|
$error = false;
|
|
$importedIDs = array();
|
|
|
|
foreach (self::$objects_instances as &$object) {
|
|
|
|
$invalid = false;
|
|
$skippedFields = array();
|
|
$object_name = str_replace('Core', '', get_class($object));
|
|
|
|
// to fix ...
|
|
if ($object_name == 'stdClass') {
|
|
$object_name = 'Category';
|
|
$object = new Category($object->id);
|
|
}
|
|
|
|
foreach ($object_name::$definition['fields'] as $field => $data) {
|
|
if (!empty($data['lang'])) {
|
|
//lang field
|
|
$values = $object->{$field};
|
|
|
|
// If the object has not been loaded in multilanguage, then the value is the one for the current language of the object
|
|
if (!is_array($values)) {
|
|
$values = array($this->context->language->id => $values);
|
|
}
|
|
|
|
// The value for the default must always be set, so we put an empty string if it does not exists
|
|
if (!isset($values[Configuration::get('PS_LANG_DEFAULT')])) {
|
|
$values[Configuration::get('PS_LANG_DEFAULT')] = '';
|
|
}
|
|
|
|
$breakParent = false;
|
|
|
|
foreach ($values as $id_lang => $value) {
|
|
$message = $object->validateField($field, $value, $id_lang);
|
|
|
|
if ($message === true)
|
|
continue;
|
|
|
|
if (!isset($this->config[0]['objectWithError']) || $this->config[0]['objectWithError'] == 'skipObject') {
|
|
$invalid = $message;
|
|
$breakParent = true;
|
|
break;
|
|
} else {
|
|
if (!in_array($field, $skippedFields))
|
|
$skippedFields[] = $field;
|
|
|
|
$object = self::pushRequiredValue($object, $field, $data, true);
|
|
}
|
|
}
|
|
|
|
if ($breakParent)
|
|
break;
|
|
}
|
|
else {
|
|
//no lang field
|
|
|
|
$message = $object->validateField($field, $object->$field);
|
|
|
|
if ($message === true)
|
|
continue;
|
|
|
|
if (!isset($this->config[0]['objectWithError']) || $this->config[0]['objectWithError'] == 'skipObject') {
|
|
$invalid = $message;
|
|
break;
|
|
} else {
|
|
if (!in_array($field, $skippedFields))
|
|
$skippedFields[] = $field;
|
|
|
|
$object = self::pushRequiredValue($object, $field, $data);
|
|
}
|
|
}
|
|
}
|
|
|
|
// DEBUGGER
|
|
if (Tools::getValue('debug') !== false) {
|
|
PShow_Import::$LOG[] = 'This object is <u>' . ($invalid === false ? 'VALID' : 'INVALID because ' . $invalid) . '</u>';
|
|
|
|
PShow_Import::$LOG[] = 'Object dump:<br>' . var_export($object, true);
|
|
|
|
if (PShow_Import::getInstance()->config[0]['what_import'] == 'all') {
|
|
$object->delete();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ($invalid !== false) {
|
|
$row_ = 1 + (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "actual_row");
|
|
PShow_Log::addImportLog("Not imported because: " . $invalid);
|
|
|
|
$error = true;
|
|
$object->delete();
|
|
|
|
$this->updateErrorsCounter();
|
|
} else {
|
|
if (count($skippedFields) > 0) {
|
|
$row_ = 1 + (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "actual_row");
|
|
PShow_Log::add(
|
|
pathinfo($this->filepath, PATHINFO_FILENAME) . ".log", "Skipped some fields because they are invalid: " . implode(', ', $skippedFields)
|
|
);
|
|
}
|
|
|
|
PShow_Log::addImportLog("validate fields for object #" . $object->id);
|
|
$message = $object->validateFields(false, true);
|
|
|
|
if ($message === true) {
|
|
try {
|
|
PShow_Log::addImportLog("save object");
|
|
$object->save(0);
|
|
file_put_contents(
|
|
_IMPORT_STATUS_PATH_ . "imported_ids", $object->id . ";", FILE_APPEND
|
|
);
|
|
$importedIDs[] = $object->id;
|
|
|
|
$this->updateImportedRowsCounter();
|
|
|
|
// push object to the selected shops for faster import
|
|
PShow_Log::addImportLog("push object with data to the selected shops");
|
|
PShow_Import_Object_Abstract::pushObjectToOtherShops($object_name, $object, $shopToImport, $shopsToImport, $importer->object_status);
|
|
|
|
// activate product only in selected shops and deactivate product in other
|
|
if (strtolower($object_name) == 'product' &&
|
|
PShow_Config::isChecked('shop_selectable_product_activation') &&
|
|
strlen($id_shops = PShow_Config::get('shop_selectable_product_activation_shops'))) {
|
|
PShow_Log::addImportLog("activate product only in selected shops and deactivate product in other");
|
|
$id_shops = explode(',', preg_replace('/[^0-9\,]/', '', $id_shops));
|
|
PShow_Import_Product::activateProductOnlyInSelectedShops($object->id, $id_shops);
|
|
}
|
|
|
|
// force add product to search index
|
|
if (strtolower($object_name) == 'product') {
|
|
Search::indexation(false, $object->id);
|
|
}
|
|
} catch (PrestaShopException $ex) {
|
|
$this->updateErrorsCounter();
|
|
|
|
$row_ = 1 + (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "actual_row");
|
|
$error = "[Fatal] Not imported because: " . $ex->getMessage();
|
|
PShow_Log::addImportLog($error);
|
|
}
|
|
} else {
|
|
$this->updateErrorsCounter();
|
|
|
|
$row_ = 1 + (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "actual_row");
|
|
$error = "[Fatal] Not imported because: " . $message;
|
|
PShow_Log::addImportLog($error);
|
|
|
|
preg_match_all('~([a-zA-Z]+)->([a-zA-Z0-9]+)~', $message, $obj);
|
|
|
|
if (isset($obj[2]) && isset($obj[2][0]) && isset($object->{$obj[2][0]})) {
|
|
$tryToSet = $object->{$obj[2][0]};
|
|
|
|
if (is_array($tryToSet))
|
|
$tryToSet = reset($tryToSet);
|
|
|
|
$error .= '<br><strong>Trying to set:</strong> ' . $tryToSet;
|
|
}
|
|
$object->delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
// break creating new products
|
|
if ($importer->object_status == PShow_Import_Object_Abstract::STATUS_NEW) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
PShow_Log::addImportLog("go to next row/object");
|
|
$this->updateActualRow();
|
|
|
|
if (self::$imported_ref !== false && array_key_exists('reference', $this->data['product']) && !in_array($this->data['product']['reference'][0], self::$imported_ref)) {
|
|
file_put_contents(
|
|
_IMPORT_STATUS_PATH_ . "imported_references", $this->data['product']['reference'][0] . ";", FILE_APPEND
|
|
);
|
|
}
|
|
|
|
//xdebug_stop_trace();
|
|
//xdebug_print_function_stack('debug import');
|
|
|
|
if ($error) {
|
|
if (PShow_Config::get('what_import') == 'all') {
|
|
foreach (self::$objects_instances as $object) {
|
|
$object->delete();
|
|
}
|
|
}
|
|
$this->addImportError(( $this->status["actual_row"] + 1), $error);
|
|
return $error;
|
|
} else {
|
|
$row_ = (int) Tools::file_get_contents(_IMPORT_STATUS_PATH_ . "actual_row");
|
|
|
|
if (count($importedIDs)) {
|
|
PShow_Log::addImportLog("Imported successfully with ID: " . implode(',', $importedIDs));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fast fix for products category depth
|
|
*/
|
|
public function fixCategoriesDepth()
|
|
{
|
|
Db::getInstance()->query('UPDATE `' . _DB_PREFIX_ . 'category` c1 '
|
|
. 'INNER JOIN `' . _DB_PREFIX_ . 'category` c2 ON (c2.`id_category` = c1.`id_parent`) '
|
|
. 'SET c1.`level_depth` = c2.`level_depth`+1;');
|
|
}
|
|
|
|
/**
|
|
* Set quantity to 0 for products which not exists in the import file
|
|
*/
|
|
public function resetQuantityForNonExistingInTheFile()
|
|
{
|
|
$refs = file_get_contents(_IMPORT_STATUS_PATH_ . "imported_references");
|
|
|
|
if (!empty($refs) && array_key_exists('setZeroForNonExisting', $this->config[0]) && $this->config[0]['setZeroForNonExisting']) {
|
|
PShow_Log::addImportLog("reset quantity not existing basing on reference");
|
|
$explode = explode(';', $refs);
|
|
$explode = array_filter($explode);
|
|
$implode = implode("','", $explode);
|
|
$q = "SELECT `id_product` FROM `" . _DB_PREFIX_ . "product` "
|
|
. "WHERE `reference` NOT IN ('" . $implode . "')";
|
|
$rows = Db::getInstance()->executeS($q);
|
|
|
|
foreach ($rows as $row) {
|
|
StockAvailable::setQuantity($row['id_product'], 0, 0);
|
|
if (PShow_Addon::getInstance('ASM') && PShow_Addon::getInstance('ASM')->isEnabled()) {
|
|
PShow_Addon::getInstance('ASM')->resetProductQuantity($row['id_product']);
|
|
}
|
|
}
|
|
}
|
|
|
|
$ids = file_get_contents(_IMPORT_STATUS_PATH_ . "imported_ids");
|
|
|
|
if (!empty($ids) && array_key_exists('setZeroForNonExisting', $this->config[0]) && $this->config[0]['setZeroForNonExisting']) {
|
|
PShow_Log::addImportLog("reset quantity not existing basing on id");
|
|
$explode = explode(';', $ids);
|
|
$explode = array_filter($explode);
|
|
$implode = implode(",", $explode);
|
|
$q = "SELECT `id_product` FROM `" . _DB_PREFIX_ . "product` "
|
|
. "WHERE `id_product` NOT IN (" . $implode . ")";
|
|
$rows = Db::getInstance()->executeS($q);
|
|
|
|
foreach ($rows as $row) {
|
|
StockAvailable::setQuantity($row['id_product'], 0, 0);
|
|
if (PShow_Addon::getInstance('ASM') && PShow_Addon::getInstance('ASM')->isEnabled()) {
|
|
PShow_Addon::getInstance('ASM')->resetProductQuantity($row['id_product']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable product which not exists in the file
|
|
*/
|
|
public function disableProductsNonExistingInTheFile()
|
|
{
|
|
if (empty(self::$shopsToImport)) {
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Disable not existing products - by reference
|
|
*/
|
|
$refs = file_get_contents(_IMPORT_STATUS_PATH_ . "imported_references");
|
|
|
|
if (!empty($refs) && PShow_Config::isChecked('disableNonExisting')) {
|
|
PShow_Log::addImportLog("disable not existing basing on references");
|
|
$explode = explode(';', $refs);
|
|
$explode = array_filter($explode);
|
|
$implode = implode("','", $explode);
|
|
$q = "SELECT `id_product` FROM `" . _DB_PREFIX_ . "product` "
|
|
. "WHERE `reference` NOT IN ('" . $implode . "')";
|
|
$rows = Db::getInstance()->executeS($q);
|
|
|
|
foreach ($rows as $row) {
|
|
PShow_Log::addImportLog(
|
|
sprintf("disable product #%d in shops [%s]", $row['id_product'], implode(',', self::$shopsToImport))
|
|
);
|
|
// $q = "UPDATE `" . _DB_PREFIX_ . "product` SET `active` = 0 "
|
|
// . "WHERE `id_product` = " . $row['id_product'];
|
|
// Db::getInstance()->query($q);
|
|
$q = "UPDATE `" . _DB_PREFIX_ . "product_shop` SET `active` = 0 "
|
|
. "WHERE `id_product` = " . $row['id_product'] . " AND "
|
|
. "`id_shop` IN (" . implode(',', self::$shopsToImport) . ") ";
|
|
Db::getInstance()->query($q);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable not existing products - by id
|
|
*/
|
|
$ids = file_get_contents(_IMPORT_STATUS_PATH_ . "imported_ids");
|
|
|
|
if (!empty($ids) && PShow_Config::isChecked('disableNonExisting')) {
|
|
PShow_Log::addImportLog("disable not existing basing on id");
|
|
$explode = explode(';', $ids);
|
|
$explode = array_filter($explode);
|
|
$implode = implode(",", $explode);
|
|
$q = "SELECT `id_product` FROM `" . _DB_PREFIX_ . "product` "
|
|
. "WHERE `id_product` NOT IN (" . $implode . ")";
|
|
$rows = Db::getInstance()->executeS($q);
|
|
|
|
foreach ($rows as $row) {
|
|
PShow_Log::addImportLog(
|
|
sprintf("disable product #%d in shops [%s]", $row['id_product'], implode(',', self::$shopsToImport))
|
|
);
|
|
// $q = "UPDATE `" . _DB_PREFIX_ . "product` SET `active` = 0 "
|
|
// . "WHERE `id_product` = " . $row['id_product'];
|
|
// Db::getInstance()->query($q);
|
|
$q = "UPDATE `" . _DB_PREFIX_ . "product_shop` SET `active` = 0 "
|
|
. "WHERE `id_product` = " . $row['id_product'] . " AND "
|
|
. "`id_shop` IN (" . implode(',', self::$shopsToImport) . ") ";
|
|
Db::getInstance()->query($q);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable categories based on category matching
|
|
*/
|
|
$ids = file_get_contents(_IMPORT_STATUS_PATH_ . "imported_ids");
|
|
$categoriesToDisable = PShow_Ini::read(_IMPORT_STATUS_PATH_ . '/categoriesToDisable.ini');
|
|
|
|
if (array_key_exists('category_matching', $this->config[0]) &&
|
|
!empty($ids) && $categoriesToDisable) {
|
|
|
|
$ids = explode(';', $ids);
|
|
$queries = "";
|
|
|
|
foreach ($categoriesToDisable as $md5 => $value) {
|
|
$type = substr($md5, 0, 4);
|
|
switch ($type) {
|
|
case 'name':
|
|
$category = Category::searchByName(0, $value, true, true);
|
|
break;
|
|
|
|
case 'path':
|
|
foreach ($this->langs as $lang) {
|
|
$category = Category::searchByPath($lang['id_lang'], $value);
|
|
if ($category && array_key_exists('id_category', $category))
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ($category && array_key_exists('id_category', $category)) {
|
|
$products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
|
SELECT cp.`id_product` as id
|
|
FROM `' . _DB_PREFIX_ . 'category_product` cp
|
|
WHERE cp.`id_category` = ' . (int) $category['id_category'] . '
|
|
ORDER BY `position` ASC'
|
|
);
|
|
foreach ($products as $product) {
|
|
if (!in_array($product['id'], $ids)) {
|
|
PShow_Log::addImportLog(
|
|
sprintf("disable product #%d in shops [%s] because has category %s", $row['id_product'], implode(',', self::$shopsToImport), $value)
|
|
);
|
|
|
|
// $queries .= "UPDATE `" . _DB_PREFIX_ . "product` SET `active` = 0 "
|
|
// . "WHERE `id_product` = " . $product['id'] . "; ";
|
|
$queries .= "UPDATE `" . _DB_PREFIX_ . "product_shop` SET `active` = 0 "
|
|
. "WHERE `id_product` = " . $product['id'] . " AND "
|
|
. "`id_shop` IN (" . implode(',', self::$shopsToImport) . "); ";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($queries)) {
|
|
Db::getInstance()->query($queries);
|
|
}
|
|
}
|
|
}
|
|
}
|