491 lines
17 KiB
PHP
491 lines
17 KiB
PHP
<?php
|
|
|
|
/**
|
|
* NOTICE OF LICENSE
|
|
*
|
|
* This source file is subject to a commercial license from SARL Ether Création
|
|
* Use, copy, modification or distribution of this source file without written
|
|
* license agreement from the SARL Ether Création is strictly forbidden.
|
|
* In order to obtain a license, please contact us: contact@ethercreation.com
|
|
* ...........................................................................
|
|
* INFORMATION SUR LA LICENCE D'UTILISATION
|
|
*
|
|
* L'utilisation de ce fichier source est soumise a une licence commerciale
|
|
* concedee par la societe Ether Création
|
|
* Toute utilisation, reproduction, modification ou distribution du present
|
|
* fichier source sans contrat de licence ecrit de la part de la SARL Ether Création est
|
|
* expressement interdite.
|
|
* Pour obtenir une licence, veuillez contacter la SARL Ether Création a l'adresse: contact@ethercreation.com
|
|
* ...........................................................................
|
|
* @package ecstock
|
|
* @author Nicolas Bedrane
|
|
* @copyright Copyright (c) 2010-2017 S.A.R.L Ether Création (http://www.ethercreation.com)
|
|
* @license Commercial license
|
|
*/
|
|
|
|
require_once dirname(__FILE__) . '/../../config/config.inc.php';
|
|
if (Tools::getValue('token') != Configuration::get('ECSTOCK_TOKEN')) {
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
|
header('Pragma: no-cache');
|
|
Tools::redirect('Location: ../');
|
|
exit();
|
|
}
|
|
|
|
$token = Tools::getValue('token');
|
|
ignore_user_abort(true);
|
|
|
|
$paramHelp = Tools::getValue('help', null);
|
|
if (!is_null($paramHelp)) {
|
|
$help = array(
|
|
'kill' => array(
|
|
'fr' => 'Arrête l\'opération en cours. Facultatif.',
|
|
'en' => 'Stops the current update. Optional.'
|
|
),
|
|
);
|
|
echo Tools::jsonEncode($help);
|
|
exit();
|
|
}
|
|
|
|
//$token = Tools::getValue('ec_token');
|
|
/*
|
|
if ($token != Catalog::getInfoEco('ECO_TOKEN')) {
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
|
header('Cache-Control: post-check=0, pre-check=0', false);
|
|
header('Pragma: no-cache');
|
|
header('Location: ../');
|
|
exit();
|
|
}
|
|
*/
|
|
|
|
$logging = true;
|
|
if ($logging) {
|
|
$logger = new FileLogger();
|
|
$logger->setFilename(_PS_ROOT_DIR_ . '/modules/ecstock/log/ecupdatestock.log');
|
|
} else {
|
|
$logger = false;
|
|
}
|
|
|
|
$stopTime = time() + 15;
|
|
$listStages = array(
|
|
'1' => 'STARTED',
|
|
'2' => 'UPDSTOCK',
|
|
);
|
|
$id_supplier = 0; // 0 => all suppliers, if else => only one supplier
|
|
|
|
// paramètres
|
|
$paramNbCron = Tools::getValue('nbC', null);
|
|
$nbCron = is_null($paramNbCron) ? 0 : (int) $paramNbCron;
|
|
|
|
$paramAct = Tools::getValue('act', null);
|
|
$action = (Configuration::getGlobalValue('ECI_USTK_ACT') === 'die') ? 'die' : (is_null($paramAct) ? 'go' : $paramAct);
|
|
|
|
$paramSpy = Tools::getValue('spy', null);
|
|
$spy = is_null($paramSpy) ? false : true;
|
|
|
|
$paramSpy2 = Tools::getValue('spytwo', null);
|
|
$spy2 = (empty($paramSpy2)) ? false : true;
|
|
$who = $spy ? ($spy2 ? 'spy2' : 'spy') : 'normal';
|
|
|
|
$paramKill = Tools::getValue('kill', null);
|
|
$kill = is_null($paramKill) ? false : true;
|
|
|
|
//link
|
|
$base_uri = (((Configuration::get('PS_SSL_ENABLED') == 1) && (Configuration::get('PS_SSL_ENABLED_EVERYWHERE') == 1)) ? 'https://' : 'http://' )
|
|
. Tools::getShopDomain()
|
|
. __PS_BASE_URI__
|
|
. str_replace(_PS_ROOT_DIR_ . '/', '', __FILE__)
|
|
. '?ts=' . microtime(true);
|
|
|
|
|
|
if ($logging) {
|
|
$logger->logInfo(
|
|
$who . ' entered, parameters '
|
|
. $nbCron . ','
|
|
. $action . ','
|
|
. $spy . ','
|
|
. $spy2 . ','
|
|
. $kill . ','
|
|
);
|
|
}
|
|
|
|
|
|
// kill
|
|
if ($kill) {
|
|
if (Configuration::getGlobalValue('ECI_USTK_STATE') != 'done') {
|
|
Configuration::updateGlobalValue('ECI_USTK_ACT', 'die');
|
|
}
|
|
exit('willdiesoon');
|
|
}
|
|
|
|
|
|
// espion
|
|
if ($spy) {
|
|
sleep(14);
|
|
$state = Configuration::getGlobalValue('ECI_USTK_STATE');
|
|
$progress = Configuration::getGlobalValue('ECI_USTK_PROGRESS');
|
|
if ($nbCron == $progress) {
|
|
if ($spy2) {
|
|
if ($state != 'done') {
|
|
Configuration::updateGlobalValue('ECI_USTK_STATE', 'still');
|
|
}
|
|
} else {
|
|
followLink($base_uri . '&spy=1&spytwo=1&nbC=' . $progress);
|
|
}
|
|
} else {
|
|
followLink($base_uri . '&spy=1&nbC=' . $progress);
|
|
}
|
|
exit('spywillreturn');
|
|
}
|
|
|
|
|
|
// abandon ou initialisation
|
|
$etat = Configuration::getGlobalValue('ECI_USTK_STATE');
|
|
$starting = is_null($paramSpy) & is_null($paramNbCron) & is_null($paramKill) & is_null($paramAct);
|
|
if (!$starting && ($action === 'die')) {
|
|
// abandon demandé par un kill
|
|
Configuration::updateGlobalValue('ECI_USTK_STATE', 'done');
|
|
Configuration::updateGlobalValue('ECI_USTK_END_TIME', date('Y-m-d H:i:s'));
|
|
Configuration::updateGlobalValue('ECI_USTK_ACT', 'go');
|
|
exit('dead');
|
|
}
|
|
if ($starting && ($etat === 'running')) {
|
|
// tentative de double lancement à éviter
|
|
$progress = Configuration::getGlobalValue('ECI_USTK_PROGRESS');
|
|
// envoi d'espion pour déjouer un plantage de serveur pendant une mise à jour
|
|
followLink($base_uri . '&spy=1&nbC=' . (int) $progress);
|
|
exit('nodoublestartplease');
|
|
}
|
|
if (!$starting && ($etat === 'still')) {
|
|
// un espion a pensé à tort qu'on était planté mais on est là !
|
|
Configuration::updateGlobalValue('ECI_USTK_STATE', 'running');
|
|
followLink($base_uri . '&spy=1&nbC=' . $nbCron);
|
|
}
|
|
if ($starting) {
|
|
// initialisation du process
|
|
$aShops = Shop::getShops(true, null, true);
|
|
asort($aShops);
|
|
$listShops = array_values($aShops);
|
|
Configuration::updateGlobalValue('ECI_USTK_START_TIME', date('Y-m-d H:i:s'));
|
|
Configuration::updateGlobalValue('ECI_USTK_END_TIME', '');
|
|
Configuration::updateGlobalValue('ECI_USTK_SHOPS_TODO', implode(',', $listShops));
|
|
Configuration::updateGlobalValue('ECI_USTK_SHOP', reset($listShops));
|
|
Configuration::updateGlobalValue('ECI_USTK_STAGE', $listStages['1']);
|
|
Configuration::updateGlobalValue('ECI_USTK_PROGRESS', 0);
|
|
Configuration::updateGlobalValue('ECI_USTK_LOOPS', 0);
|
|
Configuration::updateGlobalValue('ECI_USTK_STATE', 'running');
|
|
Configuration::updateGlobalValue('ECI_USTK_ACT', 'go');
|
|
// lancement de l'espion
|
|
followLink($base_uri . '&spy=1&nbC=0');
|
|
} else {
|
|
Configuration::updateGlobalValue('ECI_USTK_PROGRESS', $nbCron);
|
|
}
|
|
$listShopsTodo = explode(',', Configuration::getGlobalValue('ECI_USTK_SHOPS_TODO'));
|
|
$id_shop = (int) Configuration::getGlobalValue('ECI_USTK_SHOP');
|
|
$stage = Configuration::getGlobalValue('ECI_USTK_STAGE');
|
|
|
|
|
|
// gestion des reprises, ruptures, fin
|
|
if ($action === 'next') {
|
|
$action = 'go';
|
|
Configuration::updateGlobalValue('ECI_USTK_ACT', 'go');
|
|
|
|
$numStage = array_search($stage, $listStages, true);
|
|
$keys = array_keys($listStages);
|
|
$next = $nextKey = false;
|
|
foreach ($keys as $key) {
|
|
if ($next) {
|
|
$nextKey = $key;
|
|
break;
|
|
}
|
|
if ($numStage == $key) {
|
|
$next = true;
|
|
}
|
|
}
|
|
|
|
if ($nextKey) {
|
|
$stage = $listStages[$nextKey];
|
|
$nbCron = 0;
|
|
} else {
|
|
$ShopJustDone = array_shift($listShopsTodo);
|
|
if (count($listShopsTodo) > 0) {
|
|
$id_shop = reset($listShopsTodo);
|
|
$stage = $listStages['1'];
|
|
$nbCron = 0;
|
|
} else {
|
|
Configuration::updateGlobalValue('ECI_USTK_SHOPS_TODO', '');
|
|
Configuration::updateGlobalValue('ECI_USTK_STATE', 'done');
|
|
Configuration::updateGlobalValue('ECI_USTK_END_TIME', date('Y-m-d H:i:s'));
|
|
//chaining with other task
|
|
|
|
exit('alldone');
|
|
}
|
|
}
|
|
Configuration::updateGlobalValue('ECI_USTK_SHOPS_TODO', implode(',', $listShopsTodo));
|
|
Configuration::updateGlobalValue('ECI_USTK_SHOP', $id_shop);
|
|
Configuration::updateGlobalValue('ECI_USTK_STAGE', $stage);
|
|
Configuration::updateGlobalValue('ECI_USTK_LOOPS', 0);
|
|
Configuration::updateGlobalValue('ECI_USTK_PROGRESS', 0);
|
|
}
|
|
|
|
|
|
if ($logging) {
|
|
$logger->logInfo($who . ' do ' . $stage . ',' . $action);
|
|
}
|
|
|
|
|
|
// aiguillage
|
|
switch ($stage) {
|
|
case $listStages['1']:
|
|
$reps = stage1($stage);
|
|
if ($reps === true) {
|
|
Configuration::updateGlobalValue('ECI_USTK_ACT', 'next');
|
|
followLink($base_uri . '&nbC=0&act=next');
|
|
} elseif (is_numeric($reps)) {
|
|
Configuration::updateGlobalValue('ECI_USTK_LOOPS', Configuration::getGlobalValue('ECI_USTK_LOOPS') + 1);
|
|
followLink($base_uri . '&nbC=' . $reps);
|
|
}
|
|
break;
|
|
|
|
case $listStages['2']:
|
|
$reps = stage2($nbCron, $id_supplier, $id_shop, $stopTime, $logger);
|
|
if ($reps === true) {
|
|
Configuration::updateGlobalValue('ECI_USTK_ACT', 'next');
|
|
followLink($base_uri . '&nbC=0&act=next');
|
|
} elseif (is_numeric($reps)) {
|
|
Configuration::updateGlobalValue('ECI_USTK_LOOPS', Configuration::getGlobalValue('ECI_USTK_LOOPS') + 1);
|
|
followLink($base_uri . '&nbC=' . $reps);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
exit('dontunderstand');
|
|
}
|
|
|
|
if ($reps !== true && !is_numeric($reps)) {
|
|
if ($logging) {
|
|
$logger->logInfo($who . ', stage ' . $stage . ', ' . $reps);
|
|
}
|
|
}
|
|
|
|
|
|
exit('Bye');
|
|
|
|
|
|
function stage1($stage)
|
|
{
|
|
//tell the calling process that we begin working thus avoiding error 500
|
|
echo 'Task successfully started. ';
|
|
|
|
return true;
|
|
}
|
|
|
|
function stage2($nbCron, $id_supplier, $id_shop, $stopTime, $logger)
|
|
{
|
|
Shop::setContext(Shop::CONTEXT_SHOP, (int) $id_shop);
|
|
Context::getContext()->employee = 1;
|
|
Context::getContext()->shop->id = (int) $id_shop;
|
|
|
|
if (!Shop::isFeatureActive()) {
|
|
$id_shop = 0;
|
|
}
|
|
if ($logger) {
|
|
$logger->logInfo('Nbcon ' . $nbCron);
|
|
}
|
|
if ($nbCron == 0) {
|
|
if (Configuration::get('ECSTOCK_FTP')) {
|
|
$local_file = dirname(__FILE__) . '/file/1.csv';
|
|
$server_file = Configuration::get('ECSTOCK_CHEM');
|
|
|
|
$conn_id = ftp_connect(Configuration::get('ECSTOCK_HOTE'));
|
|
$login_result = ftp_login($conn_id, Configuration::get('ECSTOCK_LOGIN'), Configuration::get('ECSTOCK_PASSWORD'));
|
|
if ($logger) {
|
|
if (!$login_result) {
|
|
$logger->logInfo('Erreur login ftp ' .Configuration::get('ECSTOCK_HOTE').'..'. Configuration::get('ECSTOCK_LOGIN').'..'.Configuration::get('ECSTOCK_PASSWORD'));
|
|
}
|
|
}
|
|
if (ftp_get($conn_id, $local_file, $server_file, FTP_BINARY)) {
|
|
$lm = 1;
|
|
} else {
|
|
$lm = 0;
|
|
}
|
|
if ($logger) {
|
|
$logger->logInfo('copy ftp 1 = > oui / 0 => non ::: ' . $lm);
|
|
}
|
|
ftp_close($conn_id);
|
|
|
|
//$sstock = Configuration::get('ECSTOCK_MIN');
|
|
}
|
|
}
|
|
|
|
$fStock = dirname(__FILE__) . '/file/1.csv';
|
|
if (($handle = fopen($fStock, 'rb')) === false) {
|
|
if ($logger) {
|
|
$logger->logInfo('erreur lecture fichier ' . $fStock);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
$jobLine = 0;
|
|
while (($line = fgets($handle)) !== false) {
|
|
if (($stopTime < time()) && ($jobLine > $nbCron)) {
|
|
fclose($handle);
|
|
return $jobLine;
|
|
}
|
|
$jobLine++;
|
|
if (($jobLine < $nbCron) || empty($line)) {
|
|
continue;
|
|
}
|
|
$logger->logInfo($line);
|
|
$data = explode(';', $line);
|
|
if (count($data) < 1) {
|
|
continue;
|
|
}
|
|
|
|
$ref = trim($data[0]);
|
|
$qt = trim($data[1]);
|
|
$action = trim($data[2]);
|
|
if (0 === ($jobLine % 50)) {
|
|
Configuration::updateGlobalValue('ECI_USTK_PROGRESS', $jobLine);
|
|
}
|
|
$res = explode('-', $ref);
|
|
if (count($res) > 1) {
|
|
$ref = $res[0].'-';
|
|
$ids = getPIdsByReferenceLike($ref, $id_supplier);
|
|
foreach ($ids as $key => $value) {
|
|
$stock = StockAvailable::getQuantityAvailableByProduct(
|
|
(int) $value['id_product'],
|
|
(int) $value['id_product_attribute'],
|
|
($id_shop ? (int) $id_shop : null)
|
|
);
|
|
if ($action == 'update') {
|
|
$logger->logInfo('add ref:'.$data[0]);
|
|
StockAvailable::setQuantity(
|
|
(int) $value['id_product'],
|
|
(int) $value['id_product_attribute'],
|
|
(int) ($qt + $stock),
|
|
($id_shop ? (int) $id_shop : null),
|
|
false
|
|
);
|
|
if (0 !== ($jobLine % 50)) {
|
|
Configuration::updateGlobalValue('ECI_USTK_PROGRESS', $jobLine);
|
|
}
|
|
} else {
|
|
$logger->logInfo('maj qt '.$qt.' ref:'.$ref);
|
|
StockAvailable::setQuantity(
|
|
(int) $ids['id_product'],
|
|
(int) $ids['id_product_attribute'],
|
|
(int) $qt,
|
|
($id_shop ? (int) $id_shop : null)
|
|
);
|
|
if (0 !== ($jobLine % 50)) {
|
|
Configuration::updateGlobalValue('ECI_USTK_PROGRESS', $jobLine);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
$ids = getPIdsByReference($ref, $id_supplier);
|
|
if (!$ids) {
|
|
continue;
|
|
}
|
|
|
|
$stock = StockAvailable::getQuantityAvailableByProduct(
|
|
(int) $ids['id_product'],
|
|
(int) $ids['id_product_attribute'],
|
|
($id_shop ? (int) $id_shop : null)
|
|
);
|
|
if ($action == 'update') {
|
|
//$logger->logInfo('add ref:'.$data[0]);
|
|
StockAvailable::setQuantity(
|
|
(int) $ids['id_product'],
|
|
(int) $ids['id_product_attribute'],
|
|
(int) ($qt + $stock),
|
|
($id_shop ? (int) $id_shop : null)
|
|
);
|
|
if (0 !== ($jobLine % 50)) {
|
|
Configuration::updateGlobalValue('ECI_USTK_PROGRESS', $jobLine);
|
|
}
|
|
} else {
|
|
$logger->logInfo('maj qt '.$qt.' ref:'.$ref);
|
|
StockAvailable::setQuantity(
|
|
(int) $ids['id_product'],
|
|
(int) $ids['id_product_attribute'],
|
|
(int) $qt,
|
|
($id_shop ? (int) $id_shop : null)
|
|
);
|
|
if (0 !== ($jobLine % 50)) {
|
|
Configuration::updateGlobalValue('ECI_USTK_PROGRESS', $jobLine);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fclose($handle);
|
|
|
|
return true;
|
|
}
|
|
|
|
function getPIdsByReference($reference, $id_fournisseur = false)
|
|
{
|
|
$res = Db::getInstance()->getRow('
|
|
SELECT pa.id_product, pa.id_product_attribute
|
|
FROM ' . _DB_PREFIX_ . 'product_attribute pa ' .
|
|
(!$id_fournisseur ? '' : 'LEFT JOIN ' . _DB_PREFIX_ . 'product p ON pa.id_product = p.id_product') . '
|
|
WHERE pa.reference = "' . pSQL($reference) . '"' .
|
|
(!$id_fournisseur ? '' : ' AND p.id_supplier = ' . (int) $id_fournisseur));
|
|
if (isset($res['id_product_attribute'])) {
|
|
return $res;
|
|
}
|
|
|
|
$id = Db::getInstance()->getValue('
|
|
SELECT `id_product`
|
|
FROM `' . _DB_PREFIX_ . 'product`
|
|
WHERE `reference` = "' . pSQL($reference) . '"' .
|
|
(!$id_fournisseur ? '' : ' AND `id_supplier` = ' . (int) $id_fournisseur));
|
|
if ($id) {
|
|
return array('id_product' => $id, 'id_product_attribute' => 0);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
function getPIdsByReferenceLike($reference, $id_fournisseur = false)
|
|
{
|
|
$res = Db::getInstance()->ExecuteS('
|
|
SELECT pa.id_product, pa.id_product_attribute
|
|
FROM ' . _DB_PREFIX_ . 'product_attribute pa ' .
|
|
(!$id_fournisseur ? '' : 'LEFT JOIN ' . _DB_PREFIX_ . 'product p ON pa.id_product = p.id_product') . '
|
|
WHERE pa.reference like "' . pSQL($reference) . '%" '.
|
|
(!$id_fournisseur ? '' : ' AND p.id_supplier = ' . (int) $id_fournisseur));
|
|
//if (isset($res['id_product_attribute'])) {
|
|
return $res;
|
|
//}
|
|
|
|
//$id = Db::getInstance()->ExecuteS('
|
|
// SELECT `id_product`
|
|
// FROM `' . _DB_PREFIX_ . 'product`
|
|
// WHERE `reference` = "' . pSQL($reference) . '"' .
|
|
// (!$id_fournisseur ? '' : ' AND `id_supplier` = ' . (int) $id_fournisseur));
|
|
// if ($id) {
|
|
// return array('id_product' => $id, 'id_product_attribute' => 0);
|
|
// }
|
|
//
|
|
// return false;
|
|
}
|
|
|
|
function followLink($link, $timeout = 4)
|
|
{
|
|
$link.='&token='.Tools::getValue('token');
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $link);
|
|
curl_setopt($ch, CURLOPT_HEADER, false);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
|
$result = curl_exec($ch);
|
|
curl_close($ch);
|
|
|
|
return $result;
|
|
}
|