'sanitize_text_field',
'default' => ''
)
);
register_setting(
'aiflab_chatweb_settings_group',
'aiflab_chatweb_enable_embed',
array(
'sanitize_callback' => 'rest_sanitize_boolean',
'default' => false
)
);
register_setting(
'aiflab_chatweb_settings_group',
'aiflab_chatweb_embed_code',
array(
'sanitize_callback' => array($this, 'sanitize_embed_code_setting'),
'default' => ''
)
);
register_setting(
'aiflab_chatweb_settings_group',
'aiflab_chatweb_enable_woocommerce_sync',
array(
'sanitize_callback' => 'rest_sanitize_boolean',
'default' => false
)
);
// Add action to flush rewrite rules after settings are saved
add_action('update_option_aiflab_chatweb_enable_embed', function ($old_value, $new_value) {
// Check if enable_embed setting has changed
if ($old_value !== $new_value) {
// Flush rewrite rules
flush_rewrite_rules();
// Clear any cache
if (function_exists('wp_cache_flush')) {
wp_cache_flush();
}
}
}, 10, 2);
}
/**
* Sanitize settings
*/
public function sanitize_settings($settings)
{
// Use public sanitize_settings method from Aiflab_Chatweb_Config
return Aiflab_Chatweb_Config::sanitize_settings($settings);
}
/**
* Main admin page
*/
public function admin_page()
{
?>
0) {
ob_end_clean();
}
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('api_key.auth_error') . $e->getMessage()
));
return;
}
if (!current_user_can('manage_options')) {
while (ob_get_level() > 0) {
ob_end_clean();
}
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('common.no_permission')
));
return;
}
$api_key = isset($_POST['api_key']) ? sanitize_text_field(wp_unslash($_POST['api_key'])) : '';
$debug_log = isset($_POST['debug_log']) ? (bool)$_POST['debug_log'] : true; // Always enable debug log
if (empty($api_key)) {
while (ob_get_level() > 0) {
ob_end_clean();
}
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('api_key.empty_error')
));
return;
}
try {
// Initialize API with new key
$api = new Aiflab_Chatweb_API();
$api->set_api_key($api_key);
// Step 1: Check if activation is needed (new API key)
if ($api->needs_activation()) {
$activate_result = $api->activate_website();
if ($activate_result['success']) {
// Mark this API key as activated
$api->mark_as_activated();
} else {
// Activation failed - return error
while (ob_get_level() > 0) {
ob_end_clean();
}
wp_send_json(array(
'success' => false,
'error' => $activate_result['error'] ?? Aiflab_Chatweb_i18n::t('api_key.activation_failed')
));
return;
}
}
// Step 2: Get embed code (existing logic)
$embed_result = $api->get_website_embed();
if ($embed_result['success']) {
// Save API key to settings
try {
$api_key_saved = Aiflab_Chatweb_Config::update_setting('api_key', $api_key);
// Backup: Save API key directly
update_option('aiflab_chatweb_api_key', $api_key);
} catch (Exception $e) {
// Log error but continue
error_log('ChatWeb: Failed to save API key: ' . $e->getMessage());
}
$embed_code = '';
// If embed code was returned, save it
if (isset($embed_result['data']['embed_code'])) {
try {
$embed_code = $embed_result['data']['embed_code'];
// Save embed code to settings (use only 1 method)
$embed_saved = Aiflab_Chatweb_Config::set_embed_code($embed_code);
// Clear cache after saving embed code
if ($embed_saved) {
// Clear WordPress object cache
if (function_exists('wp_cache_flush')) {
@wp_cache_flush();
}
// Clear plugin caches
@Aiflab_Chatweb_Config::clear_plugin_caches();
}
// Automatically enable embed feature if embed code is retrieved
Aiflab_Chatweb_Config::update_setting('enable_embed', true);
// Check again if embed code has been saved
$saved_embed_code = Aiflab_Chatweb_Config::get_embed_code();
} catch (Exception $e) {
// Log error but continue
error_log('ChatWeb: Failed to save embed code: ' . $e->getMessage());
}
}
while (ob_get_level() > 0) {
ob_end_clean();
}
wp_send_json(array(
'success' => true,
'message' => Aiflab_Chatweb_i18n::t('api_key.save_success'),
'embed_code' => $embed_code,
'auto_enabled' => true,
'debug_info' => $embed_result
));
} else {
// Ensure error is a string
$error_message = is_string($embed_result['error']) ? $embed_result['error'] : (is_array($embed_result['error']) ? json_encode($embed_result['error']) :
Aiflab_Chatweb_i18n::t('api_key.invalid_error'));
while (ob_get_level() > 0) {
ob_end_clean();
}
wp_send_json(array(
'success' => false,
'error' => $error_message,
'debug_info' => $embed_result
));
}
} catch (Exception $e) {
while (ob_get_level() > 0) {
ob_end_clean();
}
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('api_key.test_error') . $e->getMessage()
));
} catch (Error $e) {
while (ob_get_level() > 0) {
ob_end_clean();
}
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('api_key.critical_error') . $e->getMessage()
));
}
}
/**
* AJAX get embed code
*/
public function ajax_get_embed_code()
{
// Suppress any output that might interfere with JSON response
ob_start();
check_ajax_referer('aiflab_chatweb_nonce', 'nonce');
if (!current_user_can('manage_options')) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('common.no_permission')
));
return;
}
$api = new Aiflab_Chatweb_API();
// Check if API key is configured
if (!$api->has_api_key()) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('api_key.not_configured')
));
return;
}
// Log for debugging
// Get embed code from API
$result = $api->get_website_embed();
// Log the result for debugging
if ($result['success'] && isset($result['data']['embed_code'])) {
// Save embed code to settings (use set_embed_code for consistency)
$embed_saved = Aiflab_Chatweb_Config::set_embed_code($result['data']['embed_code']);
// Clear cache after saving embed code
if ($embed_saved) {
// Clear WordPress object cache
if (function_exists('wp_cache_flush')) {
wp_cache_flush();
}
// Clear plugin caches
Aiflab_Chatweb_Config::clear_plugin_caches();
// Verify the embed code was saved correctly
$saved_embed_code = Aiflab_Chatweb_Config::get_embed_code();
}
ob_end_clean();
wp_send_json(array(
'success' => true,
'data' => array(
'embed_code' => $result['data']['embed_code']
),
'message' => Aiflab_Chatweb_i18n::t('embed.refresh_success'),
'saved' => $embed_saved
));
} else {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => isset($result['error']) ? $result['error'] : Aiflab_Chatweb_i18n::t('embed.refresh_error')
));
}
}
/**
* AJAX get dashboard data
*/
public function ajax_get_dashboard_data()
{
// Suppress any output that might interfere with JSON response
ob_start();
check_ajax_referer('aiflab_chatweb_nonce', 'nonce');
if (!current_user_can('manage_options')) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('common.no_permission')
));
return;
}
$api = new Aiflab_Chatweb_API();
$result = $api->get_dashboard_data();
ob_end_clean();
wp_send_json($result);
}
/**
* AJAX clear cache
*/
public function ajax_clear_cache()
{
// Suppress any output that might interfere with JSON response
ob_start();
check_ajax_referer('aiflab_chatweb_nonce', 'nonce');
if (!current_user_can('manage_options')) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('common.no_permission')
));
return;
}
Aiflab_Chatweb_Config::clear_cache();
ob_end_clean();
wp_send_json(array(
'success' => true,
'message' => Aiflab_Chatweb_i18n::t('cache.clear_success')
));
}
/**
* AJAX clear embed code
*/
public function ajax_clear_embed_code()
{
// Suppress any output that might interfere with JSON response
ob_start();
check_ajax_referer('aiflab_chatweb_nonce', 'nonce');
if (!current_user_can('manage_options')) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('common.no_permission')
));
return;
}
Aiflab_Chatweb_Config::clear_embed_code();
ob_end_clean();
wp_send_json(array(
'success' => true,
'message' => Aiflab_Chatweb_i18n::t('embed.delete_success')
));
}
/**
* AJAX sync all products
*/
public function ajax_sync_all_products()
{
// Suppress any output that might interfere with JSON response
ob_start();
check_ajax_referer('aiflab_chatweb_nonce', 'nonce');
if (!current_user_can('manage_options')) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('common.no_permission')
));
return;
}
// Check if WooCommerce is active
if (!class_exists('WooCommerce')) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('woocommerce.not_activated')
));
return;
}
// Get batch parameters
$batch_size = 50; // Number of products per batch
$batch = isset($_POST['batch']) ? intval($_POST['batch']) : 1;
$is_first_batch = $batch === 1;
// Initialize WooCommerce sync
$woocommerce_sync = new Aiflab_Chatweb_WooCommerce();
// Get products across syncable statuses so manual sync can reconcile hidden items too.
$args = array(
'post_type' => 'product',
'post_status' => array('publish', 'private', 'draft', 'pending'),
'posts_per_page' => -1,
'fields' => 'ids'
);
$all_product_ids = get_posts($args);
$total_products = count($all_product_ids);
if (empty($all_product_ids)) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('sync_products.no_products')
));
return;
}
// If first batch, store product IDs in transient to ensure consistency
if ($is_first_batch) {
set_transient('aiflab_chatweb_sync_product_ids', $all_product_ids, 3600); // 1 hour expiration
$this->log_sync_start($total_products);
} else {
// Get stored product IDs from transient
$stored_product_ids = get_transient('aiflab_chatweb_sync_product_ids');
if ($stored_product_ids) {
$all_product_ids = $stored_product_ids;
$total_products = count($all_product_ids);
}
}
// Calculate offset and get current batch of products
$offset = ($batch - 1) * $batch_size;
$current_batch_ids = array_slice($all_product_ids, $offset, $batch_size);
// If no more products in this batch, we're done
if (empty($current_batch_ids)) {
// Clean up transient
delete_transient('aiflab_chatweb_sync_product_ids');
// Log completion
$this->log_sync_complete($total_products);
ob_end_clean();
wp_send_json(array(
'success' => true,
'data' => array(
'total' => $total_products,
'synced' => $total_products, // Assume all synced
'failed' => 0,
'is_complete' => true
),
'message' => Aiflab_Chatweb_i18n::t('sync_products.complete', array($total_products))
));
return;
}
// Prepare product data for bulk sync
$synced = 0;
$failed = 0;
$failed_products = array();
$products_data = array();
// Collect product data for all products in batch
foreach ($current_batch_ids as $product_id) {
$product_data = $woocommerce_sync->prepare_product_data_for_bulk($product_id);
if ($product_data) {
$products_data[] = $product_data;
} else {
// Product data preparation failed
$failed++;
$product = wc_get_product($product_id);
$failed_products[] = array(
'id' => $product_id,
'name' => $product ? $product->get_name() : 'Unknown',
'error' => 'Failed to prepare product data'
);
}
}
// Bulk sync all products in this batch
if (!empty($products_data)) {
$result = $woocommerce_sync->bulk_sync_products($products_data);
if ($result['success']) {
// All products in batch synced successfully
$synced = count($products_data);
} else {
// Entire batch failed
$failed += count($products_data);
// Add all products to failed list
foreach ($products_data as $product_data) {
$product_id = isset($product_data['source_product_id']) ? (int) $product_data['source_product_id'] : 0;
$product = wc_get_product($product_id);
$failed_products[] = array(
'id' => $product_id,
'name' => $product ? $product->get_name() : 'Unknown',
'error' => isset($result['error']) ? $result['error'] : 'Bulk sync failed'
);
}
}
}
// Log batch progress
$processed_so_far = $offset + count($current_batch_ids);
$this->log_sync_batch_progress($batch, $processed_so_far, $total_products, $synced, $failed, $failed_products);
// Calculate progress
$is_complete = $processed_so_far >= $total_products;
$next_batch = $is_complete ? null : $batch + 1;
// If complete, clean up transient
if ($is_complete) {
delete_transient('aiflab_chatweb_sync_product_ids');
$this->log_sync_complete($total_products);
}
ob_end_clean();
wp_send_json(array(
'success' => true,
'data' => array(
'total' => $total_products,
'processed' => $processed_so_far,
'synced' => $synced,
'failed' => $failed,
'failed_products' => $failed_products,
'is_complete' => $is_complete,
'next_batch' => $next_batch,
'batch_size' => $batch_size,
'batch' => $batch
),
'message' => $is_complete
? Aiflab_Chatweb_i18n::t('sync_products.complete', array($processed_so_far))
: Aiflab_Chatweb_i18n::t('sync_products.progress', array($processed_so_far, $total_products))
));
}
/**
* Log sync start
*
* @param int $total_products
*/
private function log_sync_start($total_products)
{
$log_data = array(
'time' => current_time('mysql'),
'action' => 'sync_start',
'total_products' => $total_products,
'user_id' => get_current_user_id(),
'user_login' => wp_get_current_user()->user_login
);
// $this->write_to_sync_log($log_data);
}
/**
* Log sync batch progress
*
* @param int $batch
* @param int $processed
* @param int $total
* @param int $synced
* @param int $failed
* @param array $failed_products
*/
private function log_sync_batch_progress($batch, $processed, $total, $synced, $failed, $failed_products)
{
$log_data = array(
'time' => current_time('mysql'),
'action' => 'sync_batch_progress',
'batch' => $batch,
'processed' => $processed,
'total' => $total,
'synced' => $synced,
'failed' => $failed,
'failed_products' => $failed_products
);
// $this->write_to_sync_log($log_data);
}
/**
* Log sync complete
*
* @param int $total_products
*/
private function log_sync_complete($total_products)
{
$log_data = array(
'time' => current_time('mysql'),
'action' => 'sync_complete',
'total_products' => $total_products,
'user_id' => get_current_user_id(),
'user_login' => wp_get_current_user()->user_login
);
// $this->write_to_sync_log($log_data);
}
/**
* Write to sync log file
*
* @param array $log_data
* @return bool Success or failure
*/
private function write_to_sync_log($log_data)
{
try {
// Get upload directory
$upload_dir = wp_upload_dir();
// Check if upload directory is writable
if (isset($upload_dir['error']) && $upload_dir['error'] !== false) {
return false;
}
$logs_dir = $upload_dir['basedir'] . '/aiflab-chatweb-logs';
// Try to create logs directory if it doesn't exist
if (!file_exists($logs_dir)) {
$dir_created = wp_mkdir_p($logs_dir);
if (!$dir_created) {
return false;
}
// Create .htaccess to protect logs
$htaccess_file = $logs_dir . '/.htaccess';
$htaccess_content = "Order deny,allow\nDeny from all";
$htaccess_written = @file_put_contents($htaccess_file, $htaccess_content);
// Create index.php to prevent directory listing
$index_file = $logs_dir . '/index.php';
$index_content = ' false,
'error' => Aiflab_Chatweb_i18n::t('common.no_permission')
));
return;
}
// Chuyển đổi giá trị từ POST thành boolean
$enable_embed = isset($_POST['enable_embed']) && sanitize_text_field(wp_unslash($_POST['enable_embed'])) ? true : false;
$enable_embed_bool = (bool) $enable_embed;
// Lấy giá trị hiện tại và normalize về boolean để so sánh
$current_value_raw = Aiflab_Chatweb_Config::get_setting('enable_embed', false);
$current_value = filter_var($current_value_raw, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
if ($current_value === null) {
$current_value = (bool) $current_value_raw;
}
// Cập nhật cài đặt thông qua Aiflab_Chatweb_Config
$result = Aiflab_Chatweb_Config::update_setting('enable_embed', $enable_embed_bool);
// update_option() trả về false nếu giá trị không thay đổi
// Nếu result là false, kiểm tra xem giá trị có thực sự khác không
// Nếu giá trị giống nhau (sau khi normalize), coi như thành công
$value_changed = false;
if ($result === false) {
// Kiểm tra lại giá trị sau khi update để xác định có phải do không thay đổi không
$updated_value_raw = Aiflab_Chatweb_Config::get_setting('enable_embed', false);
$updated_value = filter_var($updated_value_raw, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
if ($updated_value === null) {
$updated_value = (bool) $updated_value_raw;
}
// Nếu giá trị sau khi update giống với giá trị muốn set, coi như thành công
$success = ($updated_value === $enable_embed_bool);
$value_changed = ($current_value !== $enable_embed_bool);
} else {
$success = true;
$value_changed = ($current_value !== $enable_embed_bool);
}
// Flush rewrite rules nếu cần và giá trị đã thay đổi
if ($success && $value_changed) {
// Suppress any output from these functions
@flush_rewrite_rules();
// Clear cache
if (function_exists('wp_cache_flush')) {
@wp_cache_flush();
}
// Clear plugin caches
@Aiflab_Chatweb_Config::clear_plugin_caches();
}
// Clean any buffered output before sending JSON
while (ob_get_level() > 0) {
ob_end_clean();
}
wp_send_json(array(
'success' => $success,
'message' => $success
? Aiflab_Chatweb_i18n::t('embed_settings.save_success')
: Aiflab_Chatweb_i18n::t('embed_settings.save_error'),
'data' => array(
'enable_embed' => $enable_embed_bool
)
));
}
/**
* AJAX update WooCommerce settings
*/
public function ajax_update_woocommerce_settings()
{
// Suppress any output that might interfere with JSON response
ob_start();
check_ajax_referer('aiflab_chatweb_nonce', 'nonce');
if (!current_user_can('manage_options')) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('common.no_permission')
));
return;
}
// Chuyển đổi giá trị từ POST thành boolean
$enable_woocommerce_sync = isset($_POST['enable_woocommerce_sync']) && sanitize_text_field(wp_unslash($_POST['enable_woocommerce_sync'])) ? true : false;
$enable_woocommerce_sync_bool = (bool) $enable_woocommerce_sync;
// Lấy giá trị hiện tại và normalize về boolean để so sánh
$current_value_raw = Aiflab_Chatweb_Config::get_setting('enable_woocommerce_sync', false);
$current_value = filter_var($current_value_raw, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
if ($current_value === null) {
$current_value = (bool) $current_value_raw;
}
// Cập nhật cài đặt thông qua Aiflab_Chatweb_Config
$result = Aiflab_Chatweb_Config::update_setting('enable_woocommerce_sync', $enable_woocommerce_sync_bool);
// update_option() trả về false nếu giá trị không thay đổi
// Nếu result là false, kiểm tra xem giá trị có thực sự khác không
// Nếu giá trị giống nhau (sau khi normalize), coi như thành công
if ($result === false) {
// Kiểm tra lại giá trị sau khi update để xác định có phải do không thay đổi không
$updated_value_raw = Aiflab_Chatweb_Config::get_setting('enable_woocommerce_sync', false);
$updated_value = filter_var($updated_value_raw, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
if ($updated_value === null) {
$updated_value = (bool) $updated_value_raw;
}
// Nếu giá trị sau khi update giống với giá trị muốn set, coi như thành công
$success = ($updated_value === $enable_woocommerce_sync_bool);
} else {
$success = true;
}
ob_end_clean();
wp_send_json(array(
'success' => $success,
'message' => $success
? Aiflab_Chatweb_i18n::t('woocommerce.save_success')
: Aiflab_Chatweb_i18n::t('embed_settings.save_error'),
'data' => array(
'enable_woocommerce_sync' => $enable_woocommerce_sync_bool
)
));
}
/**
* AJAX get sync logs
*/
public function ajax_get_sync_logs()
{
// Suppress any output that might interfere with JSON response
ob_start();
check_ajax_referer('aiflab_chatweb_nonce', 'nonce');
if (!current_user_can('manage_options')) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('common.no_permission')
));
return;
}
// Get date parameter
$date = isset($_POST['date']) ? sanitize_text_field(wp_unslash($_POST['date'])) : gmdate('Y-m-d');
$log_type = isset($_POST['log_type']) ? sanitize_text_field(wp_unslash($_POST['log_type'])) : 'summary';
// Get upload directory
$upload_dir = wp_upload_dir();
if (isset($upload_dir['error']) && $upload_dir['error'] !== false) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('logs.upload_access_error') . $upload_dir['error']
));
return;
}
$logs_dir = $upload_dir['basedir'] . '/aiflab-chatweb-logs';
if (!file_exists($logs_dir)) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('logs.dir_not_found')
));
return;
}
// Determine log file path based on log type
$log_file = '';
if ($log_type === 'detailed') {
$log_file = $logs_dir . '/product-sync-detailed-' . $date . '.log';
} else {
$log_file = $logs_dir . '/product-sync-' . $date . '.log';
}
if (!file_exists($log_file)) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('logs.file_not_found')
));
return;
}
// Read log file
$log_content = file_get_contents($log_file);
if ($log_content === false) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('logs.read_error')
));
return;
}
// Parse log entries
$log_entries = array();
$entries = explode("\n", $log_content);
foreach ($entries as $entry) {
if (empty(trim($entry)) || $entry === '---') {
continue;
}
$parsed_entry = json_decode($entry, true);
if ($parsed_entry) {
$log_entries[] = $parsed_entry;
}
}
// Get available log dates
$available_dates = array();
$log_files = glob($logs_dir . '/product-sync-*.log');
foreach ($log_files as $file) {
if (preg_match('/product-sync-(\d{4}-\d{2}-\d{2})\.log$/', $file, $matches)) {
$available_dates[] = $matches[1];
}
}
// Sort dates in descending order
rsort($available_dates);
ob_end_clean();
wp_send_json(array(
'success' => true,
'data' => array(
'entries' => $log_entries,
'available_dates' => $available_dates,
'current_date' => $date,
'log_type' => $log_type
)
));
}
/**
* AJAX sync all posts
*/
public function ajax_sync_all_posts()
{
// Suppress any output that might interfere with JSON response
ob_start();
check_ajax_referer('aiflab_chatweb_nonce', 'nonce');
if (!current_user_can('manage_options')) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('common.no_permission')
));
return;
}
// Get batch parameters
$batch_size = 10; // Number of posts per batch
$batch = isset($_POST['batch']) ? intval($_POST['batch']) : 1;
$is_first_batch = $batch === 1;
// Initialize Posts sync
$posts_sync = new Aiflab_Chatweb_Posts();
// Get all published posts
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => -1,
'fields' => 'ids'
);
$all_post_ids = get_posts($args);
$total_posts = count($all_post_ids);
if (empty($all_post_ids)) {
ob_end_clean();
wp_send_json(array(
'success' => false,
'error' => Aiflab_Chatweb_i18n::t('sync_posts.no_posts')
));
return;
}
// If first batch, store post IDs and reset counters in transient
if ($is_first_batch) {
set_transient('aiflab_chatweb_sync_post_ids', $all_post_ids, 3600); // 1 hour expiration
set_transient('aiflab_chatweb_sync_post_synced', 0, 3600);
set_transient('aiflab_chatweb_sync_post_failed', 0, 3600);
set_transient('aiflab_chatweb_sync_post_failed_posts', array(), 3600);
} else {
// Get stored post IDs from transient
$stored_post_ids = get_transient('aiflab_chatweb_sync_post_ids');
if ($stored_post_ids) {
$all_post_ids = $stored_post_ids;
$total_posts = count($all_post_ids);
}
}
// Get accumulated counts from previous batches
$total_synced = (int) get_transient('aiflab_chatweb_sync_post_synced');
$total_failed = (int) get_transient('aiflab_chatweb_sync_post_failed');
$all_failed_posts = get_transient('aiflab_chatweb_sync_post_failed_posts');
if (!is_array($all_failed_posts)) {
$all_failed_posts = array();
}
// Calculate offset and get current batch of posts
$offset = ($batch - 1) * $batch_size;
$current_batch_ids = array_slice($all_post_ids, $offset, $batch_size);
// If no more posts in this batch, we're done
if (empty($current_batch_ids)) {
// Clean up transients
delete_transient('aiflab_chatweb_sync_post_ids');
delete_transient('aiflab_chatweb_sync_post_synced');
delete_transient('aiflab_chatweb_sync_post_failed');
delete_transient('aiflab_chatweb_sync_post_failed_posts');
// Cleanup temp JSON files
$posts_sync->cleanup_temp_files();
ob_end_clean();
wp_send_json(array(
'success' => true,
'data' => array(
'total' => $total_posts,
'synced' => $total_synced,
'failed' => $total_failed,
'failed_posts' => $all_failed_posts,
'is_complete' => true
),
'message' => Aiflab_Chatweb_i18n::t('sync_posts.result', array($total_posts, $total_synced, $total_failed))
));
return;
}
// Sync posts in current batch
$batch_results = $posts_sync->sync_posts_batch($current_batch_ids);
// Accumulate counts
$batch_synced = $batch_results['synced'];
$batch_failed = $batch_results['failed'];
$batch_failed_posts = $batch_results['failed_posts'];
$total_synced += $batch_synced;
$total_failed += $batch_failed;
$all_failed_posts = array_merge($all_failed_posts, $batch_failed_posts);
// Save accumulated counts to transient
set_transient('aiflab_chatweb_sync_post_synced', $total_synced, 3600);
set_transient('aiflab_chatweb_sync_post_failed', $total_failed, 3600);
set_transient('aiflab_chatweb_sync_post_failed_posts', $all_failed_posts, 3600);
// Calculate total processed
$processed = $offset + count($current_batch_ids);
// Determine if there are more batches
$has_more = $processed < $total_posts;
$next_batch = $has_more ? $batch + 1 : null;
// If this is the last batch, cleanup transients and temp files
if (!$has_more) {
delete_transient('aiflab_chatweb_sync_post_ids');
delete_transient('aiflab_chatweb_sync_post_synced');
delete_transient('aiflab_chatweb_sync_post_failed');
delete_transient('aiflab_chatweb_sync_post_failed_posts');
$posts_sync->cleanup_temp_files();
}
ob_end_clean();
// Build accurate completion message
$complete_message = '';
if (!$has_more) {
$complete_message = Aiflab_Chatweb_i18n::t('sync_posts.result', array($total_posts, $total_synced, $total_failed));
} else {
$complete_message = Aiflab_Chatweb_i18n::t('sync_posts.progress', array($processed, $total_posts));
}
wp_send_json(array(
'success' => true,
'data' => array(
'total' => $total_posts,
'processed' => $processed,
'synced' => $total_synced,
'failed' => $total_failed,
'failed_posts' => $all_failed_posts,
'is_complete' => !$has_more,
'next_batch' => $next_batch
),
'message' => $complete_message
));
}
// Debug page removed in v1.0.3
}