Changeset 3301423
- Timestamp:
- 05/27/2025 11:13:07 AM (10 months ago)
- Location:
- connect-ecommerce
- Files:
-
- 4 added
- 4 deleted
- 26 edited
- 1 copied
-
tags/3.1.0 (copied) (copied from connect-ecommerce/trunk)
-
tags/3.1.0/connect-ecommerce.php (modified) (4 diffs)
-
tags/3.1.0/includes/Admin/Import_Products.php (modified) (3 diffs)
-
tags/3.1.0/includes/Admin/Settings.php (modified) (4 diffs)
-
tags/3.1.0/includes/Admin/Widget_Product.php (modified) (1 diff)
-
tags/3.1.0/includes/CLI (added)
-
tags/3.1.0/includes/CLI/Import_Products_Command.php (added)
-
tags/3.1.0/includes/Helpers/AI.php (modified) (4 diffs)
-
tags/3.1.0/includes/Helpers/HELPER.php (modified) (3 diffs)
-
tags/3.1.0/includes/Helpers/ORDER.php (modified) (1 diff)
-
tags/3.1.0/includes/Helpers/PROD.php (modified) (21 diffs)
-
tags/3.1.0/includes/Helpers/TAX.php (modified) (3 diffs)
-
tags/3.1.0/includes/Plugin_Main.php (modified) (3 diffs)
-
tags/3.1.0/includes/assets/sync-import.js (modified) (3 diffs)
-
tags/3.1.0/includes/license.md (deleted)
-
tags/3.1.0/includes/readme.md (deleted)
-
tags/3.1.0/readme.txt (modified) (2 diffs)
-
tags/3.1.0/vendor/composer/installed.php (modified) (2 diffs)
-
trunk/connect-ecommerce.php (modified) (4 diffs)
-
trunk/includes/Admin/Import_Products.php (modified) (3 diffs)
-
trunk/includes/Admin/Settings.php (modified) (4 diffs)
-
trunk/includes/Admin/Widget_Product.php (modified) (1 diff)
-
trunk/includes/CLI (added)
-
trunk/includes/CLI/Import_Products_Command.php (added)
-
trunk/includes/Helpers/AI.php (modified) (4 diffs)
-
trunk/includes/Helpers/HELPER.php (modified) (3 diffs)
-
trunk/includes/Helpers/ORDER.php (modified) (1 diff)
-
trunk/includes/Helpers/PROD.php (modified) (21 diffs)
-
trunk/includes/Helpers/TAX.php (modified) (3 diffs)
-
trunk/includes/Plugin_Main.php (modified) (3 diffs)
-
trunk/includes/assets/sync-import.js (modified) (3 diffs)
-
trunk/includes/license.md (deleted)
-
trunk/includes/readme.md (deleted)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/vendor/composer/installed.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
connect-ecommerce/tags/3.1.0/connect-ecommerce.php
r3289663 r3301423 6 6 * Author: Closetechnology 7 7 * Author URI: https://close.technology/ 8 * Version: 3. 0.18 * Version: 3.1.0 9 9 * 10 10 * @package WordPress … … 17 17 defined( 'ABSPATH' ) || exit; 18 18 19 define( 'CONECOM_VERSION', '3. 0.1' );19 define( 'CONECOM_VERSION', '3.1.0' ); 20 20 define( 'CONECOM_FILE', __FILE__ ); 21 21 define( 'CONECOM_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); … … 26 26 require_once CONECOM_PLUGIN_PATH . 'vendor/autoload.php'; 27 27 28 add_action( 'init', 'conecom_loads' ); 29 /** 30 * Connect WooCommerce loads. 31 * 32 * @return void 33 */ 34 function conecom_loads() { 35 /** 28 function conecom_get_options() { 29 /** 36 30 * Default values 37 31 */ 38 32 global $wpdb; 39 33 40 $conecom_options =apply_filters(34 return apply_filters( 41 35 'conecom_options_plugin', 42 36 [ … … 114 108 ] 115 109 ); 110 } 116 111 112 113 114 add_action( 'init', 'conecom_loads' ); 115 /** 116 * Connect WooCommerce loads. 117 * 118 * @return void 119 */ 120 function conecom_loads() { 117 121 require_once CONECOM_PLUGIN_PATH . 'includes/Plugin_Main.php'; 118 122 require_once CONECOM_PLUGIN_PATH . 'includes/Connector/class-api-clientify.php'; 119 123 124 $conecom_options = conecom_get_options(); 120 125 new CLOSE\ConnectEcommerce\Base( $conecom_options ); 121 126 } 127 128 if ( defined( 'WP_CLI' ) && WP_CLI ) { 129 require_once CONECOM_PLUGIN_PATH . 'includes/CLI/Import_Products_Command.php'; 130 131 /** 132 * Registers our command when cli get's initialized. 133 * 134 * @since 1.0.0 135 * @author David Perez 136 */ 137 function conecom_import_products_register_commands() { 138 WP_CLI::add_command('conecom', 'Import_Products_Command' ); 139 } 140 141 add_action( 'cli_init', 'conecom_import_products_register_commands', 20 ); 142 } -
connect-ecommerce/tags/3.1.0/includes/Admin/Import_Products.php
r3281293 r3301423 174 174 $product_erp_id = isset( $_POST['product_erp_id'] ) ? sanitize_text_field( wp_unslash( $_POST['product_erp_id'] ) ) : ''; 175 175 $product_sku = isset( $_POST['product_sku'] ) ? sanitize_text_field( wp_unslash( $_POST['product_sku'] ) ) : ''; 176 $product_id = isset( $_POST['product_id'] ) ? (int) $_POST['product_id'] : ''; 176 177 $message = ''; 177 178 $res_message = ''; 178 $generate_ai = isset( $_POST['product_ai'] ) ? sanitize_key( $_POST['product_ai'] ) : 'none'; 179 $generate_ai = ! empty( $_POST['product_ai'] ) ? sanitize_key( $_POST['product_ai'] ) : 'none'; 180 $generate_ai = 'true' === $generate_ai ? 'all' : $generate_ai; 179 181 $api_pagination = ! empty( $this->options['api_pagination'] ) ? $this->options['api_pagination'] : false; 180 182 … … 224 226 $this->msg_error_products = array(); 225 227 226 $result_sync = PROD::sync_product_item( $this->settings, $item, $this->connapi_erp, $ this->options['slug'], $generate_ai);228 $result_sync = PROD::sync_product_item( $this->settings, $item, $this->connapi_erp, $generate_ai, $product_id ); 227 229 $post_id = $result_sync['post_id'] ?? 0; 228 230 if ( 'error' === $result_sync['status'] ) { … … 321 323 322 324 $product_api = $this->connapi_erp->get_products( $product_id ); 323 $result = PROD::sync_product_item( $this->settings, $product_api, $this->connapi_erp , $this->options['slug']);325 $result = PROD::sync_product_item( $this->settings, $product_api, $this->connapi_erp ); 324 326 if ( $is_table_sync ) { 325 327 CRON::save_product_sync( $this->options['table_sync'], $result['prod_id'], $this->options['slug'] ); -
connect-ecommerce/tags/3.1.0/includes/Admin/Settings.php
r3289663 r3301423 67 67 */ 68 68 private $connapi_erp; 69 70 /**71 * Settings slug72 *73 * @var string74 */75 private $settings_slug;76 69 77 70 /** … … 544 537 ); 545 538 } 539 540 add_settings_field( 541 'wcpimh_make_discount', 542 __( 'Percentage to Make a discount from prices and save in sale price?', 'connect-ecommerce' ), 543 array( $this, 'pricesale_discount_option_callback' ), 544 'connect_ecommerce_admin', 545 'connect_woocommerce_setting_section' 546 ); 546 547 547 548 if ( $this->options['product_price_rate_option'] ) { … … 920 921 'catattr' => '', 921 922 'filter' => '', 923 'pricesale_discount' => '', 922 924 'filter_sku' => '', 923 925 'tax_option' => 'no', … … 1265 1267 </select> 1266 1268 <?php 1269 } 1270 1271 /** 1272 * Percentage price discount 1273 * 1274 * @return void 1275 */ 1276 public function pricesale_discount_option_callback() { 1277 printf( 1278 '<input class="regular-text" type="text" name="connect_ecommerce[' . esc_html( $this->connector ) . '][pricesale_discount]" id="wcpimh_pricesale_discount" value="%s" style="width:60px">%%', 1279 isset( $this->settings['pricesale_discount'] ) ? esc_attr( $this->settings['pricesale_discount'] ) : '' 1280 ); 1267 1281 } 1268 1282 -
connect-ecommerce/tags/3.1.0/includes/Admin/Widget_Product.php
r3289663 r3301423 87 87 echo '\'' . esc_html( $product_erp_id ) . '\','; 88 88 echo '\'' . esc_html( $product->get_sku() ) . '\','; 89 echo 'this.id)">' . esc_html__( 'Sync', 'connect-ecommerce' ) . '</div>'; 89 echo '\'' . esc_html( $product_id ) . '\','; 90 echo ')">' . esc_html__( 'Sync', 'connect-ecommerce' ) . '</div>'; 90 91 echo '</td>'; 91 92 echo '</tr>'; -
connect-ecommerce/tags/3.1.0/includes/Helpers/AI.php
r3281293 r3301423 97 97 ); 98 98 $content .= PHP_EOL . __( 'Generate a Title, Content, Title SEO and SEO description and export it in format JSON, with elements: title, body, seo_title, seo_description', 'connect-ecommerce' ); 99 $content .= PHP_EOL . __( 'Return only a valid and complete JSON object. If the content is too long, split it into multiple parts and clearly indicate when to continue. Do not include any text outside of the JSON.', 'connect-ecommerce' ); 99 100 100 101 $token = isset( $settings['token'] ) ? $settings['token'] : ''; … … 123 124 'Authorization' => 'Bearer ' . $token, 124 125 ), 126 'timeout' => 90, 125 127 'body' => wp_json_encode( 126 128 array( … … 136 138 'n' => 1, 137 139 'stream' => false, 138 'max_tokens' => 250,140 'max_tokens' => 1024, 139 141 'presence_penalty' => 0, 140 142 'frequency_penalty' => 0, … … 145 147 $response = wp_remote_post( $api_url, $args ); 146 148 $response_code = wp_remote_retrieve_response_code( $response ); 147 $ response= json_decode( wp_remote_retrieve_body( $response ), true );149 $body = json_decode( wp_remote_retrieve_body( $response ), true ); 148 150 149 151 if ( 200 !== $response_code ) { 152 $message .= sanitize_text_field( $response['error']['message'] ) ?? ''; 153 $message .= sanitize_text_field( $response['errors']['http_request_failed'] ) ?? ''; 154 $message .= $message ?? __( 'Unknown error', 'connect-ecommerce' ); 155 150 156 return array( 151 'status' => 0,152 'message' => isset( $response['error']['message'] ) ? sanitize_text_field( $response['error']['message'] ) : __( 'Unknown error', 'connect-ecommerce' ),157 'status' => 'error', 158 'message' => $message, 153 159 ); 154 160 } 155 161 $content = array(); 156 if ( isset( $response['choices'][0]['message']['content'] ) ) { 157 $content = str_replace( '```json', '', $response['choices'][0]['message']['content'] ); 158 $content = str_replace( '```', '', $content ); 162 if ( isset( $body['choices'][0]['message']['content'] ) ) { 163 error_log( '$content: ' . print_r( $body['choices'][0]['message']['content'], true ) ); 164 $content = str_replace( '```json', '', $body['choices'][0]['message']['content'] ); 165 $content = preg_replace( '/```[\w]*\s*/', '', $content ); 166 $content = trim( $content ); 159 167 $content = json_decode( $content, true ); 168 if ( json_last_error() !== JSON_ERROR_NONE ) { 169 return array( 170 'status' => 'error', 171 'message' => __( 'Error decoding JSON', 'connect-ecommerce' ) . ': ' . json_last_error_msg(), 172 ); 173 } 160 174 if ( ! is_array( $content ) ) { 161 175 $content = array(); 162 176 } 163 $message = __( 'Spent tokens: ', 'connect-ecommerce' ) . ( isset( $ response['usage']['total_tokens'] ) ? $response['usage']['total_tokens'] : 0 );177 $message = __( 'Spent tokens: ', 'connect-ecommerce' ) . ( isset( $body['usage']['total_tokens'] ) ? $body['usage']['total_tokens'] : 0 ); 164 178 } 165 179 -
connect-ecommerce/tags/3.1.0/includes/Helpers/HELPER.php
r3281293 r3301423 116 116 * @param array $source_data Source data. 117 117 * @param array $result Result of action. 118 * @param string $option_prefix Prefix of option.119 118 * 120 119 * @return void 121 120 */ 122 public static function save_log( $action, $source_data, $result , $option_prefix) {121 public static function save_log( $action, $source_data, $result ) { 123 122 $logger = wc_get_logger(); 124 123 $source_data = is_array( $source_data ) ? $source_data : array( $source_data ); … … 126 125 $message = $action . ': ' . wp_json_encode( $source_data ); 127 126 $message_res = 'result: ' . wp_json_encode( $result ); 128 $logger->debug( $message, array( 'source' => $option_prefix) );129 $logger->debug( $message_res, array( 'source' => $option_prefix) );127 $logger->debug( $message, array( 'source' => 'connect_ecommerce' ) ); 128 $logger->debug( $message_res, array( 'source' => 'connect_ecommerce' ) ); 130 129 } 131 130 … … 170 169 } 171 170 } 171 172 /** 173 * Time to text 174 * 175 * @param float $time_start Start time. 176 * @return string 177 */ 178 public static function time_total_text( $time_start ) { 179 $time_end = microtime(true); 180 181 $execution_time = round($time_end - $time_start, 2); 182 $end = "seg"; 183 184 if ( $execution_time > 3600 ) { 185 $execution_time = round($execution_time / 3600, 2); 186 $end = "horas"; 187 } elseif ( $execution_time > 60 ) { 188 $execution_time = round($execution_time / 60, 2); 189 $end = "min"; 190 } 191 return $execution_time . ' ' . $end; 192 } 172 193 } -
connect-ecommerce/tags/3.1.0/includes/Helpers/ORDER.php
r3289663 r3301423 97 97 } 98 98 if ( $is_debug_log ) { 99 HELPER::save_log( 'create_order', $order_data, $result , $option_prefix);99 HELPER::save_log( 'create_order', $order_data, $result ); 100 100 } 101 101 return $result; -
connect-ecommerce/tags/3.1.0/includes/Helpers/PROD.php
r3281293 r3301423 29 29 * @param object $api_erp API Object. 30 30 * @param bool $generate_ai Force AI. 31 * @param int $post_id Post ID when it comes forced. 31 32 * @return array 32 33 */ 33 public static function sync_product_item( $settings, $item, $api_erp, $generate_ai = false ) { 34 $post_id = 0; 34 public static function sync_product_item( $settings, $item, $api_erp, $generate_ai = false, $post_id = 0 ) { 35 35 $status = 'ok'; 36 36 $message = ''; 37 37 $is_filtered = self::filter_product( $settings, $item ); 38 38 $item_kind = ! empty( $item['kind'] ) ? $item['kind'] : 'simple'; 39 $is_new_product = self::find_product( $item['sku'] ) ? true : false; 39 $is_new_product = $post_id ? false : true; 40 41 if ( empty( $post_id ) ) { 42 $is_new_product = self::find_product( $item['sku'] ) ? true : false; 43 } 40 44 41 45 if ( in_array( 'woo-product-bundle/wpc-product-bundles.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { … … 50 54 51 55 if ( ! $is_filtered && $item['sku'] && 'simple' === $item_kind ) { 52 $result_post = self::sync_product_simple( $settings, $item, $api_erp );56 $result_post = self::sync_product_simple( $settings, $item, $api_erp, $post_id ); 53 57 $post_id = $result_post['post_id'] ?? 0; 54 58 $message .= $result_post['message'] ?? ''; … … 56 60 // Variable product. 57 61 // Check if any variants exists. 58 $post_parent = 0; 59 // Activar para buscar un archivo. 60 $any_variant_sku = false; 61 62 foreach ( $item['variants'] as $variant ) { 63 if ( ! $variant['sku'] ) { 64 break; 65 } else { 66 $any_variant_sku = true; 67 } 68 $post_parent = self::find_parent_product( $variant['sku'] ); 69 if ( $post_parent ) { 70 // Do not iterate if it's find it. 71 break; 72 } 73 } 62 $any_variant_sku = true; 63 if ( ! $post_id ) { 64 $post_id = 0; 65 // Activar para buscar un archivo. 66 $any_variant_sku = false; 67 68 foreach ( $item['variants'] as $variant ) { 69 if ( ! $variant['sku'] ) { 70 break; 71 } else { 72 $any_variant_sku = true; 73 } 74 $post_id = self::find_parent_product( $variant['sku'] ); 75 if ( $post_id ) { 76 // Do not iterate if it's find it. 77 break; 78 } 79 } 80 } 81 82 // Fix Parent product without SKU. 83 if ( $post_id ) { 84 $parent_product = wc_get_product( $post_id ); 85 if ( $parent_product && ! $parent_product->get_sku() && ! empty( $item['sku'] ) ) { 86 try { 87 $parent_product->set_sku( $item['sku'] ); 88 $parent_product->save(); 89 } catch ( \Exception $e ) {} 90 } 91 unset( $parent_product ); 92 } 93 74 94 if ( false === $any_variant_sku ) { 75 95 $message .= __( 'Product not imported becouse any variant has got SKU: ', 'connect-ecommerce' ) . $item['name'] . '(' . $item_kind . ') <br/>'; 76 96 } else { 77 97 // Update meta for product. 78 $result_prod = self::sync_product( $settings, $item, $api_erp, $post_ parent, 'variable', null );98 $result_prod = self::sync_product( $settings, $item, $api_erp, $post_id, 'variable', null ); 79 99 $post_id = $result_prod['prod_id'] ?? 0; 80 $message .= 0 === $post_ parent || false === $post_parent? $msg_product_created : $msg_product_synced;100 $message .= 0 === $post_id || false === $post_id ? $msg_product_created : $msg_product_synced; 81 101 $message .= $item['name'] . '. SKU: ' . $item['sku'] . '(' . $item_kind . ') ' . $result_prod['message'] ?? ''; 82 102 } 83 103 } elseif ( ! $is_filtered && 'pack' === $item_kind && $plugin_pack_active ) { 84 $post_id = self::find_product( $item['sku'] );104 $post_id = ! empty( $post_id ) ? $post_id : self::find_product( $item['sku'] ); 85 105 86 106 if ( ! $post_id ) { … … 144 164 $result_ai = AI::generate_description( $settings_ai, $item ); 145 165 if ( ! empty( $result_ai ) && 'ok' === $result_ai['status'] ) { 166 $message = ''; 146 167 $product_info = array( 147 168 'ID' => $post_id, … … 149 170 if ( ! empty( $result_ai['data']['title'] ) ) { 150 171 $product_info['post_title'] = $result_ai['data']['title']; 172 } else { 173 $message .= __( 'Title not generated. ', 'connect-ecommerce' ); 151 174 } 152 175 if ( ! empty( $result_ai['data']['body'] ) ) { 153 176 $product_info['post_content'] = $result_ai['data']['body']; 177 } else { 178 $message .= __( 'Post content not generated. ', 'connect-ecommerce' ); 154 179 } 155 180 if ( ! empty( $result_ai['data']['seo_description'] ) ) { 156 181 $product_info['post_excerpt'] = $result_ai['data']['seo_description']; 182 } else { 183 $message .= __( 'Post excerpt not generated. ', 'connect-ecommerce' ); 157 184 } 185 158 186 // Update product. 159 187 wp_update_post( … … 168 196 } else { 169 197 $message .= '<span class="error">' . __( 'Error AI: ', 'connect-ecommerce' ); 170 $message .= $result_ai[' error'] ?? '';198 $message .= $result_ai['message'] ?? ''; 171 199 $message .= '</span>'; 172 200 } … … 211 239 212 240 // Start. 213 if ( 'simple' === $type ) { 214 $product = new \WC_Product( $product_id ); 215 } elseif ( 'variable' === $type ) { 216 $product = new \WC_Product_Variable( $product_id ); 217 } elseif ( 'pack' === $type ) { 218 $product = new \WC_Product( $product_id ); 219 } 241 try { 242 if ( 'simple' === $type ) { 243 $product = new \WC_Product( $product_id ); 244 } elseif ( 'variable' === $type ) { 245 $product = new \WC_Product_Variable( $product_id ); 246 } elseif ( 'pack' === $type ) { 247 $product = new \WC_Product( $product_id ); 248 } 249 } catch ( \Exception $e ) { 250 return array( 251 'status' => 'error', 252 'props' => [], 253 'message' => __( 'Error creating variable product: ', 'connect-ecommerce' ) . $e->getMessage(), 254 ); 255 } 256 220 257 // Common and default properties. 221 258 $product_props = array( 222 259 'stock_status' => 'instock', 223 260 'backorders' => $allow_backorders, 224 'regular_price' => isset( $item['price'] ) ? $item['price'] : null,261 'regular_price' => self::get_rate_price( $item, $rate_id ), 225 262 'length' => isset( $item['lenght'] ) ? $item['lenght'] : '', 226 263 'width' => isset( $item['width'] ) ? $item['width'] : '', 227 264 'height' => isset( $item['height'] ) ? $item['height'] : '', 228 265 ); 266 $price_sale = self::get_sale_price( $item, $settings ); 267 if ( ! empty( $price_sale ) ) { 268 $product_props['sale_price'] = $price_sale; 269 } 229 270 $product_props_new = array(); 230 271 if ( $is_new_product ) { … … 260 301 } 261 302 262 if ( isset( $item['barcode'] ) ) { 263 $product->set_global_unique_id( $item['barcode'] ); 303 if ( ! empty( $item['barcode'] ) ) { 304 try { 305 $product->set_global_unique_id( $item['barcode'] ); 306 } catch ( \Exception $e ) { 307 // Error. 308 } 264 309 } 265 310 … … 314 359 } 315 360 316 // Set categories.361 // Set attributes. 317 362 $attributes = ! empty( $item['attributes'] ) && is_array( $item['attributes'] ) ? $item['attributes'] : array(); 318 363 $item_type = array_search( $attribute_cat_id, array_column( $attributes, 'id', 'value' ) ); … … 325 370 326 371 // Imports image. 327 self::put_product_image ( $settings, $item['id'], $product_id, $api_erp );372 self::put_product_images( $settings, $item, $product_id, $api_erp ); 328 373 329 374 // Adds custom fields. … … 389 434 * @param object $api_erp API Object. 390 435 * @param boolean $from_pack Item is a pack. 436 * @param integer $post_id Post ID. 391 437 * 392 438 * @return array 393 439 */ 394 private static function sync_product_simple( $settings, $item, $api_erp, $from_pack = false ) {440 private static function sync_product_simple( $settings, $item, $api_erp, $from_pack = false, $post_id = 0 ) { 395 441 $message = ''; 396 $post_id = self::find_product( $item['sku'] );442 $post_id = empty( $post_id ) ? $post_id : self::find_product( $item['sku'] ); 397 443 if ( ! $post_id ) { 398 444 $post_id = self::create_product_post( $settings, $item ); … … 404 450 $result_prod = self::sync_product( $settings, $item, $api_erp, $post_id, 'simple', null ); 405 451 $post_id = $result_prod['prod_id'] ?? 0; 452 453 // Add custom taxonomies. 454 self::add_custom_taxonomies( $post_id, $item ); 406 455 } 407 456 if ( $from_pack ) { … … 456 505 } 457 506 } 507 508 // Add custom taxonomies. 509 self::add_custom_taxonomies( $product_id, $item ); 458 510 459 511 // Remove variations without SKU blank. … … 491 543 } 492 544 // Make Variations. 493 if ( 'default' === $rate_id || '' === $rate_id ) { 494 if ( isset( $variant['price'] ) && $variant['price'] ) { 495 $variation_price = $variant['price']; 496 } else { 497 $variation_price = 0; 498 } 499 } else { 500 $variant_price_key = array_search( $rate_id, array_column( $variant['rates'], 'id' ) ); 501 $variation_price = $variant['rates'][ $variant_price_key ]['subtotal']; 502 } 545 $variation_price = self::get_rate_price( $variant, $rate_id ); 503 546 $variation_props = array( 504 547 'parent_id' => $product_id, … … 506 549 'regular_price' => $variation_price, 507 550 ); 551 552 $price_sale = self::get_sale_price( $variant, $settings ); 553 if ( ! empty( $price_sale ) ) { 554 $variation_props['sale_price'] = $price_sale; 555 } 508 556 if ( 0 === $variation_id ) { 509 557 // New variation. … … 522 570 } 523 571 $variation = new \WC_Product_Variation( $variation_id ); 572 if ( ! empty( $variant['barcode'] ) ) { 573 try { 574 $variation->set_global_unique_id( $item['barcode'] ); 575 } catch ( \Exception $e ) { 576 // Error. 577 } 578 } 524 579 $variation->set_props( $variation_props ); 525 580 // Stock. … … 721 776 * @return string $product_id Products id. 722 777 */ 723 public static function find_product( $sku ) {778 public static function find_product( $sku, $post_type = 'product' ) { 724 779 global $wpdb; 725 $post_type = 'product';726 780 $meta_key = '_sku'; 727 781 $result_query = $wpdb->get_var( $wpdb->prepare( "SELECT P.ID FROM $wpdb->posts AS P LEFT JOIN $wpdb->postmeta AS PM ON PM.post_id = P.ID WHERE P.post_type = '$post_type' AND PM.meta_key='$meta_key' AND PM.meta_value=%s AND P.post_status != 'trash' LIMIT 1", $sku ) ); … … 737 791 */ 738 792 public static function find_parent_product( $sku ) { 739 global $wpdb; 740 $post_id_var = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value=%s LIMIT 1", $sku ) ); 793 $post_id_var = self::find_product( $sku, 'product_variation' ); 741 794 742 795 if ( $post_id_var ) { 743 $post_parent = wp_get_post_parent_id( $post_id_var );796 $post_parent = wp_get_post_parent_id( (int) $post_id_var ); 744 797 return $post_parent; 745 798 } … … 808 861 * Gets image from API products 809 862 * 810 * @param string $item _id Idof API to get information.863 * @param string $item Item of API to get information. 811 864 * @param string $product_id Id of product to get information. 812 865 * @param object $api_erp API Object. 813 866 * 814 * @return array Array of products imported via API. 815 */ 816 public static function put_product_image( $settings, $item_id, $product_id, $api_erp ) { 817 // Don't import if there is thumbnail. 818 if ( has_post_thumbnail( $product_id ) ) { 867 * @return void 868 */ 869 public static function put_product_images( $settings, $item, $product_id, $api_erp ) { 870 if ( self::has_valid_thumbnail( $product_id ) ) { 819 871 return false; 820 872 } 821 873 822 $result_api = $api_erp->get_image_product( $settings, $item_id, $product_id ); 823 824 if ( isset( $result_api['upload']['url'] ) ) { 825 $attachment = array( 826 'guid' => $result_api['upload']['url'], 827 'post_mime_type' => $result_api['content_type'], 828 'post_title' => get_the_title( $product_id ), 829 'post_content' => '', 830 'post_status' => 'inherit', 831 ); 832 $attach_id = wp_insert_attachment( $attachment, $result_api['upload']['file'], 0 ); 833 add_post_meta( $product_id, '_thumbnail_id', $attach_id, true ); 874 $images = array(); 875 if ( ! empty( $item['images'] ) ) { 876 $images = $item['images'] ?? array(); 877 } else { 878 // Ask API for image. 879 $result_api = $api_erp->get_image_product( $settings, $item['id'], $product_id ); 834 880 835 881 if ( isset( $body_response['errors'] ) ) { … … 838 884 return false; 839 885 } 840 841 return $attach_id; 886 if ( isset( $result_api['upload']['url'] ) ){ 887 $images[] = [ 888 'url' => $result_api['upload']['url'], 889 'file' => $result_api['upload']['file'], 890 'content_type' => $result_api['content_type'], 891 ]; 892 } 893 } 894 895 if ( empty( $images ) ) { 896 return; 897 } 898 899 $first_image = true; 900 foreach ( $images as $image ) { 901 $attachment = array( 902 'guid' => $image['url'] ?? '', 903 'post_mime_type' => $image['content_type'] ?? '', 904 'post_title' => $image['title'] ?? get_the_title( $product_id ), 905 'post_content' => $image['content'] ?? '', 906 'post_status' => 'inherit', 907 ); 908 909 if ( empty( $image['file'] ) ) { 910 // Download image to server 911 $image_url = $image['url'] ?? ''; 912 if ( empty( $image_url ) ) { 913 continue; 914 } 915 916 $file_array = []; 917 $file_array['name'] = basename( $image_url ); 918 $file_array['tmp_name'] = download_url( $image_url ); 919 920 // Check for download errors 921 if ( is_wp_error( $file_array['tmp_name'] ) ) { 922 continue; 923 } 924 925 $attach_id = media_handle_sideload( $file_array, $product_id, $attachment['post_title'], $attachment ); 926 927 // Check for attachment errors 928 if (is_wp_error($attach_id)) { 929 @unlink($file_array['tmp_name']); 930 continue; 931 } 932 } else { 933 if ( ! file_exists( $image['file'] ) ) { 934 continue; 935 } 936 937 $attach_id = wp_insert_attachment( $attachment, $image['file'], 0 ); 938 } 939 940 if ( $first_image ) { 941 $first_image = false; 942 // Set the product image. 943 add_post_meta( $product_id, '_thumbnail_id', $attach_id, true ); 944 } else { 945 // Add the image to the product gallery. 946 $gallery = get_post_meta( $product_id, '_product_image_gallery', true ); 947 $gallery = $gallery ? $gallery . ',' . $attach_id : $attach_id; 948 update_post_meta( $product_id, '_product_image_gallery', $gallery ); 949 } 842 950 } 843 951 } … … 956 1064 } 957 1065 } 1066 1067 /** 1068 * Get sale price from item 1069 * 1070 * @param array $item Item from API. 1071 * @param array $settings Settings of the plugin. 1072 * 1073 * @return string 1074 */ 1075 private static function get_sale_price( $item, $settings ) { 1076 $pricesale_discount = (float) $settings['pricesale_discount'] ?? 0; 1077 if ( empty( $pricesale_discount ) || empty( $item['price'] ) ) { 1078 return ''; 1079 } 1080 $price_sale = $item['price'] - ( $item['price'] * ( $pricesale_discount / 100 ) ); 1081 if ( $price_sale > 0 ) { 1082 return number_format( $price_sale, 2, '.', '' ); 1083 } else { 1084 return ''; 1085 } 1086 } 1087 1088 /** 1089 * Get attribute category ID 1090 * 1091 * @param array $item Item from API. 1092 * 1093 * @return int 1094 */ 1095 private static function get_rate_price( $item, $rate_id ) { 1096 if ( empty( $item ) ) { 1097 return null; 1098 } 1099 if ( 'default' === $rate_id || '' === $rate_id || empty( $item['rates'] ) || ! is_array( $item['rates'] ) ) { 1100 return isset( $item['price'] ) ? $item['price'] : null; 1101 } else { 1102 $price_key = array_search( $rate_id, array_column( $item['rates'], 'id' ) ); 1103 return isset( $item['rates'][ $price_key ]['subtotal'] ) ? $item['rates'][ $price_key ]['subtotal'] : null; 1104 } 1105 } 1106 1107 /** 1108 * Add custom taxonomies to product 1109 * 1110 * @param int $product_id Product ID. 1111 * @param array $item Item from API. 1112 * 1113 * @return void 1114 */ 1115 private static function add_custom_taxonomies( $product_id, $item ) { 1116 // Set taxonomies. 1117 if ( ! empty( $item['taxonomies'] ) && is_array( $item['taxonomies'] ) ) { 1118 foreach ( $item['taxonomies'] as $taxonomy ) { 1119 if ( empty( $taxonomy['id'] ) || empty( $taxonomy['value'] ) ) { 1120 continue; 1121 } 1122 TAX::assign_product_term( $product_id, $taxonomy['id'], $taxonomy['value'], true ); 1123 } 1124 } 1125 } 1126 1127 /** 1128 * Checks if product has a valid thumbnail. 1129 * 1130 * @param int $product_id Product ID. 1131 * @return bool 1132 */ 1133 private static function has_valid_thumbnail( $product_id ) { 1134 $thumbnail_id = get_post_thumbnail_id( $product_id ); 1135 if ( ! $thumbnail_id ) { 1136 return false; 1137 } 1138 $image_path = get_attached_file( $thumbnail_id ); 1139 if ( ! $image_path || ! file_exists( $image_path ) ) { 1140 return false; 1141 } 1142 $image_url = wp_get_attachment_url( $thumbnail_id ); 1143 if ( ! $image_url ) { 1144 return false; 1145 } 1146 return true; 1147 } 958 1148 } -
connect-ecommerce/tags/3.1.0/includes/Helpers/TAX.php
r3281293 r3301423 218 218 * @param string $post_id Post id of actual post id. 219 219 * @param array $taxonomy_slug Slug of taxonomy. 220 * @param array $category_array Array of category.220 * @param array|string $terms Array of terms. 221 221 * @return void 222 222 */ 223 p rivate static function assign_product_term( $post_id, $taxonomy_slug, $category_array) {223 public static function assign_product_term( $post_id, $taxonomy_slug, $terms ) { 224 224 $parent_term = ''; 225 $term_levels = count( $category_array ); 225 $terms = is_array( $terms ) ? $terms : array( $terms ); 226 $term_levels = count( $terms ); 226 227 $term_level_index = 1; 227 228 228 foreach ( $ category_array as $category_name) {229 $ category_name = self::sanitize_text( $category_name);230 $search_term = term_exists( $category_name, $taxonomy_slug );229 foreach ( $terms as $term ) { 230 $term = self::sanitize_text( $term ); 231 $search_term = term_exists( $term, $taxonomy_slug ); 231 232 232 233 if ( 0 === $search_term || null === $search_term ) { 233 234 // Creates taxonomy. 234 235 $args_term = array( 235 'slug' => sanitize_title( $ category_name),236 'slug' => sanitize_title( $term ), 236 237 ); 237 238 if ( $parent_term ) { … … 239 240 } 240 241 $search_term = wp_insert_term( 241 $ category_name,242 $term, 242 243 $taxonomy_slug, 243 244 $args_term 244 245 ); 245 246 } 246 if ( $term_level_index === $term_levels ) { 247 wp_set_object_terms( $post_id, (int) $search_term['term_id'], $taxonomy_slug ); 247 248 // Check if term was found or created successfully 249 if ( ! is_wp_error( $search_term ) && $term_level_index === $term_levels ) { 250 $term_id = isset( $search_term['term_id'] ) ? (int) $search_term['term_id'] : (int) $search_term; 251 wp_set_object_terms( $post_id, $term_id, $taxonomy_slug ); 248 252 } 249 253 250 254 // Next iteration for child. 251 $parent_term = $search_term['term_id'];255 $parent_term = (int) $search_term['term_id']; 252 256 $term_level_index++; 253 257 } … … 262 266 private static function sanitize_text( $text ) { 263 267 $text = str_replace( '>', '>', $text ); 264 return $text;268 return sanitize_text_field( $text ); 265 269 } 266 270 -
connect-ecommerce/tags/3.1.0/includes/Plugin_Main.php
r3281293 r3301423 28 28 29 29 /** 30 * Options of plugin. 31 * 32 * @var array 33 */ 34 private $options = array(); 35 36 /** 30 37 * Construct of class 31 38 * … … 33 40 */ 34 41 public function __construct( $options = array() ) { 42 $this->options = $options; 35 43 if ( is_admin() ) { 36 44 new Settings( $options ); … … 44 52 new MyAccount( $options ); 45 53 } 54 55 /** 56 * Get options of plugin. 57 * 58 * @return array 59 */ 60 public function get_options( ) { 61 return $this->options; 62 } 46 63 } -
connect-ecommerce/tags/3.1.0/includes/assets/sync-import.js
r3281293 r3301423 44 44 } 45 45 46 function syncProductERP( element, action, product_erp_id = 0, product_sku = '' ) {46 function syncProductERP( element, action, product_erp_id = 0, product_sku = '', product_id = 0 ) { 47 47 element.classList.add('disabled'); 48 48 element.innerHTML = ConEcom_ajaxAction.label_syncing + ' <span class="spinner is-active"></span>'; … … 58 58 'Cache-Control': 'no-cache', 59 59 }, 60 body: 'action=' + action + '&nonce=' + ConEcom_ajaxAction.nonce + '&loop=' + loop + '&product_erp_id=' + product_erp_id + '&product_sku=' + product_sku + '&product_ ai=' + productAI,60 body: 'action=' + action + '&nonce=' + ConEcom_ajaxAction.nonce + '&loop=' + loop + '&product_erp_id=' + product_erp_id + '&product_sku=' + product_sku + '&product_id=' + product_id + '&product_ai=' + productAI, 61 61 }) 62 62 .then( (resp) => resp.json() ) … … 65 65 element.innerHTML = ConEcom_ajaxAction.label_sync; 66 66 67 // Refresh the page 68 location.reload(); 67 console.log(results.data); 68 // Message handling 69 if (results.data.message !== undefined) { 70 const aiInput = document.querySelector('#connect_ecommerce_ai'); 71 if (aiInput) { 72 const aiLabel = aiInput.closest('label'); 73 const aiMessage = document.createElement('div'); 74 aiMessage.className = 'ai-message'; 75 aiMessage.innerHTML = results.data.message; 76 77 const targetElement = aiLabel || aiInput; 78 if (targetElement.nextSibling) { 79 targetElement.parentNode.insertBefore(aiMessage, targetElement.nextSibling); 80 } else { 81 targetElement.parentNode.appendChild(aiMessage); 82 } 83 } 84 } 85 86 // Reload the page after 8 seconds if the sync was successful 87 if (results.success) { 88 setTimeout(() => { 89 window.location.reload(); 90 }, 8000); 91 } 69 92 }) 70 93 .catch(err => console.log(err)); -
connect-ecommerce/tags/3.1.0/readme.txt
r3289663 r3301423 47 47 [Official Repository GitHub](https://github.com/closemarketing/connect-ecommerce) 48 48 49 You can use WP CLI to import products from the command line. The command is: 50 ``` 51 wp conecom products --update --ai=none,new,all 52 ``` 53 49 54 == External services == 50 55 … … 59 64 60 65 == Changelog == 66 67 = 3.1.0 = 68 * Added: WP CLI command to import products. 69 * Fully support to import EAN to WooCommerce. 70 * Added: Import image products with different method. 71 * Added: Result API import in widget product. 72 * Added: Save parent SKU in product if does not exist. 73 * Added: Check if image product file exists before import. 74 * Fixed: AI connection not working in some cases. 75 * Fixed: Some errors getting products from shop to syncronize. 76 * Fixed: Not getting prices rates from API. 77 * Fixed: Prevent error when WooCommerce does not load the product. 61 78 62 79 = 3.0.1 = -
connect-ecommerce/tags/3.1.0/vendor/composer/installed.php
r3289663 r3301423 2 2 'root' => array( 3 3 'name' => 'closemarketing/connect-ecommerce', 4 'pretty_version' => '3. 0.1',5 'version' => '3. 0.1.0',6 'reference' => ' 4b85748d444a7a4ddea31f4494598d5fffd54f4a',4 'pretty_version' => '3.1.0', 5 'version' => '3.1.0.0', 6 'reference' => 'f3639f9784b938002847fc0b6395dc83d2c1b030', 7 7 'type' => 'library', 8 8 'install_path' => __DIR__ . '/../../', … … 12 12 'versions' => array( 13 13 'closemarketing/connect-ecommerce' => array( 14 'pretty_version' => '3. 0.1',15 'version' => '3. 0.1.0',16 'reference' => ' 4b85748d444a7a4ddea31f4494598d5fffd54f4a',14 'pretty_version' => '3.1.0', 15 'version' => '3.1.0.0', 16 'reference' => 'f3639f9784b938002847fc0b6395dc83d2c1b030', 17 17 'type' => 'library', 18 18 'install_path' => __DIR__ . '/../../', -
connect-ecommerce/trunk/connect-ecommerce.php
r3289663 r3301423 6 6 * Author: Closetechnology 7 7 * Author URI: https://close.technology/ 8 * Version: 3. 0.18 * Version: 3.1.0 9 9 * 10 10 * @package WordPress … … 17 17 defined( 'ABSPATH' ) || exit; 18 18 19 define( 'CONECOM_VERSION', '3. 0.1' );19 define( 'CONECOM_VERSION', '3.1.0' ); 20 20 define( 'CONECOM_FILE', __FILE__ ); 21 21 define( 'CONECOM_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); … … 26 26 require_once CONECOM_PLUGIN_PATH . 'vendor/autoload.php'; 27 27 28 add_action( 'init', 'conecom_loads' ); 29 /** 30 * Connect WooCommerce loads. 31 * 32 * @return void 33 */ 34 function conecom_loads() { 35 /** 28 function conecom_get_options() { 29 /** 36 30 * Default values 37 31 */ 38 32 global $wpdb; 39 33 40 $conecom_options =apply_filters(34 return apply_filters( 41 35 'conecom_options_plugin', 42 36 [ … … 114 108 ] 115 109 ); 110 } 116 111 112 113 114 add_action( 'init', 'conecom_loads' ); 115 /** 116 * Connect WooCommerce loads. 117 * 118 * @return void 119 */ 120 function conecom_loads() { 117 121 require_once CONECOM_PLUGIN_PATH . 'includes/Plugin_Main.php'; 118 122 require_once CONECOM_PLUGIN_PATH . 'includes/Connector/class-api-clientify.php'; 119 123 124 $conecom_options = conecom_get_options(); 120 125 new CLOSE\ConnectEcommerce\Base( $conecom_options ); 121 126 } 127 128 if ( defined( 'WP_CLI' ) && WP_CLI ) { 129 require_once CONECOM_PLUGIN_PATH . 'includes/CLI/Import_Products_Command.php'; 130 131 /** 132 * Registers our command when cli get's initialized. 133 * 134 * @since 1.0.0 135 * @author David Perez 136 */ 137 function conecom_import_products_register_commands() { 138 WP_CLI::add_command('conecom', 'Import_Products_Command' ); 139 } 140 141 add_action( 'cli_init', 'conecom_import_products_register_commands', 20 ); 142 } -
connect-ecommerce/trunk/includes/Admin/Import_Products.php
r3281293 r3301423 174 174 $product_erp_id = isset( $_POST['product_erp_id'] ) ? sanitize_text_field( wp_unslash( $_POST['product_erp_id'] ) ) : ''; 175 175 $product_sku = isset( $_POST['product_sku'] ) ? sanitize_text_field( wp_unslash( $_POST['product_sku'] ) ) : ''; 176 $product_id = isset( $_POST['product_id'] ) ? (int) $_POST['product_id'] : ''; 176 177 $message = ''; 177 178 $res_message = ''; 178 $generate_ai = isset( $_POST['product_ai'] ) ? sanitize_key( $_POST['product_ai'] ) : 'none'; 179 $generate_ai = ! empty( $_POST['product_ai'] ) ? sanitize_key( $_POST['product_ai'] ) : 'none'; 180 $generate_ai = 'true' === $generate_ai ? 'all' : $generate_ai; 179 181 $api_pagination = ! empty( $this->options['api_pagination'] ) ? $this->options['api_pagination'] : false; 180 182 … … 224 226 $this->msg_error_products = array(); 225 227 226 $result_sync = PROD::sync_product_item( $this->settings, $item, $this->connapi_erp, $ this->options['slug'], $generate_ai);228 $result_sync = PROD::sync_product_item( $this->settings, $item, $this->connapi_erp, $generate_ai, $product_id ); 227 229 $post_id = $result_sync['post_id'] ?? 0; 228 230 if ( 'error' === $result_sync['status'] ) { … … 321 323 322 324 $product_api = $this->connapi_erp->get_products( $product_id ); 323 $result = PROD::sync_product_item( $this->settings, $product_api, $this->connapi_erp , $this->options['slug']);325 $result = PROD::sync_product_item( $this->settings, $product_api, $this->connapi_erp ); 324 326 if ( $is_table_sync ) { 325 327 CRON::save_product_sync( $this->options['table_sync'], $result['prod_id'], $this->options['slug'] ); -
connect-ecommerce/trunk/includes/Admin/Settings.php
r3289663 r3301423 67 67 */ 68 68 private $connapi_erp; 69 70 /**71 * Settings slug72 *73 * @var string74 */75 private $settings_slug;76 69 77 70 /** … … 544 537 ); 545 538 } 539 540 add_settings_field( 541 'wcpimh_make_discount', 542 __( 'Percentage to Make a discount from prices and save in sale price?', 'connect-ecommerce' ), 543 array( $this, 'pricesale_discount_option_callback' ), 544 'connect_ecommerce_admin', 545 'connect_woocommerce_setting_section' 546 ); 546 547 547 548 if ( $this->options['product_price_rate_option'] ) { … … 920 921 'catattr' => '', 921 922 'filter' => '', 923 'pricesale_discount' => '', 922 924 'filter_sku' => '', 923 925 'tax_option' => 'no', … … 1265 1267 </select> 1266 1268 <?php 1269 } 1270 1271 /** 1272 * Percentage price discount 1273 * 1274 * @return void 1275 */ 1276 public function pricesale_discount_option_callback() { 1277 printf( 1278 '<input class="regular-text" type="text" name="connect_ecommerce[' . esc_html( $this->connector ) . '][pricesale_discount]" id="wcpimh_pricesale_discount" value="%s" style="width:60px">%%', 1279 isset( $this->settings['pricesale_discount'] ) ? esc_attr( $this->settings['pricesale_discount'] ) : '' 1280 ); 1267 1281 } 1268 1282 -
connect-ecommerce/trunk/includes/Admin/Widget_Product.php
r3289663 r3301423 87 87 echo '\'' . esc_html( $product_erp_id ) . '\','; 88 88 echo '\'' . esc_html( $product->get_sku() ) . '\','; 89 echo 'this.id)">' . esc_html__( 'Sync', 'connect-ecommerce' ) . '</div>'; 89 echo '\'' . esc_html( $product_id ) . '\','; 90 echo ')">' . esc_html__( 'Sync', 'connect-ecommerce' ) . '</div>'; 90 91 echo '</td>'; 91 92 echo '</tr>'; -
connect-ecommerce/trunk/includes/Helpers/AI.php
r3281293 r3301423 97 97 ); 98 98 $content .= PHP_EOL . __( 'Generate a Title, Content, Title SEO and SEO description and export it in format JSON, with elements: title, body, seo_title, seo_description', 'connect-ecommerce' ); 99 $content .= PHP_EOL . __( 'Return only a valid and complete JSON object. If the content is too long, split it into multiple parts and clearly indicate when to continue. Do not include any text outside of the JSON.', 'connect-ecommerce' ); 99 100 100 101 $token = isset( $settings['token'] ) ? $settings['token'] : ''; … … 123 124 'Authorization' => 'Bearer ' . $token, 124 125 ), 126 'timeout' => 90, 125 127 'body' => wp_json_encode( 126 128 array( … … 136 138 'n' => 1, 137 139 'stream' => false, 138 'max_tokens' => 250,140 'max_tokens' => 1024, 139 141 'presence_penalty' => 0, 140 142 'frequency_penalty' => 0, … … 145 147 $response = wp_remote_post( $api_url, $args ); 146 148 $response_code = wp_remote_retrieve_response_code( $response ); 147 $ response= json_decode( wp_remote_retrieve_body( $response ), true );149 $body = json_decode( wp_remote_retrieve_body( $response ), true ); 148 150 149 151 if ( 200 !== $response_code ) { 152 $message .= sanitize_text_field( $response['error']['message'] ) ?? ''; 153 $message .= sanitize_text_field( $response['errors']['http_request_failed'] ) ?? ''; 154 $message .= $message ?? __( 'Unknown error', 'connect-ecommerce' ); 155 150 156 return array( 151 'status' => 0,152 'message' => isset( $response['error']['message'] ) ? sanitize_text_field( $response['error']['message'] ) : __( 'Unknown error', 'connect-ecommerce' ),157 'status' => 'error', 158 'message' => $message, 153 159 ); 154 160 } 155 161 $content = array(); 156 if ( isset( $response['choices'][0]['message']['content'] ) ) { 157 $content = str_replace( '```json', '', $response['choices'][0]['message']['content'] ); 158 $content = str_replace( '```', '', $content ); 162 if ( isset( $body['choices'][0]['message']['content'] ) ) { 163 error_log( '$content: ' . print_r( $body['choices'][0]['message']['content'], true ) ); 164 $content = str_replace( '```json', '', $body['choices'][0]['message']['content'] ); 165 $content = preg_replace( '/```[\w]*\s*/', '', $content ); 166 $content = trim( $content ); 159 167 $content = json_decode( $content, true ); 168 if ( json_last_error() !== JSON_ERROR_NONE ) { 169 return array( 170 'status' => 'error', 171 'message' => __( 'Error decoding JSON', 'connect-ecommerce' ) . ': ' . json_last_error_msg(), 172 ); 173 } 160 174 if ( ! is_array( $content ) ) { 161 175 $content = array(); 162 176 } 163 $message = __( 'Spent tokens: ', 'connect-ecommerce' ) . ( isset( $ response['usage']['total_tokens'] ) ? $response['usage']['total_tokens'] : 0 );177 $message = __( 'Spent tokens: ', 'connect-ecommerce' ) . ( isset( $body['usage']['total_tokens'] ) ? $body['usage']['total_tokens'] : 0 ); 164 178 } 165 179 -
connect-ecommerce/trunk/includes/Helpers/HELPER.php
r3281293 r3301423 116 116 * @param array $source_data Source data. 117 117 * @param array $result Result of action. 118 * @param string $option_prefix Prefix of option.119 118 * 120 119 * @return void 121 120 */ 122 public static function save_log( $action, $source_data, $result , $option_prefix) {121 public static function save_log( $action, $source_data, $result ) { 123 122 $logger = wc_get_logger(); 124 123 $source_data = is_array( $source_data ) ? $source_data : array( $source_data ); … … 126 125 $message = $action . ': ' . wp_json_encode( $source_data ); 127 126 $message_res = 'result: ' . wp_json_encode( $result ); 128 $logger->debug( $message, array( 'source' => $option_prefix) );129 $logger->debug( $message_res, array( 'source' => $option_prefix) );127 $logger->debug( $message, array( 'source' => 'connect_ecommerce' ) ); 128 $logger->debug( $message_res, array( 'source' => 'connect_ecommerce' ) ); 130 129 } 131 130 … … 170 169 } 171 170 } 171 172 /** 173 * Time to text 174 * 175 * @param float $time_start Start time. 176 * @return string 177 */ 178 public static function time_total_text( $time_start ) { 179 $time_end = microtime(true); 180 181 $execution_time = round($time_end - $time_start, 2); 182 $end = "seg"; 183 184 if ( $execution_time > 3600 ) { 185 $execution_time = round($execution_time / 3600, 2); 186 $end = "horas"; 187 } elseif ( $execution_time > 60 ) { 188 $execution_time = round($execution_time / 60, 2); 189 $end = "min"; 190 } 191 return $execution_time . ' ' . $end; 192 } 172 193 } -
connect-ecommerce/trunk/includes/Helpers/ORDER.php
r3289663 r3301423 97 97 } 98 98 if ( $is_debug_log ) { 99 HELPER::save_log( 'create_order', $order_data, $result , $option_prefix);99 HELPER::save_log( 'create_order', $order_data, $result ); 100 100 } 101 101 return $result; -
connect-ecommerce/trunk/includes/Helpers/PROD.php
r3281293 r3301423 29 29 * @param object $api_erp API Object. 30 30 * @param bool $generate_ai Force AI. 31 * @param int $post_id Post ID when it comes forced. 31 32 * @return array 32 33 */ 33 public static function sync_product_item( $settings, $item, $api_erp, $generate_ai = false ) { 34 $post_id = 0; 34 public static function sync_product_item( $settings, $item, $api_erp, $generate_ai = false, $post_id = 0 ) { 35 35 $status = 'ok'; 36 36 $message = ''; 37 37 $is_filtered = self::filter_product( $settings, $item ); 38 38 $item_kind = ! empty( $item['kind'] ) ? $item['kind'] : 'simple'; 39 $is_new_product = self::find_product( $item['sku'] ) ? true : false; 39 $is_new_product = $post_id ? false : true; 40 41 if ( empty( $post_id ) ) { 42 $is_new_product = self::find_product( $item['sku'] ) ? true : false; 43 } 40 44 41 45 if ( in_array( 'woo-product-bundle/wpc-product-bundles.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { … … 50 54 51 55 if ( ! $is_filtered && $item['sku'] && 'simple' === $item_kind ) { 52 $result_post = self::sync_product_simple( $settings, $item, $api_erp );56 $result_post = self::sync_product_simple( $settings, $item, $api_erp, $post_id ); 53 57 $post_id = $result_post['post_id'] ?? 0; 54 58 $message .= $result_post['message'] ?? ''; … … 56 60 // Variable product. 57 61 // Check if any variants exists. 58 $post_parent = 0; 59 // Activar para buscar un archivo. 60 $any_variant_sku = false; 61 62 foreach ( $item['variants'] as $variant ) { 63 if ( ! $variant['sku'] ) { 64 break; 65 } else { 66 $any_variant_sku = true; 67 } 68 $post_parent = self::find_parent_product( $variant['sku'] ); 69 if ( $post_parent ) { 70 // Do not iterate if it's find it. 71 break; 72 } 73 } 62 $any_variant_sku = true; 63 if ( ! $post_id ) { 64 $post_id = 0; 65 // Activar para buscar un archivo. 66 $any_variant_sku = false; 67 68 foreach ( $item['variants'] as $variant ) { 69 if ( ! $variant['sku'] ) { 70 break; 71 } else { 72 $any_variant_sku = true; 73 } 74 $post_id = self::find_parent_product( $variant['sku'] ); 75 if ( $post_id ) { 76 // Do not iterate if it's find it. 77 break; 78 } 79 } 80 } 81 82 // Fix Parent product without SKU. 83 if ( $post_id ) { 84 $parent_product = wc_get_product( $post_id ); 85 if ( $parent_product && ! $parent_product->get_sku() && ! empty( $item['sku'] ) ) { 86 try { 87 $parent_product->set_sku( $item['sku'] ); 88 $parent_product->save(); 89 } catch ( \Exception $e ) {} 90 } 91 unset( $parent_product ); 92 } 93 74 94 if ( false === $any_variant_sku ) { 75 95 $message .= __( 'Product not imported becouse any variant has got SKU: ', 'connect-ecommerce' ) . $item['name'] . '(' . $item_kind . ') <br/>'; 76 96 } else { 77 97 // Update meta for product. 78 $result_prod = self::sync_product( $settings, $item, $api_erp, $post_ parent, 'variable', null );98 $result_prod = self::sync_product( $settings, $item, $api_erp, $post_id, 'variable', null ); 79 99 $post_id = $result_prod['prod_id'] ?? 0; 80 $message .= 0 === $post_ parent || false === $post_parent? $msg_product_created : $msg_product_synced;100 $message .= 0 === $post_id || false === $post_id ? $msg_product_created : $msg_product_synced; 81 101 $message .= $item['name'] . '. SKU: ' . $item['sku'] . '(' . $item_kind . ') ' . $result_prod['message'] ?? ''; 82 102 } 83 103 } elseif ( ! $is_filtered && 'pack' === $item_kind && $plugin_pack_active ) { 84 $post_id = self::find_product( $item['sku'] );104 $post_id = ! empty( $post_id ) ? $post_id : self::find_product( $item['sku'] ); 85 105 86 106 if ( ! $post_id ) { … … 144 164 $result_ai = AI::generate_description( $settings_ai, $item ); 145 165 if ( ! empty( $result_ai ) && 'ok' === $result_ai['status'] ) { 166 $message = ''; 146 167 $product_info = array( 147 168 'ID' => $post_id, … … 149 170 if ( ! empty( $result_ai['data']['title'] ) ) { 150 171 $product_info['post_title'] = $result_ai['data']['title']; 172 } else { 173 $message .= __( 'Title not generated. ', 'connect-ecommerce' ); 151 174 } 152 175 if ( ! empty( $result_ai['data']['body'] ) ) { 153 176 $product_info['post_content'] = $result_ai['data']['body']; 177 } else { 178 $message .= __( 'Post content not generated. ', 'connect-ecommerce' ); 154 179 } 155 180 if ( ! empty( $result_ai['data']['seo_description'] ) ) { 156 181 $product_info['post_excerpt'] = $result_ai['data']['seo_description']; 182 } else { 183 $message .= __( 'Post excerpt not generated. ', 'connect-ecommerce' ); 157 184 } 185 158 186 // Update product. 159 187 wp_update_post( … … 168 196 } else { 169 197 $message .= '<span class="error">' . __( 'Error AI: ', 'connect-ecommerce' ); 170 $message .= $result_ai[' error'] ?? '';198 $message .= $result_ai['message'] ?? ''; 171 199 $message .= '</span>'; 172 200 } … … 211 239 212 240 // Start. 213 if ( 'simple' === $type ) { 214 $product = new \WC_Product( $product_id ); 215 } elseif ( 'variable' === $type ) { 216 $product = new \WC_Product_Variable( $product_id ); 217 } elseif ( 'pack' === $type ) { 218 $product = new \WC_Product( $product_id ); 219 } 241 try { 242 if ( 'simple' === $type ) { 243 $product = new \WC_Product( $product_id ); 244 } elseif ( 'variable' === $type ) { 245 $product = new \WC_Product_Variable( $product_id ); 246 } elseif ( 'pack' === $type ) { 247 $product = new \WC_Product( $product_id ); 248 } 249 } catch ( \Exception $e ) { 250 return array( 251 'status' => 'error', 252 'props' => [], 253 'message' => __( 'Error creating variable product: ', 'connect-ecommerce' ) . $e->getMessage(), 254 ); 255 } 256 220 257 // Common and default properties. 221 258 $product_props = array( 222 259 'stock_status' => 'instock', 223 260 'backorders' => $allow_backorders, 224 'regular_price' => isset( $item['price'] ) ? $item['price'] : null,261 'regular_price' => self::get_rate_price( $item, $rate_id ), 225 262 'length' => isset( $item['lenght'] ) ? $item['lenght'] : '', 226 263 'width' => isset( $item['width'] ) ? $item['width'] : '', 227 264 'height' => isset( $item['height'] ) ? $item['height'] : '', 228 265 ); 266 $price_sale = self::get_sale_price( $item, $settings ); 267 if ( ! empty( $price_sale ) ) { 268 $product_props['sale_price'] = $price_sale; 269 } 229 270 $product_props_new = array(); 230 271 if ( $is_new_product ) { … … 260 301 } 261 302 262 if ( isset( $item['barcode'] ) ) { 263 $product->set_global_unique_id( $item['barcode'] ); 303 if ( ! empty( $item['barcode'] ) ) { 304 try { 305 $product->set_global_unique_id( $item['barcode'] ); 306 } catch ( \Exception $e ) { 307 // Error. 308 } 264 309 } 265 310 … … 314 359 } 315 360 316 // Set categories.361 // Set attributes. 317 362 $attributes = ! empty( $item['attributes'] ) && is_array( $item['attributes'] ) ? $item['attributes'] : array(); 318 363 $item_type = array_search( $attribute_cat_id, array_column( $attributes, 'id', 'value' ) ); … … 325 370 326 371 // Imports image. 327 self::put_product_image ( $settings, $item['id'], $product_id, $api_erp );372 self::put_product_images( $settings, $item, $product_id, $api_erp ); 328 373 329 374 // Adds custom fields. … … 389 434 * @param object $api_erp API Object. 390 435 * @param boolean $from_pack Item is a pack. 436 * @param integer $post_id Post ID. 391 437 * 392 438 * @return array 393 439 */ 394 private static function sync_product_simple( $settings, $item, $api_erp, $from_pack = false ) {440 private static function sync_product_simple( $settings, $item, $api_erp, $from_pack = false, $post_id = 0 ) { 395 441 $message = ''; 396 $post_id = self::find_product( $item['sku'] );442 $post_id = empty( $post_id ) ? $post_id : self::find_product( $item['sku'] ); 397 443 if ( ! $post_id ) { 398 444 $post_id = self::create_product_post( $settings, $item ); … … 404 450 $result_prod = self::sync_product( $settings, $item, $api_erp, $post_id, 'simple', null ); 405 451 $post_id = $result_prod['prod_id'] ?? 0; 452 453 // Add custom taxonomies. 454 self::add_custom_taxonomies( $post_id, $item ); 406 455 } 407 456 if ( $from_pack ) { … … 456 505 } 457 506 } 507 508 // Add custom taxonomies. 509 self::add_custom_taxonomies( $product_id, $item ); 458 510 459 511 // Remove variations without SKU blank. … … 491 543 } 492 544 // Make Variations. 493 if ( 'default' === $rate_id || '' === $rate_id ) { 494 if ( isset( $variant['price'] ) && $variant['price'] ) { 495 $variation_price = $variant['price']; 496 } else { 497 $variation_price = 0; 498 } 499 } else { 500 $variant_price_key = array_search( $rate_id, array_column( $variant['rates'], 'id' ) ); 501 $variation_price = $variant['rates'][ $variant_price_key ]['subtotal']; 502 } 545 $variation_price = self::get_rate_price( $variant, $rate_id ); 503 546 $variation_props = array( 504 547 'parent_id' => $product_id, … … 506 549 'regular_price' => $variation_price, 507 550 ); 551 552 $price_sale = self::get_sale_price( $variant, $settings ); 553 if ( ! empty( $price_sale ) ) { 554 $variation_props['sale_price'] = $price_sale; 555 } 508 556 if ( 0 === $variation_id ) { 509 557 // New variation. … … 522 570 } 523 571 $variation = new \WC_Product_Variation( $variation_id ); 572 if ( ! empty( $variant['barcode'] ) ) { 573 try { 574 $variation->set_global_unique_id( $item['barcode'] ); 575 } catch ( \Exception $e ) { 576 // Error. 577 } 578 } 524 579 $variation->set_props( $variation_props ); 525 580 // Stock. … … 721 776 * @return string $product_id Products id. 722 777 */ 723 public static function find_product( $sku ) {778 public static function find_product( $sku, $post_type = 'product' ) { 724 779 global $wpdb; 725 $post_type = 'product';726 780 $meta_key = '_sku'; 727 781 $result_query = $wpdb->get_var( $wpdb->prepare( "SELECT P.ID FROM $wpdb->posts AS P LEFT JOIN $wpdb->postmeta AS PM ON PM.post_id = P.ID WHERE P.post_type = '$post_type' AND PM.meta_key='$meta_key' AND PM.meta_value=%s AND P.post_status != 'trash' LIMIT 1", $sku ) ); … … 737 791 */ 738 792 public static function find_parent_product( $sku ) { 739 global $wpdb; 740 $post_id_var = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value=%s LIMIT 1", $sku ) ); 793 $post_id_var = self::find_product( $sku, 'product_variation' ); 741 794 742 795 if ( $post_id_var ) { 743 $post_parent = wp_get_post_parent_id( $post_id_var );796 $post_parent = wp_get_post_parent_id( (int) $post_id_var ); 744 797 return $post_parent; 745 798 } … … 808 861 * Gets image from API products 809 862 * 810 * @param string $item _id Idof API to get information.863 * @param string $item Item of API to get information. 811 864 * @param string $product_id Id of product to get information. 812 865 * @param object $api_erp API Object. 813 866 * 814 * @return array Array of products imported via API. 815 */ 816 public static function put_product_image( $settings, $item_id, $product_id, $api_erp ) { 817 // Don't import if there is thumbnail. 818 if ( has_post_thumbnail( $product_id ) ) { 867 * @return void 868 */ 869 public static function put_product_images( $settings, $item, $product_id, $api_erp ) { 870 if ( self::has_valid_thumbnail( $product_id ) ) { 819 871 return false; 820 872 } 821 873 822 $result_api = $api_erp->get_image_product( $settings, $item_id, $product_id ); 823 824 if ( isset( $result_api['upload']['url'] ) ) { 825 $attachment = array( 826 'guid' => $result_api['upload']['url'], 827 'post_mime_type' => $result_api['content_type'], 828 'post_title' => get_the_title( $product_id ), 829 'post_content' => '', 830 'post_status' => 'inherit', 831 ); 832 $attach_id = wp_insert_attachment( $attachment, $result_api['upload']['file'], 0 ); 833 add_post_meta( $product_id, '_thumbnail_id', $attach_id, true ); 874 $images = array(); 875 if ( ! empty( $item['images'] ) ) { 876 $images = $item['images'] ?? array(); 877 } else { 878 // Ask API for image. 879 $result_api = $api_erp->get_image_product( $settings, $item['id'], $product_id ); 834 880 835 881 if ( isset( $body_response['errors'] ) ) { … … 838 884 return false; 839 885 } 840 841 return $attach_id; 886 if ( isset( $result_api['upload']['url'] ) ){ 887 $images[] = [ 888 'url' => $result_api['upload']['url'], 889 'file' => $result_api['upload']['file'], 890 'content_type' => $result_api['content_type'], 891 ]; 892 } 893 } 894 895 if ( empty( $images ) ) { 896 return; 897 } 898 899 $first_image = true; 900 foreach ( $images as $image ) { 901 $attachment = array( 902 'guid' => $image['url'] ?? '', 903 'post_mime_type' => $image['content_type'] ?? '', 904 'post_title' => $image['title'] ?? get_the_title( $product_id ), 905 'post_content' => $image['content'] ?? '', 906 'post_status' => 'inherit', 907 ); 908 909 if ( empty( $image['file'] ) ) { 910 // Download image to server 911 $image_url = $image['url'] ?? ''; 912 if ( empty( $image_url ) ) { 913 continue; 914 } 915 916 $file_array = []; 917 $file_array['name'] = basename( $image_url ); 918 $file_array['tmp_name'] = download_url( $image_url ); 919 920 // Check for download errors 921 if ( is_wp_error( $file_array['tmp_name'] ) ) { 922 continue; 923 } 924 925 $attach_id = media_handle_sideload( $file_array, $product_id, $attachment['post_title'], $attachment ); 926 927 // Check for attachment errors 928 if (is_wp_error($attach_id)) { 929 @unlink($file_array['tmp_name']); 930 continue; 931 } 932 } else { 933 if ( ! file_exists( $image['file'] ) ) { 934 continue; 935 } 936 937 $attach_id = wp_insert_attachment( $attachment, $image['file'], 0 ); 938 } 939 940 if ( $first_image ) { 941 $first_image = false; 942 // Set the product image. 943 add_post_meta( $product_id, '_thumbnail_id', $attach_id, true ); 944 } else { 945 // Add the image to the product gallery. 946 $gallery = get_post_meta( $product_id, '_product_image_gallery', true ); 947 $gallery = $gallery ? $gallery . ',' . $attach_id : $attach_id; 948 update_post_meta( $product_id, '_product_image_gallery', $gallery ); 949 } 842 950 } 843 951 } … … 956 1064 } 957 1065 } 1066 1067 /** 1068 * Get sale price from item 1069 * 1070 * @param array $item Item from API. 1071 * @param array $settings Settings of the plugin. 1072 * 1073 * @return string 1074 */ 1075 private static function get_sale_price( $item, $settings ) { 1076 $pricesale_discount = (float) $settings['pricesale_discount'] ?? 0; 1077 if ( empty( $pricesale_discount ) || empty( $item['price'] ) ) { 1078 return ''; 1079 } 1080 $price_sale = $item['price'] - ( $item['price'] * ( $pricesale_discount / 100 ) ); 1081 if ( $price_sale > 0 ) { 1082 return number_format( $price_sale, 2, '.', '' ); 1083 } else { 1084 return ''; 1085 } 1086 } 1087 1088 /** 1089 * Get attribute category ID 1090 * 1091 * @param array $item Item from API. 1092 * 1093 * @return int 1094 */ 1095 private static function get_rate_price( $item, $rate_id ) { 1096 if ( empty( $item ) ) { 1097 return null; 1098 } 1099 if ( 'default' === $rate_id || '' === $rate_id || empty( $item['rates'] ) || ! is_array( $item['rates'] ) ) { 1100 return isset( $item['price'] ) ? $item['price'] : null; 1101 } else { 1102 $price_key = array_search( $rate_id, array_column( $item['rates'], 'id' ) ); 1103 return isset( $item['rates'][ $price_key ]['subtotal'] ) ? $item['rates'][ $price_key ]['subtotal'] : null; 1104 } 1105 } 1106 1107 /** 1108 * Add custom taxonomies to product 1109 * 1110 * @param int $product_id Product ID. 1111 * @param array $item Item from API. 1112 * 1113 * @return void 1114 */ 1115 private static function add_custom_taxonomies( $product_id, $item ) { 1116 // Set taxonomies. 1117 if ( ! empty( $item['taxonomies'] ) && is_array( $item['taxonomies'] ) ) { 1118 foreach ( $item['taxonomies'] as $taxonomy ) { 1119 if ( empty( $taxonomy['id'] ) || empty( $taxonomy['value'] ) ) { 1120 continue; 1121 } 1122 TAX::assign_product_term( $product_id, $taxonomy['id'], $taxonomy['value'], true ); 1123 } 1124 } 1125 } 1126 1127 /** 1128 * Checks if product has a valid thumbnail. 1129 * 1130 * @param int $product_id Product ID. 1131 * @return bool 1132 */ 1133 private static function has_valid_thumbnail( $product_id ) { 1134 $thumbnail_id = get_post_thumbnail_id( $product_id ); 1135 if ( ! $thumbnail_id ) { 1136 return false; 1137 } 1138 $image_path = get_attached_file( $thumbnail_id ); 1139 if ( ! $image_path || ! file_exists( $image_path ) ) { 1140 return false; 1141 } 1142 $image_url = wp_get_attachment_url( $thumbnail_id ); 1143 if ( ! $image_url ) { 1144 return false; 1145 } 1146 return true; 1147 } 958 1148 } -
connect-ecommerce/trunk/includes/Helpers/TAX.php
r3281293 r3301423 218 218 * @param string $post_id Post id of actual post id. 219 219 * @param array $taxonomy_slug Slug of taxonomy. 220 * @param array $category_array Array of category.220 * @param array|string $terms Array of terms. 221 221 * @return void 222 222 */ 223 p rivate static function assign_product_term( $post_id, $taxonomy_slug, $category_array) {223 public static function assign_product_term( $post_id, $taxonomy_slug, $terms ) { 224 224 $parent_term = ''; 225 $term_levels = count( $category_array ); 225 $terms = is_array( $terms ) ? $terms : array( $terms ); 226 $term_levels = count( $terms ); 226 227 $term_level_index = 1; 227 228 228 foreach ( $ category_array as $category_name) {229 $ category_name = self::sanitize_text( $category_name);230 $search_term = term_exists( $category_name, $taxonomy_slug );229 foreach ( $terms as $term ) { 230 $term = self::sanitize_text( $term ); 231 $search_term = term_exists( $term, $taxonomy_slug ); 231 232 232 233 if ( 0 === $search_term || null === $search_term ) { 233 234 // Creates taxonomy. 234 235 $args_term = array( 235 'slug' => sanitize_title( $ category_name),236 'slug' => sanitize_title( $term ), 236 237 ); 237 238 if ( $parent_term ) { … … 239 240 } 240 241 $search_term = wp_insert_term( 241 $ category_name,242 $term, 242 243 $taxonomy_slug, 243 244 $args_term 244 245 ); 245 246 } 246 if ( $term_level_index === $term_levels ) { 247 wp_set_object_terms( $post_id, (int) $search_term['term_id'], $taxonomy_slug ); 247 248 // Check if term was found or created successfully 249 if ( ! is_wp_error( $search_term ) && $term_level_index === $term_levels ) { 250 $term_id = isset( $search_term['term_id'] ) ? (int) $search_term['term_id'] : (int) $search_term; 251 wp_set_object_terms( $post_id, $term_id, $taxonomy_slug ); 248 252 } 249 253 250 254 // Next iteration for child. 251 $parent_term = $search_term['term_id'];255 $parent_term = (int) $search_term['term_id']; 252 256 $term_level_index++; 253 257 } … … 262 266 private static function sanitize_text( $text ) { 263 267 $text = str_replace( '>', '>', $text ); 264 return $text;268 return sanitize_text_field( $text ); 265 269 } 266 270 -
connect-ecommerce/trunk/includes/Plugin_Main.php
r3281293 r3301423 28 28 29 29 /** 30 * Options of plugin. 31 * 32 * @var array 33 */ 34 private $options = array(); 35 36 /** 30 37 * Construct of class 31 38 * … … 33 40 */ 34 41 public function __construct( $options = array() ) { 42 $this->options = $options; 35 43 if ( is_admin() ) { 36 44 new Settings( $options ); … … 44 52 new MyAccount( $options ); 45 53 } 54 55 /** 56 * Get options of plugin. 57 * 58 * @return array 59 */ 60 public function get_options( ) { 61 return $this->options; 62 } 46 63 } -
connect-ecommerce/trunk/includes/assets/sync-import.js
r3281293 r3301423 44 44 } 45 45 46 function syncProductERP( element, action, product_erp_id = 0, product_sku = '' ) {46 function syncProductERP( element, action, product_erp_id = 0, product_sku = '', product_id = 0 ) { 47 47 element.classList.add('disabled'); 48 48 element.innerHTML = ConEcom_ajaxAction.label_syncing + ' <span class="spinner is-active"></span>'; … … 58 58 'Cache-Control': 'no-cache', 59 59 }, 60 body: 'action=' + action + '&nonce=' + ConEcom_ajaxAction.nonce + '&loop=' + loop + '&product_erp_id=' + product_erp_id + '&product_sku=' + product_sku + '&product_ ai=' + productAI,60 body: 'action=' + action + '&nonce=' + ConEcom_ajaxAction.nonce + '&loop=' + loop + '&product_erp_id=' + product_erp_id + '&product_sku=' + product_sku + '&product_id=' + product_id + '&product_ai=' + productAI, 61 61 }) 62 62 .then( (resp) => resp.json() ) … … 65 65 element.innerHTML = ConEcom_ajaxAction.label_sync; 66 66 67 // Refresh the page 68 location.reload(); 67 console.log(results.data); 68 // Message handling 69 if (results.data.message !== undefined) { 70 const aiInput = document.querySelector('#connect_ecommerce_ai'); 71 if (aiInput) { 72 const aiLabel = aiInput.closest('label'); 73 const aiMessage = document.createElement('div'); 74 aiMessage.className = 'ai-message'; 75 aiMessage.innerHTML = results.data.message; 76 77 const targetElement = aiLabel || aiInput; 78 if (targetElement.nextSibling) { 79 targetElement.parentNode.insertBefore(aiMessage, targetElement.nextSibling); 80 } else { 81 targetElement.parentNode.appendChild(aiMessage); 82 } 83 } 84 } 85 86 // Reload the page after 8 seconds if the sync was successful 87 if (results.success) { 88 setTimeout(() => { 89 window.location.reload(); 90 }, 8000); 91 } 69 92 }) 70 93 .catch(err => console.log(err)); -
connect-ecommerce/trunk/readme.txt
r3289663 r3301423 47 47 [Official Repository GitHub](https://github.com/closemarketing/connect-ecommerce) 48 48 49 You can use WP CLI to import products from the command line. The command is: 50 ``` 51 wp conecom products --update --ai=none,new,all 52 ``` 53 49 54 == External services == 50 55 … … 59 64 60 65 == Changelog == 66 67 = 3.1.0 = 68 * Added: WP CLI command to import products. 69 * Fully support to import EAN to WooCommerce. 70 * Added: Import image products with different method. 71 * Added: Result API import in widget product. 72 * Added: Save parent SKU in product if does not exist. 73 * Added: Check if image product file exists before import. 74 * Fixed: AI connection not working in some cases. 75 * Fixed: Some errors getting products from shop to syncronize. 76 * Fixed: Not getting prices rates from API. 77 * Fixed: Prevent error when WooCommerce does not load the product. 61 78 62 79 = 3.0.1 = -
connect-ecommerce/trunk/vendor/composer/installed.php
r3289663 r3301423 2 2 'root' => array( 3 3 'name' => 'closemarketing/connect-ecommerce', 4 'pretty_version' => '3. 0.1',5 'version' => '3. 0.1.0',6 'reference' => ' 4b85748d444a7a4ddea31f4494598d5fffd54f4a',4 'pretty_version' => '3.1.0', 5 'version' => '3.1.0.0', 6 'reference' => 'f3639f9784b938002847fc0b6395dc83d2c1b030', 7 7 'type' => 'library', 8 8 'install_path' => __DIR__ . '/../../', … … 12 12 'versions' => array( 13 13 'closemarketing/connect-ecommerce' => array( 14 'pretty_version' => '3. 0.1',15 'version' => '3. 0.1.0',16 'reference' => ' 4b85748d444a7a4ddea31f4494598d5fffd54f4a',14 'pretty_version' => '3.1.0', 15 'version' => '3.1.0.0', 16 'reference' => 'f3639f9784b938002847fc0b6395dc83d2c1b030', 17 17 'type' => 'library', 18 18 'install_path' => __DIR__ . '/../../',
Note: See TracChangeset
for help on using the changeset viewer.