1671 lines
54 KiB
PHP
1671 lines
54 KiB
PHP
<?php
|
|
/**
|
|
* The admin-specific functionality of the plugin.
|
|
*
|
|
* @package MaplePress
|
|
* @subpackage MaplePress/includes
|
|
*/
|
|
|
|
class MaplePress_Admin {
|
|
|
|
/**
|
|
* The ID of this plugin.
|
|
*
|
|
* @var string
|
|
*/
|
|
private $plugin_name;
|
|
|
|
/**
|
|
* The version of this plugin.
|
|
*
|
|
* @var string
|
|
*/
|
|
private $version;
|
|
|
|
/**
|
|
* Initialize the class and set its properties.
|
|
*
|
|
* @param string $plugin_name The name of this plugin.
|
|
* @param string $version The version of this plugin.
|
|
*/
|
|
public function __construct( $plugin_name, $version ) {
|
|
$this->plugin_name = $plugin_name;
|
|
$this->version = $version;
|
|
|
|
// Add admin notices
|
|
add_action( 'admin_notices', array( $this, 'display_admin_notices' ) );
|
|
|
|
// Handle activation redirect and initial sync redirect (early priority to run before page render)
|
|
add_action( 'admin_init', array( $this, 'activation_redirect' ), 1 );
|
|
add_action( 'admin_init', array( $this, 'handle_sync_redirect' ), 1 );
|
|
|
|
// Remove default WordPress "Settings saved" message to avoid duplication
|
|
add_filter( 'pre_update_option_maplepress_settings', array( $this, 'suppress_default_success_message' ), 10, 2 );
|
|
|
|
// Hook into post/page save events for automatic syncing
|
|
add_action( 'save_post', array( $this, 'sync_page_on_save' ), 10, 3 );
|
|
add_action( 'before_delete_post', array( $this, 'delete_page_on_delete' ) );
|
|
|
|
// Bulk sync all pages action
|
|
add_action( 'admin_action_maplepress_bulk_sync', array( $this, 'bulk_sync_pages' ) );
|
|
|
|
// Handle domain verification action
|
|
add_action( 'admin_action_maplepress_verify_domain', array( $this, 'handle_verify_domain' ) );
|
|
|
|
// Handle reset settings action (for both admin.php and admin-post.php forms)
|
|
add_action( 'admin_action_maplepress_reset_settings', array( $this, 'handle_reset_settings' ) );
|
|
add_action( 'admin_post_maplepress_reset_settings', array( $this, 'handle_reset_settings' ) );
|
|
|
|
// Handle reset and delete action (for both admin.php and admin-post.php forms)
|
|
add_action( 'admin_action_maplepress_reset_and_delete', array( $this, 'handle_reset_and_delete' ) );
|
|
add_action( 'admin_post_maplepress_reset_and_delete', array( $this, 'handle_reset_and_delete' ) );
|
|
|
|
// AJAX handler for speed test
|
|
add_action( 'wp_ajax_mpss_run_test', array( $this, 'handle_speedtest_ajax' ) );
|
|
|
|
// AJAX handler for bulk sync
|
|
add_action( 'wp_ajax_maplepress_bulk_sync_ajax', array( $this, 'handle_bulk_sync_ajax' ) );
|
|
|
|
// AJAX handler for verification with sync
|
|
add_action( 'wp_ajax_maplepress_verify_and_sync_ajax', array( $this, 'handle_verify_and_sync_ajax' ) );
|
|
|
|
// AJAX handler for initial sync (from dedicated sync page)
|
|
add_action( 'wp_ajax_maplepress_initial_sync', array( $this, 'handle_initial_sync_ajax' ) );
|
|
}
|
|
|
|
/**
|
|
* Register the stylesheets for the admin area.
|
|
*/
|
|
public function enqueue_styles() {
|
|
wp_enqueue_style(
|
|
$this->plugin_name,
|
|
MAPLEPRESS_PLUGIN_URL . 'assets/css/maplepress-admin.css',
|
|
array(),
|
|
$this->version,
|
|
'all'
|
|
);
|
|
|
|
// Enqueue speed test styles on speed test page
|
|
$screen = get_current_screen();
|
|
|
|
// Check for speedtest page - try both possible screen ID formats
|
|
$is_speedtest_page = $screen && (
|
|
$screen->id === 'admin_page_maplepress-speedtest' ||
|
|
$screen->id === 'maplepress_page_maplepress-speedtest'
|
|
);
|
|
|
|
if ( $is_speedtest_page ) {
|
|
wp_enqueue_style(
|
|
'maplepress-speedtest',
|
|
MAPLEPRESS_PLUGIN_URL . 'assets/css/speedtest-admin.css',
|
|
array(),
|
|
$this->version,
|
|
'all'
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register the JavaScript for the admin area.
|
|
*/
|
|
public function enqueue_scripts() {
|
|
wp_enqueue_script(
|
|
$this->plugin_name,
|
|
MAPLEPRESS_PLUGIN_URL . 'assets/js/maplepress-admin.js',
|
|
array( 'jquery' ),
|
|
$this->version,
|
|
false
|
|
);
|
|
|
|
// Enqueue Chart.js and speed test scripts on speed test page
|
|
$screen = get_current_screen();
|
|
|
|
// Debug: Log screen ID to help diagnose issues
|
|
if ( $screen ) {
|
|
error_log( 'MaplePress: Current screen ID = ' . $screen->id );
|
|
}
|
|
|
|
// Check for speedtest page - try both possible screen ID formats
|
|
$is_speedtest_page = $screen && (
|
|
$screen->id === 'admin_page_maplepress-speedtest' ||
|
|
$screen->id === 'maplepress_page_maplepress-speedtest'
|
|
);
|
|
|
|
if ( $is_speedtest_page ) {
|
|
wp_enqueue_script(
|
|
'chartjs',
|
|
'https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js',
|
|
array(),
|
|
'4.4.0',
|
|
true
|
|
);
|
|
|
|
wp_enqueue_script(
|
|
'maplepress-speedtest',
|
|
MAPLEPRESS_PLUGIN_URL . 'assets/js/speedtest-simple.js',
|
|
array( 'jquery', 'chartjs' ),
|
|
$this->version,
|
|
true
|
|
);
|
|
|
|
// Localize script for AJAX
|
|
wp_localize_script(
|
|
'maplepress-speedtest',
|
|
'mpssAjax',
|
|
array(
|
|
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
|
'nonce' => wp_create_nonce( 'mpss_test_nonce' ),
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add plugin admin menu.
|
|
*/
|
|
public function add_plugin_admin_menu() {
|
|
// Add top-level menu item - Dashboard
|
|
add_menu_page(
|
|
__( 'MaplePress Dashboard', 'maplepress' ), // Page title
|
|
__( 'MaplePress', 'maplepress' ), // Menu title
|
|
'manage_options', // Capability
|
|
'maplepress', // Menu slug
|
|
array( $this, 'display_dashboard_page' ), // Callback
|
|
'data:image/svg+xml;base64,' . base64_encode( '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text y="75" font-size="75">🍁</text></svg>' ), // Maple leaf icon
|
|
30 // Position (below Comments)
|
|
);
|
|
|
|
// Add Dashboard submenu (rename the first item)
|
|
add_submenu_page(
|
|
'maplepress', // Parent slug
|
|
__( 'Dashboard', 'maplepress' ), // Page title
|
|
__( 'Dashboard', 'maplepress' ), // Menu title
|
|
'manage_options', // Capability
|
|
'maplepress', // Menu slug (same as parent)
|
|
array( $this, 'display_dashboard_page' ) // Callback
|
|
);
|
|
|
|
// Add Settings submenu
|
|
add_submenu_page(
|
|
'maplepress', // Parent slug
|
|
__( 'Settings', 'maplepress' ), // Page title
|
|
__( 'Settings', 'maplepress' ), // Menu title
|
|
'manage_options', // Capability
|
|
'maplepress-settings', // Menu slug
|
|
array( $this, 'display_settings_page' ) // Callback
|
|
);
|
|
|
|
// Register pages without adding to menu (for Advanced section access)
|
|
// Speed Test - accessible via dashboard Advanced section
|
|
add_submenu_page(
|
|
null, // No parent = hidden from menu
|
|
__( 'Search Speed Test', 'maplepress' ), // Page title
|
|
__( 'Search Speed Test', 'maplepress' ), // Menu title
|
|
'manage_options', // Capability
|
|
'maplepress-speedtest', // Menu slug
|
|
array( $this, 'display_speedtest_page' ) // Callback
|
|
);
|
|
|
|
// Ready to Sync - shown after first-time connection
|
|
add_submenu_page(
|
|
null, // No parent = hidden from menu
|
|
__( 'Ready to Sync', 'maplepress' ), // Page title
|
|
__( 'Ready to Sync', 'maplepress' ), // Menu title
|
|
'manage_options', // Capability
|
|
'maplepress-ready-to-sync', // Menu slug
|
|
array( $this, 'display_ready_to_sync_page' ) // Callback
|
|
);
|
|
|
|
// Initial Sync - accessible only via redirect after first connection
|
|
add_submenu_page(
|
|
null, // No parent = hidden from menu
|
|
__( 'Initial Sync', 'maplepress' ), // Page title
|
|
__( 'Initial Sync', 'maplepress' ), // Menu title
|
|
'manage_options', // Capability
|
|
'maplepress-initial-sync', // Menu slug
|
|
array( $this, 'display_initial_sync_page' ) // Callback
|
|
);
|
|
|
|
// System Info - accessible via dashboard Advanced section
|
|
add_submenu_page(
|
|
null, // No parent = hidden from menu
|
|
__( 'System Info', 'maplepress' ), // Page title
|
|
__( 'System Info', 'maplepress' ), // Menu title
|
|
'manage_options', // Capability
|
|
'maplepress-system-info', // Menu slug
|
|
array( $this, 'display_system_info_page' ) // Callback
|
|
);
|
|
|
|
// Also add under Settings menu for those who look there
|
|
add_options_page(
|
|
__( 'MaplePress Settings', 'maplepress' ),
|
|
__( 'MaplePress', 'maplepress' ),
|
|
'manage_options',
|
|
'maplepress-settings',
|
|
array( $this, 'display_settings_page' )
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Register plugin settings.
|
|
*/
|
|
public function register_settings() {
|
|
register_setting(
|
|
'maplepress_settings_group',
|
|
'maplepress_settings',
|
|
array(
|
|
'sanitize_callback' => array( $this, 'validate_settings' ),
|
|
'show_in_rest' => false,
|
|
)
|
|
);
|
|
|
|
add_settings_section(
|
|
'maplepress_api_section',
|
|
__( 'API Configuration', 'maplepress' ),
|
|
array( $this, 'api_section_callback' ),
|
|
'maplepress'
|
|
);
|
|
|
|
add_settings_field(
|
|
'api_url',
|
|
__( 'API URL', 'maplepress' ),
|
|
array( $this, 'api_url_callback' ),
|
|
'maplepress',
|
|
'maplepress_api_section'
|
|
);
|
|
|
|
add_settings_field(
|
|
'api_key',
|
|
__( 'API Key', 'maplepress' ),
|
|
array( $this, 'api_key_callback' ),
|
|
'maplepress',
|
|
'maplepress_api_section'
|
|
);
|
|
|
|
add_settings_field(
|
|
'enabled',
|
|
__( 'Enable MaplePress', 'maplepress' ),
|
|
array( $this, 'enabled_callback' ),
|
|
'maplepress',
|
|
'maplepress_api_section'
|
|
);
|
|
|
|
add_settings_field(
|
|
'enable_frontend_search',
|
|
__( 'Frontend Search', 'maplepress' ),
|
|
array( $this, 'enable_frontend_search_callback' ),
|
|
'maplepress',
|
|
'maplepress_api_section'
|
|
);
|
|
|
|
add_settings_field(
|
|
'enable_admin_search',
|
|
__( 'Admin Search', 'maplepress' ),
|
|
array( $this, 'enable_admin_search_callback' ),
|
|
'maplepress',
|
|
'maplepress_api_section'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Display the plugin settings page.
|
|
*/
|
|
public function display_plugin_setup_page() {
|
|
include_once MAPLEPRESS_PLUGIN_DIR . 'includes/admin-settings-display.php';
|
|
}
|
|
|
|
/**
|
|
* Display dashboard page.
|
|
*/
|
|
public function display_dashboard_page() {
|
|
include_once MAPLEPRESS_PLUGIN_DIR . 'includes/admin-dashboard.php';
|
|
}
|
|
|
|
/**
|
|
* Display settings page.
|
|
*/
|
|
public function display_settings_page() {
|
|
// Handle disconnect action
|
|
if ( isset( $_GET['action'] ) && $_GET['action'] === 'disconnect' ) {
|
|
check_admin_referer( 'maplepress_disconnect' );
|
|
$this->handle_disconnect();
|
|
wp_safe_redirect( admin_url( 'admin.php?page=maplepress-settings&disconnected=1' ) );
|
|
exit;
|
|
}
|
|
|
|
// Display disconnected message if redirected after disconnect
|
|
if ( isset( $_GET['disconnected'] ) && $_GET['disconnected'] === '1' ) {
|
|
add_settings_error(
|
|
'maplepress_settings',
|
|
'disconnected',
|
|
__( 'Successfully disconnected from MaplePress. Your data remains in the cloud.', 'maplepress' ),
|
|
'success'
|
|
);
|
|
}
|
|
|
|
// Display reset success message if redirected after reset
|
|
if ( isset( $_GET['reset'] ) && $_GET['reset'] === 'success' ) {
|
|
add_settings_error(
|
|
'maplepress_settings',
|
|
'reset_success',
|
|
__( '✓ Settings have been reset successfully. You can now configure MaplePress from scratch.', 'maplepress' ),
|
|
'success'
|
|
);
|
|
}
|
|
|
|
include_once MAPLEPRESS_PLUGIN_DIR . 'includes/admin-settings-page.php';
|
|
}
|
|
|
|
/**
|
|
* Handle disconnect action.
|
|
*/
|
|
private function handle_disconnect() {
|
|
// Keep API credentials but clear verification status
|
|
$options = get_option( 'maplepress_settings', array() );
|
|
|
|
// Clear all fields except the basic ones
|
|
$cleared_options = array(
|
|
'api_url' => '',
|
|
'api_key' => '',
|
|
'enabled' => false,
|
|
'is_verified' => false,
|
|
'needs_setup' => true,
|
|
'enable_frontend_search' => true,
|
|
'enable_admin_search' => false,
|
|
);
|
|
|
|
update_option( 'maplepress_settings', $cleared_options );
|
|
}
|
|
|
|
/**
|
|
* API section callback.
|
|
*/
|
|
public function api_section_callback() {
|
|
echo '<p>' . esc_html__( 'Configure your MaplePress backend API connection.', 'maplepress' ) . '</p>';
|
|
}
|
|
|
|
/**
|
|
* API URL field callback.
|
|
*/
|
|
public function api_url_callback() {
|
|
$options = get_option( 'maplepress_settings' );
|
|
$api_url = isset( $options['api_url'] ) && ! empty( $options['api_url'] ) ? $options['api_url'] : 'https://getmaplepress.ca';
|
|
printf(
|
|
'<input type="text" id="api_url" name="maplepress_settings[api_url]" value="%s" class="regular-text" placeholder="https://getmaplepress.ca">',
|
|
esc_attr( $api_url )
|
|
);
|
|
echo '<p class="description">' . esc_html__( 'The URL of your MaplePress backend API (e.g., https://getmaplepress.ca or http://localhost:8000 for local dev).', 'maplepress' ) . '</p>';
|
|
}
|
|
|
|
/**
|
|
* API Key field callback.
|
|
*/
|
|
public function api_key_callback() {
|
|
$options = get_option( 'maplepress_settings' );
|
|
$api_key = isset( $options['api_key'] ) ? $options['api_key'] : '';
|
|
printf(
|
|
'<input type="password" id="api_key" name="maplepress_settings[api_key]" value="%s" class="regular-text" placeholder="live_sk_... or test_sk_...">',
|
|
esc_attr( $api_key )
|
|
);
|
|
echo '<p class="description">' . esc_html__( 'Your site API key from the MaplePress dashboard. Use "live_" prefix for production (https://getmaplepress.ca) or "test_" prefix for development/custom URLs.', 'maplepress' ) . '</p>';
|
|
}
|
|
|
|
/**
|
|
* Enabled field callback.
|
|
*/
|
|
public function enabled_callback() {
|
|
$options = get_option( 'maplepress_settings' );
|
|
$enabled = isset( $options['enabled'] ) ? $options['enabled'] : false;
|
|
printf(
|
|
'<input type="checkbox" id="enabled" name="maplepress_settings[enabled]" value="1" %s>',
|
|
checked( 1, $enabled, false )
|
|
);
|
|
echo '<label for="enabled">' . esc_html__( 'Enable MaplePress search', 'maplepress' ) . '</label>';
|
|
}
|
|
|
|
/**
|
|
* Enable frontend search field callback.
|
|
*/
|
|
public function enable_frontend_search_callback() {
|
|
$options = get_option( 'maplepress_settings' );
|
|
$enable_frontend_search = isset( $options['enable_frontend_search'] ) ? $options['enable_frontend_search'] : true;
|
|
printf(
|
|
'<input type="checkbox" id="enable_frontend_search" name="maplepress_settings[enable_frontend_search]" value="1" %s>',
|
|
checked( 1, $enable_frontend_search, false )
|
|
);
|
|
echo '<label for="enable_frontend_search">' . esc_html__( 'Use MaplePress for public site search', 'maplepress' ) . '</label>';
|
|
echo '<p class="description">' . esc_html__( 'When visitors search on your site, use MaplePress cloud-powered search.', 'maplepress' ) . '</p>';
|
|
}
|
|
|
|
/**
|
|
* Enable admin search field callback.
|
|
*/
|
|
public function enable_admin_search_callback() {
|
|
$options = get_option( 'maplepress_settings' );
|
|
$enable_admin_search = isset( $options['enable_admin_search'] ) ? $options['enable_admin_search'] : false;
|
|
printf(
|
|
'<input type="checkbox" id="enable_admin_search" name="maplepress_settings[enable_admin_search]" value="1" %s>',
|
|
checked( 1, $enable_admin_search, false )
|
|
);
|
|
echo '<label for="enable_admin_search">' . esc_html__( 'Use MaplePress for admin post search', 'maplepress' ) . '</label>';
|
|
echo '<p class="description">' . esc_html__( 'When searching posts in the WordPress admin area, use MaplePress cloud-powered search.', 'maplepress' ) . '</p>';
|
|
}
|
|
|
|
/**
|
|
* Validate settings.
|
|
*
|
|
* @param array $input Settings input.
|
|
* @return array
|
|
*/
|
|
public function validate_settings( $input ) {
|
|
$output = array();
|
|
|
|
// Preserve existing values
|
|
$existing = get_option( 'maplepress_settings', array() );
|
|
|
|
// Validate API URL - use default if empty
|
|
if ( empty( $input['api_url'] ) ) {
|
|
// Default to production URL
|
|
$output['api_url'] = 'https://getmaplepress.ca';
|
|
} else {
|
|
$output['api_url'] = esc_url_raw( $input['api_url'] );
|
|
}
|
|
|
|
// Validate API key
|
|
if ( empty( $input['api_key'] ) ) {
|
|
add_settings_error(
|
|
'maplepress_settings',
|
|
'api_key_empty',
|
|
__( 'Please enter your MaplePress API key.', 'maplepress' ),
|
|
'error'
|
|
);
|
|
$output['api_key'] = '';
|
|
} else {
|
|
$output['api_key'] = sanitize_text_field( $input['api_key'] );
|
|
}
|
|
|
|
// Validate API key prefix based on API URL
|
|
if ( ! empty( $output['api_url'] ) && ! empty( $output['api_key'] ) ) {
|
|
$default_api_url = 'https://getmaplepress.ca';
|
|
$is_production = ( rtrim( $output['api_url'], '/' ) === rtrim( $default_api_url, '/' ) );
|
|
|
|
if ( $is_production ) {
|
|
// Production URL requires live_ prefix
|
|
if ( ! preg_match( '/^live_/', $output['api_key'] ) ) {
|
|
add_settings_error(
|
|
'maplepress_settings',
|
|
'api_key_wrong_prefix',
|
|
sprintf(
|
|
/* translators: %s: API URL */
|
|
__( 'API key must start with "live_" when using the production API URL (%s). Test keys (starting with "test_") are not allowed in production.', 'maplepress' ),
|
|
$default_api_url
|
|
),
|
|
'error'
|
|
);
|
|
// Clear the invalid key
|
|
$output['api_key'] = '';
|
|
}
|
|
} else {
|
|
// Non-production URL requires test_ prefix
|
|
if ( ! preg_match( '/^test_/', $output['api_key'] ) ) {
|
|
add_settings_error(
|
|
'maplepress_settings',
|
|
'api_key_wrong_prefix',
|
|
sprintf(
|
|
/* translators: %s: API URL */
|
|
__( 'API key must start with "test_" when using a custom/development API URL (%s). Live keys (starting with "live_") are not allowed with non-production URLs.', 'maplepress' ),
|
|
esc_html( $output['api_url'] )
|
|
),
|
|
'error'
|
|
);
|
|
// Clear the invalid key
|
|
$output['api_key'] = '';
|
|
}
|
|
}
|
|
}
|
|
|
|
$output['enabled'] = isset( $input['enabled'] ) ? true : false;
|
|
$output['enable_frontend_search'] = isset( $input['enable_frontend_search'] ) ? true : false;
|
|
$output['enable_admin_search'] = isset( $input['enable_admin_search'] ) ? true : false;
|
|
|
|
// Verify API connection only if both API URL and API key are provided and passed validation.
|
|
if ( ! empty( $output['api_url'] ) && ! empty( $output['api_key'] ) ) {
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/class-maplepress-api-client.php';
|
|
$api_client = new MaplePress_API_Client( $output['api_url'], $output['api_key'] );
|
|
$status = $api_client->verify_connection();
|
|
|
|
if ( is_wp_error( $status ) ) {
|
|
// API key is invalid
|
|
$output['is_verified'] = false;
|
|
$output['needs_setup'] = true;
|
|
|
|
add_settings_error(
|
|
'maplepress_settings',
|
|
'api_error',
|
|
sprintf(
|
|
/* translators: %s: error message */
|
|
__( 'API Connection Error: %s', 'maplepress' ),
|
|
$status->get_error_message()
|
|
),
|
|
'error'
|
|
);
|
|
} else {
|
|
// API connection successful - check verification status
|
|
$output['is_connected'] = true;
|
|
|
|
// Store site details
|
|
if ( isset( $status['site_id'] ) ) {
|
|
$output['site_id'] = sanitize_text_field( $status['site_id'] );
|
|
}
|
|
if ( isset( $status['tenant_id'] ) ) {
|
|
$output['tenant_id'] = sanitize_text_field( $status['tenant_id'] );
|
|
}
|
|
if ( isset( $status['domain'] ) ) {
|
|
$output['domain'] = sanitize_text_field( $status['domain'] );
|
|
}
|
|
if ( isset( $status['site_url'] ) ) {
|
|
$output['site_url'] = esc_url_raw( $status['site_url'] );
|
|
}
|
|
if ( isset( $status['api_key_prefix'] ) ) {
|
|
$output['api_key_prefix'] = sanitize_text_field( $status['api_key_prefix'] );
|
|
}
|
|
if ( isset( $status['api_key_last_four'] ) ) {
|
|
$output['api_key_last_four'] = sanitize_text_field( $status['api_key_last_four'] );
|
|
}
|
|
|
|
// Check verification status from backend
|
|
$verification_status = isset( $status['verification_status'] ) ? $status['verification_status'] : 'pending';
|
|
$is_verified_remote = isset( $status['is_verified'] ) ? (bool) $status['is_verified'] : false;
|
|
|
|
if ( $is_verified_remote || $verification_status === 'verified' ) {
|
|
// Site is fully verified - enable all features
|
|
$output['is_verified'] = true;
|
|
$output['verification_status'] = 'verified';
|
|
$output['needs_setup'] = false;
|
|
|
|
// Store usage data
|
|
if ( isset( $status['storage_used_bytes'] ) ) {
|
|
$output['storage_used_bytes'] = absint( $status['storage_used_bytes'] );
|
|
}
|
|
if ( isset( $status['search_requests_count'] ) ) {
|
|
$output['search_requests_count'] = absint( $status['search_requests_count'] );
|
|
}
|
|
if ( isset( $status['monthly_pages_indexed'] ) ) {
|
|
$output['monthly_pages_indexed'] = absint( $status['monthly_pages_indexed'] );
|
|
}
|
|
if ( isset( $status['total_pages_indexed'] ) ) {
|
|
$output['total_pages_indexed'] = absint( $status['total_pages_indexed'] );
|
|
}
|
|
|
|
// Always redirect to ready-to-sync page after successful verification
|
|
// The sync page will allow users to sync their pages
|
|
if ( $output['enabled'] ) {
|
|
// Set transient to trigger redirect
|
|
// We can't redirect here directly because WordPress handles the redirect after validation
|
|
set_transient( 'maplepress_redirect_to_sync', true, 60 );
|
|
} else {
|
|
// Verified but sync disabled - just show success
|
|
add_settings_error(
|
|
'maplepress_settings',
|
|
'api_success',
|
|
__( '✓ Connected and verified! Your site is ready to use MaplePress.', 'maplepress' ),
|
|
'success'
|
|
);
|
|
}
|
|
} else {
|
|
// Connected but NOT verified - show DNS instructions
|
|
$output['is_verified'] = false;
|
|
$output['verification_status'] = 'pending';
|
|
$output['needs_setup'] = false; // Connection works, just needs verification
|
|
|
|
// Store verification details
|
|
if ( isset( $status['verification_token'] ) ) {
|
|
$output['verification_token'] = sanitize_text_field( $status['verification_token'] );
|
|
}
|
|
if ( isset( $status['verification_instructions'] ) ) {
|
|
$output['verification_instructions'] = wp_kses_post( $status['verification_instructions'] );
|
|
}
|
|
|
|
add_settings_error(
|
|
'maplepress_settings',
|
|
'not_verified',
|
|
__( '⚠️ API key connected successfully, but domain verification is pending. Please complete DNS verification below to enable syncing.', 'maplepress' ),
|
|
'warning'
|
|
);
|
|
}
|
|
}
|
|
} else {
|
|
// No API key provided
|
|
$output['is_verified'] = false;
|
|
$output['needs_setup'] = true;
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
|
|
/**
|
|
* Perform initial sync and return result (doesn't add settings errors).
|
|
* Extracted for better control and reusability.
|
|
*
|
|
* @param MaplePress_API_Client $api_client API client instance.
|
|
* @return array|WP_Error Sync result or WP_Error on failure.
|
|
*/
|
|
private function perform_initial_sync( $api_client ) {
|
|
// Get all published posts and pages
|
|
$allowed_post_types = apply_filters( 'maplepress_sync_post_types', array( 'post', 'page' ) );
|
|
$posts = get_posts(
|
|
array(
|
|
'post_type' => $allowed_post_types,
|
|
'post_status' => 'publish',
|
|
'posts_per_page' => -1,
|
|
'orderby' => 'modified',
|
|
'order' => 'DESC',
|
|
)
|
|
);
|
|
|
|
if ( empty( $posts ) ) {
|
|
return new WP_Error( 'no_posts', __( 'No published posts or pages found to sync.', 'maplepress' ) );
|
|
}
|
|
|
|
// Format all pages for bulk sync
|
|
$pages = array();
|
|
foreach ( $posts as $post ) {
|
|
// Format timestamps in RFC3339 format (ISO 8601)
|
|
// Use actual GMT time if available, otherwise use server time converted to GMT
|
|
$published_at = '';
|
|
if ( $post->post_date_gmt && $post->post_date_gmt !== '0000-00-00 00:00:00' ) {
|
|
$published_at = gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_date_gmt . ' UTC' ) );
|
|
}
|
|
|
|
$modified_at = '';
|
|
if ( $post->post_modified_gmt && $post->post_modified_gmt !== '0000-00-00 00:00:00' ) {
|
|
$modified_at = gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_modified_gmt . ' UTC' ) );
|
|
}
|
|
|
|
$pages[] = array(
|
|
'page_id' => (string) $post->ID,
|
|
'title' => $post->post_title,
|
|
'content' => wp_strip_all_tags( $post->post_content ),
|
|
'excerpt' => ! empty( $post->post_excerpt ) ? $post->post_excerpt : wp_trim_words( $post->post_content, 55, '...' ),
|
|
'url' => get_permalink( $post->ID ),
|
|
'status' => $post->post_status,
|
|
'post_type' => $post->post_type,
|
|
'author' => get_the_author_meta( 'display_name', $post->post_author ),
|
|
'published_at' => $published_at,
|
|
'modified_at' => $modified_at,
|
|
);
|
|
}
|
|
|
|
// Sync pages in batches of 1000 (backend limit)
|
|
$batch_size = 1000;
|
|
$total_pages = count( $pages );
|
|
$total_synced = 0;
|
|
$batches = array_chunk( $pages, $batch_size );
|
|
|
|
error_log( 'MaplePress: perform_initial_sync() - Syncing ' . $total_pages . ' pages in ' . count( $batches ) . ' batch(es)' );
|
|
|
|
foreach ( $batches as $batch_num => $batch ) {
|
|
error_log( 'MaplePress: perform_initial_sync() - Processing batch ' . ( $batch_num + 1 ) . ' of ' . count( $batches ) . ' (' . count( $batch ) . ' pages)' );
|
|
|
|
$result = $api_client->sync_pages( $batch );
|
|
|
|
if ( is_wp_error( $result ) ) {
|
|
error_log( 'MaplePress: perform_initial_sync() - Batch ' . ( $batch_num + 1 ) . ' failed: ' . $result->get_error_message() );
|
|
return new WP_Error(
|
|
'sync_failed',
|
|
sprintf(
|
|
/* translators: 1: batch number, 2: error message */
|
|
__( 'Sync failed at batch %1$d: %2$s', 'maplepress' ),
|
|
$batch_num + 1,
|
|
$result->get_error_message()
|
|
)
|
|
);
|
|
}
|
|
|
|
$synced_in_batch = isset( $result['synced_count'] ) ? $result['synced_count'] : count( $batch );
|
|
$total_synced += $synced_in_batch;
|
|
|
|
error_log( 'MaplePress: perform_initial_sync() - Batch ' . ( $batch_num + 1 ) . ' completed. Synced ' . $synced_in_batch . ' pages. Total so far: ' . $total_synced );
|
|
}
|
|
|
|
error_log( 'MaplePress: perform_initial_sync() - All batches completed. Total synced: ' . $total_synced );
|
|
|
|
// Return success with count
|
|
return array(
|
|
'success' => true,
|
|
'synced_count' => $total_synced,
|
|
'batch_count' => count( $batches ),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Suppress the default WordPress "Settings saved" message.
|
|
* We show our own custom success message instead.
|
|
*
|
|
* @param mixed $value The new option value.
|
|
* @param mixed $old_value The old option value.
|
|
* @return mixed
|
|
*/
|
|
public function suppress_default_success_message( $value, $old_value ) {
|
|
// Remove the default "settings-updated" notice
|
|
add_filter(
|
|
'pre_set_transient_settings_errors',
|
|
function( $settings_errors ) {
|
|
if ( is_array( $settings_errors ) ) {
|
|
// Remove the default "settings updated" message
|
|
foreach ( $settings_errors as $key => $error ) {
|
|
if ( isset( $error['code'] ) && $error['code'] === 'settings_updated' ) {
|
|
unset( $settings_errors[ $key ] );
|
|
}
|
|
}
|
|
}
|
|
return $settings_errors;
|
|
}
|
|
);
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Display admin notices for setup and configuration.
|
|
*/
|
|
public function display_admin_notices() {
|
|
$options = get_option( 'maplepress_settings' );
|
|
|
|
// Check if setup is needed
|
|
if ( isset( $options['needs_setup'] ) && $options['needs_setup'] ) {
|
|
$screen = get_current_screen();
|
|
|
|
// Don't show on the settings page itself
|
|
if ( isset( $screen->id ) && $screen->id === 'settings_page_maplepress' ) {
|
|
return;
|
|
}
|
|
|
|
?>
|
|
<div class="notice notice-warning is-dismissible">
|
|
<p>
|
|
<strong><?php esc_html_e( 'MaplePress Setup Required', 'maplepress' ); ?></strong>
|
|
</p>
|
|
<p>
|
|
<?php
|
|
printf(
|
|
/* translators: 1: dashboard URL, 2: settings URL */
|
|
__( 'To get started with MaplePress, please <a href="%1$s" target="_blank">sign up</a> to get your API key, then <a href="%2$s">configure the plugin</a>.', 'maplepress' ),
|
|
'https://getmaplepress.com/register',
|
|
admin_url( 'options-general.php?page=maplepress' )
|
|
);
|
|
?>
|
|
</p>
|
|
</div>
|
|
<?php
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Redirect to dashboard/settings page after activation.
|
|
*/
|
|
public function activation_redirect() {
|
|
// Check if we should redirect
|
|
if ( get_transient( 'maplepress_activation_redirect' ) ) {
|
|
delete_transient( 'maplepress_activation_redirect' );
|
|
|
|
// Don't redirect if activating multiple plugins
|
|
if ( isset( $_GET['activate-multi'] ) ) {
|
|
return;
|
|
}
|
|
|
|
// Check if already connected
|
|
$options = get_option( 'maplepress_settings' );
|
|
$is_verified = isset( $options['is_verified'] ) && $options['is_verified'];
|
|
|
|
// Redirect to dashboard if connected, settings if not
|
|
if ( $is_verified ) {
|
|
wp_safe_redirect( admin_url( 'admin.php?page=maplepress' ) );
|
|
exit;
|
|
} else {
|
|
wp_safe_redirect( admin_url( 'admin.php?page=maplepress-settings' ) );
|
|
exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle redirect to ready-to-sync page after successful connection.
|
|
*/
|
|
public function handle_sync_redirect() {
|
|
// Check if we should redirect to sync page
|
|
if ( get_transient( 'maplepress_redirect_to_sync' ) ) {
|
|
delete_transient( 'maplepress_redirect_to_sync' );
|
|
|
|
// Redirect to ready-to-sync page
|
|
wp_safe_redirect( admin_url( 'admin.php?page=maplepress-ready-to-sync' ) );
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sync a page when it's saved or published.
|
|
*
|
|
* @param int $post_id Post ID.
|
|
* @param WP_Post $post Post object.
|
|
* @param bool $update Whether this is an existing post being updated.
|
|
*/
|
|
public function sync_page_on_save( $post_id, $post, $update ) {
|
|
// Check if MaplePress is enabled
|
|
$options = get_option( 'maplepress_settings' );
|
|
if ( empty( $options['enabled'] ) || empty( $options['is_verified'] ) ) {
|
|
return;
|
|
}
|
|
|
|
// Skip autosaves and revisions
|
|
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
|
|
return;
|
|
}
|
|
if ( wp_is_post_revision( $post_id ) ) {
|
|
return;
|
|
}
|
|
|
|
// Only sync posts and pages (you can add more post types here)
|
|
$allowed_post_types = apply_filters( 'maplepress_sync_post_types', array( 'post', 'page' ) );
|
|
if ( ! in_array( $post->post_type, $allowed_post_types, true ) ) {
|
|
return;
|
|
}
|
|
|
|
// Only sync published posts
|
|
if ( $post->post_status !== 'publish' ) {
|
|
return;
|
|
}
|
|
|
|
// Initialize API client
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/class-maplepress-api-client.php';
|
|
$api_client = new MaplePress_API_Client( $options['api_url'], $options['api_key'] );
|
|
|
|
// Sync the page
|
|
$result = $api_client->index_post( $post_id );
|
|
|
|
// Log result (for debugging)
|
|
if ( is_wp_error( $result ) ) {
|
|
error_log( 'MaplePress sync failed for post ' . $post_id . ': ' . $result->get_error_message() );
|
|
} else {
|
|
error_log( 'MaplePress synced post ' . $post_id . ' successfully' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a page from MaplePress when it's deleted from WordPress.
|
|
*
|
|
* @param int $post_id Post ID.
|
|
*/
|
|
public function delete_page_on_delete( $post_id ) {
|
|
// Check if MaplePress is enabled
|
|
$options = get_option( 'maplepress_settings' );
|
|
if ( empty( $options['enabled'] ) || empty( $options['is_verified'] ) ) {
|
|
return;
|
|
}
|
|
|
|
// Get the post to check its type
|
|
$post = get_post( $post_id );
|
|
if ( ! $post ) {
|
|
return;
|
|
}
|
|
|
|
// Only handle posts and pages
|
|
$allowed_post_types = apply_filters( 'maplepress_sync_post_types', array( 'post', 'page' ) );
|
|
if ( ! in_array( $post->post_type, $allowed_post_types, true ) ) {
|
|
return;
|
|
}
|
|
|
|
// Initialize API client
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/class-maplepress-api-client.php';
|
|
$api_client = new MaplePress_API_Client( $options['api_url'], $options['api_key'] );
|
|
|
|
// Delete the page from MaplePress
|
|
$result = $api_client->delete_post( $post_id );
|
|
|
|
// Log result
|
|
if ( is_wp_error( $result ) ) {
|
|
error_log( 'MaplePress delete failed for post ' . $post_id . ': ' . $result->get_error_message() );
|
|
} else {
|
|
error_log( 'MaplePress deleted post ' . $post_id . ' successfully' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bulk sync all existing posts and pages.
|
|
* Triggered via admin action.
|
|
*/
|
|
public function bulk_sync_pages() {
|
|
// Check permissions
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_die( esc_html__( 'You do not have permission to perform this action.', 'maplepress' ) );
|
|
}
|
|
|
|
// Check nonce
|
|
check_admin_referer( 'maplepress_bulk_sync' );
|
|
|
|
// Check if MaplePress is enabled
|
|
$options = get_option( 'maplepress_settings' );
|
|
if ( empty( $options['enabled'] ) || empty( $options['is_verified'] ) ) {
|
|
wp_die( esc_html__( 'MaplePress is not configured properly.', 'maplepress' ) );
|
|
}
|
|
|
|
// Get all published posts and pages
|
|
$allowed_post_types = apply_filters( 'maplepress_sync_post_types', array( 'post', 'page' ) );
|
|
$posts = get_posts(
|
|
array(
|
|
'post_type' => $allowed_post_types,
|
|
'post_status' => 'publish',
|
|
'posts_per_page' => -1,
|
|
'orderby' => 'modified',
|
|
'order' => 'DESC',
|
|
)
|
|
);
|
|
|
|
if ( empty( $posts ) ) {
|
|
wp_safe_redirect(
|
|
add_query_arg(
|
|
array(
|
|
'page' => 'maplepress',
|
|
'sync_status' => 'no_posts',
|
|
),
|
|
admin_url( 'admin.php' )
|
|
)
|
|
);
|
|
exit;
|
|
}
|
|
|
|
// Initialize API client
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/class-maplepress-api-client.php';
|
|
$api_client = new MaplePress_API_Client( $options['api_url'], $options['api_key'] );
|
|
|
|
// Format all pages for bulk sync
|
|
$pages = array();
|
|
foreach ( $posts as $post ) {
|
|
// Format timestamps in RFC3339 format (ISO 8601)
|
|
// Use actual GMT time if available, otherwise use server time converted to GMT
|
|
$published_at = '';
|
|
if ( $post->post_date_gmt && $post->post_date_gmt !== '0000-00-00 00:00:00' ) {
|
|
$published_at = gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_date_gmt . ' UTC' ) );
|
|
}
|
|
|
|
$modified_at = '';
|
|
if ( $post->post_modified_gmt && $post->post_modified_gmt !== '0000-00-00 00:00:00' ) {
|
|
$modified_at = gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_modified_gmt . ' UTC' ) );
|
|
}
|
|
|
|
$pages[] = array(
|
|
'page_id' => (string) $post->ID,
|
|
'title' => $post->post_title,
|
|
'content' => wp_strip_all_tags( $post->post_content ),
|
|
'excerpt' => ! empty( $post->post_excerpt ) ? $post->post_excerpt : wp_trim_words( $post->post_content, 55, '...' ),
|
|
'url' => get_permalink( $post->ID ),
|
|
'status' => $post->post_status,
|
|
'post_type' => $post->post_type,
|
|
'author' => get_the_author_meta( 'display_name', $post->post_author ),
|
|
'published_at' => $published_at,
|
|
'modified_at' => $modified_at,
|
|
);
|
|
}
|
|
|
|
// Sync pages in batches of 1000 (backend limit)
|
|
$batch_size = 1000;
|
|
$total_pages = count( $pages );
|
|
$total_synced = 0;
|
|
$batches = array_chunk( $pages, $batch_size );
|
|
|
|
error_log( 'MaplePress: Syncing ' . $total_pages . ' pages in ' . count( $batches ) . ' batch(es)' );
|
|
|
|
foreach ( $batches as $batch_num => $batch ) {
|
|
error_log( 'MaplePress: Processing batch ' . ( $batch_num + 1 ) . ' of ' . count( $batches ) . ' (' . count( $batch ) . ' pages)' );
|
|
|
|
$result = $api_client->sync_pages( $batch );
|
|
|
|
if ( is_wp_error( $result ) ) {
|
|
error_log( 'MaplePress: Batch ' . ( $batch_num + 1 ) . ' failed: ' . $result->get_error_message() );
|
|
wp_safe_redirect(
|
|
add_query_arg(
|
|
array(
|
|
'page' => 'maplepress',
|
|
'sync_status' => 'error',
|
|
'sync_message' => urlencode( 'Batch ' . ( $batch_num + 1 ) . ' failed: ' . $result->get_error_message() ),
|
|
),
|
|
admin_url( 'admin.php' )
|
|
)
|
|
);
|
|
exit;
|
|
}
|
|
|
|
$synced_in_batch = isset( $result['synced_count'] ) ? $result['synced_count'] : count( $batch );
|
|
$total_synced += $synced_in_batch;
|
|
error_log( 'MaplePress: Batch ' . ( $batch_num + 1 ) . ' completed: ' . $synced_in_batch . ' pages synced' );
|
|
}
|
|
|
|
// All batches completed successfully
|
|
error_log( 'MaplePress: All batches completed. Total synced: ' . $total_synced . ' pages' );
|
|
wp_safe_redirect(
|
|
add_query_arg(
|
|
array(
|
|
'page' => 'maplepress',
|
|
'sync_status' => 'success',
|
|
'synced_count' => $total_synced,
|
|
),
|
|
admin_url( 'admin.php' )
|
|
)
|
|
);
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Handle bulk sync via AJAX for better UX with progress feedback.
|
|
*/
|
|
public function handle_bulk_sync_ajax() {
|
|
// Check permissions
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_send_json_error(
|
|
array(
|
|
'message' => __( 'Permission denied.', 'maplepress' ),
|
|
)
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Check nonce
|
|
check_ajax_referer( 'maplepress_bulk_sync_ajax', 'nonce' );
|
|
|
|
// Check if MaplePress is enabled
|
|
$options = get_option( 'maplepress_settings' );
|
|
if ( empty( $options['enabled'] ) || empty( $options['is_verified'] ) ) {
|
|
wp_send_json_error(
|
|
array(
|
|
'message' => __( 'MaplePress is not configured properly.', 'maplepress' ),
|
|
)
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Get all published posts and pages
|
|
$allowed_post_types = apply_filters( 'maplepress_sync_post_types', array( 'post', 'page' ) );
|
|
$posts = get_posts(
|
|
array(
|
|
'post_type' => $allowed_post_types,
|
|
'post_status' => 'publish',
|
|
'posts_per_page' => -1,
|
|
'orderby' => 'modified',
|
|
'order' => 'DESC',
|
|
)
|
|
);
|
|
|
|
if ( empty( $posts ) ) {
|
|
wp_send_json_error(
|
|
array(
|
|
'message' => __( 'No published posts or pages found to sync.', 'maplepress' ),
|
|
)
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Initialize API client
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/class-maplepress-api-client.php';
|
|
$api_client = new MaplePress_API_Client( $options['api_url'], $options['api_key'] );
|
|
|
|
// Format all pages for bulk sync
|
|
$pages = array();
|
|
foreach ( $posts as $post ) {
|
|
// Format timestamps in RFC3339 format (ISO 8601)
|
|
$published_at = '';
|
|
if ( $post->post_date_gmt && $post->post_date_gmt !== '0000-00-00 00:00:00' ) {
|
|
$published_at = gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_date_gmt . ' UTC' ) );
|
|
}
|
|
|
|
$modified_at = '';
|
|
if ( $post->post_modified_gmt && $post->post_modified_gmt !== '0000-00-00 00:00:00' ) {
|
|
$modified_at = gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_modified_gmt . ' UTC' ) );
|
|
}
|
|
|
|
$pages[] = array(
|
|
'page_id' => (string) $post->ID,
|
|
'title' => $post->post_title,
|
|
'content' => wp_strip_all_tags( $post->post_content ),
|
|
'excerpt' => ! empty( $post->post_excerpt ) ? $post->post_excerpt : wp_trim_words( $post->post_content, 55, '...' ),
|
|
'url' => get_permalink( $post->ID ),
|
|
'status' => $post->post_status,
|
|
'post_type' => $post->post_type,
|
|
'author' => get_the_author_meta( 'display_name', $post->post_author ),
|
|
'published_at' => $published_at,
|
|
'modified_at' => $modified_at,
|
|
);
|
|
}
|
|
|
|
// Sync pages in batches of 1000 (backend limit)
|
|
$batch_size = 1000;
|
|
$total_pages = count( $pages );
|
|
$total_synced = 0;
|
|
$batches = array_chunk( $pages, $batch_size );
|
|
|
|
error_log( 'MaplePress AJAX: Syncing ' . $total_pages . ' pages in ' . count( $batches ) . ' batch(es)' );
|
|
|
|
foreach ( $batches as $batch_num => $batch ) {
|
|
error_log( 'MaplePress AJAX: Processing batch ' . ( $batch_num + 1 ) . ' of ' . count( $batches ) . ' (' . count( $batch ) . ' pages)' );
|
|
|
|
$result = $api_client->sync_pages( $batch );
|
|
|
|
if ( is_wp_error( $result ) ) {
|
|
error_log( 'MaplePress AJAX: Batch ' . ( $batch_num + 1 ) . ' failed: ' . $result->get_error_message() );
|
|
wp_send_json_error(
|
|
array(
|
|
'message' => sprintf(
|
|
/* translators: %d: batch number */
|
|
__( 'Sync failed at batch %d', 'maplepress' ),
|
|
$batch_num + 1
|
|
),
|
|
'details' => $result->get_error_message(),
|
|
)
|
|
);
|
|
return;
|
|
}
|
|
|
|
$synced_in_batch = isset( $result['synced_count'] ) ? $result['synced_count'] : count( $batch );
|
|
$total_synced += $synced_in_batch;
|
|
error_log( 'MaplePress AJAX: Batch ' . ( $batch_num + 1 ) . ' completed: ' . $synced_in_batch . ' pages synced' );
|
|
}
|
|
|
|
// All batches completed successfully
|
|
error_log( 'MaplePress AJAX: All batches completed. Total synced: ' . $total_synced . ' pages' );
|
|
|
|
wp_send_json_success(
|
|
array(
|
|
'message' => sprintf(
|
|
/* translators: %d: number of pages synced */
|
|
__( 'Successfully synced %d pages to MaplePress!', 'maplepress' ),
|
|
$total_synced
|
|
),
|
|
'details' => sprintf(
|
|
/* translators: %d: number of batches */
|
|
__( 'Completed in %d batch(es)', 'maplepress' ),
|
|
count( $batches )
|
|
),
|
|
'synced_count' => $total_synced,
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Handle AJAX verification with progress tracking.
|
|
* Verifies domain and syncs pages with progress updates.
|
|
*/
|
|
public function handle_verify_and_sync_ajax() {
|
|
// Verify nonce
|
|
check_ajax_referer( 'maplepress_verify_and_sync_ajax', 'nonce' );
|
|
|
|
// Check permissions
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_send_json_error( __( 'You do not have permission to perform this action.', 'maplepress' ) );
|
|
}
|
|
|
|
// Get settings
|
|
$options = get_option( 'maplepress_settings' );
|
|
|
|
if ( empty( $options['api_url'] ) || empty( $options['api_key'] ) ) {
|
|
wp_send_json_error( __( 'API URL and API Key are required.', 'maplepress' ) );
|
|
}
|
|
|
|
// Step 1: Verify domain
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/class-maplepress-api-client.php';
|
|
$api_client = new MaplePress_API_Client( $options['api_url'], $options['api_key'] );
|
|
$result = $api_client->verify_domain();
|
|
|
|
if ( is_wp_error( $result ) ) {
|
|
wp_send_json_error( $result->get_error_message() );
|
|
}
|
|
|
|
// ✅ Verification succeeded!
|
|
$options['is_verified'] = true;
|
|
$options['verification_status'] = 'verified';
|
|
|
|
// Clear verification token
|
|
unset( $options['verification_token'] );
|
|
unset( $options['verification_instructions'] );
|
|
|
|
update_option( 'maplepress_settings', $options );
|
|
|
|
// Step 2: Sync pages if enabled
|
|
if ( isset( $options['enabled'] ) && $options['enabled'] ) {
|
|
// Get all published posts and pages
|
|
$allowed_post_types = apply_filters( 'maplepress_sync_post_types', array( 'post', 'page' ) );
|
|
$posts = get_posts(
|
|
array(
|
|
'post_type' => $allowed_post_types,
|
|
'post_status' => 'publish',
|
|
'posts_per_page' => -1,
|
|
'orderby' => 'modified',
|
|
'order' => 'DESC',
|
|
)
|
|
);
|
|
|
|
if ( empty( $posts ) ) {
|
|
wp_send_json_success(
|
|
array(
|
|
'message' => __( 'Domain verified successfully! No pages to sync.', 'maplepress' ),
|
|
'details' => __( 'No published posts or pages found.', 'maplepress' ),
|
|
)
|
|
);
|
|
}
|
|
|
|
// Format all pages for bulk sync
|
|
$pages = array();
|
|
foreach ( $posts as $post ) {
|
|
$published_at = '';
|
|
if ( $post->post_date_gmt && $post->post_date_gmt !== '0000-00-00 00:00:00' ) {
|
|
$published_at = gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_date_gmt . ' UTC' ) );
|
|
}
|
|
|
|
$modified_at = '';
|
|
if ( $post->post_modified_gmt && $post->post_modified_gmt !== '0000-00-00 00:00:00' ) {
|
|
$modified_at = gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $post->post_modified_gmt . ' UTC' ) );
|
|
}
|
|
|
|
$pages[] = array(
|
|
'page_id' => (string) $post->ID,
|
|
'title' => $post->post_title,
|
|
'content' => wp_strip_all_tags( $post->post_content ),
|
|
'excerpt' => ! empty( $post->post_excerpt ) ? $post->post_excerpt : wp_trim_words( $post->post_content, 55, '...' ),
|
|
'url' => get_permalink( $post->ID ),
|
|
'status' => $post->post_status,
|
|
'post_type' => $post->post_type,
|
|
'author' => get_the_author_meta( 'display_name', $post->post_author ),
|
|
'published_at' => $published_at,
|
|
'modified_at' => $modified_at,
|
|
);
|
|
}
|
|
|
|
// Sync pages in batches of 1000
|
|
$batch_size = 1000;
|
|
$total_pages = count( $pages );
|
|
$total_synced = 0;
|
|
$batches = array_chunk( $pages, $batch_size );
|
|
|
|
foreach ( $batches as $batch_num => $batch ) {
|
|
$result = $api_client->sync_pages( $batch );
|
|
|
|
if ( is_wp_error( $result ) ) {
|
|
wp_send_json_error(
|
|
sprintf(
|
|
/* translators: 1: batch number, 2: error message */
|
|
__( 'Domain verified but sync failed at batch %1$d: %2$s', 'maplepress' ),
|
|
$batch_num + 1,
|
|
$result->get_error_message()
|
|
)
|
|
);
|
|
}
|
|
|
|
$synced_in_batch = isset( $result['synced_count'] ) ? $result['synced_count'] : count( $batch );
|
|
$total_synced += $synced_in_batch;
|
|
}
|
|
|
|
// Success with sync
|
|
wp_send_json_success(
|
|
array(
|
|
'message' => sprintf(
|
|
/* translators: %d: number of pages synced */
|
|
__( 'Domain verified and %d pages synced successfully!', 'maplepress' ),
|
|
$total_synced
|
|
),
|
|
'details' => sprintf(
|
|
/* translators: 1: number of batches, 2: total pages */
|
|
__( 'Synced %1$d pages in %2$d batch(es)', 'maplepress' ),
|
|
$total_synced,
|
|
count( $batches )
|
|
),
|
|
)
|
|
);
|
|
} else {
|
|
// Verified but sync disabled
|
|
wp_send_json_success(
|
|
array(
|
|
'message' => __( 'Domain verified successfully!', 'maplepress' ),
|
|
'details' => __( 'MaplePress is ready to use.', 'maplepress' ),
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle AJAX initial sync from dedicated sync page.
|
|
* This performs the actual sync with batch processing.
|
|
*/
|
|
public function handle_initial_sync_ajax() {
|
|
// Verify nonce
|
|
check_ajax_referer( 'maplepress_initial_sync', 'nonce' );
|
|
|
|
// Check permissions
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_send_json_error( __( 'You do not have permission to perform this action.', 'maplepress' ) );
|
|
}
|
|
|
|
// Get settings
|
|
$options = get_option( 'maplepress_settings', array() );
|
|
|
|
if ( empty( $options['api_url'] ) || empty( $options['api_key'] ) ) {
|
|
wp_send_json_error( __( 'MaplePress is not configured properly.', 'maplepress' ) );
|
|
}
|
|
|
|
if ( empty( $options['is_verified'] ) ) {
|
|
wp_send_json_error( __( 'Domain not verified. Please verify your domain first.', 'maplepress' ) );
|
|
}
|
|
|
|
// Initialize API client
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/class-maplepress-api-client.php';
|
|
$api_client = new MaplePress_API_Client( $options['api_url'], $options['api_key'] );
|
|
|
|
// Perform the sync using our existing batch processing method
|
|
$sync_result = $this->perform_initial_sync( $api_client );
|
|
|
|
if ( is_wp_error( $sync_result ) ) {
|
|
wp_send_json_error( $sync_result->get_error_message() );
|
|
}
|
|
|
|
// Success
|
|
$synced_count = isset( $sync_result['synced_count'] ) ? $sync_result['synced_count'] : 0;
|
|
$batch_count = isset( $sync_result['batch_count'] ) ? $sync_result['batch_count'] : 0;
|
|
|
|
wp_send_json_success(
|
|
array(
|
|
'message' => sprintf(
|
|
/* translators: %d: number of pages synced */
|
|
__( 'Successfully synced %d pages!', 'maplepress' ),
|
|
$synced_count
|
|
),
|
|
'details' => sprintf(
|
|
/* translators: 1: number of pages, 2: number of batches */
|
|
__( 'Synced %1$d pages in %2$d batch(es). Your content is now searchable via MaplePress.', 'maplepress' ),
|
|
$synced_count,
|
|
$batch_count
|
|
),
|
|
'synced_count' => $synced_count,
|
|
'batch_count' => $batch_count,
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Handle domain verification request from plugin.
|
|
* This is where auto-sync happens (after successful verification).
|
|
*/
|
|
public function handle_verify_domain() {
|
|
// Debug: Log that handler was called
|
|
error_log( 'MaplePress: handle_verify_domain() called' );
|
|
error_log( 'MaplePress: POST data = ' . print_r( $_POST, true ) );
|
|
|
|
// Check permissions
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
error_log( 'MaplePress: Permission denied' );
|
|
wp_die( esc_html__( 'You do not have permission to perform this action.', 'maplepress' ) );
|
|
}
|
|
|
|
// Check nonce
|
|
error_log( 'MaplePress: Checking nonce' );
|
|
check_admin_referer( 'maplepress_verify_domain' );
|
|
error_log( 'MaplePress: Nonce validated successfully' );
|
|
|
|
// Get settings
|
|
$options = get_option( 'maplepress_settings' );
|
|
error_log( 'MaplePress: api_url = ' . ( $options['api_url'] ?? 'NOT SET' ) );
|
|
error_log( 'MaplePress: api_key = ' . ( isset( $options['api_key'] ) ? substr( $options['api_key'], 0, 10 ) . '...' : 'NOT SET' ) );
|
|
|
|
if ( empty( $options['api_url'] ) || empty( $options['api_key'] ) ) {
|
|
error_log( 'MaplePress: Configuration incomplete - api_url or api_key missing' );
|
|
|
|
// Redirect with detailed error message
|
|
wp_safe_redirect(
|
|
add_query_arg(
|
|
array(
|
|
'page' => 'maplepress-settings',
|
|
'verification_status' => 'failed',
|
|
'verification_message' => urlencode(
|
|
empty( $options['api_url'] ) && empty( $options['api_key'] )
|
|
? __( 'API URL and API Key are required. Please save your settings first.', 'maplepress' )
|
|
: ( empty( $options['api_url'] )
|
|
? __( 'API URL is required. Please save your settings first.', 'maplepress' )
|
|
: __( 'API Key is required. Please save your settings first.', 'maplepress' )
|
|
)
|
|
),
|
|
),
|
|
admin_url( 'admin.php' )
|
|
)
|
|
);
|
|
exit;
|
|
}
|
|
|
|
// Call verification endpoint
|
|
error_log( 'MaplePress: Calling verify_domain() API endpoint' );
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/class-maplepress-api-client.php';
|
|
$api_client = new MaplePress_API_Client( $options['api_url'], $options['api_key'] );
|
|
$result = $api_client->verify_domain();
|
|
error_log( 'MaplePress: verify_domain() returned: ' . print_r( $result, true ) );
|
|
|
|
if ( is_wp_error( $result ) ) {
|
|
// Verification failed - show detailed error
|
|
error_log( 'MaplePress: Verification failed - ' . $result->get_error_message() );
|
|
wp_safe_redirect(
|
|
add_query_arg(
|
|
array(
|
|
'page' => 'maplepress-settings',
|
|
'verification_status' => 'failed',
|
|
'verification_message' => urlencode( $result->get_error_message() ),
|
|
),
|
|
admin_url( 'admin.php' )
|
|
)
|
|
);
|
|
exit;
|
|
}
|
|
|
|
// ✅ Verification succeeded!
|
|
$options['is_verified'] = true;
|
|
$options['verification_status'] = 'verified';
|
|
|
|
// Clear verification token (no longer needed)
|
|
unset( $options['verification_token'] );
|
|
unset( $options['verification_instructions'] );
|
|
|
|
update_option( 'maplepress_settings', $options );
|
|
|
|
// 🎯 REDIRECT TO READY-TO-SYNC PAGE - user must manually start sync
|
|
if ( isset( $options['enabled'] ) && $options['enabled'] ) {
|
|
// Redirect to ready-to-sync page (user clicks button to start sync)
|
|
wp_safe_redirect( admin_url( 'admin.php?page=maplepress-ready-to-sync' ) );
|
|
exit;
|
|
} else {
|
|
// Verified but sync disabled - just show verification success
|
|
wp_safe_redirect(
|
|
add_query_arg(
|
|
array(
|
|
'page' => 'maplepress-settings',
|
|
'verification_status' => 'success',
|
|
),
|
|
admin_url( 'admin.php' )
|
|
)
|
|
);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Display the speed test page.
|
|
*/
|
|
public function display_speedtest_page() {
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/admin-speedtest-page-simple.php';
|
|
}
|
|
|
|
/**
|
|
* Display the ready-to-sync page.
|
|
*/
|
|
public function display_ready_to_sync_page() {
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/admin-ready-to-sync-page.php';
|
|
}
|
|
|
|
/**
|
|
* Display the initial sync page.
|
|
*/
|
|
public function display_initial_sync_page() {
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/admin-initial-sync-page.php';
|
|
}
|
|
|
|
/**
|
|
* Display the system info page.
|
|
*/
|
|
public function display_system_info_page() {
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/admin-system-info-page.php';
|
|
}
|
|
|
|
/**
|
|
* Handle reset settings action.
|
|
*/
|
|
public function handle_reset_settings() {
|
|
// Check permissions
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_die( esc_html__( 'You do not have permission to perform this action.', 'maplepress' ) );
|
|
}
|
|
|
|
// Check nonce
|
|
check_admin_referer( 'maplepress_reset_settings' );
|
|
|
|
// Delete all plugin settings
|
|
delete_option( 'maplepress_settings' );
|
|
|
|
// Log the reset
|
|
error_log( 'MaplePress: Settings reset by user' );
|
|
|
|
// Build redirect URL
|
|
$redirect_url = add_query_arg(
|
|
array(
|
|
'page' => 'maplepress-settings',
|
|
'reset' => 'success',
|
|
),
|
|
admin_url( 'admin.php' )
|
|
);
|
|
|
|
error_log( 'MaplePress: Redirecting to: ' . $redirect_url );
|
|
|
|
// Redirect back to settings page with success message
|
|
wp_safe_redirect( $redirect_url );
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Handle reset and delete plugin action.
|
|
* This removes all settings, deactivates, and deletes the plugin.
|
|
*/
|
|
public function handle_reset_and_delete() {
|
|
// Check permissions
|
|
if ( ! current_user_can( 'delete_plugins' ) ) {
|
|
wp_die( esc_html__( 'You do not have permission to delete plugins.', 'maplepress' ) );
|
|
}
|
|
|
|
// Check nonce
|
|
check_admin_referer( 'maplepress_reset_and_delete' );
|
|
|
|
// Delete all plugin settings immediately (before deactivation)
|
|
delete_option( 'maplepress_settings' );
|
|
delete_transient( 'maplepress_activation_redirect' );
|
|
delete_transient( 'maplepress_redirect_to_sync' );
|
|
|
|
// Log the reset and delete
|
|
error_log( 'MaplePress: Plugin data cleared and plugin being deleted by user' );
|
|
|
|
// Get plugin file path
|
|
$plugin_file = plugin_basename( MAPLEPRESS_PLUGIN_FILE );
|
|
|
|
// Deactivate the plugin first
|
|
deactivate_plugins( $plugin_file );
|
|
|
|
// Require the plugin deletion functions
|
|
if ( ! function_exists( 'delete_plugins' ) ) {
|
|
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
|
}
|
|
if ( ! function_exists( 'request_filesystem_credentials' ) ) {
|
|
require_once ABSPATH . 'wp-admin/includes/file.php';
|
|
}
|
|
|
|
// Delete the plugin files
|
|
$delete_result = delete_plugins( array( $plugin_file ) );
|
|
|
|
// Redirect to plugins page with status
|
|
if ( is_wp_error( $delete_result ) ) {
|
|
wp_safe_redirect(
|
|
add_query_arg(
|
|
array(
|
|
'error' => 'delete_failed',
|
|
'message' => urlencode( $delete_result->get_error_message() ),
|
|
),
|
|
admin_url( 'plugins.php' )
|
|
)
|
|
);
|
|
} else {
|
|
wp_safe_redirect(
|
|
add_query_arg(
|
|
array(
|
|
'deleted' => 'true',
|
|
'plugin_deleted' => 'maplepress',
|
|
),
|
|
admin_url( 'plugins.php' )
|
|
)
|
|
);
|
|
}
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Handle AJAX request to run speed test.
|
|
*/
|
|
public function handle_speedtest_ajax() {
|
|
try {
|
|
// Check permissions
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_send_json_error( array( 'message' => __( 'Permission denied.', 'maplepress' ) ) );
|
|
return;
|
|
}
|
|
|
|
// Check nonce
|
|
check_ajax_referer( 'mpss_test_nonce', 'nonce' );
|
|
|
|
// Get parameters from request
|
|
$query_count = isset( $_POST['query_count'] ) ? intval( $_POST['query_count'] ) : 10;
|
|
$execution_mode = isset( $_POST['execution_mode'] ) ? sanitize_text_field( $_POST['execution_mode'] ) : 'serial';
|
|
|
|
// Validate execution mode
|
|
if ( ! in_array( $execution_mode, array( 'serial', 'parallel' ), true ) ) {
|
|
$execution_mode = 'serial';
|
|
}
|
|
|
|
// Run speed test
|
|
require_once MAPLEPRESS_PLUGIN_DIR . 'includes/class-speedtest-simple.php';
|
|
|
|
$speedtest = new MPSS_SpeedTest_Simple();
|
|
$result = $speedtest->run( $query_count, $execution_mode );
|
|
|
|
if ( is_wp_error( $result ) ) {
|
|
wp_send_json_error(
|
|
array(
|
|
'message' => $result->get_error_message(),
|
|
)
|
|
);
|
|
return;
|
|
}
|
|
|
|
wp_send_json_success( $result );
|
|
} catch ( Exception $e ) {
|
|
error_log( 'MaplePress Speed Test Exception: ' . $e->getMessage() );
|
|
wp_send_json_error(
|
|
array(
|
|
'message' => 'Exception: ' . $e->getMessage(),
|
|
)
|
|
);
|
|
} catch ( Error $e ) {
|
|
error_log( 'MaplePress Speed Test Error: ' . $e->getMessage() );
|
|
wp_send_json_error(
|
|
array(
|
|
'message' => 'Error: ' . $e->getMessage(),
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|