/* Plugin Name: Oktabit Woo Sync Description: Συγχρονισμ̲ προϊόντων από Oktabit XML API στο WooCommerce με χαρακτηριστικό, εικόνες, κατηγορίες και διαθεσιμότητα. Version: 1.4 Author: ChatGPT */ ini_set('max_execution_time', 600); ini_set('memory_limit', '512M'); function get_existing_image_id_by_meta($url) { global $wpdb; $attachment_id = $wpdb->get_var($wpdb->prepare( "SELECT post_id FROM {$wpdb->prefix}postmeta WHERE meta_key = '_source_image_url' AND meta_value = %s LIMIT 1", $url )); return $attachment_id ? (int)$attachment_id : false; } function oktabit_sync_products() { set_time_limit(0); ini_set('memory_limit', '1024M'); error_log('⚙️ Sync ξεκίνησε'); $xml_url = 'https://www.oktabit.gr/api/data/?format=xml'; $token = 'b86ec0ed819ac16cc3da185c3c51db11bb213e3f'; $response = wp_remote_get($xml_url, [ 'headers' => ['Authorization' => 'Token ' . $token], 'timeout' => 120 ]); if (is_wp_error($response)) { error_log('❌ Oktabit XML API error: ' . $response->get_error_message()); return; } $xml_content = wp_remote_retrieve_body($response); if (!$xml_content) { error_log('❌ Άδειο XML περιεχόμενο από Oktabit'); return; } $xml_data = simplexml_load_string($xml_content); if ($xml_data === false || empty($xml_data->item)) { error_log('❌ Μη έγκυρο ή κενό XML'); return; } $plugin_dir = plugin_dir_path(__FILE__); $sku_path = $plugin_dir . 'skus.json'; $new_skus = []; $category_mapping = [ 'USB Flash Drives' => 'USB Flash Drives', 'Κάρτες Μνήμης Flash' => 'Κάρτες Μνήμης Flash', 'Εκτυπωτές' => 'Εκτυπωτές', 'Πολυμηχανήματα' => 'Πολυμηχανήματα', 'Οθόνες' => 'Οθόνες', 'Βάσεις Στήριξης' => 'Βάσεις Στήριξης', 'Soundbar Οθόνης' => 'Soundbar Οθόνης', 'Κάρτες Γραφικών' => 'Κάρτες Γραφικών', 'Δίσκοι SSD' => 'Δίσκοι SSD', 'Σκληροί Δίσκοι' => 'Σκληροί Δίσκοι', 'Κουτιά Υπολογιστών' => 'Κουτιά Υπολογιστών', 'Τροφοδοτικά' => 'Τροφοδοτικά', 'Laptops' => 'Laptops', 'UPS' => 'UPS', 'Rack / Ερμάρια' => 'Rack / Ερμάρια', 'Κονσόλες' => 'Κονσόλες', 'Χειριστήρια' => 'Χειριστήρια', 'Τιμονιέρες' => 'Τιμονιέρες', 'Adapters' => 'Adapters', 'USB καλώδια' => 'USB καλώδια', 'Switches' => 'Switches', 'Routers' => 'Routers', 'Access Points' => 'Access Points', 'Wi-Fi Extenders' => 'Wi-Fi Extenders', 'Power Lines' => 'Power Lines', 'Κάρτες Δικτύου' => 'Κάρτες Δικτύου', 'Networking Adapters' => 'Networking Adapters', 'Controlers' => 'Controlers', 'Switch Accessories / Parts' => 'Switch Accessories / Parts', 'POE Injectors / Splitters' => 'POE Injectors / Splitters', 'Power Supplies' => 'Power Supplies', 'Κεραίες' => 'Κεραίες', 'Room Solutions' => 'Room Solutions', 'Conference & Web Cams' => 'Conference & Web Cams', 'Conference Peripherals' => 'Conference Peripherals', 'Speakerphones' => 'Speakerphones', 'Βιντεοπροβολείς' => 'Βιντεοπροβολείς', 'Document Camera' => 'Document Camera', 'Ηχεία' => 'Ηχεία', 'Headsets' => 'Headsets', 'Earphones' => 'Earphones', 'Ακουστικά' => 'Ακουστικά', 'Ηχεία Φορητά' => 'Ηχεία Φορητά', 'Web Cameras' => 'Web Cameras', 'Ζυγαριές' => 'Ζυγαριές', 'Σκούπες Ρομπότ' => 'Σκούπες Ρομπότ', 'Φορητά Ψυγεία' => 'Φορητά Ψυγεία', 'Wireless Bulbs' => 'Wireless Bulbs', 'Wireless Plugs' => 'Wireless Plugs', 'Καρέκλες Gaming' => 'Καρέκλες Gaming', 'Gaming Chair Accessories' => 'Gaming Chair Accessories', 'Ηλεκτροκίνηση' => 'Ηλεκτροκίνηση', 'EV Chargers' => 'EV Chargers', 'Power Stations' => 'Power Stations', 'Portable Solar Panels' => 'Portable Solar Panels', 'All In One Συστήματα' => 'All In One Συστήματα', 'Έτοιμα Συστήματα Desktop' => 'Έτοιμα Συστήματα Desktop', 'Barebone PCs' => 'Barebone PCs' ]; foreach ($xml_data->item as $item) { $sku = '801003-' . (string)$item->product_code; $title = (string)$item->titlos; $description = trim((string)$item->description); $price = floatval($item->timi_lianikis); $availability_text = mb_strtolower((string)$item->availability, 'UTF-8'); $stock_status = 'onbackorder'; if ($availability_text === 'διαθέσιμο') { $stock_status = 'instock'; } elseif (preg_match('/διαθέσιμο σε (\d+)/u', $availability_text, $matches)) { $days = (int)$matches[1]; $stock_status = ($days <= 3) ? 'instock' : 'onbackorder'; } elseif (strpos($availability_text, 'κατόπιν παραγγελίας') !== false) { $stock_status = 'onbackorder'; } elseif (strpos($availability_text, 'μη διαθέσιμο') !== false) { $stock_status = 'outofstock'; } $cat_key = (string)$item->subcategory ?: (string)$item->parent_category; if (!isset($category_mapping[$cat_key])) continue; $new_skus[] = $sku; $product_id = wc_get_product_id_by_sku($sku); $product = $product_id ? wc_get_product($product_id) : new WC_Product_Simple(); $product->set_name($title); if (!empty($description)) $product->set_description($description); $product->set_sku($sku); $product->set_regular_price($price); $product->set_stock_status($stock_status); $product->set_weight((float)$item->meikto_varos / 1000); $product->set_length((float)$item->mikos_syskevasias); $product->set_width((float)$item->platos_syskevasias); $product->set_height((float)$item->ypsos_syskevasias); $attributes = []; if (!empty($item->product_attributes)) { foreach ($item->product_attributes->children() as $attr) { $raw_label = (string)$attr->getName(); $value = (string)$attr; if (empty($raw_label) || empty($value)) continue; $label_slug = sanitize_title($raw_label); $label_slug = substr($label_slug, 0, 28); $taxonomy = 'pa_' . $label_slug; global $wpdb; $exists = $wpdb->get_var($wpdb->prepare( "SELECT attribute_id FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_name = %s", $label_slug )); if (!$exists) { $wpdb->insert("{$wpdb->prefix}woocommerce_attribute_taxonomies", [ 'attribute_label' => ucfirst($raw_label), 'attribute_name' => $label_slug, 'attribute_type' => 'select', 'attribute_orderby' => 'menu_order', 'attribute_public' => 1, ]); delete_transient('wc_attribute_taxonomies'); } if (!taxonomy_exists($taxonomy)) { register_taxonomy($taxonomy, 'product', [ 'hierarchical' => false, 'label' => ucfirst($raw_label), 'show_ui' => true, 'query_var' => true, 'rewrite' => ['slug' => $label_slug], ]); } if (!term_exists($value, $taxonomy)) { wp_insert_term($value, $taxonomy); } wp_set_object_terms($product->get_id(), $value, $taxonomy, true); $attr_obj = new WC_Product_Attribute(); $attr_obj->set_name($taxonomy); $attr_obj->set_options([$value]); $attr_obj->set_position(0); $attr_obj->set_visible(true); $attr_obj->set_variation(false); $attributes[] = $attr_obj; } } $product->set_attributes($attributes); if (!$product->get_image_id()) { $images = []; if (!empty($item->image)) $images[] = (string)$item->image; $img_ids = []; foreach ($images as $img_url) { $img_id = get_existing_image_id_by_meta($img_url); if (!$img_id) { $img_id = media_sideload_image($img_url, $product->get_id(), null, 'id'); if (!is_wp_error($img_id)) { // Βάζουμε το URL σαν custom meta update_post_meta($img_id, '_source_image_url', $img_url); } } if (!is_wp_error($img_id)) { $img_ids[] = $img_id; } } if (!empty($img_ids)) { $product->set_image_id(array_shift($img_ids)); $product->set_gallery_image_ids($img_ids); } } $product->save(); wc_delete_product_transients($product->get_id()); wp_set_object_terms($product->get_id(), $category_mapping[$cat_key], 'product_cat'); } $existing_skus = file_exists($sku_path) ? json_decode(file_get_contents($sku_path), true) : []; if (!is_array($existing_skus)) $existing_skus = []; foreach ($existing_skus as $sku_check) { if (!in_array($sku_check, $new_skus)) { $id = wc_get_product_id_by_sku($sku_check); if ($id) wp_delete_post($id, true); } } file_put_contents($sku_path, json_encode($new_skus)); error_log('✅ Oktabit sync complete. Συνολικά νέα SKU: ' . count($new_skus)); } add_action('oktabit_sync_cron', 'oktabit_sync_products'); if (!wp_next_scheduled('oktabit_sync_cron')) { wp_schedule_event(time() + 600, 'daily', 'oktabit_sync_cron'); } add_action('admin_menu', function () { add_submenu_page( 'tools.php', 'Oktabit Sync', 'Oktabit Sync', 'manage_options', 'oktabit-sync', 'oktabit_sync_admin_page' ); }); function oktabit_sync_admin_page() { if (isset($_POST['run_oktabit_sync'])) { oktabit_sync_products(); echo '
✅ Ο συγχρονισμός ολοκληρώθηκε!