From 1d8ce9c68b40741e46a6d45dc910cb4200e77fbe Mon Sep 17 00:00:00 2001 From: kamel Date: Fri, 11 Mar 2022 15:52:38 +0100 Subject: [PATCH] 4.0.103.0: - Le lien de l'image fournt a woocommerce comptient le nom reel de l'image - Le nom de l'image sans son extension est fournit comme nom et nom alternatif a woocommerce - Ajout de la synchronisation de la hauteur, largeur et profondeur du produit avec woocommerce - Correction de l'envoi de la description du produit vers woocommerce 4.0.102.0: - Ajout d'un script executant l'action du bouton de synchro des produits de Dolibarr vers le site --- ChangeLog.md | 9 + admin/eCommerceSetup.php | 6 +- admin/tpl/eCommerceSetup.tpl.php | 22 ++ class/business/eCommerceSynchro.class.php | 8 +- ...eCommerceRemoteAccessWoocommerce.class.php | 56 +++- core/modules/modECommerceNg.class.php | 2 +- document/.htaccess | 4 +- langs/en_US/ecommerce.lang | 4 + langs/fr_FR/ecommerce.lang | 4 + scripts/syncronize_products_to_ecommerce.php | 261 ++++++++++++++++++ 10 files changed, 362 insertions(+), 14 deletions(-) create mode 100755 scripts/syncronize_products_to_ecommerce.php diff --git a/ChangeLog.md b/ChangeLog.md index 7aa4f39..edc5dca 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,14 @@ # ChangeLog +## 4.0.103.0 +- Le lien de l'image fournt a woocommerce comptient le nom reel de l'image +- Le nom de l'image sans son extension est fournit comme nom et nom alternatif a woocommerce +- Ajout de la synchronisation de la hauteur, largeur et profondeur du produit avec woocommerce +- Correction de l'envoi de la description du produit vers woocommerce + +## 4.0.102.0 +- Ajout d'un script executant l'action du bouton de synchro des produits de Dolibarr vers le site + ## 4.0.101.0 - Compatibilité v13+ pour la gestion des champs complémentaires - Ajout du triggers sur la creation du lien d'une commande diff --git a/admin/eCommerceSetup.php b/admin/eCommerceSetup.php index e9c707f..e743598 100644 --- a/admin/eCommerceSetup.php +++ b/admin/eCommerceSetup.php @@ -331,6 +331,7 @@ 'description' => isset($_POST['ecommerce_product_description_synch_direction']) ? GETPOST('ecommerce_product_description_synch_direction', 'alpha') : 'etod', 'short_description' => isset($_POST['ecommerce_product_short_description_synch_direction']) ? GETPOST('ecommerce_product_short_description_synch_direction', 'alpha') : 'etod', 'weight' => isset($_POST['ecommerce_product_weight_synch_direction']) ? GETPOST('ecommerce_product_weight_synch_direction', 'alpha') : 'etod', + 'dimension' => isset($_POST['ecommerce_product_dimension_synch_direction']) ? GETPOST('ecommerce_product_dimension_synch_direction', 'alpha') : 'etod', 'tax' => isset($_POST['ecommerce_product_tax_synch_direction']) ? GETPOST('ecommerce_product_tax_synch_direction', 'alpha') : 'etod', 'status' => isset($_POST['ecommerce_product_status_synch_direction']) ? GETPOST('ecommerce_product_status_synch_direction', 'alpha') : 'etod', ); @@ -361,6 +362,7 @@ 'product_synch_direction' => $ecommerceProductSynchDirection, 'product_synch_price' => $ecommerceProductSynchPrice, 'product_weight_units' => $_POST['ecommerce_product_weight_units'], + 'product_dimension_units' => $_POST['ecommerce_product_dimension_units'], 'product_variation_mode' => GETPOSTISSET('ecommerce_product_variation_mode') ? GETPOST('ecommerce_product_variation_mode', 'aZ09') : 'one_to_one', 'customer_roles' => $ecommerceWoocommerceCustomerRoles, 'create_invoice_type' => $ecommerceCreateInvoiceType, @@ -1007,13 +1009,15 @@ } $ecommerceProductWeightUnits = (isset($siteDb->parameters['product_weight_units']) ? $siteDb->parameters['product_weight_units'] : (empty($conf->global->MAIN_WEIGHT_DEFAULT_UNIT)?0:$conf->global->MAIN_WEIGHT_DEFAULT_UNIT)); + $ecommerceProductDimensionUnits = (isset($siteDb->parameters['product_dimension_units']) ? $siteDb->parameters['product_dimension_units'] : -2); // -2 = cm $ecommerceProductSynchPrice = isset($siteDb->parameters['product_synch_price']) ? $siteDb->parameters['product_synch_price'] : 'regular'; $ecommerceProductImageSynchDirection = isset($siteDb->parameters['product_synch_direction']['image']) ? $siteDb->parameters['product_synch_direction']['image'] : 'etod'; $ecommerceProductRefSynchDirection = isset($siteDb->parameters['product_synch_direction']['ref']) ? $siteDb->parameters['product_synch_direction']['ref'] : 'etod'; $ecommerceProductDescriptionSynchDirection = isset($siteDb->parameters['product_synch_direction']['description']) ? $siteDb->parameters['product_synch_direction']['description'] : 'etod'; $ecommerceProductShortDescriptionSynchDirection = isset($siteDb->parameters['product_synch_direction']['short_description']) ? $siteDb->parameters['product_synch_direction']['short_description'] : 'etod'; - $ecommerceProductWeightSynchDirection = isset($siteDb->parameters['product_synch_direction']['weight']) ? $siteDb->parameters['product_synch_direction']['weight'] : 'etod'; + $ecommerceProductWeightSynchDirection = isset($siteDb->parameters['product_synch_direction']['weight']) ? $siteDb->parameters['product_synch_direction']['weight'] : 'etod'; + $ecommerceProductDimensionSynchDirection = isset($siteDb->parameters['product_synch_direction']['dimension']) ? $siteDb->parameters['product_synch_direction']['dimension'] : 'etod'; $ecommerceProductTaxSynchDirection = isset($siteDb->parameters['product_synch_direction']['tax']) ? $siteDb->parameters['product_synch_direction']['tax'] : 'etod'; $ecommerceProductStatusSynchDirection = isset($siteDb->parameters['product_synch_direction']['status']) ? $siteDb->parameters['product_synch_direction']['status'] : 'etod'; $ecommerceProductVariationMode = isset($siteDb->parameters['product_variation_mode']) ? $siteDb->parameters['product_variation_mode'] : 'one_to_one'; diff --git a/admin/tpl/eCommerceSetup.tpl.php b/admin/tpl/eCommerceSetup.tpl.php index 822d293..5894366 100644 --- a/admin/tpl/eCommerceSetup.tpl.php +++ b/admin/tpl/eCommerceSetup.tpl.php @@ -559,6 +559,28 @@ function(token) { trans('ECommerceProductWeightUnitsDescription') ?> + > + trans('ECommerceProductDimensionSyncDirection') ?> + + selectarray('ecommerce_product_dimension_synch_direction', $sync_direction_array, $ecommerceProductDimensionSynchDirection); + ?> + + trans('ECommerceProductDimensionSyncDirectionDescription') ?> + + > + trans('ECommerceProductDimensionUnits') ?> + + select_measuring_units("ecommerce_product_dimension_units", "size", $ecommerceProductDimensionUnits); + } else { + print $formproduct->selectMeasuringUnits("ecommerce_product_dimension_units", "size", $ecommerceProductDimensionUnits, 0, 2); + } + ?> + + trans('ECommerceProductDimensionUnitsDescription') ?> + > trans('ECommerceProductTaxSyncDirection') ?> diff --git a/class/business/eCommerceSynchro.class.php b/class/business/eCommerceSynchro.class.php index e0483ad..db4c94c 100755 --- a/class/business/eCommerceSynchro.class.php +++ b/class/business/eCommerceSynchro.class.php @@ -114,7 +114,7 @@ class eCommerceSynchro private $commandeToUpdate; private $factureToUpdate; - private $cache_categories; + public $cache_categories; public $payment_gateways_cached; public $product_category_cached; @@ -3630,6 +3630,12 @@ public function synchronizeProduct($product_data, $object_origin = null) $product->description = isset($product_data['description']) ? $product_data['description'] : $product->description; $product->weight = isset($product_data['weight']) ? $product_data['weight'] : $product->weight; $product->weight_units = isset($product_data['weight_units']) ? $product_data['weight_units'] : $product->weight_units; + $product->width = isset($product_data['width']) ? $product_data['width'] : $product->width; + $product->width_units = isset($product_data['width_units']) ? $product_data['width_units'] : $product->width_units; + $product->height = isset($product_data['height']) ? $product_data['height'] : $product->height; + $product->height_units = isset($product_data['height_units']) ? $product_data['height_units'] : $product->height_units; + $product->length = isset($product_data['length']) ? $product_data['length'] : $product->length; + $product->length_units = isset($product_data['length_units']) ? $product_data['length_units'] : $product->length_units; $product->type = $product_data['fk_product_type']; $product->finished = $product_data['finished']; $product->status = $product_data['envente']; diff --git a/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php b/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php index 0f8f524..2d92acc 100755 --- a/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php +++ b/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php @@ -985,9 +985,11 @@ public function convertProductDataIntoProcessedData($remote_data, $parent_remote $productDescriptionSynchDirection = isset($this->site->parameters['product_synch_direction']['description']) ? $this->site->parameters['product_synch_direction']['description'] : ''; $productShortDescriptionSynchDirection = isset($this->site->parameters['product_synch_direction']['short_description']) ? $this->site->parameters['product_synch_direction']['short_description'] : ''; $productWeightSynchDirection = isset($this->site->parameters['product_synch_direction']['weight']) ? $this->site->parameters['product_synch_direction']['weight'] : ''; + $productDimensionSynchDirection = isset($this->site->parameters['product_synch_direction']['dimension']) ? $this->site->parameters['product_synch_direction']['dimension'] : ''; $productTaxSynchDirection = isset($this->site->parameters['product_synch_direction']['tax']) ? $this->site->parameters['product_synch_direction']['tax'] : ''; $productStatusSynchDirection = isset($this->site->parameters['product_synch_direction']['status']) ? $this->site->parameters['product_synch_direction']['status'] : ''; $productWeightUnits = isset($this->site->parameters['product_weight_units']) ? $this->site->parameters['product_weight_units'] : (empty($conf->global->MAIN_WEIGHT_DEFAULT_UNIT)?0:$conf->global->MAIN_WEIGHT_DEFAULT_UNIT); + $productDimensionUnits = isset($this->site->parameters['product_dimension_units']) ? $this->site->parameters['product_dimension_units'] : -2; // -2 = cm $product_variation_mode_all_to_one = !empty($this->site->parameters['product_variation_mode']) && $this->site->parameters['product_variation_mode'] == 'all_to_one'; // Categories @@ -1115,6 +1117,15 @@ public function convertProductDataIntoProcessedData($remote_data, $parent_remote $product['weight'] = empty($remote_data->weight) ? $parent_remote_data->weight : $remote_data->weight; $product['weight_units'] = $productWeightUnits; } + // Synchronize weight + if ($productDimensionSynchDirection == 'etod' || $productDimensionSynchDirection == 'all') { + $product['width'] = empty($remote_data->dimensions->width) ? $parent_remote_data->dimensions->width : $remote_data->dimensions->width; + $product['width_units'] = $productDimensionUnits; + $product['height'] = empty($remote_data->dimensions->height) ? $parent_remote_data->dimensions->height : $remote_data->dimensions->height; + $product['height_units'] = $productDimensionUnits; + $product['length'] = empty($remote_data->dimensions->length) ? $parent_remote_data->dimensions->length : $remote_data->dimensions->length; + $product['length_units'] = $productDimensionUnits; + } // Synchronize tax $tax_info = $this->getTaxInfoFromTaxClass(empty($remote_data->tax_class) ? $parent_remote_data->tax_class : $remote_data->tax_class, empty($remote_data->tax_status) ? $parent_remote_data->tax_status : $remote_data->tax_status); if (!$isVariation) $product['tax_rate'] = $tax_info['tax_rate']; @@ -1977,7 +1988,8 @@ public function convertObjectIntoProductData($remote_id, $object) $productRefSynchDirection = isset($this->site->parameters['product_synch_direction']['ref']) ? $this->site->parameters['product_synch_direction']['ref'] : ''; $productDescriptionSynchDirection = isset($this->site->parameters['product_synch_direction']['description']) ? $this->site->parameters['product_synch_direction']['description'] : ''; $productShortDescriptionSynchDirection = isset($this->site->parameters['product_synch_direction']['short_description']) ? $this->site->parameters['product_synch_direction']['short_description'] : ''; - $productWeightSynchDirection = isset($this->site->parameters['product_synch_direction']['weight']) ? $this->site->parameters['product_synch_direction']['weight'] : ''; + $productWeightSynchDirection = isset($this->site->parameters['product_synch_direction']['weight']) ? $this->site->parameters['product_synch_direction']['weight'] : ''; + $productDimensionSynchDirection = isset($this->site->parameters['product_synch_direction']['dimension']) ? $this->site->parameters['product_synch_direction']['dimension'] : ''; $productTaxSynchDirection = isset($this->site->parameters['product_synch_direction']['tax']) ? $this->site->parameters['product_synch_direction']['tax'] : ''; $productStatusSynchDirection = isset($this->site->parameters['product_synch_direction']['status']) ? $this->site->parameters['product_synch_direction']['status'] : ''; $product_variation_mode_all_to_one = !empty($this->site->parameters['product_variation_mode']) && $this->site->parameters['product_variation_mode'] == 'all_to_one'; @@ -1991,11 +2003,20 @@ public function convertObjectIntoProductData($remote_id, $object) } } - // Convert Weight + // Convert Weight $from_unit = $object->weight_units; $to_unit = isset($this->site->parameters['product_weight_units']) ? $this->site->parameters['product_weight_units'] : (empty($conf->global->MAIN_WEIGHT_DEFAULT_UNIT)?0:$conf->global->MAIN_WEIGHT_DEFAULT_UNIT); $totalWeight = weight_convert($object->weight, $from_unit, $to_unit); + // Convert Dimension + $from_unit = $object->width_units; + $to_unit = isset($this->site->parameters['product_direction_units']) ? $this->site->parameters['product_direction_units'] : -2; // -2 = cm + $totalWidth = weight_convert($object->width, $from_unit, $to_unit); + $from_unit = $object->height_units; + $totalHeight = weight_convert($object->height, $from_unit, $to_unit); + $from_unit = $object->length_units; + $totalLength = weight_convert($object->length, $from_unit, $to_unit); + // Price $error_price = 0; if (!empty($conf->global->PRODUIT_MULTIPRICES)) { @@ -2215,11 +2236,13 @@ public function convertObjectIntoProductData($remote_id, $object) foreach ($filearray as $key => $file) { if (empty($file['share'])) continue; - $filename = ecommerceng_wordpress_sanitize_file_name($file['name']); + $filename = pathinfo($file['name'], PATHINFO_FILENAME); + $filename = ecommerceng_wordpress_sanitize_file_name($filename); $img = [ 'name' => $filename, - 'src' => $url_root . '/' . $file['share'] . '.jpg', + 'alt' => $filename, + 'src' => $url_root . '/' . $file['share'] . '/' . $file['name'], 'position' => $key, ]; if (isset($current_images[$filename])) { @@ -2326,16 +2349,23 @@ public function convertObjectIntoProductData($remote_id, $object) $variationData['sku'] = $object->ref; } if ($productDescriptionSynchDirection == 'dtoe' || $productDescriptionSynchDirection == 'all') { - $variationData['description'] = nl2br($object->array_options["options_ecommerceng_description_{$conf->entity}"]); + $variationData['description'] = dol_textishtml($object->array_options["options_ecommerceng_description_{$conf->entity}"]) ? $object->array_options["options_ecommerceng_description_{$conf->entity}"] : nl2br($object->array_options["options_ecommerceng_description_{$conf->entity}"]); if (empty($variationData['description']) || $initial_data) { - $variationData['description'] = nl2br($object->description); + $variationData['description'] = dol_textishtml($object->description) ? $object->description : nl2br($object->description); $object->array_options["options_ecommerceng_description_{$conf->entity}"] = $variationData['description']; } } if ($productWeightSynchDirection == 'dtoe' || $productWeightSynchDirection == 'all') { $variationData['weight'] = (!empty($totalWeight) ? $totalWeight : ''); } + if ($productDimensionSynchDirection == 'dtoe' || $productDimensionSynchDirection == 'all') { + $variationData['dimensions'] = array( + 'length' => (string)(!empty($totalLength) ? $totalLength : ''), + 'width' => (string)(!empty($totalWidth) ? $totalWidth : ''), + 'height' => (string)(!empty($totalHeight) ? $totalHeight : ''), + ); + } if ($productTaxSynchDirection == 'dtoe' || $productTaxSynchDirection == 'all') { $variationData['tax_status'] = 'none'; @@ -2553,19 +2583,26 @@ public function convertObjectIntoProductData($remote_id, $object) $productData['sku'] = $object->ref; } if ($productDescriptionSynchDirection == 'dtoe' || $productDescriptionSynchDirection == 'all') { - $productData['description'] = nl2br($object->array_options["options_ecommerceng_description_{$conf->entity}"]); + $productData['description'] = dol_textishtml($object->array_options["options_ecommerceng_description_{$conf->entity}"]) ? $object->array_options["options_ecommerceng_description_{$conf->entity}"] : nl2br($object->array_options["options_ecommerceng_description_{$conf->entity}"]); if (empty($productData['description']) || $initial_data) { - $productData['description'] = nl2br($object->description); + $productData['description'] = dol_textishtml($object->description) ? $object->description : nl2br($object->description); $object->array_options["options_ecommerceng_description_{$conf->entity}"] = $productData['description']; } } if ($productShortDescriptionSynchDirection == 'dtoe' || $productShortDescriptionSynchDirection == 'all') { - $productData['short_description'] = nl2br($object->array_options["options_ecommerceng_short_description_{$conf->entity}"]); + $productData['short_description'] = dol_textishtml($object->array_options["options_ecommerceng_short_description_{$conf->entity}"]) ? $object->array_options["options_ecommerceng_short_description_{$conf->entity}"] : nl2br($object->array_options["options_ecommerceng_short_description_{$conf->entity}"]); } if ($productWeightSynchDirection == 'dtoe' || $productWeightSynchDirection == 'all') { $productData['weight'] = (!empty($totalWeight) ? $totalWeight : ''); } + if ($productDimensionSynchDirection == 'dtoe' || $productDimensionSynchDirection == 'all') { + $productData['dimensions'] = array( + 'length' => (string)(!empty($totalLength) ? $totalLength : ''), + 'width' => (string)(!empty($totalWidth) ? $totalWidth : ''), + 'height' => (string)(!empty($totalHeight) ? $totalHeight : ''), + ); + } if ($productTaxSynchDirection == 'dtoe' || $productTaxSynchDirection == 'all') { $productData['tax_status'] = 'none'; @@ -3396,6 +3433,7 @@ public function batchUpdateRemoteProducts($batch) dol_syslog(__METHOD__ . ": Create batch products from Dolibarr products IDs: '{$ids}' for site ID {$this->site->id}", LOG_DEBUG); global $conf, $langs; + return array(); // Todo to remake $this->errors = array(); require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; diff --git a/core/modules/modECommerceNg.class.php b/core/modules/modECommerceNg.class.php index 7bc7cd2..1327fbb 100644 --- a/core/modules/modECommerceNg.class.php +++ b/core/modules/modECommerceNg.class.php @@ -61,7 +61,7 @@ function __construct($db) $this->editor_url = 'http://www.open-dsi.fr'; // Possible values for version are: 'development', 'experimental', 'dolibarr' or version - $this->version = '4.0.101'; + $this->version = '4.0.103'; // Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase) $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); // Where to store the module in setup page (0=common,1=interface,2=others,3=very specific) diff --git a/document/.htaccess b/document/.htaccess index ba673c3..efd76f7 100644 --- a/document/.htaccess +++ b/document/.htaccess @@ -1,5 +1,5 @@ RewriteEngine on -RewriteRule (.*)\.jpg ../../../document.php?hashp=$1 [NC] -#RewriteRule (.*)\.jpg ../../../../document.php?hashp=$1 [NC] +RewriteRule (.*)/.* ../../../document.php?hashp=$1 [NC] +#RewriteRule (.*)/.* ../../document.php?hashp=$1 [NC] # if the module is installed in the htdocs and not in custom diff --git a/langs/en_US/ecommerce.lang b/langs/en_US/ecommerce.lang index 7f06757..d6c8c84 100755 --- a/langs/en_US/ecommerce.lang +++ b/langs/en_US/ecommerce.lang @@ -260,6 +260,8 @@ ECommerceProductShortDescriptionSyncDirection=Short description synchronization ECommerceProductShortDescriptionSyncDirectionDescription=This parameter determines the direction in which the short description is updated ECommerceProductWeightSyncDirection=Product weight synchronization ECommerceProductWeightSyncDirectionDescription=This parameter determines the direction in which the product weight is updated +ECommerceProductDimensionSyncDirection =Synchronisation des dimensions du produit +ECommerceProductDimensionSyncDirectionDescription =Ce paramètre détermine le sens de mise à jour des dimensions du produit ECommerceProductTaxSyncDirection=VAT classes of the store synchronization ECommerceProductTaxSyncDirectionDescription=This parameter determines the direction in which the VAT classes of the store are updated ECommerceProductStatusSyncDirection=Status on the store synchronization @@ -267,6 +269,8 @@ ECommerceProductStatusSyncDirectionDescription=This parameter determines the dir ECommerceProductWeightUnits=Unit of weight in the store ECommerceProductWeightUnitsDescription=This parameter determines the unit of weight in the store +ECommerceProductDimensionUnits =Unité des dimensions sur la boutique +ECommerceProductDimensionUnitsDescription =Ce paramètre détermine l'unité des dimensions sur la boutique ECommerceExportProductsPrices=Export of product prices (WooSync) ECommerceImportProductsPrices=Import of product prices (WooSync) (Does not support the addition of new products, the update is only supported by the CSV) diff --git a/langs/fr_FR/ecommerce.lang b/langs/fr_FR/ecommerce.lang index 5d3fd41..89c5016 100644 --- a/langs/fr_FR/ecommerce.lang +++ b/langs/fr_FR/ecommerce.lang @@ -252,6 +252,8 @@ ECommerceProductShortDescriptionSyncDirection ECommerceProductShortDescriptionSyncDirectionDescription =Ce paramètre détermine le sens de mise à jour de la description courte ECommerceProductWeightSyncDirection =Synchronisation du poids du produit ECommerceProductWeightSyncDirectionDescription =Ce paramètre détermine le sens de mise à jour du poids du produit +ECommerceProductDimensionSyncDirection =Synchronisation des dimensions du produit +ECommerceProductDimensionSyncDirectionDescription =Ce paramètre détermine le sens de mise à jour des dimensions du produit ECommerceProductTaxSyncDirection =Synchronisation de la classes de TVA sur la boutique ECommerceProductTaxSyncDirectionDescription =Ce paramètre détermine le sens de mise à jour de la classes de TVA sur la boutique ECommerceProductStatusSyncDirection =Synchronisation du statut sur la boutique @@ -259,6 +261,8 @@ ECommerceProductStatusSyncDirectionDescription ECommerceProductWeightUnits =Unité de poids sur la boutique ECommerceProductWeightUnitsDescription =Ce paramètre détermine l'unité de poids sur la boutique +ECommerceProductDimensionUnits =Unité des dimensions sur la boutique +ECommerceProductDimensionUnitsDescription =Ce paramètre détermine l'unité des dimensions sur la boutique ECommerceExportProductsPrices =Export des prix des produits (WooSync) ECommerceImportProductsPrices =Import des prix des produits (WooSync) (Ne supporte pas l'ajout de nouveaux produits, la mise à jour n'est supportée que par un fichier CSV) diff --git a/scripts/syncronize_products_to_ecommerce.php b/scripts/syncronize_products_to_ecommerce.php new file mode 100755 index 0000000..8fb0cb4 --- /dev/null +++ b/scripts/syncronize_products_to_ecommerce.php @@ -0,0 +1,261 @@ +#!/usr/bin/env php + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file scripts/osv_companies_categories.php + * \ingroup cron + * \brief Execute pendings jobs + */ +if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Disables token renewal +if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); +if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); +if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); +if (! defined('NOLOGIN')) define('NOLOGIN','1'); +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); + + +$sapi_type = php_sapi_name(); +$script_file = basename(__FILE__); +$path=dirname(__FILE__).'/'; + +// Test if batch mode +if (substr($sapi_type, 0, 3) == 'cgi') { + echo "Error: You are using PHP for CGI. To execute ".$script_file." from command line, you must use PHP for CLI mode.\n"; + exit(-1); +} + +// Check parameters +if (! isset($argv[1]) || ! $argv[1]) { + print 'Usage: ' . $script_file . ' user_login_in_dolibarr'; + exit(-1); +} +$userlogin=$argv[1]; + +// Change this following line to use the correct relative path (../, ../../, etc) +$res=0; +if (! $res && file_exists("../../main.inc.php")) $res=@include '../../main.inc.php'; // to work if your module directory is into a subdir of root htdocs directory +if (! $res && file_exists("../../../main.inc.php")) $res=@include '../../../main.inc.php'; // to work if your module directory is into a subdir of root htdocs directory +if (! $res) die("Include of main fails"); +require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; +dol_include_once('/ecommerceng/class/data/eCommerceSite.class.php'); +dol_include_once('/ecommerceng/class/business/eCommerceSynchro.class.php'); +dol_include_once('/ecommerceng/class/data/eCommerceProduct.class.php'); + +// Global variables +$version=DOL_VERSION; +$product_cached = array(); + +/* + * Main + */ + +// current date +$now=dol_now(); + +@set_time_limit(0); +print "***** ".$script_file." (".$version.") pid=".dol_getmypid()." ***** userlogin=" . $userlogin . " ***** " . $now . " *****\n"; +print "\n"; + +$user = new User($db); +$res = $user->fetch('', $userlogin); +if ($res == 0) { + print "Error user (Login: $userlogin) not found\n"; + $db->close(); + exit(0); +} elseif ($res < 0) { + print "Error fetch user (Login: $userlogin) : " . $user->errorsToString() . "\n"; + $db->close(); + exit(0); +} + +$siteDb = new eCommerceSite($db); +$sites = $siteDb->listSites('object'); + +$max_sites = count($sites); +$num_sites = 0; + +if ($max_sites > 0) { + $startTime = microtime(true); + + foreach ($sites as $site) { + print "Processing the site '{$site->name}'.\n"; + $num_sites++; + $max_jobs = 0; + $num_jobs = 0; + + print "Connect to the site.\n"; + $eCommerceSynchro = new eCommerceSynchro($db, $site); + $eCommerceSynchro->connect(); + if (count($eCommerceSynchro->errors)) { + print "Warning: Connect to site fails: {$eCommerceSynchro->errorsToString()}.\n"; + continue; + } + + print "Get all WooCommerce product categories.\n"; + $eCommerceSynchro->fetch_categories('product', $site->fk_cat_product); + $woocommerce_product_categories = array_keys($eCommerceSynchro->cache_categories['product']); + if (empty($woocommerce_product_categories)) { + print "Warning: WooCommerce product categories not found.\n"; + continue; + } + + $supported_warehouses = is_array($site->parameters['fk_warehouse_to_ecommerce']) ? $site->parameters['fk_warehouse_to_ecommerce'] : array(); + if (empty($supported_warehouses)) { + print "Warning: Warehouses not configured.\n"; + continue; + } + + $sql = "SELECT DISTINCT p.rowid AS product_id, IFNULL(ep.remote_id, '') as remote_id, ep.rowid AS link_id FROM " . MAIN_DB_PREFIX . "product as p" . + " INNER JOIN " . MAIN_DB_PREFIX . "categorie_product as cp ON p.rowid = cp.fk_product AND cp.fk_categorie IN (" . implode(',', $woocommerce_product_categories) . ")" . + " LEFT JOIN " . MAIN_DB_PREFIX . "ecommerce_product as ep ON p.rowid = ep.fk_product AND ep.fk_site=" . $site->id . + " LEFT JOIN " . MAIN_DB_PREFIX . "product_extrafields as pf ON pf.fk_object = p.rowid" . + " WHERE (ep.rowid IS NULL OR ep.last_update < p.tms OR (pf.tms IS NOT NULL AND ep.last_update < pf.tms))" . + " AND p.entity IN (" . getEntity('product') . ")"; + + $resql = $db->query($sql); + if ($resql) { + $eCommerceProduct = new eCommerceProduct($db); + + $ec_price_entities = explode(',', getEntity('productprice')); + $max_jobs = $db->num_rows($resql); + + while ($obj = $db->fetch_object($resql)) { + $remote_id = $obj->remote_id; + $error = 0; + + // Get product + if (!$error) { + $dbProduct = getProduct($obj->product_id); + if (!($dbProduct->id > 0)) { + print "\nError: Get product (ID: {$obj->product_id}): " . errorsToString($dbProduct) . ".\n"; + $error++; + } else { + $dbProduct->context['ec_price_entities'] = $ec_price_entities; + } + } + + if (!$error) { + $db->begin(); + + if (empty($remote_id)) { + // Create remote product + $result = $eCommerceSynchro->eCommerceRemoteAccess->createRemoteProduct($dbProduct); + if (!$result) { + print "\nError: Create product (ID: {$obj->product_id}): " . errorsToString($eCommerceSynchro->eCommerceRemoteAccess) . ".\n"; + $error++; + } else { + $remote_id = $result; + } + } else { + // Update remote product + $result = $eCommerceSynchro->eCommerceRemoteAccess->updateRemoteProduct($obj->remote_id, $dbProduct); + if (!$result) { + print "\nError: Update product (ID: {$obj->product_id}, remote ID: {$obj->remote_id}): " . errorsToString($eCommerceSynchro->eCommerceRemoteAccess) . ".\n"; + $error++; + } + } + + if (!$error) { + if (empty($obj->link_id)) { + // Create product link + $eCommerceProduct->remote_id = $remote_id; + $eCommerceProduct->fk_site = $site->id; + $eCommerceProduct->fk_product = $dbProduct->id; + $eCommerceProduct->last_update = dol_print_date(dol_now(), '%Y-%m-%d %H:%M:%S'); + $result = $eCommerceProduct->create($user); + if ($result < 0) { + print "\nError: Create product link (ID: {$obj->product_id}): " . errorsToString($eCommerceProduct) . ".\n"; + $error++; + } + } else { + // Update product link + $result = $eCommerceProduct->fetch($obj->link_id); + if ($result > 0) { + $eCommerceProduct->last_update = dol_print_date(dol_now(), '%Y-%m-%d %H:%M:%S'); + $result = $eCommerceProduct->update($user); + } + if ($result < 0) { + print "\nError: Update product link (ID: {$obj->product_id}): " . errorsToString($eCommerceProduct) . ".\n"; + $error++; + } + } + } + + if ($error) { + $db->rollback(); + } else { + $db->commit(); + } + } + + $num_jobs++; + printStatus($num_sites, $max_sites, $num_jobs, $max_jobs); + } + + $db->free($resql); + } else { + print "\nError: SQL : $sql; Error: " . $db->lasterror() . "\n"; + continue; + } + } +} + +print "\nEnd.\n"; + +$db->close(); + +exit(0); + +function getProduct($product_id) +{ + global $db, $product_cached; + + if (!isset($product_cached[$product_id])) { + $dbProduct = new Product($db); + $dbProduct->fetch($product_id); + $dbProduct->load_stock(); + + $product_cached[$product_id] = $dbProduct; + } + + return $product_cached[$product_id]; +} + +function errorsToString($object, $separator = ', ') +{ + return $object->error . (is_array($object->errors) ? (!empty($object->error) ? $separator : '') . join($separator, $object->errors) : ''); +} + +function printStatus($num_sites, $max_sites, $num_jobs, $max_jobs) +{ + global $startTime; + + $sub_percent = $num_sites * 100 / $max_sites; + $percent = $num_jobs * $sub_percent / $max_jobs; + $elapsedTime = microtime(true) - $startTime; + $remainingTime = $percent > 0 ? $elapsedTime * (100 - $percent) / $percent : 0; + print sprintf("\rStatus: Site: %2d / %2d - Product: %6d / %6d - %3d%% - Elapsed: " . microTimeToTime($elapsedTime) . " - Remaining: " . microTimeToTime($remainingTime), $num_sites, $max_sites, $num_jobs, $max_jobs, $percent); +} + +function microTimeToTime($microtime) +{ + $hours = (int)($microtime / 60 / 60); + $minutes = (int)($microtime / 60) - $hours * 60; + $seconds = (int)$microtime - $hours * 60 * 60 - $minutes * 60; + return sprintf("%02d:%02d:%02d", $hours, $minutes, $seconds); +} \ No newline at end of file