' . esc_html__('Reset will: clear the completion flag, delete the per-row "_aieo_variation_migrated" + "_aieo_swatch_term_migrated" markers from every product/term. The next "Run all" will reprocess every legacy row from scratch. Continue?', 'ai-eshop-optimizer') . '
'
);
echo $reset_ask;
if ($as_pending > 0) {
$clear_ask = \Rooster\Admin\States::confirm(
'aieo-dmm-vg-mig-clear-as-dialog',
'reset',
__('Stop the migration in the background?', 'ai-eshop-optimizer'),
'
' . esc_html(sprintf(
_n(
'Deletes the %s pending Action Scheduler job of this migration, so it no longer runs in the background. Run all batches here finishes it.',
'Deletes the %s pending Action Scheduler jobs of this migration, so it no longer runs in the background. Run all batches here finishes it.',
$as_pending,
'ai-eshop-optimizer'
),
number_format_i18n($as_pending)
)) . '
',
array('confirm' => __('Delete pending AS jobs', 'ai-eshop-optimizer'))
);
echo $clear_ask;
}
?>
get_var($wpdb->prepare(
"SELECT COUNT(DISTINCT legacy.post_id)
FROM {$wpdb->postmeta} AS legacy
INNER JOIN {$wpdb->posts} AS posts
ON posts.ID = legacy.post_id AND posts.post_type = 'product_variation'
LEFT JOIN {$wpdb->postmeta} AS canonical
ON canonical.post_id = legacy.post_id
AND canonical.meta_key = '_product_image_gallery'
AND canonical.meta_value <> ''
LEFT JOIN {$wpdb->postmeta} AS attempted
ON attempted.post_id = legacy.post_id
AND attempted.meta_key = %s
AND attempted.meta_value = 'yes'
WHERE legacy.meta_key = 'botiga_variation_gallery'
AND legacy.meta_value <> ''
AND canonical.post_id IS NULL
AND attempted.post_id IS NULL",
$migrated_meta
));
$terms_remaining = (int) $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(DISTINCT tm.term_id)
FROM {$wpdb->termmeta} AS tm
INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = tm.term_id
LEFT JOIN {$wpdb->termmeta} AS canonical
ON canonical.term_id = tm.term_id
AND canonical.meta_key = 'color'
AND canonical.meta_value <> ''
LEFT JOIN {$wpdb->termmeta} AS sidecar_type
ON sidecar_type.term_id = tm.term_id
AND sidecar_type.meta_key = '_aieo_swatch_color_type'
LEFT JOIN {$wpdb->termmeta} AS sidecar_image
ON sidecar_image.term_id = tm.term_id
AND sidecar_image.meta_key = '_aieo_swatch_image_id'
LEFT JOIN {$wpdb->termmeta} AS attempted
ON attempted.term_id = tm.term_id
AND attempted.meta_key = %s
AND attempted.meta_value = 'yes'
WHERE tm.meta_key IN ('product_attribute_color', 'product_attribute_image')
AND tm.meta_value <> ''
AND tt.taxonomy LIKE %s
AND canonical.term_id IS NULL
AND sidecar_type.term_id IS NULL
AND sidecar_image.term_id IS NULL
AND attempted.term_id IS NULL",
$term_migrated_meta,
$wpdb->esc_like('pa_') . '%'
));
$as_pending = (int) $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM {$wpdb->prefix}actionscheduler_actions
WHERE hook = %s AND status = 'pending'",
AIEO_WC_Compat_Migration::UPDATE_HOOK
));
$completed_raw = get_option(AIEO_WC_Compat_Migration::COMPLETED_OPTION);
$completed_at = is_numeric($completed_raw)
? (int) $completed_raw
: ($completed_raw ? (int) strtotime((string) $completed_raw) : 0);
return array(
'variations_remaining' => $variations_remaining,
'terms_remaining' => $terms_remaining,
'as_pending' => $as_pending,
'completed_at' => $completed_at,
'completed_at_formatted' => $completed_at ? gmdate('Y-m-d H:i:s', $completed_at) . ' UTC' : '',
);
}
public function ajax_migration_status() {
AIEO_DMM::verify_ajax_request();
wp_send_json_success($this->migration_status_snapshot());
}
public function ajax_migration_run_batch() {
AIEO_DMM::verify_ajax_request();
if (!class_exists('AIEO_WC_Compat_Migration')) {
wp_send_json_error(array('message' => __('Migration class not loaded.', 'ai-eshop-optimizer')));
}
$had_completed = get_option(AIEO_WC_Compat_Migration::COMPLETED_OPTION);
if ($had_completed) { delete_option(AIEO_WC_Compat_Migration::COMPLETED_OPTION); }
$more = AIEO_WC_Compat_Migration::run();
$snap = $this->migration_status_snapshot();
wp_send_json_success(array_merge($snap, array('more' => (bool) $more)));
}
public function ajax_migration_reset() {
AIEO_DMM::verify_ajax_request();
if (!class_exists('AIEO_WC_Compat_Migration')) {
wp_send_json_error(array('message' => __('Migration class not loaded.', 'ai-eshop-optimizer')));
}
global $wpdb;
delete_option(AIEO_WC_Compat_Migration::COMPLETED_OPTION);
$migrated_meta = AIEO_WC_Compat_Migration::MIGRATED_META;
$term_migrated_meta = AIEO_WC_Compat_Migration::TERM_MIGRATED_META;
$pm_deleted = (int) $wpdb->query($wpdb->prepare(
"DELETE FROM {$wpdb->postmeta} WHERE meta_key = %s",
$migrated_meta
));
$tm_deleted = (int) $wpdb->query($wpdb->prepare(
"DELETE FROM {$wpdb->termmeta} WHERE meta_key = %s",
$term_migrated_meta
));
wp_send_json_success(array(
'message' => sprintf(
__('Reset done. Cleared completion flag + %1$d postmeta + %2$d termmeta markers.', 'ai-eshop-optimizer'),
$pm_deleted,
$tm_deleted
),
));
}
public function ajax_migration_clear_as() {
AIEO_DMM::verify_ajax_request();
if (!class_exists('AIEO_WC_Compat_Migration')) {
wp_send_json_error(array('message' => __('Migration class not loaded.', 'ai-eshop-optimizer')));
}
global $wpdb;
$deleted = (int) $wpdb->query($wpdb->prepare(
"DELETE FROM {$wpdb->prefix}actionscheduler_actions
WHERE hook = %s AND status IN ('pending','in-progress')",
AIEO_WC_Compat_Migration::UPDATE_HOOK
));
wp_send_json_success(array(
'message' => sprintf(
__('Deleted %d pending/in-progress AS jobs.', 'ai-eshop-optimizer'),
$deleted
),
'deleted' => $deleted,
));
}
}