From c1c47d122974ec6d0d832a692add46b25c2a444b Mon Sep 17 00:00:00 2001 From: Kamel Khelifa Date: Thu, 22 Aug 2024 14:57:12 +0200 Subject: [PATCH] =?UTF-8?q?-=20Correction=20et=20amelioration=20du=20suppo?= =?UTF-8?q?rt=20WPML=20pour=20les=20produits=20variables=20traduits=20sync?= =?UTF-8?q?hronis=C3=A9s=20-=20Correction=20de=20warnings=20et=20divers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog.md | 9 +- VERSION | 2 +- class/business/eCommerceSynchro.class.php | 36 +- ...eCommerceRemoteAccessWoocommerce.class.php | 122 ++- lib/eCommerce.lib.php | 878 +++++++++--------- ...ines_with_update_orders_lines_if_exist.php | 4 +- 6 files changed, 545 insertions(+), 506 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 7bffa32..6fcf63f 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,9 @@ # ChangeLog +## [14.0.11] - 22-08-2024 +- Correction et amelioration du support WPML pour les produits variables traduits synchronisés +- Correction de warnings et divers + ## [14.0.10] - 21-08-2024 - Correction et amelioration du support WPML pour les produits traduits synchronisés via les crochets WEB @@ -9,7 +13,7 @@ ## [14.0.8] - 14-08-2024 - Correction du nettoyage des id distants en doublons par site - Precision lors d'un message d'erreur lors de la synchro des categories -- Correction d'une synchro du site vers dolibarr de produit avec creation lorsque le codebare est obligatoire, il est generé maintenant automatiquement +- Correction d'une synchro du site vers dolibarr de produit avec creation lorsque le code-barre est obligatoire, il est generé maintenant automatiquement ## [14.0.7] - 01-08-2024 - Correction de la synchro des modes de paiements @@ -927,7 +931,8 @@ - Initial version. -[Non Distribué]: https://github.com/OPEN-DSI/ecommerceng_woosync/compare/14.0.10...HEAD +[Non Distribué]: https://github.com/OPEN-DSI/ecommerceng_woosync/compare/14.0.11...HEAD +[14.0.11]: https://github.com/OPEN-DSI/ecommerceng_woosync/commits/14.0.11 [14.0.10]: https://github.com/OPEN-DSI/ecommerceng_woosync/commits/14.0.10 [14.0.9]: https://github.com/OPEN-DSI/ecommerceng_woosync/commits/14.0.9 [14.0.8]: https://github.com/OPEN-DSI/ecommerceng_woosync/commits/14.0.8 diff --git a/VERSION b/VERSION index 150937c..6bd3187 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -14.0.10 \ No newline at end of file +14.0.11 \ No newline at end of file diff --git a/class/business/eCommerceSynchro.class.php b/class/business/eCommerceSynchro.class.php index a5fcdbb..f543ceb 100755 --- a/class/business/eCommerceSynchro.class.php +++ b/class/business/eCommerceSynchro.class.php @@ -3183,7 +3183,7 @@ public function synchronizeProduct($product_data, $object_origin = null) $this->errors[] = $this->langs->trans('ECommerceErrorFetchProductLinkByProductId', $product->id, $this->eCommerceSite->id); $this->errors[] = $this->eCommerceProduct->error; $error++; - } elseif ($result > 0 && strpos($product_data['remote_id'], '|') === false && preg_match('/^' . preg_quote($product_data['remote_id'] . '|') . '/', $this->eCommerceProduct->remote_id)) { + } elseif ($result > 0 && strpos($product_data['remote_id'], '|') === false && preg_match('/^' . preg_quote($product_data['remote_id'] . '|', '/') . '/', $this->eCommerceProduct->remote_id)) { // Variation who is transformed to simple // Get all product to unlink (product variations) @@ -3208,7 +3208,7 @@ public function synchronizeProduct($product_data, $object_origin = null) } $this->initECommerceProduct(); - } elseif ($result > 0 && strpos($this->eCommerceProduct->remote_id, '|') === false && preg_match('/^' . preg_quote($this->eCommerceProduct->remote_id . '|') . '/', $product_data['remote_id'])) { + } elseif ($result > 0 && strpos($this->eCommerceProduct->remote_id, '|') === false && preg_match('/^' . preg_quote($this->eCommerceProduct->remote_id . '|', '/') . '/', $product_data['remote_id'])) { // Simple who is transformed to variable $result = $this->unlinkProduct($this->eCommerceSite->id, 0, $this->eCommerceProduct->remote_id); if ($result < 0) { @@ -3316,19 +3316,19 @@ public function synchronizeProduct($product_data, $object_origin = null) $product->note = $product->note_private; if ($product->type == Product::TYPE_PRODUCT) { - $product->accountancy_code_sell = isset($this->eCommerceSite->parameters['default_account']['accounting_product_sold_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_sold_account'] : $conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT; - $product->accountancy_code_sell_intra = isset($this->eCommerceSite->parameters['default_account']['accounting_product_sold_intra_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_sold_intra_account'] : $conf->global->ACCOUNTING_PRODUCT_SOLD_INTRA_ACCOUNT; - $product->accountancy_code_sell_export = isset($this->eCommerceSite->parameters['default_account']['accounting_product_sold_export_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_sold_export_account'] : $conf->global->ACCOUNTING_PRODUCT_SOLD_EXPORT_ACCOUNT; - $product->accountancy_code_buy = isset($this->eCommerceSite->parameters['default_account']['accounting_product_buy_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_buy_account'] : $conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT; - $product->accountancy_code_buy_intra = isset($this->eCommerceSite->parameters['default_account']['accounting_product_buy_intra_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_buy_intra_account'] : $conf->global->ACCOUNTING_PRODUCT_BUY_INTRA_ACCOUNT; - $product->accountancy_code_buy_export = isset($this->eCommerceSite->parameters['default_account']['accounting_product_buy_export_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_buy_export_account'] : $conf->global->ACCOUNTING_PRODUCT_BUY_EXPORT_ACCOUNT; + $product->accountancy_code_sell = isset($this->eCommerceSite->parameters['default_account']['accounting_product_sold_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_sold_account'] : getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_ACCOUNT'); + $product->accountancy_code_sell_intra = isset($this->eCommerceSite->parameters['default_account']['accounting_product_sold_intra_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_sold_intra_account'] : getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_INTRA_ACCOUNT'); + $product->accountancy_code_sell_export = isset($this->eCommerceSite->parameters['default_account']['accounting_product_sold_export_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_sold_export_account'] : getDolGlobalString('ACCOUNTING_PRODUCT_SOLD_EXPORT_ACCOUNT'); + $product->accountancy_code_buy = isset($this->eCommerceSite->parameters['default_account']['accounting_product_buy_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_buy_account'] : getDolGlobalString('ACCOUNTING_PRODUCT_BUY_ACCOUNT'); + $product->accountancy_code_buy_intra = isset($this->eCommerceSite->parameters['default_account']['accounting_product_buy_intra_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_buy_intra_account'] : getDolGlobalString('ACCOUNTING_PRODUCT_BUY_INTRA_ACCOUNT'); + $product->accountancy_code_buy_export = isset($this->eCommerceSite->parameters['default_account']['accounting_product_buy_export_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_product_buy_export_account'] : getDolGlobalString('ACCOUNTING_PRODUCT_BUY_EXPORT_ACCOUNT'); } elseif ($product->type == Product::TYPE_SERVICE) { - $product->accountancy_code_sell = isset($this->eCommerceSite->parameters['default_account']['accounting_service_sold_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_sold_account'] : $conf->global->ACCOUNTING_SERVICE_SOLD_ACCOUNT; - $product->accountancy_code_sell_intra = isset($this->eCommerceSite->parameters['default_account']['accounting_service_sold_intra_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_sold_intra_account'] : $conf->global->ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT; - $product->accountancy_code_sell_export = isset($this->eCommerceSite->parameters['default_account']['accounting_service_sold_export_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_sold_export_account'] : $conf->global->ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT; - $product->accountancy_code_buy = isset($this->eCommerceSite->parameters['default_account']['accounting_service_buy_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_buy_account'] : $conf->global->ACCOUNTING_SERVICE_BUY_ACCOUNT; - $product->accountancy_code_buy_intra = isset($this->eCommerceSite->parameters['default_account']['accounting_service_buy_intra_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_buy_intra_account'] : $conf->global->ACCOUNTING_SERVICE_BUY_INTRA_ACCOUNT; - $product->accountancy_code_buy_export = isset($this->eCommerceSite->parameters['default_account']['accounting_service_buy_export_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_buy_export_account'] : $conf->global->ACCOUNTING_SERVICE_BUY_EXPORT_ACCOUNT; + $product->accountancy_code_sell = isset($this->eCommerceSite->parameters['default_account']['accounting_service_sold_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_sold_account'] : getDolGlobalString('ACCOUNTING_SERVICE_SOLD_ACCOUNT'); + $product->accountancy_code_sell_intra = isset($this->eCommerceSite->parameters['default_account']['accounting_service_sold_intra_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_sold_intra_account'] : getDolGlobalString('ACCOUNTING_SERVICE_SOLD_INTRA_ACCOUNT'); + $product->accountancy_code_sell_export = isset($this->eCommerceSite->parameters['default_account']['accounting_service_sold_export_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_sold_export_account'] : getDolGlobalString('ACCOUNTING_SERVICE_SOLD_EXPORT_ACCOUNT'); + $product->accountancy_code_buy = isset($this->eCommerceSite->parameters['default_account']['accounting_service_buy_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_buy_account'] : getDolGlobalString('ACCOUNTING_SERVICE_BUY_ACCOUNT'); + $product->accountancy_code_buy_intra = isset($this->eCommerceSite->parameters['default_account']['accounting_service_buy_intra_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_buy_intra_account'] : getDolGlobalString('ACCOUNTING_SERVICE_BUY_INTRA_ACCOUNT'); + $product->accountancy_code_buy_export = isset($this->eCommerceSite->parameters['default_account']['accounting_service_buy_export_account']) ? $this->eCommerceSite->parameters['default_account']['accounting_service_buy_export_account'] : getDolGlobalString('ACCOUNTING_SERVICE_BUY_EXPORT_ACCOUNT'); } $product->barcode = -1; @@ -3353,12 +3353,12 @@ public function synchronizeProduct($product_data, $object_origin = null) foreach ($product_data['translates'] as $lang => $infos) { if ($current_lang == $lang) { $product->label = $infos['label']; - // $product->description = dol_htmlcleanlastbr($infos['description']); - // $product->other = ''; + //$product->description = dol_htmlcleanlastbr($infos['description']); + //$product->other = ''; } else { $product->multilangs[$lang]["label"] = $infos['label']; - // $product->multilangs[$lang]["description"] = dol_htmlcleanlastbr($infos['description']); - // $product->multilangs[$lang]["other"] = ''; + $product->multilangs[$lang]["description"] = $product->multilangs[$lang]["description"] ?? ''; // dol_htmlcleanlastbr($infos['description'] ?? ''); + $product->multilangs[$lang]["other"] = $product->multilangs[$lang]["other"] ?? ''; } } diff --git a/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php b/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php index 09d7539..d732c3c 100755 --- a/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php +++ b/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php @@ -892,7 +892,7 @@ public function convertRemoteObjectIntoDolibarrProduct($from_date = null, $to_da 'include' => implode(',', $requestVariations), ]; - $variations = $this->client->sendToApi(eCommerceClientApi::METHOD_GET, 'products/' . $product['id'] . '/variations', [GuzzleHttp\RequestOptions::QUERY => $variation_filters]); + $variations = $this->client->sendToApi(eCommerceClientApi::METHOD_GET, 'products', [GuzzleHttp\RequestOptions::QUERY => $variation_filters]); if (!isset($variations)) { $this->errors[] = $langs->trans('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProductVariations', $this->site->name); $this->errors[] = $this->client->errorsToString(); @@ -900,6 +900,19 @@ public function convertRemoteObjectIntoDolibarrProduct($from_date = null, $to_da return false; } + if (empty($variations)) { + foreach ($requestVariations as $requestVariationsId) { + $variation = $this->client->sendToApi(eCommerceClientApi::METHOD_GET, 'products/' . $requestVariationsId); + if (!isset($variation)) { + $this->errors[] = $langs->trans('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProductVariations', $this->site->name) . ' - Remote ID : ' . $requestVariationsId; + $this->errors[] = $this->client->errorsToString(); + dol_syslog(__METHOD__ . ': Error:' . $this->errorsToString(), LOG_ERR); + return false; + } + $variations[] = $variation; + } + } + if (is_array($variations)) { foreach ($variations as $variation) { $data = $this->convertProductDataIntoProcessedData($variation, $product); @@ -970,8 +983,9 @@ public function getNameFromRemoteProductData($remote_data, $parent_remote_data) global $conf, $langs; $this->errors = array(); - $isVariation = isset($parent_remote_data) || $remote_data['parent_id'] > 0; - $parent_id = isset($parent_remote_data) ? $parent_remote_data['id'] : ($remote_data['parent_id'] > 0 ? $remote_data['parent_id'] : 0); + $parent_id = $remote_data['parent_id'] ?? 0; + if (empty($parent_id)) $parent_id = $parent_remote_data['id'] ?? 0; + $isVariation = $parent_id > 0; if ($isVariation && empty($parent_remote_data)) { $this->errors[] = $langs->trans('ECommerceWoocommerceErrorMissingParentRemoteDate'); dol_syslog(__METHOD__ . ': Error:' . $this->errorsToString(), LOG_ERR); @@ -995,7 +1009,7 @@ public function getNameFromRemoteProductData($remote_data, $parent_remote_data) $label .= ' - '; // Attributes of the variation if (!empty($remote_data['name'])) { - $label .= preg_replace('/^' . preg_quote($label) . '/', '', $remote_data['name']); + $label .= preg_replace('/^' . preg_quote($label, '/') . '/', '', $remote_data['name']); } elseif (is_array($remote_data['attributes'])) { $to_print = []; foreach ($remote_data['attributes'] as $attribute) { @@ -1005,7 +1019,7 @@ public function getNameFromRemoteProductData($remote_data, $parent_remote_data) } } } else { - $label = $remote_data['name']; + $label = $remote_data['name'] ?? ''; } // $label = dol_trunc($label, 255); @@ -1026,17 +1040,26 @@ public function convertProductDataIntoProcessedData($remote_data, $parent_remote $this->errors = array(); + if (empty($remote_data) || empty($remote_data['id'])) { + $this->errors[] = $langs->trans('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProduct', $this->site->name); + $this->errors[] = 'Remote data empty'; + dol_syslog(__METHOD__ . ': Error:' . $this->errorsToString(), LOG_ERR); + return false; + } + $multilangs = !empty($conf->global->MAIN_MULTILANGS) && !empty($this->site->parameters['enable_product_plugin_wpml_support']); - if ($multilangs) { - if (empty($remote_data['translations']) || empty($remote_data['lang'])) { - $remote_data = $this->client->sendToApi(eCommerceClientApi::METHOD_GET, 'products/' . $remote_data['id']); - if (!isset($remote_data)) { - $this->errors[] = $langs->trans('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProduct', $this->site->name); - $this->errors[] = $this->client->errorsToString(); - dol_syslog(__METHOD__ . ': Error:' . $this->errorsToString(), LOG_ERR); - return false; - } + + if (($multilangs && (empty($remote_data['translations']) || empty($remote_data['lang']))) || empty($remote_data['type'])) { + $remote_data = $this->client->sendToApi(eCommerceClientApi::METHOD_GET, 'products/' . $remote_data['id']); + if (!isset($remote_data)) { + $this->errors[] = $langs->trans('ECommerceWoocommerceConvertRemoteObjectIntoDolibarrProduct', $this->site->name); + $this->errors[] = $this->client->errorsToString(); + dol_syslog(__METHOD__ . ': Error:' . $this->errorsToString(), LOG_ERR); + return false; } + } + + if ($multilangs) { $min_remote_id = null; if (!empty($remote_data['translations'])) { foreach ($remote_data['translations'] as $l => $id) { @@ -1091,8 +1114,8 @@ public function convertProductDataIntoProcessedData($remote_data, $parent_remote // Categories $categories = []; - $parent_categories = is_array($parent_remote_data['categories']) ? $parent_remote_data['categories'] : array(); - $categories_data = is_array(($remote_data['categories'] ?? '')) ? $remote_data['categories'] : array(); + $parent_categories = is_array($parent_remote_data['categories'] ?? '') ? $parent_remote_data['categories'] : array(); + $categories_data = is_array($remote_data['categories'] ?? '') ? $remote_data['categories'] : array(); $categories_data = array_merge($categories_data, $parent_categories); foreach ($categories_data as $category) { $categories[$category['id']] = $category['id']; @@ -1178,7 +1201,7 @@ public function convertProductDataIntoProcessedData($remote_data, $parent_remote $found = false; if ($remote_lang == $remote_data['lang']) { $translated_label = $label; - $translated_description = $this->replace4byte(empty($remote_data['description']) ? $parent_remote_data['description'] : $remote_data['description']); + $translated_description = $this->replace4byte(empty($remote_data['description']) ? $parent_remote_data['description'] ?? '' : $remote_data['description']); $found = true; } else { $translated_product_data = $this->getProductLanguage($isVariation ? $remote_parent_id : $remote_data['id'], $isVariation ? $remote_data['id'] : 0, $remote_lang); @@ -1200,7 +1223,7 @@ public function convertProductDataIntoProcessedData($remote_data, $parent_remote } $translated_description = $this->replace4byte($translated_product_data['description']); // short_description $found = true; - $translations_ids[] = (isset($translated_parent_product_data) ? $translated_parent_product_data['id'] . '|' : '') . $translated_product_data['id']; + $translations_ids[] = (!empty($translated_parent_product_data['id']) ? $translated_parent_product_data['id'] . '|' : '') . $translated_product_data['id']; } } @@ -1231,7 +1254,7 @@ public function convertProductDataIntoProcessedData($remote_data, $parent_remote 'categories' => $categories, 'price_min' => '', 'fk_country' => '', - 'url' => $isVariation && $product_variation_mode_all_to_one ? $parent_remote_data['permalink'] : $remote_data['permalink'], + 'url' => $isVariation && $product_variation_mode_all_to_one ? $parent_remote_data['permalink'] ?? '' : $remote_data['permalink'], // Stock 'stock_qty' => $remote_data['stock_quantity'] < 0 ? 0 : $remote_data['stock_quantity'], 'is_in_stock' => ($remote_data['in_stock'] ?? ''), // not used @@ -1256,27 +1279,27 @@ public function convertProductDataIntoProcessedData($remote_data, $parent_remote } // Synchronize short and long description if ($productDescriptionSynchDirection == 'etod' || $productDescriptionSynchDirection == 'all') { - $product['extrafields']["ecommerceng_description_{$conf->entity}"] = $this->replace4byte(empty($remote_data['description']) ? $parent_remote_data['description'] : $remote_data['description']); + $product['extrafields']["ecommerceng_description_{$conf->entity}"] = $this->replace4byte(empty($remote_data['description']) ? $parent_remote_data['description'] ?? '' : $remote_data['description']); } if ($productShortDescriptionSynchDirection == 'etod' || $productShortDescriptionSynchDirection == 'all') { - $product['extrafields']["ecommerceng_short_description_{$conf->entity}"] = $this->replace4byte(empty($remote_data['short_description']) ? $parent_remote_data['short_description'] : $remote_data['short_description']); + $product['extrafields']["ecommerceng_short_description_{$conf->entity}"] = $this->replace4byte(empty($remote_data['short_description']) ? $parent_remote_data['short_description'] ?? '' : $remote_data['short_description']); } // Synchronize weight if ($productWeightSynchDirection == 'etod' || $productWeightSynchDirection == 'all') { - $product['weight'] = empty($remote_data['weight']) ? $parent_remote_data['weight'] : $remote_data['weight']; + $product['weight'] = empty($remote_data['weight']) ? $parent_remote_data['weight'] ?? 0 : $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'] = empty($remote_data['dimensions']['width']) ? $parent_remote_data['dimensions']['width'] ?? 0 : $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'] = empty($remote_data['dimensions']['height']) ? $parent_remote_data['dimensions']['height'] ?? 0 : $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'] = empty($remote_data['dimensions']['length']) ? $parent_remote_data['dimensions']['length'] ?? 0 : $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']); + $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']; if ($productTaxSynchDirection == 'etod' || $productTaxSynchDirection == 'all') { if ($isVariation) $product['tax_rate'] = $tax_info['tax_rate']; @@ -1284,15 +1307,15 @@ public function convertProductDataIntoProcessedData($remote_data, $parent_remote } // Synchronize status if ($productStatusSynchDirection == 'etod' || $productStatusSynchDirection == 'all') { - $product['extrafields']["ecommerceng_wc_status_{$this->site->id}_{$conf->entity}"] = empty($remote_data['status']) ? $parent_remote_data['status'] : $remote_data['status']; + $product['extrafields']["ecommerceng_wc_status_{$this->site->id}_{$conf->entity}"] = empty($remote_data['status']) ? $parent_remote_data['status'] ?? '' : $remote_data['status']; } // Synchronize images if ($productImageSynchDirection == 'etod' || $productImageSynchDirection == 'all') { $images = []; // Image of the product or the parent product if is a variation - $images_data = $isVariation ? $parent_remote_data['images'] : $remote_data['images']; - $images_data = is_array($images_data) ? $images_data : array(); + $images_data = $isVariation ? $parent_remote_data['images'] ?? [] : $remote_data['images']; + $images_data = is_array($images_data) ? $images_data : []; // Image of the variation if ($isVariation && !empty($remote_data['image'])) $images_data[] = $remote_data['image']; if ($isVariation && !empty($remote_data['images'])) { @@ -2609,37 +2632,38 @@ public function getProductLanguage($remote_product_id, $remote_product_variation { global $langs; - if (!isset($this->product_language_cached[$remote_product_id][$remote_product_variation_id][$language]) || $forced) { - $remote_product = $this->client->sendToApi(eCommerceClientApi::METHOD_GET, "products/{$remote_product_id}" . (!empty($remote_product_variation_id) ? "/variations/{$remote_product_variation_id}" : "")); + $remote_id = $remote_product_variation_id; + if (empty($remote_id)) $remote_id = $remote_product_id; + + if (!isset($this->product_language_cached[$remote_id]) || $forced) { + $remote_product = $this->client->sendToApi(eCommerceClientApi::METHOD_GET, "products/" . $remote_id); if (!isset($remote_product)) { - $this->errors[] = $langs->trans('ECommerceWoocommerceGetRemoteProduct', $remote_product_id . (!empty($remote_product_variation_id) ? "|{$remote_product_variation_id}" : ""), $this->site->name); + $this->errors[] = $langs->trans('ECommerceWoocommerceGetRemoteProduct', $remote_id, $this->site->name); $this->errors[] = $this->client->errorsToString(); dol_syslog(__METHOD__ . ': Error:' . $this->errorsToString(), LOG_ERR); return false; } - if ($remote_product['lang'] != $language) { - $found = false; - foreach ($remote_product['translations'] as $k => $v) { - if ($k == $language) { - $sub_remote_product = $this->client->sendToApi(eCommerceClientApi::METHOD_GET, "products/" . (empty($remote_product_variation_id) ? $v : $remote_product_id) . (!empty($remote_product_variation_id) ? "/variations/" . $v : "")); - if (!isset($sub_remote_product)) { - $this->errors[] = $langs->trans('ECommerceWoocommerceGetRemoteProduct', $v . (!empty($remote_product_variation_id) ? "|{$remote_product_variation_id}" : ""), $this->site->name); - $this->errors[] = $this->client->errorsToString(); - dol_syslog(__METHOD__ . ': Error:' . $this->errorsToString(), LOG_ERR); - return false; - } - $found = true; - break; + $language_list = $this->site->getLanguages(); + foreach ($language_list as $remote_lang => $lang) { + $id = $remote_product['translations'][$remote_lang] ?? 0; + + if (empty($id) || $id == $remote_product['id']) { + $this->product_language_cached[$remote_id][$remote_lang] = $remote_product; + } else { + $sub_remote_product = $this->client->sendToApi(eCommerceClientApi::METHOD_GET, "products/" . $id); + if (!isset($sub_remote_product)) { + $this->errors[] = $langs->trans('ECommerceWoocommerceGetRemoteProduct', $id, $this->site->name); + $this->errors[] = $this->client->errorsToString(); + dol_syslog(__METHOD__ . ': Error:' . $this->errorsToString(), LOG_ERR); + return false; } + $this->product_language_cached[$remote_id][$remote_lang] = $sub_remote_product; } - $remote_product = $found && !empty($sub_remote_product) ? $sub_remote_product : array(); } - - $this->product_language_cached[$remote_product_id][$remote_product_variation_id][$language] = $remote_product; } - return $this->product_language_cached[$remote_product_id][$remote_product_variation_id][$language]; + return $this->product_language_cached[$remote_id][$language] ?? []; } /** diff --git a/lib/eCommerce.lib.php b/lib/eCommerce.lib.php index fc7f686..c1ecc5a 100644 --- a/lib/eCommerce.lib.php +++ b/lib/eCommerce.lib.php @@ -17,7 +17,8 @@ */ -include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/images.lib.php'; dol_include_once('/ecommerceng/class/data/eCommerceProduct.class.php'); dol_include_once('/ecommerceng/class/business/eCommerceSynchro.class.php'); dol_include_once('/ecommerceng/class/data/woocommerce/eCommerceRemoteAccessWoocommerce.class.php'); @@ -41,15 +42,15 @@ function ecommercengConfigSitePrepareHead($object) if ($object->id > 0) { if (!empty($conf->societe->enabled)) { - $langs->load('companies'); - $head[$h][0] = dol_buildpath("/ecommerceng/admin/thirdparty.php", 1) . '?id=' . $object->id; + $langs->load('companies'); + $head[$h][0] = dol_buildpath("/ecommerceng/admin/thirdparty.php", 1) . '?id=' . $object->id; $head[$h][1] = $langs->trans("ThirdParty"); $head[$h][2] = 'thirdparty'; $h++; } if (!empty($conf->product->enabled)) { - $langs->load('products'); + $langs->load('products'); $head[$h][0] = dol_buildpath("/ecommerceng/admin/product.php", 1) . '?id=' . $object->id; $head[$h][1] = $langs->trans("Product"); $head[$h][2] = 'product'; @@ -57,7 +58,7 @@ function ecommercengConfigSitePrepareHead($object) } if (!empty($conf->stock->enabled)) { - $langs->load('products'); + $langs->load('products'); $head[$h][0] = dol_buildpath("/ecommerceng/admin/stock.php", 1) . '?id=' . $object->id; $head[$h][1] = $langs->trans("Stock"); $head[$h][2] = 'stock'; @@ -65,7 +66,7 @@ function ecommercengConfigSitePrepareHead($object) } if (!empty($conf->commande->enabled) || !empty($conf->facture->enabled)) { - $langs->loadLangs(array('orders','bills')); + $langs->loadLangs(array('orders', 'bills')); $labels = array(); if (!empty($conf->commande->enabled)) $labels[] = $langs->trans("Order"); if (!empty($conf->facture->enabled)) $labels[] = $langs->trans("Invoice"); @@ -90,9 +91,9 @@ function ecommercengConfigSitePrepareHead($object) $h++; $head[$h][0] = dol_buildpath("/ecommerceng/admin/changelog.php", 1); - $head[$h][1] = $langs->trans("OpenDsiChangeLog"); - $head[$h][2] = 'changelog'; - $h++; + $head[$h][1] = $langs->trans("OpenDsiChangeLog"); + $head[$h][2] = 'changelog'; + $h++; return $head; } @@ -105,156 +106,157 @@ function ecommercengConfigSitePrepareHead($object) */ function updatePriceLevel($siteDb) { - global $db, $conf; - - if (!empty($conf->global->PRODUIT_MULTIPRICES) && $siteDb->price_level > 0 && $siteDb->price_level <= intval($conf->global->PRODUIT_MULTIPRICES_LIMIT)) { - $sql = 'SELECT p.rowid'; - $sql.= ' FROM ' . MAIN_DB_PREFIX . 'product as p'; - $sql.= ' LEFT JOIN ' . MAIN_DB_PREFIX . "categorie_product as cp ON p.rowid = cp.fk_product"; - $sql.= ' WHERE p.entity IN (' . getEntity('product', 1) . ')'; - $sql.= ' AND cp.fk_categorie = ' . $siteDb->fk_cat_product; - $sql.= ' GROUP BY p.rowid'; - - $db->begin(); - - dol_syslog("updatePriceLevel sql=" . $sql); - $resql = $db->query($sql); - if ($resql) { - $product = new Product($db); - $eCommerceProduct = new eCommerceProduct($db); - - while ($obj = $db->fetch_object($resql)) { - $product->fetch($obj->rowid); - $eCommerceProduct->fetchByProductId($obj->rowid, $siteDb->id); - - if ($eCommerceProduct->remote_id > 0) { - $eCommerceSynchro = new eCommerceSynchro($db, $siteDb); - $eCommerceSynchro->connect(); - if (count($eCommerceSynchro->errors)) { - dol_syslog("updatePriceLevel eCommerceSynchro->connect() ".$eCommerceSynchro->error, LOG_ERR); - setEventMessages($eCommerceSynchro->error, $eCommerceSynchro->errors, 'errors'); - - $db->rollback(); - return -1; - } - - $product->price = $product->multiprices[$siteDb->price_level]; - - $result = $eCommerceSynchro->eCommerceRemoteAccess->updateRemoteProduct($eCommerceProduct->remote_id, $product); - if (!$result) { - dol_syslog("updatePriceLevel eCommerceSynchro->eCommerceRemoteAccess->updateRemoteProduct() ".$eCommerceSynchro->eCommerceRemoteAccess->error, LOG_ERR); - setEventMessages($eCommerceSynchro->eCommerceRemoteAccess->error, $eCommerceSynchro->eCommerceRemoteAccess->errors, 'errors'); - - $db->rollback(); - return -2; - } - } else { - dol_syslog("updatePriceLevel Product with id " . $product->id . " is not linked to an ecommerce record but has category flag to push on eCommerce. So we push it"); - // TODO - //$result = $eCommerceSynchro->eCommerceRemoteAccess->updateRemoteProduct($eCommerceProduct->remote_id); - } - } - } - - $db->commit(); - } - - return 1; + global $db, $conf; + + if (!empty($conf->global->PRODUIT_MULTIPRICES) && $siteDb->price_level > 0 && $siteDb->price_level <= intval($conf->global->PRODUIT_MULTIPRICES_LIMIT)) { + $sql = 'SELECT p.rowid'; + $sql .= ' FROM ' . MAIN_DB_PREFIX . 'product as p'; + $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . "categorie_product as cp ON p.rowid = cp.fk_product"; + $sql .= ' WHERE p.entity IN (' . getEntity('product', 1) . ')'; + $sql .= ' AND cp.fk_categorie = ' . $siteDb->fk_cat_product; + $sql .= ' GROUP BY p.rowid'; + + $db->begin(); + + dol_syslog("updatePriceLevel sql=" . $sql); + $resql = $db->query($sql); + if ($resql) { + $product = new Product($db); + $eCommerceProduct = new eCommerceProduct($db); + + while ($obj = $db->fetch_object($resql)) { + $product->fetch($obj->rowid); + $eCommerceProduct->fetchByProductId($obj->rowid, $siteDb->id); + + if ($eCommerceProduct->remote_id > 0) { + $eCommerceSynchro = new eCommerceSynchro($db, $siteDb); + $eCommerceSynchro->connect(); + if (count($eCommerceSynchro->errors)) { + dol_syslog("updatePriceLevel eCommerceSynchro->connect() " . $eCommerceSynchro->error, LOG_ERR); + setEventMessages($eCommerceSynchro->error, $eCommerceSynchro->errors, 'errors'); + + $db->rollback(); + return -1; + } + + $product->price = $product->multiprices[$siteDb->price_level]; + + $result = $eCommerceSynchro->eCommerceRemoteAccess->updateRemoteProduct($eCommerceProduct->remote_id, $product); + if (!$result) { + dol_syslog("updatePriceLevel eCommerceSynchro->eCommerceRemoteAccess->updateRemoteProduct() " . $eCommerceSynchro->eCommerceRemoteAccess->error, LOG_ERR); + setEventMessages($eCommerceSynchro->eCommerceRemoteAccess->error, $eCommerceSynchro->eCommerceRemoteAccess->errors, 'errors'); + + $db->rollback(); + return -2; + } + } else { + dol_syslog("updatePriceLevel Product with id " . $product->id . " is not linked to an ecommerce record but has category flag to push on eCommerce. So we push it"); + // TODO + //$result = $eCommerceSynchro->eCommerceRemoteAccess->updateRemoteProduct($eCommerceProduct->remote_id); + } + } + } + + $db->commit(); + } + + return 1; } -function ecommerceng_wordpress_sanitize_file_name( $filename ) { - //$filename_raw = $filename; - $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0)); - /** - * Filters the list of characters to remove from a filename. - * - * @since 2.8.0 - * - * @param array $special_chars Characters to remove. - * @param string $filename_raw Filename as it was passed into sanitize_file_name(). - */ - $filename = preg_replace( "#\x{00a0}#siu", ' ', $filename ); - $filename = str_replace( $special_chars, '', $filename ); - $filename = str_replace( array( '%20', '+' ), '-', $filename ); - $filename = preg_replace( '/[\r\n\t -]+/', '-', $filename ); - $filename = trim( $filename, '.-_' ); - - /*if ( false === strpos( $filename, '.' ) ) { - $mime_types = wp_get_mime_types(); - $filetype = wp_check_filetype( 'test.' . $filename, $mime_types ); - if ( $filetype['ext'] === $filename ) { - $filename = 'unnamed-file.' . $filetype['ext']; - } - }*/ - - // Split the filename into a base and extension[s] - //$parts = explode('.', $filename); - - // Return if only one extension - /*if ( count( $parts ) <= 2 ) { - /** - * Filters a sanitized filename string. - * - * @since 2.8.0 - * - * @param string $filename Sanitized filename. - * @param string $filename_raw The filename prior to sanitization. - */ - /* return apply_filters( 'sanitize_file_name', $filename, $filename_raw ); - }*/ - - // Process multiple extensions - /*$filename = array_shift($parts); - $extension = array_pop($parts); - $mimes = get_allowed_mime_types(); - - /* - * Loop over any intermediate extensions. Postfix them with a trailing underscore - * if they are a 2 - 5 character long alpha string not in the extension whitelist. - */ - /*foreach ( (array) $parts as $part) { - $filename .= '.' . $part; - - if ( preg_match("/^[a-zA-Z]{2,5}\d?$/", $part) ) { - $allowed = false; - foreach ( $mimes as $ext_preg => $mime_match ) { - $ext_preg = '!^(' . $ext_preg . ')$!i'; - if ( preg_match( $ext_preg, $part ) ) { - $allowed = true; - break; - } - } - if ( !$allowed ) - $filename .= '_'; - } - } - $filename .= '.' . $extension; - /** This filter is documented in wp-includes/formatting.php */ - //return apply_filters('sanitize_file_name', $filename, $filename_raw); - return $filename; +function ecommerceng_wordpress_sanitize_file_name( $filename ) +{ + //$filename_raw = $filename; + $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0)); + /** + * Filters the list of characters to remove from a filename. + * + * @param array $special_chars Characters to remove. + * @param string $filename_raw Filename as it was passed into sanitize_file_name(). + * @since 2.8.0 + * + */ + $filename = preg_replace("#\x{00a0}#siu", ' ', $filename); + $filename = str_replace($special_chars, '', $filename); + $filename = str_replace(array('%20', '+'), '-', $filename); + $filename = preg_replace('/[\r\n\t -]+/', '-', $filename); + $filename = trim($filename, '.-_'); + + /*if ( false === strpos( $filename, '.' ) ) { + $mime_types = wp_get_mime_types(); + $filetype = wp_check_filetype( 'test.' . $filename, $mime_types ); + if ( $filetype['ext'] === $filename ) { + $filename = 'unnamed-file.' . $filetype['ext']; + } + }*/ + + // Split the filename into a base and extension[s] + //$parts = explode('.', $filename); + + // Return if only one extension + /*if ( count( $parts ) <= 2 ) { + /** + * Filters a sanitized filename string. + * + * @since 2.8.0 + * + * @param string $filename Sanitized filename. + * @param string $filename_raw The filename prior to sanitization. + */ + /* return apply_filters( 'sanitize_file_name', $filename, $filename_raw ); + }*/ + + // Process multiple extensions + /*$filename = array_shift($parts); + $extension = array_pop($parts); + $mimes = get_allowed_mime_types(); + + /* + * Loop over any intermediate extensions. Postfix them with a trailing underscore + * if they are a 2 - 5 character long alpha string not in the extension whitelist. + */ + /*foreach ( (array) $parts as $part) { + $filename .= '.' . $part; + + if ( preg_match("/^[a-zA-Z]{2,5}\d?$/", $part) ) { + $allowed = false; + foreach ( $mimes as $ext_preg => $mime_match ) { + $ext_preg = '!^(' . $ext_preg . ')$!i'; + if ( preg_match( $ext_preg, $part ) ) { + $allowed = true; + break; + } + } + if ( !$allowed ) + $filename .= '_'; + } + } + $filename .= '.' . $extension; + /** This filter is documented in wp-includes/formatting.php */ + //return apply_filters('sanitize_file_name', $filename, $filename_raw); + return $filename; } function ecommerceng_download_image($image, $product, &$error_message) { - dol_syslog(__METHOD__.': image=' . implode(',',$image) . ' product_id=' . $product->id, LOG_DEBUG); - global $db, $conf, $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini; - - if ($product->type != Product::TYPE_PRODUCT && $product->type != Product::TYPE_SERVICE) { - $error_message = "Error the product is not a product or service type"; - dol_syslog(__METHOD__.': '.$error_message, LOG_ERR); - return false; - } - - $entity = isset($product->entity) ? $product->entity : $conf->entity; - - // Set upload directory - if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { // For backward compatiblity, we scan also old dirs - if ($product->type == Product::TYPE_PRODUCT) { - $upload_dir = $conf->product->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos"; - } else { - $upload_dir = $conf->service->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos"; - } - } else { + dol_syslog(__METHOD__ . ': image=' . implode(',', $image) . ' product_id=' . $product->id, LOG_DEBUG); + global $db, $conf, $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini; + + if ($product->type != Product::TYPE_PRODUCT && $product->type != Product::TYPE_SERVICE) { + $error_message = "Error the product is not a product or service type"; + dol_syslog(__METHOD__ . ': ' . $error_message, LOG_ERR); + return false; + } + + $entity = isset($product->entity) ? $product->entity : $conf->entity; + + // Set upload directory + if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { // For backward compatiblity, we scan also old dirs + if ($product->type == Product::TYPE_PRODUCT) { + $upload_dir = $conf->product->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos"; + } else { + $upload_dir = $conf->service->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos"; + } + } else { if (version_compare(DOL_VERSION, "13.0.0") >= 0) { if ($product->type == Product::TYPE_PRODUCT) { $upload_dir = $conf->product->multidir_output[$entity] . '/' . get_exdir(0, 0, 0, 1, $product, 'product'); @@ -268,56 +270,56 @@ function ecommerceng_download_image($image, $product, &$error_message) $upload_dir = $conf->service->multidir_output[$entity] . '/' . get_exdir(0, 0, 0, 0, $product, 'product') . dol_sanitizeFileName($product->ref); } } - } - - // Define $destpath (path to file including filename) and $destfile (only filename) - $file_name = dol_sanitizeFileName($image['filename']); //basename(parse_url($image['url'], PHP_URL_PATH)); - $destpath = $upload_dir . "/" . $file_name; - $destfile = $file_name; - - // lowercase extension - $info = pathinfo($destpath); - $destpath = $info['dirname'] . '/' . $info['filename'] . '.' . strtolower($info['extension']); - $info = pathinfo($destfile); - $destfile = $info['filename'] . '.' . strtolower($info['extension']); - - // Security: - // Disallow file with some extensions. We rename them. - // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code. - if (preg_match('/\.htm|\.html|\.php|\.pl|\.cgi|\.exe$/i', $destfile) && empty($conf->global->MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED)) { - $destfile .= '.noexe'; - $destpath .= '.noexe'; - } + } + + // Define $destpath (path to file including filename) and $destfile (only filename) + $file_name = dol_sanitizeFileName($image['filename']); //basename(parse_url($image['url'], PHP_URL_PATH)); + $destpath = $upload_dir . "/" . $file_name; + $destfile = $file_name; + + // lowercase extension + $info = pathinfo($destpath); + $destpath = $info['dirname'] . '/' . $info['filename'] . '.' . strtolower($info['extension']); + $info = pathinfo($destfile); + $destfile = $info['filename'] . '.' . strtolower($info['extension']); + + // Security: + // Disallow file with some extensions. We rename them. + // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code. + if (preg_match('/\.htm|\.html|\.php|\.pl|\.cgi|\.exe$/i', $destfile) && empty($conf->global->MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED)) { + $destfile .= '.noexe'; + $destpath .= '.noexe'; + } $destpath = dol_sanitizePathName($destpath); - // Check if image is modified - if (file_exists($destpath)) { - $local_image_date = new DateTime(); - $local_image_date->setTimestamp(filectime($destpath)); - $remote_image_date = new DateTime($image['date_modified']); - - if ($local_image_date >= $remote_image_date) { - return true; - } - } - - dol_syslog(__METHOD__.': upload_dir=' . $upload_dir . ' image=' . implode(',',$image) . ' product_id=' . $product->id . ' dest_path=' . $destpath, LOG_DEBUG); - - if (dol_mkdir($upload_dir) < 0) { - $error_message = "Error create product images directory ($upload_dir)"; - dol_syslog(__METHOD__.': '.$error_message, LOG_ERR); - return false; - } - - $error = 0; - - // Get file - $timeout = !empty($conf->global->ECOMMERCE_DOWNLOAD_TIMEOUT) ? $conf->global->ECOMMERCE_DOWNLOAD_TIMEOUT : 30; - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $image['url']); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); + // Check if image is modified + if (file_exists($destpath)) { + $local_image_date = new DateTime(); + $local_image_date->setTimestamp(filectime($destpath)); + $remote_image_date = new DateTime($image['date_modified']); + + if ($local_image_date >= $remote_image_date) { + return true; + } + } + + dol_syslog(__METHOD__ . ': upload_dir=' . $upload_dir . ' image=' . implode(',', $image) . ' product_id=' . $product->id . ' dest_path=' . $destpath, LOG_DEBUG); + + if (dol_mkdir($upload_dir) < 0) { + $error_message = "Error create product images directory ($upload_dir)"; + dol_syslog(__METHOD__ . ': ' . $error_message, LOG_ERR); + return false; + } + + $error = 0; + + // Get file + $timeout = !empty($conf->global->ECOMMERCE_DOWNLOAD_TIMEOUT) ? $conf->global->ECOMMERCE_DOWNLOAD_TIMEOUT : 30; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $image['url']); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); $userAgent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)'; if (!empty($conf->global->ECOMMERCE_USER_AGENT)) $userAgent = $conf->global->ECOMMERCE_USER_AGENT; curl_setopt($ch, CURLOPT_USERAGENT, $userAgent); @@ -333,14 +335,14 @@ function ecommerceng_download_image($image, $product, &$error_message) $data = curl_exec($ch); if (curl_errno($ch) || $data === false) { - $error_message = "CURL - " . curl_error($ch); - dol_syslog(__METHOD__.': '.$error_message, LOG_ERR); + $error_message = "CURL - " . curl_error($ch); + dol_syslog(__METHOD__ . ': ' . $error_message, LOG_ERR); $error++; } else { $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($code != 200) { $error_message = "CURL - HTTP code: $code"; - dol_syslog(__METHOD__.': '.$error_message, LOG_ERR); + dol_syslog(__METHOD__ . ': ' . $error_message, LOG_ERR); $error++; } } @@ -353,106 +355,114 @@ function ecommerceng_download_image($image, $product, &$error_message) return false; } - // Get in temporary file name - if (version_compare(phpversion(), '5.2.1', '<')) { - if ($conf->global->ECOMMERCE_DOWNLOAD_TMP_DIRECTORY_PATH) { - $tmp_path = $conf->global->ECOMMERCE_DOWNLOAD_TMP_DIRECTORY_PATH; - } else { - $error_message = "Error ECOMMERCE_DOWNLOAD_TMP_DIRECTORY_PATH not defined"; - dol_syslog(__METHOD__.': '.$error_message, LOG_ERR); - return false; - } - } else { - $tmp_path = sys_get_temp_dir(); - } - - if (dol_mkdir($tmp_path) < 0) { - $error_message = "Error create download temporary directory ($tmp_path)"; - dol_syslog(__METHOD__.': '.$error_message, LOG_ERR); - return false; - } - - // Save temporary file - $temp_file = tempnam($tmp_path, $destfile); - $fh = @fopen($temp_file, "w"); - if ($fh === false) { - $error_message = "Error open temporary file ($temp_file)"; - dol_syslog(__METHOD__.': '.$error_message, LOG_ERR); - return false; - } - $ret = fwrite($fh, $data); - if ($ret === false) { - $error_message = "Error write data in temporary file ($temp_file)"; - dol_syslog(__METHOD__.': '.$error_message, LOG_ERR); - return false; - } - $ret = fclose($fh); - if ($ret === false) { - $error_message = "Error close temporary file ($temp_file)"; - dol_syslog(__METHOD__.': '.$error_message, LOG_ERR); - return false; - } - - // If we need to make a virus scan - if (empty($disablevirusscan) && file_exists($temp_file) && !empty($conf->global->MAIN_ANTIVIRUS_COMMAND)) { - if (!class_exists('AntiVir')) { - require_once DOL_DOCUMENT_ROOT . '/core/class/antivir.class.php'; - } - $antivir = new AntiVir($db); - $result = $antivir->dol_avscan_file($temp_file); - if ($result < 0) // If virus or error, we stop here - { - $error_message = 'Error file is infected with a virus: ' . join(',', $antivir->errors); - dol_syslog('Files.lib::dol_move_uploaded_file File "' . $temp_file . '" (target name "' . $temp_file . '") KO with antivirus: result=' . $result . ' errors=' . join(',', $antivir->errors), LOG_ERR); - return false; - } - } - - if (!dol_move($temp_file, $destpath)) { - unlink($temp_file); - $error_message = "Error move temporary file ($temp_file) in product image directory ($destpath)"; - dol_syslog(__METHOD__.': '.$error_message, LOG_ERR); - return false; - } - - include_once DOL_DOCUMENT_ROOT . '/core/lib/images.lib.php'; - if (image_format_supported($destpath) == 1) { - // Create thumbs - // We can't use $object->addThumbs here because there is no $object known - - // Used on logon for example - $imgThumbSmall = vignette($destpath, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs"); - // Create mini thumbs for image (Ratio is near 16/9) - // Used on menu or for setup page for example - $imgThumbMini = vignette($destpath, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs"); - } - - return true; + // Get in temporary file name + if (version_compare(phpversion(), '5.2.1', '<')) { + if ($conf->global->ECOMMERCE_DOWNLOAD_TMP_DIRECTORY_PATH) { + $tmp_path = $conf->global->ECOMMERCE_DOWNLOAD_TMP_DIRECTORY_PATH; + } else { + $error_message = "Error ECOMMERCE_DOWNLOAD_TMP_DIRECTORY_PATH not defined"; + dol_syslog(__METHOD__ . ': ' . $error_message, LOG_ERR); + return false; + } + } else { + $tmp_path = sys_get_temp_dir(); + } + + if (dol_mkdir($tmp_path) < 0) { + $error_message = "Error create download temporary directory ($tmp_path)"; + dol_syslog(__METHOD__ . ': ' . $error_message, LOG_ERR); + return false; + } + + // Save temporary file + $temp_file = tempnam($tmp_path, $destfile); + $fh = @fopen($temp_file, "w"); + if ($fh === false) { + $error_message = "Error open temporary file ($temp_file)"; + dol_syslog(__METHOD__ . ': ' . $error_message, LOG_ERR); + return false; + } + $ret = fwrite($fh, $data); + if ($ret === false) { + $error_message = "Error write data in temporary file ($temp_file)"; + dol_syslog(__METHOD__ . ': ' . $error_message, LOG_ERR); + return false; + } + $ret = fclose($fh); + if ($ret === false) { + $error_message = "Error close temporary file ($temp_file)"; + dol_syslog(__METHOD__ . ': ' . $error_message, LOG_ERR); + return false; + } + + // If we need to make a virus scan + if (empty($disablevirusscan) && file_exists($temp_file) && !empty($conf->global->MAIN_ANTIVIRUS_COMMAND)) { + if (!class_exists('AntiVir')) { + require_once DOL_DOCUMENT_ROOT . '/core/class/antivir.class.php'; + } + $antivir = new AntiVir($db); + $result = $antivir->dol_avscan_file($temp_file); + if ($result < 0) // If virus or error, we stop here + { + $error_message = 'Error file is infected with a virus: ' . join(',', $antivir->errors); + dol_syslog('Files.lib::dol_move_uploaded_file File "' . $temp_file . '" (target name "' . $temp_file . '") KO with antivirus: result=' . $result . ' errors=' . join(',', $antivir->errors), LOG_ERR); + return false; + } + } + + if (!dol_move($temp_file, $destpath)) { + unlink($temp_file); + $error_message = "Error move temporary file ($temp_file) in product image directory ($destpath)"; + dol_syslog(__METHOD__ . ': ' . $error_message, LOG_ERR); + return false; + } + + if (image_format_supported($destpath) == 1) { + global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini, $quality; + + // Fix Define size of logo small and mini + $maxwidthsmall = $maxwidthsmall ?? 480; + $maxheightsmall = $maxheightsmall ?? 270; // Near 16/9eme + $maxwidthmini = $maxwidthmini ?? 128; + $maxheightmini = $maxheightmini ?? 72; // 16/9eme + $quality = $quality ?? 80; + + // Create thumbs + // We can't use $object->addThumbs here because there is no $object known + + // Used on logon for example + $imgThumbSmall = vignette($destpath, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs"); + // Create mini thumbs for image (Ratio is near 16/9) + // Used on menu or for setup page for example + $imgThumbMini = vignette($destpath, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs"); + } + + return true; } function ecommerceng_remove_obsolete_image($product, $images, &$error_message) { $images = is_array($images) ? $images : array(); - dol_syslog(__METHOD__.': product_id=' . $product->id . ' images=' . implode(',', $images), LOG_DEBUG); - global $db, $conf; - - if ($product->type != Product::TYPE_PRODUCT && $product->type != Product::TYPE_SERVICE) { - $error_message = "Error the product is not a product or service type"; - dol_syslog(__METHOD__.': '.$error_message, LOG_ERR); - return false; - } - - $entity = isset($product->entity) ? $product->entity : $conf->entity; - - // Set upload directory - if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { // For backward compatiblity, we scan also old dirs - if ($product->type == Product::TYPE_PRODUCT) { - $upload_dir = $conf->product->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos/"; - } else { - $upload_dir = $conf->service->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos/"; - } - } else { + dol_syslog(__METHOD__ . ': product_id=' . $product->id . ' images=' . json_encode($images), LOG_DEBUG); + global $db, $conf; + + if ($product->type != Product::TYPE_PRODUCT && $product->type != Product::TYPE_SERVICE) { + $error_message = "Error the product is not a product or service type"; + dol_syslog(__METHOD__ . ': ' . $error_message, LOG_ERR); + return false; + } + + $entity = isset($product->entity) ? $product->entity : $conf->entity; + + // Set upload directory + if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { // For backward compatiblity, we scan also old dirs + if ($product->type == Product::TYPE_PRODUCT) { + $upload_dir = $conf->product->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos/"; + } else { + $upload_dir = $conf->service->multidir_output[$entity] . '/' . substr(substr("000" . $product->id, -2), 1, 1) . '/' . substr(substr("000" . $product->id, -2), 0, 1) . '/' . $product->id . "/photos/"; + } + } else { if (version_compare(DOL_VERSION, "13.0.0") >= 0) { if ($product->type == Product::TYPE_PRODUCT) { $upload_dir = $conf->product->multidir_output[$entity] . '/' . get_exdir(0, 0, 0, 1, $product, 'product') . '/'; @@ -466,67 +476,68 @@ function ecommerceng_remove_obsolete_image($product, $images, &$error_message) $upload_dir = $conf->service->multidir_output[$entity] . '/' . get_exdir(0, 0, 0, 0, $product, 'product') . dol_sanitizeFileName($product->ref) . '/'; } } - } - - $images_name = []; - foreach ($images as $image) { - // Define $destpath (path to file including filename) and $destfile (only filename) - $file_name = dol_sanitizeFileName($image['filename']); //basename(parse_url($image['url'], PHP_URL_PATH)); - $destfile = $file_name; - - // lowercase extension - $info = pathinfo($destfile); - $destfile = $info['filename'] . '.' . strtolower($info['extension']); - - // Security: - // Disallow file with some extensions. We rename them. - // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code. - if (preg_match('/\.htm|\.html|\.php|\.pl|\.cgi|\.exe$/i', $destfile) && empty($conf->global->MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED)) { - $destfile .= '.noexe'; - } - - $images_name[] = $destfile; - } - - dol_syslog(__METHOD__.': upload_dir=' . $upload_dir . ' images=' . implode(',',$images_name) . ' product_id=' . $product->id, LOG_DEBUG); - - $photos = $product->liste_photos($upload_dir); - foreach ($photos as $index => $photo) { - if (! in_array($photo['photo'], $images_name, true)) { - unlink($upload_dir . $photo['photo']); - } - } - - return true; + } + + $images_name = []; + foreach ($images as $image) { + // Define $destpath (path to file including filename) and $destfile (only filename) + $file_name = dol_sanitizeFileName($image['filename']); //basename(parse_url($image['url'], PHP_URL_PATH)); + $destfile = $file_name; + + // lowercase extension + $info = pathinfo($destfile); + $destfile = $info['filename'] . '.' . strtolower($info['extension']); + + // Security: + // Disallow file with some extensions. We rename them. + // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code. + if (preg_match('/\.htm|\.html|\.php|\.pl|\.cgi|\.exe$/i', $destfile) && empty($conf->global->MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED)) { + $destfile .= '.noexe'; + } + + $images_name[] = $destfile; + } + + dol_syslog(__METHOD__ . ': upload_dir=' . $upload_dir . ' images=' . implode(',', $images_name) . ' product_id=' . $product->id, LOG_DEBUG); + + $photos = $product->liste_photos($upload_dir); + foreach ($photos as $index => $photo) { + if (!in_array($photo['photo'], $images_name, true)) { + unlink($upload_dir . $photo['photo']); + } + } + + return true; } -function ecommerceng_add_extrafields($db, $langs, $extrafields, &$error) { - $result = 1; - - $efields = new ExtraFields($db); - foreach ($extrafields as $extrafield) { - $result = $efields->addExtraField( - $extrafield['attrname'], - $langs->trans($extrafield['label']), - $extrafield['type'], - $extrafield['pos'], - $extrafield['size'], - $extrafield['elementtype'], - $extrafield['unique'], - $extrafield['required'], - $extrafield['default_value'], - $extrafield['param'], - $extrafield['alwayseditable'], - $extrafield['perms'], - $extrafield['list'] - ); - if ($result <= 0) { - $error = $efields->error; - return -1; - } - } - - return $result; +function ecommerceng_add_extrafields($db, $langs, $extrafields, &$error) +{ + $result = 1; + + $efields = new ExtraFields($db); + foreach ($extrafields as $extrafield) { + $result = $efields->addExtraField( + $extrafield['attrname'], + $langs->trans($extrafield['label']), + $extrafield['type'], + $extrafield['pos'], + $extrafield['size'], + $extrafield['elementtype'], + $extrafield['unique'], + $extrafield['required'], + $extrafield['default_value'], + $extrafield['param'], + $extrafield['alwayseditable'], + $extrafield['perms'], + $extrafield['list'] + ); + if ($result <= 0) { + $error = $efields->error; + return -1; + } + } + + return $result; } function ecommerceng_update_woocommerce_attribute($db, $site) @@ -551,10 +562,10 @@ function ecommerceng_update_woocommerce_attribute($db, $site) return false; } - $eCommerceDict = new eCommerceDict($db, MAIN_DB_PREFIX.'c_ecommerceng_attribute'); + $eCommerceDict = new eCommerceDict($db, MAIN_DB_PREFIX . 'c_ecommerceng_attribute'); // Get all attributes in dictionary for this entity and site - $dict_attributes = $eCommerceDict->search(['entity'=>['value'=>$conf->entity],'site_id'=>['value'=>$site->id]]); + $dict_attributes = $eCommerceDict->search(['entity' => ['value' => $conf->entity], 'site_id' => ['value' => $site->id]]); // Disable attribute not found in woocommerce foreach ($dict_attributes as $line) { @@ -569,11 +580,11 @@ function ecommerceng_update_woocommerce_attribute($db, $site) } else { $attribute = $attributes[$line['attribute_id']]; $result = $eCommerceDict->update([ - 'attribute_name' => ['value'=>$attribute['name'],'type'=>'string'], - 'attribute_slug' => ['value'=>$attribute['slug'],'type'=>'string'], - 'attribute_type' => ['value'=>$attribute['type'],'type'=>'string'], - 'attribute_order_by' => ['value'=>$attribute['order_by'],'type'=>'string'], - 'attribute_has_archives' => ['value'=>$attribute['has_archives']?1:0], + 'attribute_name' => ['value' => $attribute['name'], 'type' => 'string'], + 'attribute_slug' => ['value' => $attribute['slug'], 'type' => 'string'], + 'attribute_type' => ['value' => $attribute['type'], 'type' => 'string'], + 'attribute_order_by' => ['value' => $attribute['order_by'], 'type' => 'string'], + 'attribute_has_archives' => ['value' => $attribute['has_archives'] ? 1 : 0], ], ['rowid' => ['value' => $line['rowid']]]); if ($result == false) { setEventMessage($langs->trans('ECommerceWoocommerceErrorUpdateDictAttribute', $line['attribute_slug'], $db->error()), 'errors'); @@ -588,14 +599,14 @@ function ecommerceng_update_woocommerce_attribute($db, $site) foreach ($attributes as $attribute) { if (!isset($attribute['founded'])) { // Add new attribute - $result = $eCommerceDict->insert(['site_id','attribute_id','attribute_name','attribute_slug','attribute_type','attribute_order_by','attribute_has_archives','entity','active'], ['site_id'=>['value'=>$site->id], - 'attribute_id'=>['value'=>$attribute['id']], - 'attribute_name'=>['value'=>$attribute['name'],'type'=>'string'], - 'attribute_slug'=>['value'=>$attribute['slug'],'type'=>'string'], - 'attribute_type'=>['value'=>$attribute['type'],'type'=>'string'], - 'attribute_order_by'=>['value'=>$attribute['order_by'],'type'=>'string'], - 'attribute_has_archives'=>['value'=>$attribute['has_archives']?1:0], - 'entity'=>['value'=>$conf->entity],'active'=>['value'=>1]]); + $result = $eCommerceDict->insert(['site_id', 'attribute_id', 'attribute_name', 'attribute_slug', 'attribute_type', 'attribute_order_by', 'attribute_has_archives', 'entity', 'active'], ['site_id' => ['value' => $site->id], + 'attribute_id' => ['value' => $attribute['id']], + 'attribute_name' => ['value' => $attribute['name'], 'type' => 'string'], + 'attribute_slug' => ['value' => $attribute['slug'], 'type' => 'string'], + 'attribute_type' => ['value' => $attribute['type'], 'type' => 'string'], + 'attribute_order_by' => ['value' => $attribute['order_by'], 'type' => 'string'], + 'attribute_has_archives' => ['value' => $attribute['has_archives'] ? 1 : 0], + 'entity' => ['value' => $conf->entity], 'active' => ['value' => 1]]); if ($result == false) { setEventMessage($langs->trans('ECommerceWoocommerceErrorAddDictAttribute', $attribute['slug'], $attribute['name'], $db->error()), 'errors'); $db->rollback(); @@ -630,10 +641,10 @@ function ecommerceng_update_woocommerce_dict_tax($db, $site) return false; } - $eCommerceDict = new eCommerceDict($db, MAIN_DB_PREFIX.'c_ecommerceng_tax_class'); + $eCommerceDict = new eCommerceDict($db, MAIN_DB_PREFIX . 'c_ecommerceng_tax_class'); // Get all tax class in dictionary for this entity and site - $dict_tax_classes = $eCommerceDict->search(['entity'=>['value'=>$conf->entity],'site_id'=>['value'=>$site->id]]); + $dict_tax_classes = $eCommerceDict->search(['entity' => ['value' => $conf->entity], 'site_id' => ['value' => $site->id]]); // Desactive code not found in woocommerce foreach ($dict_tax_classes as $line) { @@ -646,7 +657,7 @@ function ecommerceng_update_woocommerce_dict_tax($db, $site) return false; } } else { - $result = $eCommerceDict->update(['label' => ['value'=>$taxClasses[$line['code']]['name'],'type'=>'string']], ['rowid' => ['value' => $line['rowid']]]); + $result = $eCommerceDict->update(['label' => ['value' => $taxClasses[$line['code']]['name'], 'type' => 'string']], ['rowid' => ['value' => $line['rowid']]]); if ($result == false) { setEventMessage($langs->trans('ECommerceWoocommerceErrorUpdateDictTaxClass', $line['code'], $db->error()), 'errors'); $db->rollback(); @@ -660,7 +671,7 @@ function ecommerceng_update_woocommerce_dict_tax($db, $site) foreach ($taxClasses as $taxClass) { if (!isset($taxClass['founded'])) { // Add new tax class code - $result = $eCommerceDict->insert(['site_id','code','label','entity','active'], ['site_id'=>['value'=>$site->id],'code'=>['value'=>$taxClass['slug'],'type'=>'string'],'label'=>['value'=>$taxClass['name'],'type'=>'string'],'entity'=>['value'=>$conf->entity],'active'=>['value'=>1]]); + $result = $eCommerceDict->insert(['site_id', 'code', 'label', 'entity', 'active'], ['site_id' => ['value' => $site->id], 'code' => ['value' => $taxClass['slug'], 'type' => 'string'], 'label' => ['value' => $taxClass['name'], 'type' => 'string'], 'entity' => ['value' => $conf->entity], 'active' => ['value' => 1]]); if ($result == false) { setEventMessage($langs->trans('ECommerceWoocommerceErrorAddDictTaxClass', $taxClass['slug'], $taxClass['name']) . ' ' . $db->error(), 'errors'); $db->rollback(); @@ -676,10 +687,10 @@ function ecommerceng_update_woocommerce_dict_tax($db, $site) return false; } - $eCommerceDict = new eCommerceDict($db, MAIN_DB_PREFIX.'c_ecommerceng_tax_rate'); + $eCommerceDict = new eCommerceDict($db, MAIN_DB_PREFIX . 'c_ecommerceng_tax_rate'); // Get all tax class in dictionary for this entity and site - $dict_tax_rates = $eCommerceDict->search(['entity'=>['value'=>$conf->entity],'site_id'=>['value'=>$site->id]]); + $dict_tax_rates = $eCommerceDict->search(['entity' => ['value' => $conf->entity], 'site_id' => ['value' => $site->id]]); // Desactive code not found in woocommerce foreach ($dict_tax_rates as $line) { @@ -694,11 +705,11 @@ function ecommerceng_update_woocommerce_dict_tax($db, $site) } else { $taxRate = $taxRates[$line['tax_id']]; $rate = price2num($taxRate['rate']); - if (strpos((string)$rate, '.') === false) $rate = $rate . '.0'; - $result = $eCommerceDict->update(['tax_country'=>['value'=>$taxRate['country'],'type'=>'string'],'tax_state'=>['value'=>$taxRate['state'],'type'=>'string'], - 'tax_postcode'=>['value'=>$taxRate['postcode'],'type'=>'string'],'tax_city'=>['value'=>$taxRate['city'],'type'=>'string'],'tax_rate'=>['value'=>$rate,'type'=>'string'], - 'tax_name'=>['value'=>$taxRate['name'],'type'=>'string'],'tax_priority'=>['value'=>$taxRate['priority']],'tax_compound'=>['value'=>$taxRate['compound']?1:0], - 'tax_shipping'=>['value'=>$taxRate['shipping']?1:0],'tax_order'=>['value'=>$taxRate['order']],'tax_class'=>['value'=>$taxRate['class'],'type'=>'string']], ['rowid' => ['value' => $line['rowid']]]); + if (strpos((string) $rate, '.') === false) $rate = $rate . '.0'; + $result = $eCommerceDict->update(['tax_country' => ['value' => $taxRate['country'], 'type' => 'string'], 'tax_state' => ['value' => $taxRate['state'], 'type' => 'string'], + 'tax_postcode' => ['value' => $taxRate['postcode'], 'type' => 'string'], 'tax_city' => ['value' => $taxRate['city'], 'type' => 'string'], 'tax_rate' => ['value' => $rate, 'type' => 'string'], + 'tax_name' => ['value' => $taxRate['name'], 'type' => 'string'], 'tax_priority' => ['value' => $taxRate['priority']], 'tax_compound' => ['value' => $taxRate['compound'] ? 1 : 0], + 'tax_shipping' => ['value' => $taxRate['shipping'] ? 1 : 0], 'tax_order' => ['value' => $taxRate['order']], 'tax_class' => ['value' => $taxRate['class'], 'type' => 'string']], ['rowid' => ['value' => $line['rowid']]]); if ($result == false) { setEventMessage($langs->trans('ECommerceWoocommerceErrorUpdateDictTaxRate', $line['tax_id'], $db->error()), 'errors'); $db->rollback(); @@ -712,14 +723,14 @@ function ecommerceng_update_woocommerce_dict_tax($db, $site) foreach ($taxRates as $taxRate) { if (!isset($taxRate['founded'])) { $rate = price2num($taxRate['rate']); - if (strpos((string)$rate, '.') === false) $rate = $rate . '.0'; + if (strpos((string) $rate, '.') === false) $rate = $rate . '.0'; // Add new tax rate - $result = $eCommerceDict->insert(['site_id','tax_id','tax_country','tax_state','tax_postcode','tax_city','tax_rate','tax_name','tax_priority','tax_compound','tax_shipping','tax_order','tax_class','entity','active'], - ['site_id'=>['value'=>$site->id],'tax_id'=>['value'=>$taxRate['id']],'tax_country'=>['value'=>$taxRate['country'],'type'=>'string'],'tax_state'=>['value'=>$taxRate['state'],'type'=>'string'], - 'tax_postcode'=>['value'=>$taxRate['postcode'],'type'=>'string'],'tax_city'=>['value'=>$taxRate['city'],'type'=>'string'],'tax_rate'=>['value'=>$rate,'type'=>'string'], - 'tax_name'=>['value'=>$taxRate['name'],'type'=>'string'],'tax_priority'=>['value'=>$taxRate['priority']],'tax_compound'=>['value'=>$taxRate['compound']?1:0], - 'tax_shipping'=>['value'=>$taxRate['shipping']?1:0],'tax_order'=>['value'=>$taxRate['order']],'tax_class'=>['value'=>$taxRate['class'],'type'=>'string'] - ,'entity'=>['value'=>$conf->entity],'active'=>['value'=>1]]); + $result = $eCommerceDict->insert(['site_id', 'tax_id', 'tax_country', 'tax_state', 'tax_postcode', 'tax_city', 'tax_rate', 'tax_name', 'tax_priority', 'tax_compound', 'tax_shipping', 'tax_order', 'tax_class', 'entity', 'active'], + ['site_id' => ['value' => $site->id], 'tax_id' => ['value' => $taxRate['id']], 'tax_country' => ['value' => $taxRate['country'], 'type' => 'string'], 'tax_state' => ['value' => $taxRate['state'], 'type' => 'string'], + 'tax_postcode' => ['value' => $taxRate['postcode'], 'type' => 'string'], 'tax_city' => ['value' => $taxRate['city'], 'type' => 'string'], 'tax_rate' => ['value' => $rate, 'type' => 'string'], + 'tax_name' => ['value' => $taxRate['name'], 'type' => 'string'], 'tax_priority' => ['value' => $taxRate['priority']], 'tax_compound' => ['value' => $taxRate['compound'] ? 1 : 0], + 'tax_shipping' => ['value' => $taxRate['shipping'] ? 1 : 0], 'tax_order' => ['value' => $taxRate['order']], 'tax_class' => ['value' => $taxRate['class'], 'type' => 'string'] + , 'entity' => ['value' => $conf->entity], 'active' => ['value' => 1]]); if ($result == false) { setEventMessage($langs->trans('ECommerceWoocommerceErrorAddDictTaxRate', $taxRate['slug'], $db->error()), 'errors'); $db->rollback(); @@ -734,56 +745,55 @@ function ecommerceng_update_woocommerce_dict_tax($db, $site) function ecommerceng_update_payment_gateways($db, $site) { - global $conf, $langs; - $langs->load('ecommerce@ecommerceng'); - - dol_include_once('/ecommerceng/class/business/eCommerceSynchro.class.php'); - $synchro = new eCommerceSynchro($db, $site, 0, 0); - - dol_syslog("site.php Try to connect to eCommerce site ".$site->name); - $synchro->connect(); - if (count($synchro->errors)) - { - setEventMessages($synchro->error, $synchro->errors, 'errors'); - return false; - } - - $paymentGateways = $synchro->getAllPaymentGateways(); - if ($paymentGateways === false) { - setEventMessages($synchro->error, $synchro->errors, 'errors'); - return false; - } - - // Get all payment gateways - dol_include_once('/ecommerceng/class/data/eCommercePaymentGateways.class.php'); - $pay_gateways = new eCommercePaymentGateways($db); - $currentPaymentGateways = $pay_gateways->get_all($site->id); - if (!is_array($currentPaymentGateways) && $currentPaymentGateways < 0) { - setEventMessages('', $pay_gateways->errors, 'errors'); - return false; - } - - $payment_gateways = array(); - foreach ($paymentGateways as $id => $label) { - $payment_gateways[$id] = array( - 'payment_gateway_label' => $label, - 'payment_mode_id' => $currentPaymentGateways[$id]['payment_mode_id'] > 0 ? $currentPaymentGateways[$id]['payment_mode_id'] : 0, - 'bank_account_id' => $currentPaymentGateways[$id]['bank_account_id'] > 0 ? $currentPaymentGateways[$id]['bank_account_id'] : 0, - 'supplier_id' => $currentPaymentGateways[$id]['supplier_id'] > 0 ? $currentPaymentGateways[$id]['supplier_id'] : 0, + global $conf, $langs; + $langs->load('ecommerce@ecommerceng'); + + dol_include_once('/ecommerceng/class/business/eCommerceSynchro.class.php'); + $synchro = new eCommerceSynchro($db, $site, 0, 0); + + dol_syslog("site.php Try to connect to eCommerce site " . $site->name); + $synchro->connect(); + if (count($synchro->errors)) { + setEventMessages($synchro->error, $synchro->errors, 'errors'); + return false; + } + + $paymentGateways = $synchro->getAllPaymentGateways(); + if ($paymentGateways === false) { + setEventMessages($synchro->error, $synchro->errors, 'errors'); + return false; + } + + // Get all payment gateways + dol_include_once('/ecommerceng/class/data/eCommercePaymentGateways.class.php'); + $pay_gateways = new eCommercePaymentGateways($db); + $currentPaymentGateways = $pay_gateways->get_all($site->id); + if (!is_array($currentPaymentGateways) && $currentPaymentGateways < 0) { + setEventMessages('', $pay_gateways->errors, 'errors'); + return false; + } + + $payment_gateways = array(); + foreach ($paymentGateways as $id => $label) { + $payment_gateways[$id] = array( + 'payment_gateway_label' => $label, + 'payment_mode_id' => $currentPaymentGateways[$id]['payment_mode_id'] > 0 ? $currentPaymentGateways[$id]['payment_mode_id'] : 0, + 'bank_account_id' => $currentPaymentGateways[$id]['bank_account_id'] > 0 ? $currentPaymentGateways[$id]['bank_account_id'] : 0, + 'supplier_id' => $currentPaymentGateways[$id]['supplier_id'] > 0 ? $currentPaymentGateways[$id]['supplier_id'] : 0, 'create_invoice_payment' => $currentPaymentGateways[$id]['create_invoice_payment'] > 0 ? $currentPaymentGateways[$id]['create_invoice_payment'] : 0, 'mail_model_for_send_invoice' => $currentPaymentGateways[$id]['mail_model_for_send_invoice'], 'product_id_for_fee' => $currentPaymentGateways[$id]['product_id_for_fee'] > 0 ? $currentPaymentGateways[$id]['product_id_for_fee'] : 0, 'create_supplier_invoice_payment' => $currentPaymentGateways[$id]['create_supplier_invoice_payment'] > 0 ? $currentPaymentGateways[$id]['create_supplier_invoice_payment'] : 0 ); - } + } - $result = $pay_gateways->set($site->id, $payment_gateways); - if ($result < 0) { - setEventMessages($pay_gateways->error, $pay_gateways->errors, 'errors'); - return false; - } + $result = $pay_gateways->set($site->id, $payment_gateways); + if ($result < 0) { + setEventMessages($pay_gateways->error, $pay_gateways->errors, 'errors'); + return false; + } - return true; + return true; } function ecommerceng_update_remote_warehouses($db, $site) @@ -827,7 +837,7 @@ function ecommerceng_update_remote_warehouses($db, $site) $finalRemoteWarehouses[$remote_warehouse_id] = array( 'remote_id' => $infos['remote_id'], 'remote_code' => $infos['remote_code'], - 'remote_name' => $infos['name'], + 'remote_name' => $infos['name'], 'warehouse_id' => $currentRemoteWarehouses[$remote_warehouse_id]['warehouse_id'] > 0 ? $currentRemoteWarehouses[$remote_warehouse_id]['warehouse_id'] : 0, 'set_even_if_empty_stock' => $currentRemoteWarehouses[$remote_warehouse_id]['set_even_if_empty_stock'] > 0 ? $currentRemoteWarehouses[$remote_warehouse_id]['set_even_if_empty_stock'] : 0, 'old_entry' => 0, @@ -840,7 +850,7 @@ function ecommerceng_update_remote_warehouses($db, $site) $finalRemoteWarehouses[$remote_warehouse_id] = array( 'remote_id' => $infos['remote_id'], 'remote_code' => $infos['remote_code'], - 'remote_name' => $infos['name'], + 'remote_name' => $infos['name'], 'warehouse_id' => $infos['warehouse_id'], 'set_even_if_empty_stock' => $infos['set_even_if_empty_stock'], 'old_entry' => 1, diff --git a/scripts/fix_invoices_lines_with_update_orders_lines_if_exist.php b/scripts/fix_invoices_lines_with_update_orders_lines_if_exist.php index bb2c925..29c9531 100644 --- a/scripts/fix_invoices_lines_with_update_orders_lines_if_exist.php +++ b/scripts/fix_invoices_lines_with_update_orders_lines_if_exist.php @@ -165,10 +165,10 @@ $num_jobs++; printStatus($num_sites, $max_sites, $num_jobs, $max_jobs); - if (preg_match('/^' . preg_quote('eCommerce-' . $site->id . '-') . '(\d+)' . preg_quote('-refund-') . '(\d+)/', $obj->ref_ext, $matches)) { + if (preg_match('/^' . preg_quote('eCommerce-' . $site->id . '-', '/') . '(\d+)' . preg_quote('-refund-', '/') . '(\d+)/', $obj->ref_ext, $matches)) { $remote_id = $matches[1]; $refund_remote_id = $matches[2]; - } elseif (preg_match('/^' . preg_quote('eCommerce-' . $site->id . '-') . '(\d+)/', $obj->ref_ext, $matches)) { + } elseif (preg_match('/^' . preg_quote('eCommerce-' . $site->id . '-', '/') . '(\d+)/', $obj->ref_ext, $matches)) { $remote_id = $matches[1]; $refund_remote_id = 0; } else {