diff --git a/admin/wp-connect-io6-admin-page.php b/admin/wp-connect-io6-admin-page.php index f2ee0971303ce8a5c5c842a437a4cd17cb3c31e0..f7a335a7c93655a55207da8bbb77ca3a935f6d2f 100755 --- a/admin/wp-connect-io6-admin-page.php +++ b/admin/wp-connect-io6-admin-page.php @@ -78,6 +78,16 @@ add_action('admin_notices', function () { </div> <?php } + + $token_data = getIO6TokenData(); + + if ($token_data["error"]){ + ?> + <div class="notice notice-error requirements"> + <?php echo $token_data["message"] ?> + </div> + <?php + } } }); @@ -108,6 +118,9 @@ add_action('wp_ajax_io6-test-api', 'io6_test_api'); add_action('wp_ajax_nopriv_io6-single-sync', 'io6_single_sync'); add_action('wp_ajax_io6-single-sync', 'io6_single_sync'); +add_action('wp_ajax_nopriv_io6-associate', 'io6_associate'); +add_action('wp_ajax_io6-associate', 'io6_associate'); + add_action('wp_ajax_nopriv_io6-export-categories', 'io6_export_categories'); add_action('wp_ajax_io6-export-categories', 'io6_export_categories'); @@ -127,7 +140,7 @@ add_action('wp_ajax_nopriv_io6-get-statistic', 'io6_get_statistic'); add_action('wp_ajax_io6-get-statistic', 'io6_get_statistic'); add_action('edit_form_top', function ($post) { - global $pagenow, $wpdb; + global $pagenow, $wpdb, $io6_configuration, $io6Engine; if (!is_admin()) return false; $io6_tableName = $wpdb->prefix . 'io6_products'; @@ -135,9 +148,33 @@ add_action('edit_form_top', function ($post) { $sql = "SELECT io6_id_product FROM $io6_tableName WHERE id_product = ". $post->ID; $io6_id_product = intval($wpdb->get_var($wpdb->prepare($sql))); - if ($post->post_type != 'product' || in_array($pagenow, array('post-new.php')) || empty($io6_id_product)) return false; - echo ('<button name="io6-single-sync" id="io6-single-sync" class="button button-large" type="submit" href="'.site_url().'/wp-admin/admin-ajax.php?action=io6-single-sync&io6_post_id='.$io6_id_product.'">Sync ImporterONE</button>'); - echo ('<div id="io6-res-single-sync" class="notice d-none"></div>'); + if ($post->post_type != 'product' || in_array($pagenow, array('post-new.php'))) return false; + + if (!empty($io6_id_product)) { + echo ('<button name="io6-single-sync" id="io6-single-sync" class="button button-large" type="submit" href="'.site_url().'/wp-admin/admin-ajax.php?action=io6-single-sync&io6_post_id='.$io6_id_product.'">Sync ImporterONE</button>'); + echo ('<div id="io6-res-single-sync" class="notice d-none"></div>'); + } + else { + $post_meta = get_post_meta($post->ID); + + $eanField = $io6_configuration->selectedEanField; + $partNumberField = $io6_configuration->selectedPartNumberField; + $brandField = $io6_configuration->selectedBrandField; + + $sql = "SELECT im.io6_brand_code FROM $wpdb->term_taxonomy tt + INNER JOIN $wpdb->term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id + INNER JOIN wp_io6_manufacturers im ON im.id_manufacturer = tt.term_id + WHERE tr.object_id = $post->ID AND tt.taxonomy = '".$brandField."'"; + $io6_brand_code = $wpdb->get_var($wpdb->prepare($sql)); + + if (isset($post_meta) && is_array($post_meta) && (!empty($post_meta[$eanField]) || (!empty($post_meta[$partNumberField]) && !empty($io6_brand_code)))) { + + echo ('<button name="io6-associate" id="io6-associate" class="button button-large" type="submit" href="'.site_url().'/wp-admin/admin-ajax.php?action=io6-associate&post_id='.$post->ID.'">Associa ad ImporterONE</button>'); + echo ('<div id="io6-res-associate" class="d-none"> + <h4>Associa ad ImporterONE</h4> + </div>'); + } + } }); add_action('save_post', 'io6_save_post', 10); @@ -149,21 +186,87 @@ function io6_single_sync() { function io6_save_post($post_id) { global $post, $wpdb; - if ($post->post_type == 'product' && isset($_POST['io6-single-sync'])) { - + if ($post->post_type == 'product' && (isset($_POST['io6-single-sync']) || isset($_POST["io6-single-sync-associate"]))) { + $io6_tableName = $wpdb->prefix . 'io6_products'; $sql = "SELECT io6_id_product FROM $io6_tableName WHERE id_product = ". $post->ID; $io6_id_product = intval($wpdb->get_var($wpdb->prepare($sql))); + if(empty($io6_id_product) && !empty($_POST["io6-sync-radios-associate"])){ + $io6_id_product = $_POST["io6-sync-radios-associate"]; + io6_include_products($post->ID); + } + if (!empty($io6_id_product)){ remove_action('save_post', 'io6_save_post', 10); - io6_sync($io6_id_product); //TODO: EM20210302 => utilizzare PRODUCTS per fare log warning ed errori + io6_sync($io6_id_product, $post->ID); //TODO: EM20210302 => utilizzare PRODUCTS per fare log warning ed errori add_action('save_post', 'io6_save_post', 10); } } }; +function io6_associate() { + global $io6_configuration, $io6Engine, $wpdb; + + $post_id = $_GET['post_id']; + + $post_meta = get_post_meta($post_id); + + + $eanField = $io6_configuration->selectedEanField; + $partNumberField = $io6_configuration->selectedPartNumberField; + $brandField = $io6_configuration->selectedBrandField; + + if (isset($post_meta) && is_array($post_meta)) { + $io6_results = []; + $io6_results_ean = []; + $io6_results_mpn = []; + + if (!empty($post_meta[$eanField])){ + $io6_results_ean = $io6Engine->GetIO6Products(1, 0, $post_meta[$eanField][0]); + } + + if (!empty($post_meta[$partNumberField])){ + + $sql = "SELECT im.io6_brand_code FROM $wpdb->term_taxonomy tt + INNER JOIN $wpdb->term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id + INNER JOIN wp_io6_manufacturers im ON im.id_manufacturer = tt.term_id + WHERE tr.object_id = $post_id AND tt.taxonomy = '".$brandField."'"; + $io6_brand_code = $wpdb->get_var($wpdb->prepare($sql)); + + if (!empty($io6_brand_code)) + $io6_results_mpn = $io6Engine->GetIO6Products(1, 0, 0, $post_meta[$partNumberField][0], $io6_brand_code); + } + + $io6_results = array_merge($io6_results_ean, $io6_results_mpn); + if (count($io6_results['products']) > 0){ + $io6_tableName = $wpdb->prefix . 'io6_products'; + + foreach ($io6_results['products'] as $key => $io6_product) { + $sql = "SELECT * FROM $io6_tableName WHERE io6_id_product = ". $io6_product->id; + $io6_product_data = $wpdb->get_row($wpdb->prepare($sql), ARRAY_A); + + if (!empty($io6_product_data)) + $io6_results['products'][$key]->is_io6_id_already_taken = $io6_product_data['id_product']; + + if ($io6_configuration->selectedSkuField != 'io6_sku_id'){ + $sql = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_sku' AND meta_value = '". $io6_product->code . "'"; + $wp_same_sku = $wpdb->get_var($wpdb->prepare($sql)); + + if (!empty($wp_same_sku)) + $io6_results['products'][$key]->is_wp_same_sku = $wp_same_sku; + } + } + } + } + + if (isset($io6_results['products']) && !empty($io6_results['products'])) + wp_send_json(['success' => true, 'site_url' => site_url(), 'products' => $io6_results['products']]); + else + wp_send_json(['success' => false, 'message' => "ImporterONE: Corrispondenza non trovata per EAN ed MPN"]); +} + function io6_export_categories(){ global $wpdb; @@ -220,7 +323,7 @@ function io6_exclude_products(){ } -function io6_include_products(){ +function io6_include_products($wp_post_id = 0){ global $wpdb; $io6_tableName = $wpdb->prefix . 'io6_products'; @@ -250,14 +353,23 @@ function io6_include_products(){ NULL FROM $wpdb->posts p LEFT JOIN $io6_tableName ip ON ip.id_product = p.ID - WHERE ip.id_product IS NULL AND p.post_type = 'product'"; + WHERE p.post_type = 'product'"; + + if (empty($wp_post_id)) + $sql .= "AND ip.id_product IS NULL"; + else + $sql .= "AND p.ID = ". $wp_post_id; + $res = $wpdb->query($wpdb->prepare($sql)); - if ($res){ - echo wp_send_json(["success" => true, "message" => "Prodotti inclusi correttamente"]); - } else { - echo wp_send_json(["success" => false, "message" => "Errore durante lo spostamento dei prodotti"]); + if (empty($wp_post_id)){ + if ($res){ + echo wp_send_json(["success" => true, "message" => "Prodotti inclusi correttamente"]); + } else { + echo wp_send_json(["success" => false, "message" => "Errore durante lo spostamento dei prodotti"]); + } } + } function io6_download_not_io6_products(){ @@ -419,8 +531,8 @@ function io6_show_statistic(){ <div id="io6_info_num_products_io6_no_images"></div> <div id="io6_donwload_info_num_products_io6_no_images"></div></p></div>'; - //ICECAT PRODUCT SAME MPN - $output .= '<div><p><span>Numero di prodotti Icecat con lo stesso MPN</span> <strong>' . $num_products_same_mpn . '</strong>'; + //PRESTASHOP PRODUCT SAME MPN + $output .= '<div><p><span>Numero di prodotti Prestashop con lo stesso MPN</span> <strong>' . $num_products_same_mpn . '</strong>'; if($num_products_same_mpn > 0){ $output .= '<a id="btnShow_num_products_same_mpn" onclick="callStatisticList(this)" class="button button-small io6-get-statistic" data-url="'. site_url() .'/wp-admin/admin-ajax.php?action=io6-get-statistic&request=num_products_same_mpn">Mostra lista</a> @@ -431,8 +543,8 @@ function io6_show_statistic(){ <div id="io6_info_num_products_same_mpn"></div> <div id="io6_donwload_info_num_products_same_mpn"></div></p></div>'; - //ICECAT PRODUCT SAME EAN - $output .= '<div><p><span>Numero di prodotti Icecat con lo stesso EAN</span> <strong>' . $num_products_same_ean . '</strong>'; + //PRESTASHOP PRODUCT SAME EAN + $output .= '<div><p><span>Numero di prodotti Prestashop con lo stesso EAN</span> <strong>' . $num_products_same_ean . '</strong>'; if($num_products_same_ean > 0){ $output .= '<a id="btnShow_num_products_same_ean" onclick="callStatisticList(this)" class="button button-small io6-get-statistic" data-url="'. site_url() .'/wp-admin/admin-ajax.php?action=io6-get-statistic&request=num_products_same_ean">Mostra lista</a> @@ -1323,8 +1435,13 @@ function io6_render_apiendpoint($args) function io6_render_apitoken($args) { global $io6_configuration; + + $token_data = getIO6TokenData(); ?> + <input type="text" id="<?php echo esc_attr($args['id']); ?>" class="regular-text" name="io6_options[apitoken]" value="<?php echo esc_attr($io6_configuration->apiToken) ?>" <?php echo ($args['required'] ? 'required' : '') ?> /> + <br /> + <small><?php echo $token_data["message"] ?></small> <?php } @@ -1616,3 +1733,30 @@ function checkServerRequirements() return $server_checking; } + +function getIO6TokenData(){ + global $io6_configuration; + + $token_message = ''; + $error = false; + if (!empty($token = $io6_configuration->apiToken)){ + list($base64Header, $base64UrlPayload, $signature) = explode('.', $token); + $header = base64_decode($base64Header); + $payload = json_decode(base64_decode($base64UrlPayload)); + + if (!empty($header) && !empty($payload) && !empty($signature)){ + $token_expiration = date('d-m-Y',$payload->exp); + if(strtotime($token_expiration) < strtotime(date('d-m-Y'))){ + $token_message .= 'Il token IO6 è scaduto in data:'.$token_expiration.'. '; + $error = true; + } else { + $token_message .= ' Data scadenza token IO6: '.$token_expiration.'.'; + } + } + } else { + $token_message = "Token IO6 non configurato"; + $error = true; + } + + return ["message" => $token_message, "error" => $error]; +} diff --git a/assets/css/main.css b/assets/css/main.css index aeddb12d8a20272f0f100087ed7b519bbe6ab987..7583d0b98fe950d9c0c73b2ee22d99c8dc42c926 100755 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -93,4 +93,20 @@ a[id^=btnShow_].button.button-small { .export-categories-section h4{ margin: 1rem 0 0.5rem 0; +} + +#io6-res-associate .form-check { + margin-bottom: 0.5rem; +} + +#io6-res-associate span{ + margin-left: 1.5rem; +} + +#io6-res-associate .form-check small{ + margin-left: 1.5rem; +} + +#io6-res-associate #io6-single-sync-associate { + margin-top: 1rem; } \ No newline at end of file diff --git a/assets/js/settings.js b/assets/js/settings.js index 4ac37fa1357fef28b06469d236ab5e40df70b532..43e0a07e34e6e2c388b74798dd3ee0f08e0379c7 100755 --- a/assets/js/settings.js +++ b/assets/js/settings.js @@ -57,7 +57,44 @@ if (typeof jQuery !== 'undefined') { }); + jQuery(document).on('click', '#io6-associate', async function(e) { + e.preventDefault(); + + await jQuery.ajax({ + method: "get", + async: true, + url: jQuery(this).attr('href'), + success: function (data) { + jQuery('#io6-res-associate').empty(); + if (data.success){ + data.products.forEach(product => { + var extraInfo = ''; + if (product['is_wp_same_sku']) + extraInfo += 'Il prodotto IO6 trovato presenta lo stesso SKU del prodotto Wordpress: '+product['is_wp_same_sku']+'. '; + + if (product['is_io6_id_already_taken']) + extraInfo += 'Il prodotto IO6 trovato presenta lo stesso ID ImporterONE del prodotto Wordpress: '+product['is_io6_id_already_taken']+'. '; + if (extraInfo != '') + jQuery('#io6-res-associate').append('<div class="form-check"><input class="form-check-input" name="io6-sync-radios-associate" type="radio" value="'+product['id']+'" id="io6-product-'+product['id']+'" checked disabled><label class="form-check-label" for="'+product['id']+'"> Prodotto: '+product['title']+'</label><br/><span> ID: '+product['id']+'</span><br/><small>'+extraInfo+'</small></div>'); + else + jQuery('#io6-res-associate').append('<div class="form-check"><input class="form-check-input" name="io6-sync-radios-associate" type="radio" value="'+product['id']+'" id="io6-product-'+product['id']+'" checked><label class="form-check-label" for="'+product['id']+'"> Prodotto: '+product['title']+'</label><br/><span> ID:'+product['id']+'</span><br/></div>'); + }); + jQuery('#io6-res-associate').append('<button name="io6-single-sync-associate" id="io6-single-sync-associate" class="button button-large" type="submit" data-base-url="'+data['site_url']+'/wp-admin/admin-ajax.php?action=io6-single-sync" href="">Sync ImporterONE</button>'); + + } else { + jQuery('#io6-res-associate').append('<span>'+data.message+'</span>'); + } + }, + error: function (error) { + jQuery('#io6-res-associate').append('<div class="module_confirmation alert alert-danger' + '"><h4 style="margin-bottom:0;">'+ error.status + ' ' + error.responseText + '</h4></div>'); + }, + complete: function (){ + jQuery('#io6-res-associate').removeClass("d-none"); + e.target.style.display = 'none' + } + }); + }); jQuery(document).on('click', '#io6-statistic', async function(e) { diff --git a/core/src/classes/IO6ConnectEngine.php b/core/src/classes/IO6ConnectEngine.php index 55d7c2c10ae8155ca165ea5780c324f7f3987111..a8726542145c0c3490f2250e5487ee2c5b6ec206 100755 --- a/core/src/classes/IO6ConnectEngine.php +++ b/core/src/classes/IO6ConnectEngine.php @@ -111,7 +111,7 @@ class IO6ConnectEngine return $brands; } - public function GetIO6Products($currentPage = 1, $io6_id_product_syngle_sync = 0) + public function GetIO6Products($currentPage = 1, $io6_id_product_syngle_sync = 0, $ean = 0, $mpn = '', $brand_code = '') { $elementsFounds = isset($_SESSION['elementsfounds']) ? intval($_SESSION['elementsfounds']) : 0; $pages = isset($_SESSION['pages']) ? intval($_SESSION['pages']) : 0; @@ -131,9 +131,18 @@ class IO6ConnectEngine $parameters['imagesSearch'] = $this->configuration->excludeNoImage ? 1 : 0; $parameters['isActive'] = 1; $parameters['isObsolete'] = 0; + $parameters['orderFields'] = ['productid' => 'ASC']; if (!empty($io6_id_product_syngle_sync)) $parameters['productIds'] = [$io6_id_product_syngle_sync]; + + if (!empty($ean)) + $parameters['ean'] = $ean; + + if (!empty($mpn) && !empty($brand_code)){ + $parameters['PartNumber'] = $mpn; + $parameters['brandCode'] = $brand_code; + } $results = $this->callIO6API(sprintf('catalogs/%s/products/search', $this->configuration->catalogId), 'POST', $parameters); diff --git a/wp-connect-io6-functions.php b/wp-connect-io6-functions.php index 6da857b2d14de46a1a8e105ce281d22ff4613a42..2dc73242f6ac044f3e25526ef1e8c0a1b676fef4 100755 --- a/wp-connect-io6-functions.php +++ b/wp-connect-io6-functions.php @@ -7,9 +7,14 @@ if (!function_exists('wp_generate_attachment_metadata')) { if (!wp_mkdir_p($images_path)) throw new Exception('Cannot create image folder!'); -function cleanIO6Tables() { +add_action('transition_post_status', 'cleanIO6Tables', 10, 3); + +function cleanIO6Tables($new_status = '', $old_status = '', $post = null) { global $wpdb; + if (!empty($post) && $post->post_type != "product") + return; + $io6_tableName = $wpdb->prefix . 'io6_manufacturers'; $sql = "DELETE b FROM $io6_tableName b LEFT OUTER JOIN $wpdb->terms t ON t.term_id = b.id_manufacturer @@ -89,6 +94,16 @@ function preloadProducts() { $_SESSION['products_cache'] = $wp_products_cache; } +function getImporteroneConnectProduct($wp_product_id){ + global $wpdb; + + $io6_tableName = $wpdb->prefix . 'io6_products'; + + $sql = "SELECT * FROM $io6_tableName WHERE id_product = $wp_product_id"; + + return $wpdb->get_row($wpdb->prepare($sql), ARRAY_A); +} + function syncBrands() { global $wpdb, $io6Engine, $io6_configuration; @@ -289,7 +304,7 @@ function syncCategories($categories = null) { io6_write_log('FINE SYNC CATEGORIES' , IO6_LOG_INFO); } -function syncProducts($currentPage = 1, $fastSync = false, $resume_sync = false, $realign_sync, $io6_id_product_syngle_sync = 0) { +function syncProducts($currentPage = 1, $fastSync = false, $resume_sync = false, $realign_sync, $io6_id_product_syngle_sync = 0, $wp_post_id = 0) { global $wpdb, $images_path, $io6Engine, $io6_configuration; if ($currentPage == 1 && empty($io6_id_product_syngle_sync)) @@ -351,7 +366,11 @@ function syncProducts($currentPage = 1, $fastSync = false, $resume_sync = false, ); io6_write_log('INIZIO RICERCA WP IDS, PRODUCT '. $product->$skuProp, IO6_LOG_DEBUG); - $wp_product_id = reset($wp_product_row) !== false ? intval(reset($wp_product_row)->id_product) : 0; + + $wp_product_id = $wp_post_id; + + if (empty($wp_product_id)) + $wp_product_id = reset($wp_product_row) !== false ? intval(reset($wp_product_row)->id_product) : 0; //$wp_product_id = isset($wp_products_cache[$product->id]) ? intval($wp_products_cache[$product->id]->id_product) : 0; $wp_brand_id = isset($_SESSION['brands_cache'][$product->brandCode]) ? intval($_SESSION['brands_cache'][$product->brandCode]) : 0; @@ -430,16 +449,19 @@ function syncProducts($currentPage = 1, $fastSync = false, $resume_sync = false, $retProduct['wp_product_id'] = $wp_product_id; $post_metas = !empty($wp_products_cache) && !empty($wp_products_cache[$wp_product_id]) ? $wp_products_cache[$wp_product_id] : null; + if (!isset($post_metas)) + $post_metas = getImporteroneConnectProduct($wp_product_id); + if(!$realign_sync) { - if (!isset($post_metas) || $post_metas->sync_exclude == null || intval($post_metas->sync_exclude) == 1) { + if (!isset($post_metas) || (isset($post_metas->sync_exclude) && intval($post_metas->sync_exclude) == 1)) { $sync_exclude = 1; throw new Exception("Product $product->partNumber is not managed by " . IO6_PLUGIN_NAME); } } - if($resume_sync && isset($wp_products_cache[$wp_product_id]->sync_status)) { + if($resume_sync && isset($post_metas->sync_status)) { $retProduct['sync_message'] = "AGGIORNAMENTO NON NECESSARIO"; - $retProduct['sync_status'] = $wp_products_cache[$wp_product_id]->sync_status; + $retProduct['sync_status'] = $post_metas->sync_status; array_push($syncResults['products'], $retProduct); continue; } @@ -564,6 +586,9 @@ function syncProducts($currentPage = 1, $fastSync = false, $resume_sync = false, //$raeeAmount; NN c'è un campo su WooCommerce } + if ($product->sellingPrice <= 0) + throw new Exception("Product ".$product->id." has price equal to 0 (zero)"); + $hookReturn = apply_filters("actionIO6ProductSaveBefore", true, $product, $wp_product); if ($hookReturn){ diff --git a/wp-connect-io6.php b/wp-connect-io6.php index 5ee241929b631088a8ef3729fe4c26d4a7b63db7..52fb664130e24d5ee3f979fd53f7e73064a4a113 100755 --- a/wp-connect-io6.php +++ b/wp-connect-io6.php @@ -108,7 +108,7 @@ function io6_test_api() { wp_die(); } -function io6_sync($io6_id_product_syngle_sync = 0) { +function io6_sync($io6_id_product_syngle_sync = 0, $wp_post_id = 0) { global $resume_sync, $realign_sync; try { session_id(IO6_SESSION_ID); @@ -147,7 +147,7 @@ function io6_sync($io6_id_product_syngle_sync = 0) { syncCategories(); } - $results = syncProducts($currentPage, $fastSync, $resume_sync, $realign_sync, $io6_id_product_syngle_sync); + $results = syncProducts($currentPage, $fastSync, $resume_sync, $realign_sync, $io6_id_product_syngle_sync, $wp_post_id); //resetCatalog();