sdk = new MiraviaSdk(); } /** * Submit single product to Feed API */ public function submitSingleProduct($productId) { return $this->submitProducts([$productId]); } /** * Submit multiple products to Feed API */ public function submitProducts($productIds) { global $wpdb; if(empty($productIds)) { return ['success' => false, 'error' => 'No products provided']; } // Validate all products exist $validProducts = []; foreach($productIds as $productId) { $product = wc_get_product($productId); if($product) { $validProducts[] = $productId; } } if(empty($validProducts)) { return ['success' => false, 'error' => 'No valid products found']; } // Create feed job record $jobId = $wpdb->insert( $wpdb->prefix . 'miravia_feed_jobs', [ 'feed_type' => 'PRODUCT_LISTING', 'status' => 'CREATING_DOCUMENT', 'product_count' => count($validProducts), 'product_ids' => json_encode($validProducts) ], ['%s', '%s', '%d', '%s'] ); if(!$jobId) { return ['success' => false, 'error' => 'Failed to create job record']; } $jobId = $wpdb->insert_id; LOG::add("Feed Manager: Starting job {$jobId} for " . count($validProducts) . " products"); try { // Build products data for feed $feedData = $this->buildFeedData($validProducts); // Submit to Feed API $result = $this->sdk->submitFeed($feedData); if($result && $result['success']) { // Update job with feed ID $wpdb->update( $wpdb->prefix . 'miravia_feed_jobs', [ 'feed_id' => $result['feed_id'], 'feed_document_id' => $result['feed_document_id'], 'status' => 'SUBMITTED', 'processing_start_time' => current_time('mysql') ], ['id' => $jobId], ['%s', '%s', '%s', '%s'], ['%d'] ); LOG::add("Feed Manager: Job {$jobId} submitted successfully - Feed ID: {$result['feed_id']}"); return [ 'success' => true, 'job_id' => $jobId, 'feed_id' => $result['feed_id'], 'message' => "Feed submitted successfully for " . count($validProducts) . " products" ]; } else { // Update job with error $wpdb->update( $wpdb->prefix . 'miravia_feed_jobs', [ 'status' => 'FAILED', 'error_message' => $this->sdk->last_error ], ['id' => $jobId], ['%s', '%s'], ['%d'] ); return ['success' => false, 'error' => $this->sdk->last_error]; } } catch (Exception $e) { // Update job with error $wpdb->update( $wpdb->prefix . 'miravia_feed_jobs', [ 'status' => 'FAILED', 'error_message' => $e->getMessage() ], ['id' => $jobId], ['%s', '%s'], ['%d'] ); LOG::add("Feed Manager: Job {$jobId} failed - " . $e->getMessage()); return ['success' => false, 'error' => $e->getMessage()]; } } /** * Build feed data from WooCommerce products */ private function buildFeedData($productIds) { $feedProducts = []; foreach($productIds as $productId) { $product = wc_get_product($productId); if(!$product) continue; // Get product images $images = []; $imageId = $product->get_image_id(); if($imageId) { $images[] = wp_get_attachment_image_url($imageId, 'full'); } $galleryIds = $product->get_gallery_image_ids(); foreach($galleryIds as $galleryId) { $images[] = wp_get_attachment_image_url($galleryId, 'full'); } // Build product data for feed $productKey = "Product_" . $productId; $feedProducts[$productKey] = [ 'PrimaryCategory' => get_option('miravia_default_category', 201336100), 'Images' => ['Image' => $images], 'Attributes' => [ 'name' => $product->get_name(), 'description' => $product->get_description() ?: $product->get_short_description(), 'short_description' => $product->get_short_description(), 'brand' => get_option('miravia_default_brand', 'No Brand'), 'delivery_option_sof' => 'No', 'Hazmat' => 'None' ], 'Skus' => [ 'Sku' => [[ 'SellerSku' => $product->get_sku() ?: "wp_" . $productId, 'quantity' => $product->get_stock_quantity() ?: get_option('_miravia_default_stock', 100), 'price' => $product->get_regular_price(), 'special_price' => $product->get_sale_price(), 'package_height' => '1', 'package_length' => '1', 'package_width' => '1', 'package_weight' => $product->get_weight() ?: '0.1', 'package_content' => $product->get_name(), 'ean_code' => get_post_meta($productId, get_option('miravia_ean_key', '_ean'), true), 'Images' => ['Image' => array_slice($images, 0, 1)] // First image for SKU ]] ] ]; } return $feedProducts; } /** * Update job status by checking Feed API */ public function updateJobStatus($jobId) { global $wpdb; $job = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}miravia_feed_jobs WHERE id = %d", $jobId )); if(!$job || !$job->feed_id) { return false; } // Get feed status from API $status = $this->sdk->getFeedStatus($job->feed_id); if($status) { $updateData = ['updated' => current_time('mysql')]; switch($status->processing_status) { case 'DONE': $updateData['status'] = 'COMPLETED'; $updateData['processing_end_time'] = current_time('mysql'); // Get detailed results if available if(isset($status->result_feed_document_id)) { $results = $this->sdk->getFeedResults($status->result_feed_document_id); if($results) { $updateData['result_data'] = json_encode($results); } } break; case 'IN_PROGRESS': $updateData['status'] = 'PROCESSING'; break; case 'FAILED': case 'CANCELLED': case 'FATAL': $updateData['status'] = 'FAILED'; $updateData['processing_end_time'] = current_time('mysql'); if(isset($status->error_message)) { $updateData['error_message'] = $status->error_message; } break; } $wpdb->update( $wpdb->prefix . 'miravia_feed_jobs', $updateData, ['id' => $jobId], array_fill(0, count($updateData), '%s'), ['%d'] ); LOG::add("Feed Manager: Job {$jobId} status updated to {$updateData['status']}"); return true; } return false; } /** * Get all jobs with pagination */ public function getJobs($limit = 20, $offset = 0, $status = null) { global $wpdb; $where = ''; $params = []; if($status) { $where = ' WHERE status = %s'; $params[] = $status; } $params[] = $limit; $params[] = $offset; return $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}miravia_feed_jobs{$where} ORDER BY created DESC LIMIT %d OFFSET %d", ...$params )); } /** * Get job count */ public function getJobCount($status = null) { global $wpdb; $where = ''; $params = []; if($status) { $where = ' WHERE status = %s'; $params[] = $status; } return $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}miravia_feed_jobs{$where}", ...$params )); } /** * Resubmit failed job */ public function resubmitJob($jobId) { global $wpdb; $job = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}miravia_feed_jobs WHERE id = %d", $jobId )); if(!$job) { return ['success' => false, 'error' => 'Job not found']; } $productIds = json_decode($job->product_ids, true); if(!$productIds) { return ['success' => false, 'error' => 'No products found in job']; } // Reset job status $wpdb->update( $wpdb->prefix . 'miravia_feed_jobs', [ 'status' => 'RESUBMITTING', 'feed_id' => null, 'feed_document_id' => null, 'error_message' => null, 'processing_start_time' => null, 'processing_end_time' => null ], ['id' => $jobId], ['%s', '%s', '%s', '%s', '%s', '%s'], ['%d'] ); // Resubmit return $this->submitProducts($productIds); } }