Refactor(Admin): Implement Settings API & AJAX save for Settings Manager
- Refactored WPALLSTARS_Settings_Manager to use WordPress Settings API. - Stores settings in single 'wpallstars_options' array. - Implemented robust AJAX saving for specific settings (e.g., color scheme, auto-upload) via WPALLSTARS_Admin_Manager::update_option. - Updated JS and setting render functions for AJAX. - Corrected admin menu registration and script enqueue hooks. - Includes file renames from wp-allstars to wpallstars.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -11,10 +11,10 @@ if (!defined('ABSPATH')) {
|
||||
// Define readme content
|
||||
function wp_allstars_get_readme_content() {
|
||||
// Get README.md content
|
||||
$readme_path = WP_PLUGIN_DIR . '/wpa-superstar-plugin/README.md';
|
||||
$readme_path = WP_PLUGIN_DIR . '/wpallstars-superstar-plugin/README.md';
|
||||
$readme_content = '';
|
||||
|
||||
if (file_exists($readme_path)) {
|
||||
if (file_exists($readme_path) && is_readable($readme_path)) {
|
||||
$readme_content = file_get_contents($readme_path);
|
||||
} else {
|
||||
// Fallback content if README.md is not found
|
||||
|
||||
@@ -2,33 +2,39 @@
|
||||
/**
|
||||
* WPALLSTARS Admin Manager
|
||||
*
|
||||
* @package WP_ALLSTARS
|
||||
* @since 0.2.0
|
||||
* Manages the overall admin interface for the WPALLSTARS plugin, including menus, scripts, styles, and AJAX handlers.
|
||||
* Uses WPALLSTARS for class names/package/strings and wpallstars for slugs/handles/actions/nonces/options/textdomain/js vars/css classes.
|
||||
*
|
||||
* @package WPALLSTARS
|
||||
* @subpackage Admin
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class WP_Allstars_Admin_Manager {
|
||||
class WPALLSTARS_Admin_Manager {
|
||||
|
||||
/**
|
||||
* Initialize the class and register hooks
|
||||
*/
|
||||
public static function init() {
|
||||
add_action('admin_menu', array(__CLASS__, 'register_admin_menu'));
|
||||
add_action('wp_ajax_wp_allstars_update_option', array(__CLASS__, 'update_option'));
|
||||
add_action('admin_init', array(__CLASS__, 'register_settings'));
|
||||
add_action('wp_ajax_wpallstars_update_option', array(__CLASS__, 'update_option'));
|
||||
// remove settings registration from here, it's handled by Settings_Manager
|
||||
// add_action('admin_init', array(__CLASS__, 'register_settings'));
|
||||
add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_admin_scripts'));
|
||||
|
||||
// Initialize all manager classes
|
||||
WP_Allstars_Settings_Manager::init();
|
||||
WP_Allstars_Theme_Manager::init();
|
||||
WP_Allstars_Workflow_Manager::init();
|
||||
WP_Allstars_Pro_Plugins_Manager::init();
|
||||
WP_Allstars_Tools_Manager::init();
|
||||
WP_Allstars_Hosting_Manager::init();
|
||||
WP_Allstars_Free_Plugins_Manager::init();
|
||||
WPALLSTARS_Settings_Manager::init();
|
||||
WPALLSTARS_Theme_Manager::init();
|
||||
WPALLSTARS_Workflow_Manager::init();
|
||||
WPALLSTARS_Pro_Plugins_Manager::init();
|
||||
WPALLSTARS_Tools_Manager::init();
|
||||
WPALLSTARS_Hosting_Manager::init();
|
||||
WPALLSTARS_Free_Plugins_Manager::init();
|
||||
WPALLSTARS_Readme_Manager::init(); // Ensure Readme Manager is initialized
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,105 +43,167 @@ class WP_Allstars_Admin_Manager {
|
||||
* @param string $hook The current admin page hook
|
||||
*/
|
||||
public static function enqueue_admin_scripts($hook) {
|
||||
if ('settings_page_wp-allstars' !== $hook) {
|
||||
return;
|
||||
// Correct hook for the settings submenu page
|
||||
$settings_page_hook = 'wpallstars_page_wpallstars-settings';
|
||||
|
||||
// Only load specific assets on our settings page
|
||||
if ($settings_page_hook !== $hook) {
|
||||
// Maybe load global assets on all wpallstars pages?
|
||||
// if (strpos($hook, 'wpallstars') === false) return;
|
||||
return; // Exit if not the settings page for now
|
||||
}
|
||||
|
||||
// Enqueue admin stylesheet
|
||||
// Enqueue main admin stylesheet
|
||||
wp_enqueue_style(
|
||||
'wp-allstars-admin',
|
||||
plugins_url('css/wp-allstars-admin.css', dirname(__FILE__)),
|
||||
'wpallstars-admin', // Handle for the main admin CSS
|
||||
WPALLSTARS_URL . 'admin/css/wpallstars-admin.css', // Use constant defined in main plugin file
|
||||
array(),
|
||||
WP_ALLSTARS_VERSION
|
||||
WPALLSTARS_VERSION // Use constant defined in main plugin file
|
||||
);
|
||||
|
||||
// Enqueue admin JavaScript
|
||||
// Enqueue main admin JavaScript (likely contains toggle functionality)
|
||||
wp_enqueue_script(
|
||||
'wp-allstars-admin',
|
||||
plugins_url('js/wp-allstars-admin.js', dirname(__FILE__)),
|
||||
array('jquery'),
|
||||
WP_ALLSTARS_VERSION,
|
||||
true
|
||||
'wpallstars-admin', // Handle for the main admin JS
|
||||
WPALLSTARS_URL . 'admin/js/wpallstars-admin.js', // Use constant for URL
|
||||
array('jquery'), // Dependencies
|
||||
WPALLSTARS_VERSION, // Use constant for version
|
||||
true // Load in footer
|
||||
);
|
||||
|
||||
// Localize the script with necessary data for AJAX
|
||||
wp_localize_script('wp-allstars-admin', 'wpAllstars', array(
|
||||
'nonce' => wp_create_nonce('wp-allstars-nonce'),
|
||||
'ajaxurl' => admin_url('admin-ajax.php')
|
||||
// Localize script with data for AJAX and other JS needs
|
||||
wp_localize_script('wpallstars-admin', 'wpallstars', array(
|
||||
'ajaxurl' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce('wpallstars-nonce'), // Generic nonce for general actions
|
||||
'update_option_nonce' => wp_create_nonce('wpallstars_update_option'), // Specific nonce for updating options via AJAX (if still needed)
|
||||
'l10n' => array( // Localization strings for JS
|
||||
'updating' => __('Updating...', WPALLSTARS_TEXT_DOMAIN),
|
||||
'error' => __('Error', WPALLSTARS_TEXT_DOMAIN),
|
||||
'success' => __('Success', WPALLSTARS_TEXT_DOMAIN),
|
||||
),
|
||||
// Add any other data needed by wpallstars-admin.js
|
||||
));
|
||||
|
||||
// Settings Manager handles its own enqueuing via its init hook
|
||||
// WPALLSTARS_Settings_Manager::enqueue_settings_scripts($hook); // Removed
|
||||
|
||||
// Other managers can still enqueue specific assets if needed
|
||||
// Example:
|
||||
// WPALLSTARS_Theme_Manager::enqueue_theme_scripts($hook);
|
||||
// WPALLSTARS_Free_Plugins_Manager::enqueue_free_plugins_scripts($hook);
|
||||
|
||||
// Combine inline styles from various managers
|
||||
$inline_styles = ''; // Initialize
|
||||
// Uncomment and adjust class/method names as needed
|
||||
// $inline_styles .= WPALLSTARS_Pro_Plugins_Manager::get_inline_styles();
|
||||
// $inline_styles .= WPALLSTARS_Hosting_Manager::get_inline_styles();
|
||||
// $inline_styles .= WPALLSTARS_Tools_Manager::get_inline_styles();
|
||||
if (!empty($inline_styles)) {
|
||||
wp_add_inline_style('wpallstars-admin', $inline_styles);
|
||||
}
|
||||
|
||||
// Combine inline scripts from various managers (use with caution)
|
||||
$inline_scripts = ''; // Initialize
|
||||
// $inline_scripts .= WPALLSTARS_Theme_Manager::get_theme_scripts();
|
||||
// $inline_scripts .= WPALLSTARS_Free_Plugins_Manager::get_plugin_scripts();
|
||||
// $inline_scripts .= WPALLSTARS_Settings_Manager::get_settings_scripts(); // Removed
|
||||
if (!empty($inline_scripts)) {
|
||||
wp_add_inline_script('wpallstars-admin', $inline_scripts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register core plugin settings
|
||||
* Register core plugin settings - REMOVED
|
||||
* Settings registration is now handled by WPALLSTARS_Settings_Manager::register_settings
|
||||
*/
|
||||
public static function register_settings() {
|
||||
// Core settings groups - tab-specific settings are registered in their respective manager classes
|
||||
register_setting('wp_allstars_general', 'wp_allstars_general_settings');
|
||||
register_setting('wp_allstars_advanced', 'wp_allstars_advanced_settings');
|
||||
}
|
||||
// public static function register_settings() { ... }
|
||||
|
||||
/**
|
||||
* AJAX handler for updating options
|
||||
* AJAX handler for updating options (Generic handler, specific validation can be added)
|
||||
* Note: This is likely NOT used for the main settings form save action anymore,
|
||||
* which is handled by options.php via the Settings API.
|
||||
* Keep it if it's used for dynamic updates elsewhere.
|
||||
* Handles saving *individual* setting keys within the 'wpallstars_options' array via AJAX.
|
||||
*/
|
||||
public static function update_option() {
|
||||
// Verify nonce for security
|
||||
check_ajax_referer('wp-allstars-nonce', 'nonce');
|
||||
// Check nonce
|
||||
check_ajax_referer('wpallstars_update_option', 'nonce');
|
||||
|
||||
// Check if user has proper permissions
|
||||
// Check user capabilities
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error('Insufficient permissions');
|
||||
wp_send_json_error(__('You do not have permission to perform this action.', WPALLSTARS_TEXT_DOMAIN));
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate and sanitize input
|
||||
if (!isset($_POST['option']) || !isset($_POST['value'])) {
|
||||
wp_send_json_error('Missing required parameters');
|
||||
// Get setting key and value from POST data
|
||||
$setting_key = isset($_POST['setting_key']) ? sanitize_key($_POST['setting_key']) : '';
|
||||
// Don't sanitize value yet, do it based on the key type later
|
||||
$setting_value = isset($_POST['setting_value']) ? wp_unslash($_POST['setting_value']) : null;
|
||||
|
||||
if (empty($setting_key) || is_null($setting_value)) {
|
||||
wp_send_json_error(__('Setting key or value is missing.', WPALLSTARS_TEXT_DOMAIN));
|
||||
return;
|
||||
}
|
||||
|
||||
$option = sanitize_text_field($_POST['option']);
|
||||
|
||||
// Different sanitization based on expected value type
|
||||
$value = $_POST['value'];
|
||||
if (is_numeric($value)) {
|
||||
$value = intval($value);
|
||||
} elseif (is_string($value)) {
|
||||
$value = sanitize_text_field($value);
|
||||
} elseif (is_array($value)) {
|
||||
$value = array_map('sanitize_text_field', $value);
|
||||
}
|
||||
|
||||
// Whitelist of allowed options to update for security
|
||||
// --- Security & Validation ---
|
||||
// Whitelist setting KEYS within 'wpallstars_options' that can be updated via this AJAX handler
|
||||
$allowed_options = array(
|
||||
'wp_allstars_simple_setting',
|
||||
'wp_allstars_auto_upload_images',
|
||||
'wp_allstars_admin_color_scheme',
|
||||
'wp_allstars_max_width',
|
||||
'wp_allstars_max_height',
|
||||
'wp_allstars_exclude_urls',
|
||||
'wp_allstars_image_name_pattern',
|
||||
'wp_allstars_image_alt_pattern'
|
||||
'admin_color_scheme', // Example: Key for admin color scheme
|
||||
'enable_auto_upload', // Example: Key for auto-upload toggle
|
||||
'max_image_width', // Example: Key for max image width
|
||||
// Add other keys registered in Settings_Manager that should be AJAX-updatable
|
||||
);
|
||||
|
||||
if (!in_array($option, $allowed_options)) {
|
||||
wp_send_json_error('Invalid option');
|
||||
if (!in_array($setting_key, $allowed_options, true)) {
|
||||
wp_send_json_error(__('Invalid setting key specified for AJAX update.', WPALLSTARS_TEXT_DOMAIN));
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the option
|
||||
$result = update_option($option, $value);
|
||||
// Sanitize the value based on the specific setting key
|
||||
$sanitized_value = '';
|
||||
switch ($setting_key) {
|
||||
case 'admin_color_scheme':
|
||||
// Assuming it's a class name or identifier
|
||||
$sanitized_value = sanitize_html_class($setting_value);
|
||||
// If it was intended to be a hex color, use sanitize_hex_color($setting_value);
|
||||
break;
|
||||
case 'enable_auto_upload':
|
||||
// Boolean toggle (common JS values are 'true'/'false' strings)
|
||||
$sanitized_value = rest_sanitize_boolean($setting_value);
|
||||
break;
|
||||
case 'max_image_width':
|
||||
// Positive integer
|
||||
$sanitized_value = absint($setting_value);
|
||||
break;
|
||||
// Add cases for other allowed keys
|
||||
default:
|
||||
// Should not happen due to whitelist check, but as a fallback:
|
||||
$sanitized_value = sanitize_text_field($setting_value);
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the existing options array
|
||||
$options = get_option(WPALLSTARS_Settings_Manager::$option_name, array());
|
||||
|
||||
// Store the old value for comparison
|
||||
$old_value = isset($options[$setting_key]) ? $options[$setting_key] : null;
|
||||
|
||||
// Update the specific key in the options array
|
||||
$options[$setting_key] = $sanitized_value;
|
||||
|
||||
// Save the entire options array back
|
||||
// update_option handles serialization and DB storage
|
||||
$result = update_option(WPALLSTARS_Settings_Manager::$option_name, $options);
|
||||
|
||||
if ($result) {
|
||||
wp_send_json_success(array(
|
||||
'message' => 'Option updated successfully',
|
||||
'option' => $option,
|
||||
'value' => $value
|
||||
));
|
||||
wp_send_json_success(__('Option updated successfully.', WPALLSTARS_TEXT_DOMAIN));
|
||||
} else {
|
||||
wp_send_json_success(array(
|
||||
'message' => 'No changes made to option',
|
||||
'option' => $option
|
||||
));
|
||||
// Option might not have changed, or error occurred
|
||||
// Check if the value is the same as the old value (update_option returns false if value hasn't changed)
|
||||
if ($old_value === $sanitized_value) {
|
||||
wp_send_json_success(__('Option unchanged.', WPALLSTARS_TEXT_DOMAIN));
|
||||
} else {
|
||||
wp_send_json_error(__('Failed to update option.', WPALLSTARS_TEXT_DOMAIN));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,172 +211,141 @@ class WP_Allstars_Admin_Manager {
|
||||
* Register the admin menu item
|
||||
*/
|
||||
public static function register_admin_menu() {
|
||||
add_options_page(
|
||||
'WP ALLSTARS Settings',
|
||||
'WP ALLSTARS',
|
||||
add_menu_page(
|
||||
__('WP Allstars', WPALLSTARS_TEXT_DOMAIN),
|
||||
__('WP Allstars', WPALLSTARS_TEXT_DOMAIN),
|
||||
'manage_options',
|
||||
'wp-allstars',
|
||||
array(__CLASS__, 'render_settings_page')
|
||||
'wpallstars-dashboard', // Main dashboard slug
|
||||
array(__CLASS__, 'render_settings_page'), // Default to settings page for now
|
||||
'dashicons-star-filled',
|
||||
85
|
||||
);
|
||||
|
||||
// Add actual settings submenu
|
||||
add_submenu_page(
|
||||
'wpallstars-dashboard', // Parent slug
|
||||
__('Settings', WPALLSTARS_TEXT_DOMAIN), // Page title
|
||||
__('Settings', WPALLSTARS_TEXT_DOMAIN), // Menu title
|
||||
'manage_options', // Capability
|
||||
'wpallstars-settings', // Settings slug << THIS IS THE SLUG TO USE
|
||||
array(__CLASS__, 'render_settings_page') // Callback function
|
||||
);
|
||||
|
||||
// Add other submenus here using their respective managers or callbacks
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the settings page
|
||||
* Render the settings page container and handle tab navigation.
|
||||
* Content for each tab is rendered by the respective manager class.
|
||||
*/
|
||||
public static function render_settings_page() {
|
||||
global $tabs;
|
||||
|
||||
$active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'general';
|
||||
$active_category = isset($_GET['category']) ? $_GET['category'] : 'minimal';
|
||||
|
||||
// Tab-specific resources
|
||||
if ($active_tab === 'recommended') {
|
||||
WP_Allstars_Plugin_Manager::clear_plugin_cache();
|
||||
wp_enqueue_script('plugin-install');
|
||||
wp_enqueue_script('updates');
|
||||
add_thickbox();
|
||||
wp_enqueue_style('wp-allstars-plugins', plugins_url('css/wp-allstars-plugins.css', dirname(__FILE__)));
|
||||
|
||||
// Add inline script to load plugins on page load
|
||||
wp_add_inline_script('wp-allstars-admin', '
|
||||
jQuery(document).ready(function($) {
|
||||
if ($("#wpa-plugin-list").length && $("#wpa-plugin-list").is(":empty")) {
|
||||
var category = "' . esc_js($active_category) . '";
|
||||
var $container = $("#wpa-plugin-list");
|
||||
var $loadingOverlay = $("<div class=\"wp-allstars-loading-overlay\"><span class=\"spinner is-active\"></span></div>");
|
||||
|
||||
// Show loading overlay
|
||||
$container.css("position", "relative").append($loadingOverlay);
|
||||
|
||||
// AJAX request to get plugins
|
||||
$.ajax({
|
||||
url: ajaxurl,
|
||||
type: "POST",
|
||||
data: {
|
||||
action: "wp_allstars_get_plugins",
|
||||
category: category,
|
||||
_wpnonce: wpAllstars.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
$loadingOverlay.remove();
|
||||
if (response.success) {
|
||||
$container.html(response.data);
|
||||
// Initialize plugin action buttons
|
||||
if (typeof initPluginActions === "function") {
|
||||
initPluginActions();
|
||||
// Check user capabilities
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_die(__('You do not have sufficient permissions to access this page.', WPALLSTARS_TEXT_DOMAIN));
|
||||
}
|
||||
|
||||
// Spinners have been removed from individual cards
|
||||
} else {
|
||||
$container.html("<div class=\"notice notice-error\"><p>" + response.data + "</p></div>");
|
||||
// Whitelist of valid tabs
|
||||
$valid_tabs = array(
|
||||
'general' => __('General', WPALLSTARS_TEXT_DOMAIN),
|
||||
'advanced' => __('Advanced', WPALLSTARS_TEXT_DOMAIN),
|
||||
'workflow' => __('Workflow', WPALLSTARS_TEXT_DOMAIN),
|
||||
'theme' => __('Theme', WPALLSTARS_TEXT_DOMAIN),
|
||||
'recommended' => __('Free Plugins', WPALLSTARS_TEXT_DOMAIN),
|
||||
'pro' => __('Pro Plugins', WPALLSTARS_TEXT_DOMAIN),
|
||||
'hosting' => __('Hosting', WPALLSTARS_TEXT_DOMAIN),
|
||||
'tools' => __('Tools', WPALLSTARS_TEXT_DOMAIN),
|
||||
'readme' => __('Read Me', WPALLSTARS_TEXT_DOMAIN),
|
||||
);
|
||||
|
||||
// Get current tab from URL, default to 'general'
|
||||
$current_tab = isset($_GET['tab']) ? sanitize_key($_GET['tab']) : 'general';
|
||||
|
||||
// Fallback to 'general' if the tab is not in the whitelist
|
||||
if (!array_key_exists($current_tab, $valid_tabs)) {
|
||||
$current_tab = 'general';
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$loadingOverlay.remove();
|
||||
$container.html("<div class=\"notice notice-error\"><p>Failed to load plugins. Please try again. Error: " + error + "</p></div>");
|
||||
console.error("AJAX Error:", xhr.responseText);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
');
|
||||
|
||||
?>
|
||||
<div class="wrap wpallstars-wrap wpallstars-settings-wrap">
|
||||
<h1><?php esc_html_e('WP Allstars Settings', WPALLSTARS_TEXT_DOMAIN); ?></h1>
|
||||
|
||||
<?php settings_errors(); // Display any settings errors registered by the Settings API ?>
|
||||
|
||||
<div class="wpallstars-settings-container">
|
||||
<h2 class="nav-tab-wrapper">
|
||||
<?php
|
||||
// Define tabs with their labels (already defined in $valid_tabs)
|
||||
$tabs = $valid_tabs;
|
||||
|
||||
// Output tab navigation links using the correct settings page slug
|
||||
foreach ($tabs as $tab_slug => $tab_label) {
|
||||
$tab_url = add_query_arg(array('page' => 'wpallstars-settings', 'tab' => $tab_slug), admin_url('admin.php'));
|
||||
$class = ($current_tab === $tab_slug) ? 'nav-tab nav-tab-active' : 'nav-tab';
|
||||
echo '<a href="' . esc_url($tab_url) . '" class="' . esc_attr($class) . '">' . esc_html($tab_label) . '</a>';
|
||||
}
|
||||
?>
|
||||
<div class="wrap wp-allstars-wrap">
|
||||
<div class="wp-allstars-header">
|
||||
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
||||
<div class="wp-allstars-header-actions">
|
||||
<span class="wp-allstars-version"><?php echo esc_html(WP_ALLSTARS_VERSION); ?></span>
|
||||
<a href="https://www.wpallstars.com/" target="_blank" class="button button-secondary green-button-secondary green-visit-website">
|
||||
<?php esc_html_e('Visit Website', 'wp-allstars'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wp-allstars-tabs-wrapper">
|
||||
<h2 class="nav-tab-wrapper">
|
||||
<a href="?page=wp-allstars&tab=general" class="nav-tab <?php echo $active_tab === 'general' ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e('General', 'wp-allstars'); ?>
|
||||
</a>
|
||||
<a href="?page=wp-allstars&tab=advanced" class="nav-tab <?php echo $active_tab === 'advanced' ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e('Advanced', 'wp-allstars'); ?>
|
||||
</a>
|
||||
<a href="?page=wp-allstars&tab=workflow" class="nav-tab <?php echo $active_tab === 'workflow' ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e('Workflow', 'wp-allstars'); ?>
|
||||
</a>
|
||||
<a href="?page=wp-allstars&tab=theme" class="nav-tab <?php echo $active_tab === 'theme' ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e('Theme', 'wp-allstars'); ?>
|
||||
</a>
|
||||
<a href="?page=wp-allstars&tab=recommended" class="nav-tab <?php echo $active_tab === 'recommended' ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e('Free Plugins', 'wp-allstars'); ?>
|
||||
</a>
|
||||
<a href="?page=wp-allstars&tab=pro" class="nav-tab <?php echo $active_tab === 'pro' ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e('Pro Plugins', 'wp-allstars'); ?>
|
||||
</a>
|
||||
<a href="?page=wp-allstars&tab=hosting" class="nav-tab <?php echo $active_tab === 'hosting' ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e('Hosting', 'wp-allstars'); ?>
|
||||
</a>
|
||||
<a href="?page=wp-allstars&tab=tools" class="nav-tab <?php echo $active_tab === 'tools' ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e('Tools', 'wp-allstars'); ?>
|
||||
</a>
|
||||
<a href="?page=wp-allstars&tab=readme" class="nav-tab <?php echo $active_tab === 'readme' ? 'nav-tab-active' : ''; ?>">
|
||||
<?php esc_html_e('Read Me', 'wp-allstars'); ?>
|
||||
</a>
|
||||
</h2>
|
||||
|
||||
<div class="wp-allstars-tab-content">
|
||||
<div class="wpallstars-tab-content-container">
|
||||
<?php
|
||||
// Each tab's content is handled by its respective manager class
|
||||
switch ($active_tab) {
|
||||
// Display content based on the active tab by calling the appropriate manager's display method
|
||||
// Using a switch statement for clarity
|
||||
switch ($current_tab) {
|
||||
case 'general':
|
||||
WP_Allstars_Settings_Manager::display_general_tab();
|
||||
if (class_exists('WPALLSTARS_Settings_Manager')) WPALLSTARS_Settings_Manager::display_general_tab();
|
||||
break;
|
||||
|
||||
case 'advanced':
|
||||
WP_Allstars_Settings_Manager::display_advanced_tab();
|
||||
if (class_exists('WPALLSTARS_Settings_Manager')) WPALLSTARS_Settings_Manager::display_advanced_tab();
|
||||
break;
|
||||
|
||||
case 'workflow':
|
||||
WP_Allstars_Workflow_Manager::display_tab_content();
|
||||
if (class_exists('WPALLSTARS_Workflow_Manager')) WPALLSTARS_Workflow_Manager::display_tab_content();
|
||||
break;
|
||||
|
||||
case 'theme':
|
||||
WP_Allstars_Theme_Manager::display_tab_content();
|
||||
if (class_exists('WPALLSTARS_Theme_Manager')) WPALLSTARS_Theme_Manager::display_tab_content();
|
||||
break;
|
||||
|
||||
case 'recommended':
|
||||
WP_Allstars_Free_Plugins_Manager::display_tab_content();
|
||||
if (class_exists('WPALLSTARS_Free_Plugins_Manager')) WPALLSTARS_Free_Plugins_Manager::display_tab_content();
|
||||
break;
|
||||
|
||||
case 'pro':
|
||||
WP_Allstars_Pro_Plugins_Manager::display_tab_content();
|
||||
if (class_exists('WPALLSTARS_Pro_Plugins_Manager')) WPALLSTARS_Pro_Plugins_Manager::display_tab_content();
|
||||
break;
|
||||
|
||||
case 'hosting':
|
||||
WP_Allstars_Hosting_Manager::display_tab_content();
|
||||
if (class_exists('WPALLSTARS_Hosting_Manager')) WPALLSTARS_Hosting_Manager::display_tab_content();
|
||||
break;
|
||||
|
||||
case 'tools':
|
||||
WP_Allstars_Tools_Manager::display_tab_content();
|
||||
if (class_exists('WPALLSTARS_Tools_Manager')) WPALLSTARS_Tools_Manager::display_tab_content();
|
||||
break;
|
||||
|
||||
case 'readme':
|
||||
WP_Allstars_Readme_Manager::display_tab_content();
|
||||
if (class_exists('WPALLSTARS_Readme_Manager')) WPALLSTARS_Readme_Manager::display_tab_content();
|
||||
break;
|
||||
default:
|
||||
// Should not happen due to whitelist check, but good practice
|
||||
if (class_exists('WPALLSTARS_Settings_Manager')) WPALLSTARS_Settings_Manager::display_general_tab();
|
||||
break;
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- .wpallstars-tab-content-container -->
|
||||
</div><!-- .wpallstars-settings-container -->
|
||||
</div><!-- .wrap -->
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for enqueue_admin_scripts to maintain compatibility with settings.php
|
||||
* Alias for enqueue_admin_scripts to potentially maintain compatibility
|
||||
* if other parts of the codebase mistakenly call this.
|
||||
*
|
||||
* @param string $hook The current admin page hook
|
||||
* @deprecated Prefer calling enqueue_admin_scripts directly.
|
||||
* @param string $hook The current admin page hook.
|
||||
*/
|
||||
public static function enqueue_scripts($hook) {
|
||||
self::enqueue_admin_scripts($hook);
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate the Admin Manager when the admin area is loaded
|
||||
if (is_admin()) {
|
||||
// Ensure the class exists before calling init (optional safety check)
|
||||
if (class_exists('WPALLSTARS_Admin_Manager')) {
|
||||
WPALLSTARS_Admin_Manager::init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,15 +50,15 @@ class WP_Allstars_Free_Plugins_Manager {
|
||||
// Define all categories in the desired display order
|
||||
$priority_categories = array(
|
||||
'minimal', 'admin', 'affiliates', 'ai', 'cms',
|
||||
'compliance', 'crm', 'ecommerce', 'lms', 'media',
|
||||
'seo', 'setup', 'social', 'speed', 'translation',
|
||||
'compliance', 'crm', 'ecommerce', 'events', 'lms', 'media',
|
||||
'members', 'seo', 'setup', 'social', 'speed', 'translation',
|
||||
'advanced', 'debug'
|
||||
);
|
||||
|
||||
// Start HTML output
|
||||
?>
|
||||
<div class="wp-allstars-settings-content tab-content" id="recommended">
|
||||
<div id="wpa-plugin-filters" class="wp-filter">
|
||||
<div id="wpallstars-plugin-filters" class="wp-filter">
|
||||
<ul class="filter-links">
|
||||
<?php
|
||||
// First output priority categories
|
||||
@@ -100,7 +100,7 @@ class WP_Allstars_Free_Plugins_Manager {
|
||||
</div>
|
||||
|
||||
<div class="wp-allstars-plugin-browser" style="margin-top: 22px;">
|
||||
<div id="wpa-plugin-list" class="wpa-plugin-container" style="position: relative; min-height: 200px;">
|
||||
<div id="wpallstars-plugin-list" class="wpallstars-plugin-container" style="position: relative; min-height: 200px;">
|
||||
<!-- Plugin content will be loaded via AJAX -->
|
||||
<div class="wp-allstars-loading-overlay">
|
||||
<span class="spinner is-active"></span>
|
||||
@@ -112,14 +112,14 @@ class WP_Allstars_Free_Plugins_Manager {
|
||||
<script>
|
||||
jQuery(document).ready(function($) {
|
||||
// Filter tab click handler
|
||||
$('#wpa-plugin-filters .filter-links a').on('click', function(e) {
|
||||
$('#wpallstars-plugin-filters .filter-links a').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var category = $(this).data('category');
|
||||
var $container = $('#wpa-plugin-list');
|
||||
var $container = $('#wpallstars-plugin-list');
|
||||
|
||||
// Update filter UI
|
||||
$('#wpa-plugin-filters .filter-links a').removeClass('current');
|
||||
$('#wpallstars-plugin-filters .filter-links a').removeClass('current');
|
||||
$(this).addClass('current');
|
||||
|
||||
// Create new loading overlay
|
||||
@@ -163,7 +163,7 @@ class WP_Allstars_Free_Plugins_Manager {
|
||||
});
|
||||
|
||||
// Load initial category (minimal or from URL)
|
||||
$('#wpa-plugin-filters .filter-links a.current').trigger('click');
|
||||
$('#wpallstars-plugin-filters .filter-links a.current').trigger('click');
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
@@ -24,7 +24,7 @@ class WP_Allstars_Hosting_Manager {
|
||||
public static function display_tab_content() {
|
||||
?>
|
||||
<div class="wp-allstars-settings-content tab-content" id="hosting">
|
||||
<div class="wpa-pro-plugins">
|
||||
<div class="wpallstars-pro-plugins">
|
||||
<?php
|
||||
$hosting_providers = self::get_hosting_providers();
|
||||
// Sort providers alphabetically by name
|
||||
@@ -33,7 +33,7 @@ class WP_Allstars_Hosting_Manager {
|
||||
});
|
||||
foreach ($hosting_providers as $provider) {
|
||||
?>
|
||||
<div class="wpa-pro-plugin">
|
||||
<div class="wpallstars-pro-plugin">
|
||||
<h3><?php echo esc_html($provider['name']); ?></h3>
|
||||
<p><?php echo esc_html($provider['description']); ?></p>
|
||||
<?php if (isset($provider['button_group'])): ?>
|
||||
@@ -100,7 +100,7 @@ class WP_Allstars_Hosting_Manager {
|
||||
|
||||
// Add inline CSS for hosting to match the single column layout
|
||||
$custom_css = '
|
||||
#hosting .wpa-pro-plugins {
|
||||
#hosting .wpallstars-pro-plugins {
|
||||
padding: 15px 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -108,7 +108,7 @@ class WP_Allstars_Hosting_Manager {
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
#hosting .wpa-pro-plugin {
|
||||
#hosting .wpallstars-pro-plugin {
|
||||
background: #fff;
|
||||
border: 1px solid #ddd;
|
||||
padding: 24px;
|
||||
@@ -121,14 +121,14 @@ class WP_Allstars_Hosting_Manager {
|
||||
margin-bottom: 24px;
|
||||
max-width: 100%;
|
||||
}
|
||||
#hosting .wpa-pro-plugin:last-child {
|
||||
#hosting .wpallstars-pro-plugin:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#hosting .wpa-pro-plugin:hover {
|
||||
#hosting .wpallstars-pro-plugin:hover {
|
||||
border-color: #2271b1;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
||||
}
|
||||
#hosting .wpa-pro-plugin .button-group {
|
||||
#hosting .wpallstars-pro-plugin .button-group {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
';
|
||||
|
||||
@@ -65,7 +65,7 @@ class WP_Allstars_Pro_Plugins_Manager {
|
||||
});
|
||||
|
||||
// Start the tab content container
|
||||
echo '<div class="wp-allstars-settings-content tab-content" id="pro"><div class="wpa-pro-plugins">';
|
||||
echo '<div class="wp-allstars-settings-content tab-content" id="pro"><div class="wpallstars-pro-plugins">';
|
||||
|
||||
// Render each plugin card
|
||||
foreach ($pro_plugins as $plugin) {
|
||||
@@ -83,7 +83,7 @@ class WP_Allstars_Pro_Plugins_Manager {
|
||||
*/
|
||||
public static function display_plugin_card($plugin) {
|
||||
?>
|
||||
<div class="wpa-pro-plugin">
|
||||
<div class="wpallstars-pro-plugin">
|
||||
<h3><?php echo esc_html($plugin['name']); ?></h3>
|
||||
<p><?php echo esc_html($plugin['description']); ?></p>
|
||||
<?php if (isset($plugin['button_group'])): ?>
|
||||
@@ -138,7 +138,7 @@ class WP_Allstars_Pro_Plugins_Manager {
|
||||
|
||||
// Add inline CSS for pro plugins
|
||||
$custom_css = '
|
||||
.wpa-pro-plugins {
|
||||
.wpallstars-pro-plugins {
|
||||
padding: 15px 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -146,7 +146,7 @@ class WP_Allstars_Pro_Plugins_Manager {
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.wpa-pro-plugin {
|
||||
.wpallstars-pro-plugin {
|
||||
background: #fff;
|
||||
border: 1px solid #ddd;
|
||||
padding: 24px;
|
||||
@@ -159,34 +159,34 @@ class WP_Allstars_Pro_Plugins_Manager {
|
||||
margin-bottom: 24px;
|
||||
max-width: 100%;
|
||||
}
|
||||
.wpa-pro-plugin:last-child {
|
||||
.wpallstars-pro-plugin:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.wpa-pro-plugin:hover {
|
||||
.wpallstars-pro-plugin:hover {
|
||||
border-color: #2271b1;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
||||
}
|
||||
.wpa-pro-plugin h3 {
|
||||
.wpallstars-pro-plugin h3 {
|
||||
margin: 0 0 12px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #1d2327;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.wpa-pro-plugin p {
|
||||
.wpallstars-pro-plugin p {
|
||||
margin: 0 0 16px;
|
||||
color: #50575e;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.wpa-pro-plugin .button-group {
|
||||
.wpallstars-pro-plugin .button-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: auto;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.wpa-pro-plugin .button {
|
||||
.wpallstars-pro-plugin .button {
|
||||
text-decoration: none;
|
||||
min-width: 120px;
|
||||
text-align: center;
|
||||
@@ -205,17 +205,17 @@ class WP_Allstars_Pro_Plugins_Manager {
|
||||
box-shadow: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.wpa-pro-plugin .button:hover {
|
||||
.wpallstars-pro-plugin .button:hover {
|
||||
background: #f0f0f1;
|
||||
border-color: #0071a1;
|
||||
color: #0071a1;
|
||||
}
|
||||
.wpa-pro-plugin .button-primary {
|
||||
.wpallstars-pro-plugin .button-primary {
|
||||
background: #0071a1;
|
||||
border-color: #0071a1;
|
||||
color: #fff;
|
||||
}
|
||||
.wpa-pro-plugin .button-primary:hover {
|
||||
.wpallstars-pro-plugin .button-primary:hover {
|
||||
background: #006291;
|
||||
border-color: #006291;
|
||||
color: #fff;
|
||||
|
||||
@@ -50,14 +50,14 @@ class WP_Allstars_Readme_Manager {
|
||||
* Display the readme tab content
|
||||
*/
|
||||
public static function display_tab_content() {
|
||||
$readme = self::get_readme_content();
|
||||
$readme_content = self::get_readme_content();
|
||||
|
||||
?>
|
||||
<div class="wp-allstars-settings-content tab-content" id="readme">
|
||||
<div class="wpa-pro-plugins">
|
||||
<div class="wpa-pro-plugin">
|
||||
<div class="wpallstars-pro-plugins">
|
||||
<div class="wpallstars-pro-plugin">
|
||||
<div class="wp-allstars-markdown-content">
|
||||
<?php echo self::parse_markdown($readme['content']); ?>
|
||||
<?php echo self::parse_markdown($readme_content['content']); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Settings Manager Class
|
||||
*
|
||||
* Handles the display and management of plugin settings tabs (General and Advanced).
|
||||
* Leverages the WordPress Settings API.
|
||||
*/
|
||||
|
||||
// If this file is called directly, abort.
|
||||
@@ -10,186 +11,400 @@ if ( ! defined( 'WPINC' ) ) {
|
||||
die;
|
||||
}
|
||||
|
||||
class WP_Allstars_Settings_Manager {
|
||||
/**
|
||||
* Class WPALLSTARS_Settings_Manager
|
||||
* Manages WP Allstars plugin settings using the WordPress Settings API.
|
||||
*/
|
||||
class WPALLSTARS_Settings_Manager {
|
||||
|
||||
/**
|
||||
* Option group name.
|
||||
* @var string
|
||||
*/
|
||||
private static $option_group = 'wpallstars_settings_group';
|
||||
|
||||
/**
|
||||
* Option name stored in the database.
|
||||
* @var string
|
||||
*/
|
||||
private static $option_name = 'wpallstars_options';
|
||||
|
||||
/**
|
||||
* Initialize the class
|
||||
*/
|
||||
public static function init() {
|
||||
// Register settings
|
||||
// Register settings using admin_init hook
|
||||
add_action('admin_init', array(self::class, 'register_settings'));
|
||||
|
||||
// Enqueue scripts and styles if needed
|
||||
// Enqueue scripts and styles needed for settings page
|
||||
add_action('admin_enqueue_scripts', array(self::class, 'enqueue_scripts'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register plugin settings
|
||||
* Register plugin settings, sections, and fields.
|
||||
*/
|
||||
public static function register_settings() {
|
||||
// General settings
|
||||
register_setting('wp_allstars_settings', 'wp_allstars_simple_setting');
|
||||
register_setting('wp_allstars_settings', 'wp_allstars_admin_color_scheme');
|
||||
// Register the single option array to store all settings
|
||||
register_setting(
|
||||
self::$option_group, // Option group
|
||||
self::$option_name, // Option name
|
||||
array(self::class, 'sanitize_settings') // Sanitize callback
|
||||
);
|
||||
|
||||
// --- General Settings Section ---
|
||||
add_settings_section(
|
||||
'wpallstars_general_settings_section', // ID
|
||||
__('General Settings', WPALLSTARS_TEXT_DOMAIN), // Title
|
||||
null, // Callback function (optional description)
|
||||
'wpallstars_general_settings_page' // Page slug where this section will be shown
|
||||
);
|
||||
|
||||
// Field: Admin Color Scheme
|
||||
add_settings_field(
|
||||
'admin_color_scheme', // Field ID (matches key in options array)
|
||||
__('Modern Admin Colors', WPALLSTARS_TEXT_DOMAIN), // Title
|
||||
array(self::class, 'render_admin_color_field'), // Callback to render the field
|
||||
'wpallstars_general_settings_page', // Page
|
||||
'wpallstars_general_settings_section' // Section
|
||||
);
|
||||
|
||||
// Field: Simple Toggle Example (Keeping for now, can be removed later)
|
||||
add_settings_field(
|
||||
'simple_toggle_example', // Field ID
|
||||
__('Example: Simple Toggle', WPALLSTARS_TEXT_DOMAIN), // Title
|
||||
array(self::class, 'render_simple_toggle_field'), // Callback
|
||||
'wpallstars_general_settings_page', // Page
|
||||
'wpallstars_general_settings_section' // Section
|
||||
);
|
||||
|
||||
// --- Advanced Settings Section ---
|
||||
add_settings_section(
|
||||
'wpallstars_advanced_settings_section', // ID
|
||||
__('Advanced Settings', WPALLSTARS_TEXT_DOMAIN), // Title
|
||||
null, // Callback
|
||||
'wpallstars_advanced_settings_page' // Page slug
|
||||
);
|
||||
|
||||
// Field: Auto Upload Images
|
||||
add_settings_field(
|
||||
'auto_upload_enabled', // Field ID (matching key used in WPALLSTARS_Auto_Upload)
|
||||
__('Auto Upload External Images', WPALLSTARS_TEXT_DOMAIN), // Title
|
||||
array(self::class, 'render_auto_upload_field'), // Callback
|
||||
'wpallstars_advanced_settings_page', // Page
|
||||
'wpallstars_advanced_settings_section' // Section
|
||||
);
|
||||
|
||||
// Field: Sync Guard Enabled
|
||||
add_settings_field(
|
||||
'sync_guard_enabled', // Field ID (matching key used in WPALLSTARS_Sync_Guard)
|
||||
__('Enable Sync Guard', WPALLSTARS_TEXT_DOMAIN), // Title
|
||||
array(self::class, 'render_sync_guard_field'), // Callback
|
||||
'wpallstars_advanced_settings_page', // Page
|
||||
'wpallstars_advanced_settings_section' // Section
|
||||
);
|
||||
|
||||
// Add more fields for other settings as needed (e.g., Sync Guard Mode, Debug Mode)
|
||||
// ... add_settings_field(...) ...
|
||||
|
||||
// Advanced settings
|
||||
register_setting('wp_allstars_settings', 'wp_allstars_auto_upload_images');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts and styles needed for settings
|
||||
* Sanitize settings array before saving.
|
||||
*
|
||||
* @param array $input The input array from the settings form.
|
||||
* @return array The sanitized array to be saved.
|
||||
*/
|
||||
public static function sanitize_settings($input) {
|
||||
$sanitized_input = array();
|
||||
$options = get_option(self::$option_name, array()); // Get existing options
|
||||
|
||||
// Ensure $input is an array
|
||||
if (!is_array($input)) {
|
||||
$input = array();
|
||||
}
|
||||
|
||||
// Sanitize: Admin Color Scheme (checkbox - 1 or 0)
|
||||
$sanitized_input['admin_color_scheme'] = isset($input['admin_color_scheme']) ? 1 : 0;
|
||||
|
||||
// Sanitize: Simple Toggle Example (checkbox - 1 or 0)
|
||||
$sanitized_input['simple_toggle_example'] = isset($input['simple_toggle_example']) ? 1 : 0;
|
||||
|
||||
// Sanitize: Auto Upload Enabled (checkbox - 1 or 0)
|
||||
$sanitized_input['auto_upload_enabled'] = isset($input['auto_upload_enabled']) ? 1 : 0;
|
||||
|
||||
// Sanitize: Sync Guard Enabled (checkbox - 1 or 0)
|
||||
$sanitized_input['sync_guard_enabled'] = isset($input['sync_guard_enabled']) ? 1 : 0;
|
||||
|
||||
// Example: Sanitize a text field (if we add one later)
|
||||
// if (isset($input['api_key'])) {
|
||||
// $sanitized_input['api_key'] = sanitize_text_field($input['api_key']);
|
||||
// } else {
|
||||
// $sanitized_input['api_key'] = $options['api_key'] ?? ''; // Keep existing if not set
|
||||
// }
|
||||
|
||||
// Merge with existing options to preserve settings not on the current form
|
||||
// This might not be necessary if all settings are always present or handled by defaults.
|
||||
// Consider if default values are sufficient or if merging is required.
|
||||
// $sanitized_input = array_merge($options, $sanitized_input);
|
||||
|
||||
// Add settings saved notice (WordPress handles this automatically on successful save)
|
||||
// add_settings_error(...); // No need for this here anymore
|
||||
|
||||
return $sanitized_input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts and styles needed for settings page.
|
||||
*
|
||||
* @param string $hook The current admin page hook.
|
||||
*/
|
||||
public static function enqueue_scripts($hook) {
|
||||
// Only load on the plugin settings page
|
||||
if (strpos($hook, 'wp-allstars') === false) {
|
||||
// Define the specific hook for the WPAllstars settings page
|
||||
$settings_page_hook = 'wpallstars_page_wpallstars-settings';
|
||||
|
||||
// Only enqueue assets on the WPAllstars settings page
|
||||
if ($settings_page_hook !== $hook) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add inline JS for toggle functionality
|
||||
$toggle_js = '
|
||||
jQuery(document).ready(function($) {
|
||||
// Toggle expandable settings panels
|
||||
$(".wp-allstars-toggle-header").on("click", function() {
|
||||
var $this = $(this);
|
||||
var $settings = $this.next(".wp-allstars-toggle-settings");
|
||||
var isExpanded = $this.attr("aria-expanded") === "true";
|
||||
// Enqueue the color picker if needed (example)
|
||||
// wp_enqueue_style('wp-color-picker');
|
||||
// wp_enqueue_script('wp-color-picker');
|
||||
|
||||
// Toggle aria-expanded attribute
|
||||
$this.attr("aria-expanded", !isExpanded);
|
||||
// Enqueue specific CSS for the settings page if necessary
|
||||
// Example:
|
||||
// wp_enqueue_style(
|
||||
// 'wpallstars-settings-styles',
|
||||
// WPALLSTARS_URL . 'admin/css/wpallstars-settings.css',
|
||||
// array(),
|
||||
// WPALLSTARS_VERSION
|
||||
// );
|
||||
|
||||
// Toggle settings visibility
|
||||
$settings.slideToggle(200);
|
||||
});
|
||||
});
|
||||
';
|
||||
// If there was specific JS for settings toggles/interactions (removed inline JS previously)
|
||||
// it should be enqueued here from a dedicated file.
|
||||
// Example:
|
||||
// wp_enqueue_script(
|
||||
// 'wpallstars-settings-script',
|
||||
// WPALLSTARS_URL . 'admin/js/wpallstars-settings.js',
|
||||
// array('jquery', 'wp-color-picker'), // Add dependencies
|
||||
// WPALLSTARS_VERSION,
|
||||
// true // Load in footer
|
||||
// );
|
||||
|
||||
wp_add_inline_script('wp-allstars-admin', $toggle_js);
|
||||
// Localize data specifically for the settings script if needed
|
||||
// wp_localize_script('wpallstars-settings-script', 'wpallstarsSettings', array(
|
||||
// 'someSettingNonce' => wp_create_nonce('wpallstars-setting-action-nonce'),
|
||||
// // Add other data...
|
||||
// ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the general tab content
|
||||
* Renders the form structure for the General Settings Tab.
|
||||
* Called by the Admin Manager when displaying the settings page.
|
||||
*/
|
||||
public static function display_general_tab() {
|
||||
?>
|
||||
<div class="wp-allstars-settings-section">
|
||||
<div class="wp-allstars-settings-grid">
|
||||
<!-- Admin Color Scheme Setting -->
|
||||
<div class="wp-setting-row">
|
||||
<div class="wp-setting-header">
|
||||
<div class="wp-setting-main">
|
||||
<div class="wp-setting-left">
|
||||
<div class="wp-toggle-switch">
|
||||
<input type="checkbox"
|
||||
id="wp_allstars_admin_color_scheme"
|
||||
name="wp_allstars_admin_color_scheme"
|
||||
value="1"
|
||||
<?php checked(get_option('wp_allstars_admin_color_scheme', false)); ?>
|
||||
/>
|
||||
<span class="wp-toggle-slider"></span>
|
||||
</div>
|
||||
<label for="wp_allstars_admin_color_scheme" class="wp-setting-label">
|
||||
<?php esc_html_e('Modern Admin Colors', 'wp-allstars'); ?>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<p class="wp-setting-description">
|
||||
<?php esc_html_e('Switch to the Modern Admin colors, to remind that you\'re using WP Allstars.', 'wp-allstars'); ?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
// Output security fields for the registered setting group
|
||||
settings_fields(self::$option_group); // Use the option group name
|
||||
|
||||
<!-- Example of a simple toggle setting (no panel) -->
|
||||
// Output setting sections and fields for the 'general' page
|
||||
do_settings_sections('wpallstars_general_settings_page'); // Use the page slug
|
||||
|
||||
// Output save settings button
|
||||
submit_button(__('Save General Settings', WPALLSTARS_TEXT_DOMAIN));
|
||||
?>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the form structure for the Advanced Settings Tab.
|
||||
* Called by the Admin Manager when displaying the settings page.
|
||||
*/
|
||||
public static function display_advanced_tab() {
|
||||
?>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
// Output security fields for the registered setting group
|
||||
settings_fields(self::$option_group); // Use the option group name
|
||||
|
||||
// Output setting sections and fields for the 'advanced' page
|
||||
do_settings_sections('wpallstars_advanced_settings_page'); // Use the page slug
|
||||
|
||||
// Output save settings button
|
||||
submit_button(__('Save Advanced Settings', WPALLSTARS_TEXT_DOMAIN));
|
||||
?>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
|
||||
// --- Field Rendering Callbacks --- //
|
||||
|
||||
/**
|
||||
* Get the current value for a specific setting key.
|
||||
*
|
||||
* @param string $key The key within the wpallstars_options array.
|
||||
* @param mixed $default Default value if the key is not set.
|
||||
* @return mixed The setting value.
|
||||
*/
|
||||
private static function get_setting_value($key, $default = '') {
|
||||
$options = get_option(self::$option_name, array());
|
||||
return $options[$key] ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Admin Color Scheme toggle field.
|
||||
*/
|
||||
public static function render_admin_color_field() {
|
||||
$options = get_option(self::$option_name, array());
|
||||
$setting_key = 'admin_color_scheme'; // Key in the options array
|
||||
$value = isset($options[$setting_key]) ? $options[$setting_key] : 'default'; // Default value
|
||||
$field_id = self::$option_name . '_' . $setting_key; // Unique ID for label 'for' attribute
|
||||
|
||||
// Define color scheme options (example)
|
||||
$color_schemes = array(
|
||||
'default' => __('Default', WPALLSTARS_TEXT_DOMAIN),
|
||||
'light' => __('Light', WPALLSTARS_TEXT_DOMAIN),
|
||||
'blue' => __('Blue', WPALLSTARS_TEXT_DOMAIN),
|
||||
'coffee' => __('Coffee', WPALLSTARS_TEXT_DOMAIN),
|
||||
'ectoplasm' => __('Ectoplasm', WPALLSTARS_TEXT_DOMAIN),
|
||||
'midnight' => __('Midnight', WPALLSTARS_TEXT_DOMAIN),
|
||||
'ocean' => __('Ocean', WPALLSTARS_TEXT_DOMAIN),
|
||||
'sunrise' => __('Sunrise', WPALLSTARS_TEXT_DOMAIN),
|
||||
'modern' => __('Modern (WPAllstars)', WPALLSTARS_TEXT_DOMAIN),
|
||||
);
|
||||
|
||||
?>
|
||||
<select
|
||||
id="<?php echo esc_attr($field_id); ?>"
|
||||
name="<?php echo esc_attr(self::$option_name . '[' . $setting_key . ']'); ?>"
|
||||
class="wpallstars-ajax-save"
|
||||
data-setting-key="<?php echo esc_attr($setting_key); ?>"
|
||||
>
|
||||
<?php foreach ($color_schemes as $scheme_slug => $scheme_name) : ?>
|
||||
<option value="<?php echo esc_attr($scheme_slug); ?>" <?php selected($value, $scheme_slug); ?>>
|
||||
<?php echo esc_html($scheme_name); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<span class="wpallstars-ajax-feedback"></span> <!-- Feedback area for AJAX -->
|
||||
<p class="description">
|
||||
<?php esc_html_e('Select an admin color scheme. Changes are saved instantly.', WPALLSTARS_TEXT_DOMAIN); ?>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Simple Toggle example field.
|
||||
*/
|
||||
public static function render_simple_toggle_field() {
|
||||
$key = 'simple_toggle_example';
|
||||
$value = self::get_setting_value($key, 0);
|
||||
?>
|
||||
<div class="wp-setting-row">
|
||||
<div class="wp-setting-header">
|
||||
<div class="wp-setting-main">
|
||||
<div class="wp-setting-left">
|
||||
<div class="wp-toggle-switch">
|
||||
<input type="checkbox"
|
||||
id="wp_allstars_simple_setting"
|
||||
name="wp_allstars_simple_setting"
|
||||
id="<?php echo esc_attr(self::$option_name . '_' . $key); ?>"
|
||||
name="<?php echo esc_attr(self::$option_name . '[' . $key . ']'); ?>"
|
||||
value="1"
|
||||
<?php checked(get_option('wp_allstars_simple_setting', false)); ?>
|
||||
<?php checked($value, 1); ?>
|
||||
/>
|
||||
<span class="wp-toggle-slider"></span>
|
||||
</div>
|
||||
<label for="wp_allstars_simple_setting" class="wp-setting-label">
|
||||
<?php esc_html_e('Example: Simple Toggle', 'wp-allstars'); ?>
|
||||
<label for="<?php echo esc_attr(self::$option_name . '_' . $key); ?>" class="wp-setting-label">
|
||||
<?php // Label is provided by add_settings_field ?>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<p class="wp-setting-description">
|
||||
<?php esc_html_e('This is an example of a simple toggle setting without an expandable panel. Currently for demonstration purposes only.', 'wp-allstars'); ?>
|
||||
<p class="wp-setting-description description">
|
||||
<?php esc_html_e('This is an example of a simple toggle setting without an expandable panel. Currently for demonstration purposes only.', WPALLSTARS_TEXT_DOMAIN); ?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the advanced tab content
|
||||
* Render the Auto Upload toggle field.
|
||||
*/
|
||||
public static function display_advanced_tab() {
|
||||
public static function render_auto_upload_field() {
|
||||
$options = get_option(self::$option_name, array());
|
||||
$setting_key = 'auto_upload_enabled'; // Key in the options array
|
||||
$value = isset($options[$setting_key]) ? (bool) $options[$setting_key] : false; // Default to false
|
||||
$field_id = self::$option_name . '_' . $setting_key; // Unique ID for label 'for' attribute
|
||||
?>
|
||||
<label for="<?php echo esc_attr($field_id); ?>">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="<?php echo esc_attr($field_id); ?>"
|
||||
name="<?php echo esc_attr(self::$option_name . '[' . $setting_key . ']'); ?>"
|
||||
value="1"
|
||||
class="wpallstars-ajax-save"
|
||||
data-setting-key="<?php echo esc_attr($setting_key); ?>"
|
||||
<?php checked($value); ?>
|
||||
>
|
||||
<?php esc_html_e('Automatically upload external images referenced in post content on save.', WPALLSTARS_TEXT_DOMAIN); ?>
|
||||
</label>
|
||||
<span class="wpallstars-ajax-feedback"></span> <!-- Feedback area for AJAX -->
|
||||
<p class="description">
|
||||
<?php esc_html_e('When enabled, images from external URLs will be downloaded to the media library and their URLs updated in the post.', WPALLSTARS_TEXT_DOMAIN); ?><br>
|
||||
<em><?php esc_html_e('Note: This happens instantly when the checkbox is changed.', WPALLSTARS_TEXT_DOMAIN); ?></em>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Sync Guard toggle field.
|
||||
*/
|
||||
public static function render_sync_guard_field() {
|
||||
$key = 'sync_guard_enabled';
|
||||
$value = self::get_setting_value($key, 0);
|
||||
?>
|
||||
<div class="wp-allstars-settings-section">
|
||||
<div class="wp-allstars-settings-grid">
|
||||
<!-- Example of an expandable panel setting -->
|
||||
<div class="wp-allstars-toggle">
|
||||
<div class="wp-allstars-toggle-header" aria-expanded="false">
|
||||
<div class="wp-allstars-toggle-main">
|
||||
<div class="wp-allstars-toggle-left">
|
||||
<div class="wp-toggle-switch">
|
||||
<input type="checkbox"
|
||||
id="wp_allstars_auto_upload_images"
|
||||
name="wp_allstars_auto_upload_images"
|
||||
id="<?php echo esc_attr(self::$option_name . '_' . $key); ?>"
|
||||
name="<?php echo esc_attr(self::$option_name . '[' . $key . ']'); ?>"
|
||||
value="1"
|
||||
<?php checked(get_option('wp_allstars_auto_upload_images', false)); ?>
|
||||
<?php checked($value, 1); ?>
|
||||
/>
|
||||
<span class="wp-toggle-slider"></span>
|
||||
</div>
|
||||
<label for="wp_allstars_auto_upload_images">
|
||||
<?php esc_html_e('Example: Expandable Panel', 'wp-allstars'); ?>
|
||||
<label for="<?php echo esc_attr(self::$option_name . '_' . $key); ?>">
|
||||
<?php // Label provided by add_settings_field ?>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<p class="wp-setting-description">
|
||||
<?php esc_html_e('This is an example of an expandable panel setting. Currently for demonstration purposes only - no actual functionality.', 'wp-allstars'); ?>
|
||||
<p class="wp-setting-description description">
|
||||
<?php esc_html_e('Protect against data loss during simultaneous edits or synchronization.', WPALLSTARS_TEXT_DOMAIN); ?>
|
||||
</p>
|
||||
</div>
|
||||
<div class="wp-allstars-toggle-settings">
|
||||
<div class="wp-allstars-toggle-settings" style="display: none;">
|
||||
<div class="wp-allstars-setting-row">
|
||||
<label for="example_text"><?php esc_html_e('Example Text Field', 'wp-allstars'); ?></label>
|
||||
<input type="text"
|
||||
id="example_text"
|
||||
name="example_text"
|
||||
value="Example value"
|
||||
/>
|
||||
<p class="description"><?php esc_html_e('This is an example text field for demonstration purposes.', 'wp-allstars'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="description">
|
||||
<?php esc_html_e('When enabled, Sync Guard uses timestamps or locking mechanisms (depending on mode) to prevent multiple users or processes from overwriting each other\s changes, especially during sync operations like cloud storage or Git.', WPALLSTARS_TEXT_DOMAIN); ?>
|
||||
</p>
|
||||
<?php /* Add sub-settings for Sync Guard mode here */ ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings
|
||||
*/
|
||||
public static function save_settings() {
|
||||
// Check for nonce
|
||||
if (!isset($_POST['wp_allstars_settings_nonce']) || !wp_verify_nonce($_POST['wp_allstars_settings_nonce'], 'wp_allstars_save_settings')) {
|
||||
return;
|
||||
/* Removed the custom save_settings method as it's handled by the Settings API */
|
||||
// public static function save_settings() { ... }
|
||||
|
||||
}
|
||||
|
||||
// Save general settings
|
||||
update_option('wp_allstars_simple_setting', isset($_POST['wp_allstars_simple_setting']) ? 1 : 0);
|
||||
update_option('wp_allstars_admin_color_scheme', isset($_POST['wp_allstars_admin_color_scheme']) ? 1 : 0);
|
||||
|
||||
// Save advanced settings
|
||||
update_option('wp_allstars_auto_upload_images', isset($_POST['wp_allstars_auto_upload_images']) ? 1 : 0);
|
||||
|
||||
// Add settings saved notice
|
||||
add_settings_error('wp_allstars_settings', 'settings_updated', __('Settings saved.', 'wp-allstars'), 'updated');
|
||||
}
|
||||
}
|
||||
// --- Initialization ---
|
||||
// Assuming WPALLSTARS_Admin_Manager calls WPALLSTARS_Settings_Manager::init()
|
||||
// If not, uncomment the line below, but it's better practice to centralize initialization.
|
||||
// WPALLSTARS_Settings_Manager::init();
|
||||
|
||||
@@ -98,8 +98,8 @@ class WP_Allstars_Theme_Manager {
|
||||
private static function get_theme_scripts() {
|
||||
return '
|
||||
jQuery(document).ready(function($) {
|
||||
if ($("#wpa-theme-list").length) {
|
||||
var $container = $("#wpa-theme-list");
|
||||
if ($("#wpallstars-theme-list").length) {
|
||||
var $container = $("#wpallstars-theme-list");
|
||||
var $loadingOverlay = $container.find(".wp-allstars-loading-overlay");
|
||||
|
||||
// AJAX request to get themes
|
||||
@@ -139,7 +139,7 @@ class WP_Allstars_Theme_Manager {
|
||||
public static function display_tab_content() {
|
||||
?>
|
||||
<div class="wp-allstars-settings-content tab-content" id="theme">
|
||||
<div id="wpa-theme-list" class="wpa-theme-container">
|
||||
<div id="wpallstars-theme-list" class="wpallstars-theme-container">
|
||||
<!-- Theme content will be loaded via AJAX -->
|
||||
<div class="wp-allstars-loading-overlay">
|
||||
<span class="spinner is-active"></span>
|
||||
|
||||
@@ -38,7 +38,7 @@ class WP_Allstars_Tools_Manager {
|
||||
|
||||
// Add inline CSS for tools to match the single column layout
|
||||
$custom_css = '
|
||||
#tools .wpa-pro-plugins {
|
||||
#tools .wpallstars-pro-plugins {
|
||||
padding: 15px 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -46,7 +46,7 @@ class WP_Allstars_Tools_Manager {
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
#tools .wpa-pro-plugin {
|
||||
#tools .wpallstars-pro-plugin {
|
||||
background: #fff;
|
||||
border: 1px solid #ddd;
|
||||
padding: 24px;
|
||||
@@ -59,14 +59,14 @@ class WP_Allstars_Tools_Manager {
|
||||
margin-bottom: 24px;
|
||||
max-width: 100%;
|
||||
}
|
||||
#tools .wpa-pro-plugin:last-child {
|
||||
#tools .wpallstars-pro-plugin:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#tools .wpa-pro-plugin:hover {
|
||||
#tools .wpallstars-pro-plugin:hover {
|
||||
border-color: #2271b1;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
||||
}
|
||||
#tools .wpa-pro-plugin .button-group {
|
||||
#tools .wpallstars-pro-plugin .button-group {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
';
|
||||
@@ -96,7 +96,7 @@ class WP_Allstars_Tools_Manager {
|
||||
|
||||
?>
|
||||
<div class="wp-allstars-settings-content tab-content" id="tools">
|
||||
<div class="wpa-pro-plugins">
|
||||
<div class="wpallstars-pro-plugins">
|
||||
<?php
|
||||
foreach ($tools as $tool) {
|
||||
self::display_tool_card(self::sanitize_tool_data($tool));
|
||||
@@ -118,7 +118,7 @@ class WP_Allstars_Tools_Manager {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="wpa-pro-plugin">
|
||||
<div class="wpallstars-pro-plugin">
|
||||
<h3><?php echo esc_html($tool['name']); ?></h3>
|
||||
|
||||
<?php if (!empty($tool['description'])): ?>
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* WP Allstars Admin Script
|
||||
*
|
||||
* Handles UI interactions in the admin settings
|
||||
*/
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
// Document ready handler
|
||||
$(document).ready(function() {
|
||||
// Handle toggle switches
|
||||
$('.wp-toggle-switch input[type="checkbox"]').on('change', function() {
|
||||
var $this = $(this);
|
||||
var option = $this.attr('id');
|
||||
var value = $this.is(':checked') ? 1 : 0;
|
||||
|
||||
// Don't handle the admin color scheme toggle here - it has its own handler
|
||||
if (option === 'wp_allstars_admin_color_scheme') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Show update notification
|
||||
var $notification = $this.closest('label').find('.wp-setting-notification');
|
||||
if ($notification.length === 0) {
|
||||
$notification = $('<span class="wp-setting-notification">Saving...</span>');
|
||||
$this.closest('label').append($notification);
|
||||
} else {
|
||||
$notification.text('Saving...').removeClass('error').show();
|
||||
}
|
||||
|
||||
// Save the option via AJAX
|
||||
$.ajax({
|
||||
url: wpAllstars.ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wp_allstars_update_option',
|
||||
nonce: wpAllstars.nonce,
|
||||
option: option,
|
||||
value: value
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
$notification.text('Saved!');
|
||||
setTimeout(function() {
|
||||
$notification.fadeOut(300);
|
||||
}, 2000);
|
||||
} else {
|
||||
$notification.text('Error').addClass('error');
|
||||
console.error('Error saving option:', response.data);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$notification.text('Error').addClass('error');
|
||||
console.error('AJAX error:', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Toggle expandable panels
|
||||
$('.wp-allstars-toggle-header').on('click', function() {
|
||||
var $this = $(this);
|
||||
var $settings = $this.next('.wp-allstars-toggle-settings');
|
||||
var isExpanded = $this.attr('aria-expanded') === 'true';
|
||||
|
||||
// Toggle aria-expanded attribute
|
||||
$this.attr('aria-expanded', !isExpanded);
|
||||
|
||||
// Toggle settings visibility
|
||||
$settings.slideToggle(200);
|
||||
});
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* WP Allstars Admin Script
|
||||
*
|
||||
* Handles generic UI interactions in the admin settings page.
|
||||
* Specific AJAX handlers for themes/plugins are handled in inline scripts
|
||||
* loaded by their respective managers.
|
||||
*/
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
// --- General UI Enhancements ---
|
||||
|
||||
// Toggle expandable sections/panels (using consistent class names)
|
||||
$('.wpallstars-toggle-header').on('click', function() {
|
||||
var $this = $(this);
|
||||
var $content = $this.next('.wpallstars-toggle-content'); // Use a consistent content class
|
||||
var isExpanded = $this.attr('aria-expanded') === 'true';
|
||||
|
||||
// Toggle ARIA attribute for accessibility
|
||||
$this.attr('aria-expanded', !isExpanded);
|
||||
|
||||
// Toggle content visibility with animation
|
||||
$content.slideToggle(200);
|
||||
|
||||
// Optional: Toggle an icon class on the header (e.g., dashicons-arrow-down / dashicons-arrow-up)
|
||||
$this.find('.dashicons').toggleClass('dashicons-arrow-down dashicons-arrow-up');
|
||||
});
|
||||
|
||||
// Initialize state for expandable sections (ensure icons are correct on load)
|
||||
$('.wpallstars-toggle-header').each(function() {
|
||||
var $this = $(this);
|
||||
var isExpanded = $this.attr('aria-expanded') === 'true';
|
||||
if (isExpanded) {
|
||||
$this.find('.dashicons').removeClass('dashicons-arrow-down').addClass('dashicons-arrow-up');
|
||||
$this.next('.wpallstars-toggle-content').show();
|
||||
} else {
|
||||
$this.find('.dashicons').removeClass('dashicons-arrow-up').addClass('dashicons-arrow-down');
|
||||
$this.next('.wpallstars-toggle-content').hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// --- Settings Save Logic (Example for simple toggles/inputs via AJAX) ---
|
||||
|
||||
// AJAX saving for specific settings (e.g., checkboxes, selects)
|
||||
// Add the class 'wpallstars-ajax-save' and 'data-setting-key="your_key"' to the input elements
|
||||
$('.wpallstars-settings-wrap').on('change', 'input.wpallstars-ajax-save, select.wpallstars-ajax-save', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const $input = $(this);
|
||||
const settingKey = $input.data('setting-key'); // Get key from data attribute
|
||||
let settingValue;
|
||||
|
||||
// Determine the value based on input type
|
||||
if ($input.is(':checkbox')) {
|
||||
settingValue = $input.is(':checked'); // Send true/false
|
||||
} else {
|
||||
settingValue = $input.val(); // Get value from select or other inputs
|
||||
}
|
||||
|
||||
// Find the feedback element (could be next to the input, or a general area)
|
||||
let $feedback = $input.siblings('.wpallstars-ajax-feedback');
|
||||
if (!$feedback.length) {
|
||||
// Fallback to a general feedback area if specific one not found
|
||||
$feedback = $input.closest('td, p, div').find('.wpallstars-ajax-feedback');
|
||||
if (!$feedback.length) {
|
||||
// If still no feedback area, maybe create one dynamically or log error
|
||||
console.error('WPAllstars: Feedback element not found for AJAX save.', $input);
|
||||
return; // Stop if no feedback area
|
||||
}
|
||||
}
|
||||
|
||||
// Check if settingKey is valid
|
||||
if (!settingKey) {
|
||||
console.error('WPAllstars: Missing data-setting-key attribute for AJAX save.', $input);
|
||||
$feedback.removeClass('spinner success is-active').addClass('error').text('Error: Missing setting key.').show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Show spinner/updating message
|
||||
if ($feedback.hasClass('spinner')) {
|
||||
// If it's already designed as a spinner container
|
||||
$feedback.removeClass('success error').addClass('is-active').show();
|
||||
// Optionally add text: $feedback.text(wpallstars.l10n.updating || 'Updating...');
|
||||
} else {
|
||||
$feedback.removeClass('success error').addClass('spinner is-active').text(wpallstars.l10n.updating || 'Updating...').show();
|
||||
}
|
||||
|
||||
// Use localized strings and the specific nonce
|
||||
// $feedback.text(wpallstars.l10n.updating || 'Updating...'); // Moved spinner text above
|
||||
|
||||
|
||||
// Perform AJAX request
|
||||
$.ajax({
|
||||
url: wpallstars.ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wpallstars_update_option', // The action hook in WPALLSTARS_Admin_Manager
|
||||
nonce: wpallstars.update_option_nonce, // Use the specific nonce
|
||||
setting_key: settingKey, // Send the setting key
|
||||
setting_value: settingValue // Send the setting value
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
$feedback.removeClass('spinner is-active error').addClass('success').text(response.data || wpallstars.l10n.success || 'Saved!');
|
||||
// Optionally fade out the success message after a delay
|
||||
setTimeout(function() {
|
||||
// $feedback.fadeOut();
|
||||
// Or just remove the text/class if element should stay
|
||||
$feedback.removeClass('success').text('');
|
||||
}, 3000);
|
||||
} else {
|
||||
const errorMessage = response.data || wpallstars.l10n.error || 'Error';
|
||||
$feedback.removeClass('spinner is-active success').addClass('error').text(errorMessage);
|
||||
console.error('WPAllstars AJAX Error:', response.data);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
$feedback.removeClass('spinner is-active success').addClass('error').text(wpallstars.l10n.error || 'Error');
|
||||
console.error('WPAllstars AJAX Request Failed:', textStatus, errorThrown);
|
||||
},
|
||||
// Removed complete: function() { ... } as feedback is handled in success/error
|
||||
});
|
||||
});
|
||||
|
||||
// --- Tab Handling ---
|
||||
// Basic tab switching is handled by WordPress core CSS (.nav-tab-active) and page reloads.
|
||||
// If you need AJAX tab loading in the future, implement it here.
|
||||
|
||||
// --- Initialization ---
|
||||
// Add any code that needs to run on page load after elements are ready.
|
||||
// Example: Initialize color pickers if added via WPALLSTARS_Settings_Manager
|
||||
|
||||
|
||||
}); // End document ready
|
||||
|
||||
})(jQuery);
|
||||
@@ -1,169 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WP ALLSTARS Admin Colors Feature
|
||||
*
|
||||
* Handles setting the admin color scheme based on user preferences
|
||||
*
|
||||
* @package WP_ALLSTARS
|
||||
* @since 0.2.3.1
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin Colors Handler Class
|
||||
*/
|
||||
class WP_Allstars_Admin_Colors {
|
||||
|
||||
/**
|
||||
* Option name for the admin color scheme setting
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $option_name = 'wp_allstars_admin_color_scheme';
|
||||
|
||||
/**
|
||||
* Modern color scheme key
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $modern_scheme = 'modern';
|
||||
|
||||
/**
|
||||
* Default color scheme key
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $default_scheme = 'fresh';
|
||||
|
||||
/**
|
||||
* Initialize the class and set up hooks
|
||||
*/
|
||||
public function __construct() {
|
||||
// Set up hooks
|
||||
add_action('admin_init', array($this, 'set_admin_color_scheme'));
|
||||
add_action('wp_ajax_wp_allstars_update_color_scheme', array($this, 'handle_color_scheme_update'));
|
||||
|
||||
// Add script to handle the toggle
|
||||
add_action('admin_enqueue_scripts', array($this, 'enqueue_color_scripts'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts and styles for the color scheme toggle
|
||||
*/
|
||||
public function enqueue_color_scripts() {
|
||||
// Only enqueue on our plugin pages
|
||||
$screen = get_current_screen();
|
||||
if (!isset($screen->id) || strpos($screen->id, 'wp-allstars') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_script(
|
||||
'wp-allstars-color-toggle',
|
||||
plugin_dir_url(dirname(__FILE__)) . 'admin/js/wp-allstars-admin-colors.js',
|
||||
array('jquery'),
|
||||
WP_ALLSTARS_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script('wp-allstars-color-toggle', 'wpAllstarsColors', array(
|
||||
'ajax_url' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce('wp_allstars_color_nonce'),
|
||||
'option_name' => $this->option_name,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the admin color scheme based on user preference
|
||||
*/
|
||||
public function set_admin_color_scheme() {
|
||||
// Only apply for administrators
|
||||
if (!current_user_can('manage_options')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current user
|
||||
$user_id = get_current_user_id();
|
||||
if (!$user_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if our option is enabled
|
||||
$enable_modern = get_option($this->option_name, false);
|
||||
|
||||
// Set the appropriate color scheme
|
||||
if ($enable_modern) {
|
||||
// Use modern scheme if available, otherwise use default
|
||||
$this->set_user_color_scheme($user_id, $this->modern_scheme);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a user's color scheme
|
||||
*
|
||||
* @param int $user_id The user ID
|
||||
* @param string $scheme The color scheme to set
|
||||
*/
|
||||
private function set_user_color_scheme($user_id, $scheme) {
|
||||
// Check if the scheme exists
|
||||
global $_wp_admin_css_colors;
|
||||
|
||||
// If the scheme doesn't exist, use the default
|
||||
if (!isset($_wp_admin_css_colors[$scheme])) {
|
||||
$scheme = $this->default_scheme;
|
||||
}
|
||||
|
||||
// Update the user's color scheme
|
||||
update_user_meta($user_id, 'admin_color', $scheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle AJAX request to update color scheme
|
||||
*/
|
||||
public function handle_color_scheme_update() {
|
||||
// Verify nonce
|
||||
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'wp_allstars_color_nonce')) {
|
||||
wp_send_json_error('Invalid nonce');
|
||||
}
|
||||
|
||||
// Verify user can manage options
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error('Insufficient permissions');
|
||||
}
|
||||
|
||||
// Get the new value
|
||||
$enabled = isset($_POST['enabled']) ? (bool) $_POST['enabled'] : false;
|
||||
|
||||
// Update the option
|
||||
update_option($this->option_name, $enabled);
|
||||
|
||||
// Get current user
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
// Set the color scheme
|
||||
if ($enabled) {
|
||||
$this->set_user_color_scheme($user_id, $this->modern_scheme);
|
||||
$message = 'Modern admin colors enabled';
|
||||
} else {
|
||||
$this->set_user_color_scheme($user_id, $this->default_scheme);
|
||||
$message = 'Default admin colors restored';
|
||||
}
|
||||
|
||||
// Send success response
|
||||
wp_send_json_success(array(
|
||||
'message' => $message,
|
||||
'enabled' => $enabled,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if modern color scheme is enabled
|
||||
*
|
||||
* @return bool Whether modern color scheme is enabled
|
||||
*/
|
||||
public function is_modern_color_scheme_enabled() {
|
||||
return (bool) get_option($this->option_name, false);
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Auto Upload Images functionality
|
||||
*
|
||||
* @package WP_ALLSTARS
|
||||
* @since 0.2.0
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class WP_Allstars_Auto_Upload {
|
||||
/**
|
||||
* Initialize the class
|
||||
*/
|
||||
public function __construct() {
|
||||
add_filter('content_save_pre', array($this, 'process_content'));
|
||||
add_action('wp_allstars_image_upload_error', array($this, 'log_error'), 10, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process content for external images
|
||||
*
|
||||
* @param string $content The post content
|
||||
* @return string Modified content with local image URLs
|
||||
*/
|
||||
public function process_content($content) {
|
||||
// Check if auto upload is enabled
|
||||
$options = get_option('wp_allstars_workflow_options', array('auto_upload_images' => false));
|
||||
if (!$options['auto_upload_images']) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
// Regular expression to find image URLs
|
||||
$pattern = '/<img[^>]+src=[\'"]([^\'"]+)[\'"][^>]*>/i';
|
||||
|
||||
return preg_replace_callback($pattern, array($this, 'process_image_url'), $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process individual image URL
|
||||
*
|
||||
* @param array $matches Regex matches
|
||||
* @return string Updated img tag
|
||||
*/
|
||||
private function process_image_url($matches) {
|
||||
if (empty($matches[1])) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
$url = $matches[1];
|
||||
|
||||
// Skip if already a local URL
|
||||
if ($this->is_local_url($url)) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
try {
|
||||
$local_url = $this->upload_image($url);
|
||||
if ($local_url) {
|
||||
return str_replace($url, $local_url, $matches[0]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Trigger error action for logging
|
||||
do_action('wp_allstars_image_upload_error', esc_url($url), $e->getMessage());
|
||||
}
|
||||
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if URL is local
|
||||
*
|
||||
* @param string $url URL to check
|
||||
* @return boolean
|
||||
*/
|
||||
private function is_local_url($url) {
|
||||
$site_url = parse_url(get_site_url(), PHP_URL_HOST);
|
||||
$image_host = parse_url($url, PHP_URL_HOST);
|
||||
return $site_url === $image_host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload external image to media library
|
||||
*
|
||||
* @param string $url External image URL
|
||||
* @return string|false Local URL on success, false on failure
|
||||
* @throws Exception If download or upload fails
|
||||
*/
|
||||
private function upload_image($url) {
|
||||
$file_array = array(
|
||||
'name' => sanitize_file_name(basename($url))
|
||||
);
|
||||
|
||||
// Download file to temp location
|
||||
$file_array['tmp_name'] = download_url($url);
|
||||
|
||||
if (is_wp_error($file_array['tmp_name'])) {
|
||||
throw new Exception('Failed to download image: ' . $file_array['tmp_name']->get_error_message());
|
||||
}
|
||||
|
||||
// Check file type for security
|
||||
$wp_filetype = wp_check_filetype_and_ext($file_array['tmp_name'], $file_array['name']);
|
||||
if (!$wp_filetype['type']) {
|
||||
unlink($file_array['tmp_name']);
|
||||
throw new Exception('Invalid file type');
|
||||
}
|
||||
|
||||
// Upload the file to media library
|
||||
$attachment_id = media_handle_sideload($file_array, 0);
|
||||
|
||||
if (is_wp_error($attachment_id)) {
|
||||
unlink($file_array['tmp_name']);
|
||||
throw new Exception('Failed to upload image: ' . $attachment_id->get_error_message());
|
||||
}
|
||||
|
||||
return wp_get_attachment_url($attachment_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log errors to WordPress debug log
|
||||
*
|
||||
* @param string $url URL that failed
|
||||
* @param string $error Error message
|
||||
*/
|
||||
public function log_error($url, $error) {
|
||||
if (WP_DEBUG) {
|
||||
error_log(sprintf(
|
||||
'[WP ALLSTARS] Auto Upload Images Error - URL: %s, Error: %s',
|
||||
esc_url_raw($url),
|
||||
sanitize_text_field($error)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WP ALLSTARS Sync Guard
|
||||
*
|
||||
* Prevents plugin loading during sync operations to avoid fatal errors.
|
||||
*
|
||||
* @package WP_ALLSTARS
|
||||
* @since 0.2.3.1
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class responsible for detecting sync operations and preventing plugin loading
|
||||
*/
|
||||
class WP_Allstars_Sync_Guard {
|
||||
|
||||
/**
|
||||
* Flag file name for sync operations
|
||||
*/
|
||||
const SYNC_FLAG_FILE = '.syncing';
|
||||
|
||||
/**
|
||||
* Check if sync is in progress
|
||||
*
|
||||
* @return bool Whether sync is in progress
|
||||
*/
|
||||
public static function is_sync_in_progress() {
|
||||
$flag_file = plugin_dir_path(dirname(__FILE__)) . self::SYNC_FLAG_FILE;
|
||||
return file_exists($flag_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle sync mode by showing admin notice and preventing plugin loading
|
||||
*
|
||||
* @return bool True if sync is in progress, false otherwise
|
||||
*/
|
||||
public static function handle_sync_mode() {
|
||||
if (self::is_sync_in_progress()) {
|
||||
// Add admin notice
|
||||
add_action('admin_notices', array(__CLASS__, 'display_sync_notice'));
|
||||
|
||||
// Return true to indicate plugin should not continue loading
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display sync in progress notice
|
||||
*/
|
||||
public static function display_sync_notice() {
|
||||
echo '<div class="notice notice-warning is-dismissible">';
|
||||
echo '<p><strong>WP Allstars:</strong> Plugin files are currently syncing. The plugin functionality is temporarily disabled to prevent errors. Please try again in a moment.</p>';
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
@@ -1,330 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Allstars UI Enhancements
|
||||
*
|
||||
* Responsible for enhancing the WordPress admin interface with improved UI components
|
||||
* like cards, panels, buttons, and responsive design elements.
|
||||
*
|
||||
* @package WP_ALLSTARS
|
||||
* @version v0.2.3.3
|
||||
*/
|
||||
|
||||
if (!defined('WPINC')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class WP_Allstars_UI_Enhancements {
|
||||
/**
|
||||
* Constructor
|
||||
* Initialize hooks and settings
|
||||
*/
|
||||
public function __construct() {
|
||||
// Register scripts and styles
|
||||
add_action('admin_enqueue_scripts', array($this, 'enqueue_assets'));
|
||||
|
||||
// Add body class for enhanced UI
|
||||
add_filter('admin_body_class', array($this, 'add_body_class'));
|
||||
|
||||
// Initialize UI components
|
||||
$this->init_components();
|
||||
|
||||
// Ensure toggle functionality works
|
||||
add_action('admin_footer', array($this, 'ensure_toggle_functionality'), 99);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue CSS and JavaScript assets
|
||||
*/
|
||||
public function enqueue_assets($hook) {
|
||||
// Only load on WP Allstars pages
|
||||
if (strpos($hook, 'wp-allstars') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Already registered in main plugin file, but ensure they're enqueued
|
||||
wp_enqueue_style('wp-allstars-admin');
|
||||
wp_enqueue_script('wp-allstars-admin');
|
||||
|
||||
// Add UI enhancements script
|
||||
wp_enqueue_script(
|
||||
'wp-allstars-ui-enhancements',
|
||||
plugin_dir_url(dirname(__FILE__)) . 'admin/js/wp-allstars-ui-enhancements.js',
|
||||
array('jquery', 'wp-allstars-admin'),
|
||||
WP_ALLSTARS_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
// Add enhanced UI styles
|
||||
wp_enqueue_style(
|
||||
'wp-allstars-ui-enhancements',
|
||||
plugin_dir_url(dirname(__FILE__)) . 'admin/css/wp-allstars-ui-enhancements.css',
|
||||
array('wp-allstars-admin'),
|
||||
WP_ALLSTARS_VERSION
|
||||
);
|
||||
|
||||
// Localize script with settings
|
||||
wp_localize_script('wp-allstars-ui-enhancements', 'wpAllstarsUI', array(
|
||||
'ajaxurl' => admin_url('ajax.php'),
|
||||
'nonce' => wp_create_nonce('wp_allstars_ui_nonce'),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add body class for enhanced UI
|
||||
*/
|
||||
public function add_body_class($classes) {
|
||||
if (isset($_GET['page']) && strpos($_GET['page'], 'wp-allstars') !== false) {
|
||||
$classes .= ' wp-allstars-enhanced-ui';
|
||||
}
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize UI components
|
||||
*/
|
||||
private function init_components() {
|
||||
// Add accordion functionality
|
||||
add_action('admin_footer', array($this, 'render_accordion_template'));
|
||||
|
||||
// Add card component
|
||||
add_action('admin_footer', array($this, 'render_card_template'));
|
||||
|
||||
// Add notification system
|
||||
add_action('admin_footer', array($this, 'render_notification_template'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure toggle switch functionality
|
||||
* This adds JS to reinitialize toggle switch handlers after our enhanced UI is applied
|
||||
*/
|
||||
public function ensure_toggle_functionality() {
|
||||
// Only on WP Allstars pages
|
||||
if (!isset($_GET['page']) || strpos($_GET['page'], 'wp-allstars') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the nonce value
|
||||
$nonce = wp_create_nonce('wp-allstars-nonce');
|
||||
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
jQuery(document).ready(function($) {
|
||||
// Make sure the wpAllstars object is available
|
||||
if (typeof wpAllstars === 'undefined') {
|
||||
window.wpAllstars = {
|
||||
ajaxurl: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
|
||||
nonce: '<?php echo esc_js($nonce); ?>'
|
||||
};
|
||||
}
|
||||
|
||||
// Remove any existing handlers first to prevent duplicates
|
||||
$('.wp-toggle-switch input[type="checkbox"]').off('change');
|
||||
$('.wp-allstars-toggle-header').off('click');
|
||||
|
||||
// Re-bind toggle switch handlers
|
||||
$('.wp-toggle-switch input[type="checkbox"]').on('change', function() {
|
||||
console.log('Toggle switch changed:', this.id);
|
||||
var $this = $(this);
|
||||
var option = $this.attr('id');
|
||||
var value = $this.is(':checked') ? 1 : 0;
|
||||
|
||||
// Don't handle the admin color scheme toggle here - it has its own handler
|
||||
if (option === 'wp_allstars_admin_color_scheme') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Show update notification
|
||||
var $notification = $this.closest('.wp-setting-left').find('.wp-setting-notification');
|
||||
if ($notification.length === 0) {
|
||||
$notification = $('<span class="wp-setting-notification">Saving...</span>');
|
||||
$this.closest('.wp-setting-left').append($notification);
|
||||
} else {
|
||||
$notification.text('Saving...').removeClass('error').show();
|
||||
}
|
||||
|
||||
// Save the option via AJAX
|
||||
$.ajax({
|
||||
url: wpAllstars.ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wp_allstars_update_option',
|
||||
nonce: wpAllstars.nonce,
|
||||
option: option,
|
||||
value: value
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
$notification.text('Saved!');
|
||||
setTimeout(function() {
|
||||
$notification.fadeOut(300);
|
||||
}, 2000);
|
||||
} else {
|
||||
$notification.text('Error').addClass('error');
|
||||
console.error('Error saving option:', response.data);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$notification.text('Error').addClass('error');
|
||||
console.error('AJAX error:', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Re-bind expandable panels
|
||||
$('.wp-allstars-toggle-header').on('click', function() {
|
||||
var $this = $(this);
|
||||
var $settings = $this.next('.wp-allstars-toggle-settings');
|
||||
var isExpanded = $this.attr('aria-expanded') === 'true';
|
||||
|
||||
// Toggle aria-expanded attribute
|
||||
$this.attr('aria-expanded', !isExpanded);
|
||||
|
||||
// Toggle settings visibility
|
||||
$settings.slideToggle(200);
|
||||
});
|
||||
|
||||
// Special handling for admin color scheme toggle if exists
|
||||
if (typeof wpAllstarsColors !== 'undefined') {
|
||||
var $colorToggle = $('#wp_allstars_admin_color_scheme');
|
||||
if ($colorToggle.length) {
|
||||
$colorToggle.off('change').on('change', function() {
|
||||
var isModern = $(this).is(':checked');
|
||||
|
||||
// Show saving notification
|
||||
var $notification = $colorToggle.closest('.wp-setting-left').find('.wp-setting-notification');
|
||||
if ($notification.length === 0) {
|
||||
$notification = $('<span class="wp-setting-notification">Saving...</span>');
|
||||
$colorToggle.closest('.wp-setting-left').append($notification);
|
||||
} else {
|
||||
$notification.text('Saving...').removeClass('error').show();
|
||||
}
|
||||
|
||||
// Save the option via AJAX
|
||||
$.ajax({
|
||||
url: wpAllstarsColors.ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'wp_allstars_update_color_scheme',
|
||||
nonce: wpAllstarsColors.nonce,
|
||||
is_modern: isModern ? 1 : 0
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
if (isModern) {
|
||||
$('body').addClass('wp-allstars-modern-admin');
|
||||
} else {
|
||||
$('body').removeClass('wp-allstars-modern-admin');
|
||||
}
|
||||
|
||||
$notification.text('Saved!');
|
||||
setTimeout(function() {
|
||||
$notification.fadeOut(300);
|
||||
}, 2000);
|
||||
} else {
|
||||
$notification.text('Error').addClass('error');
|
||||
console.error('Error updating color scheme:', response.data);
|
||||
|
||||
// Revert toggle
|
||||
$colorToggle.prop('checked', !isModern);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$notification.text('Error').addClass('error');
|
||||
console.error('AJAX error:', error);
|
||||
|
||||
// Revert toggle
|
||||
$colorToggle.prop('checked', !isModern);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render accordion template
|
||||
*/
|
||||
public function render_accordion_template() {
|
||||
// Only on WP Allstars pages
|
||||
if (!isset($_GET['page']) || strpos($_GET['page'], 'wp-allstars') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<script type="text/html" id="tmpl-wp-allstars-accordion">
|
||||
<div class="wp-allstars-accordion" role="tablist">
|
||||
<div class="wp-allstars-accordion-header" role="tab" id="accordion-header-{{data.id}}" aria-expanded="false">
|
||||
<div class="wp-allstars-accordion-title">{{data.title}}</div>
|
||||
<div class="wp-allstars-accordion-icon"></div>
|
||||
</div>
|
||||
<div class="wp-allstars-accordion-content" role="tabpanel" aria-labelledby="accordion-header-{{data.id}}">
|
||||
<div class="wp-allstars-accordion-inner">
|
||||
{{{data.content}}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render card template
|
||||
*/
|
||||
public function render_card_template() {
|
||||
// Only on WP Allstars pages
|
||||
if (!isset($_GET['page']) || strpos($_GET['page'], 'wp-allstars') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<script type="text/html" id="tmpl-wp-allstars-card">
|
||||
<div class="wp-allstars-card">
|
||||
<# if (data.header) { #>
|
||||
<div class="wp-allstars-card-header">
|
||||
<# if (data.icon) { #>
|
||||
<div class="wp-allstars-card-icon">{{{data.icon}}}</div>
|
||||
<# } #>
|
||||
<div class="wp-allstars-card-title">{{data.header}}</div>
|
||||
</div>
|
||||
<# } #>
|
||||
<div class="wp-allstars-card-content">
|
||||
{{{data.content}}}
|
||||
</div>
|
||||
<# if (data.footer) { #>
|
||||
<div class="wp-allstars-card-footer">
|
||||
{{{data.footer}}}
|
||||
</div>
|
||||
<# } #>
|
||||
</div>
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render notification template
|
||||
*/
|
||||
public function render_notification_template() {
|
||||
// Only on WP Allstars pages
|
||||
if (!isset($_GET['page']) || strpos($_GET['page'], 'wp-allstars') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<script type="text/html" id="tmpl-wp-allstars-notification">
|
||||
<div class="wp-allstars-notification wp-allstars-notification-{{data.type}}">
|
||||
<div class="wp-allstars-notification-icon"></div>
|
||||
<div class="wp-allstars-notification-content">
|
||||
<# if (data.title) { #>
|
||||
<div class="wp-allstars-notification-title">{{data.title}}</div>
|
||||
<# } #>
|
||||
<div class="wp-allstars-notification-message">{{data.message}}</div>
|
||||
</div>
|
||||
<div class="wp-allstars-notification-dismiss"></div>
|
||||
</div>
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
/**
|
||||
* WPALLSTARS Admin Colors Feature
|
||||
*
|
||||
* Manages the admin color scheme override, allowing users to toggle between
|
||||
* the default WordPress scheme and a custom 'modern' scheme provided by the plugin.
|
||||
*
|
||||
* @package WPALLSTARS
|
||||
* @subpackage Core
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Class WPALLSTARS_Admin_Colors
|
||||
*
|
||||
* Handles the registration, application, and AJAX updates for the admin color scheme setting.
|
||||
*/
|
||||
class WPALLSTARS_Admin_Colors {
|
||||
|
||||
/**
|
||||
* Option key stored in wp_options table for the toggle setting.
|
||||
* Uses 'wpallstars_options' array with a specific key for better organization.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $options_key = 'wpallstars_options';
|
||||
|
||||
/**
|
||||
* Specific key within the options array for the color scheme setting.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $color_scheme_option_key = 'admin_color_scheme_enabled'; // Matches setting registration
|
||||
|
||||
/**
|
||||
* The slug/key for the custom 'modern' color scheme.
|
||||
* Assumes this scheme is registered elsewhere (e.g., via wp_admin_css_color).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $modern_scheme_slug = 'modern'; // Ensure this matches registration
|
||||
|
||||
/**
|
||||
* The slug/key for the default WordPress color scheme ('fresh').
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $default_scheme_slug = 'fresh';
|
||||
|
||||
/**
|
||||
* Nonce action name for security checks in AJAX handler.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $ajax_nonce_action = 'wpallstars_update_color_scheme_nonce'; // More specific nonce
|
||||
|
||||
/**
|
||||
* Initialize the class and set up WordPress hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
// Hook into admin initialization to potentially apply the scheme.
|
||||
add_action('admin_init', array($this, 'apply_user_admin_color_scheme'), 10); // Priority 10 is standard
|
||||
|
||||
// Hook into AJAX action for updating the color scheme setting.
|
||||
add_action('wp_ajax_wpallstars_update_admin_color_scheme', array($this, 'handle_ajax_color_scheme_update'));
|
||||
|
||||
// Hook to enqueue scripts specifically for the color scheme toggle functionality.
|
||||
// Note: This assumes the toggle appears on WP Allstars admin pages.
|
||||
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_color_scripts'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue JavaScript and localize data for the color scheme toggle.
|
||||
*
|
||||
* Only enqueues scripts on admin pages related to WP Allstars.
|
||||
*
|
||||
* @param string $hook_suffix The hook suffix of the current admin page.
|
||||
*/
|
||||
public function enqueue_admin_color_scripts($hook_suffix) {
|
||||
// Use a more robust check for WP Allstars pages (using the registered page hook)
|
||||
$wpallstars_pages = [
|
||||
'toplevel_page_wpallstars-settings', // Example for top-level page
|
||||
'wpallstars_page_wpallstars-settings-network', // Example for network admin
|
||||
// Add other WP Allstars page slugs as needed
|
||||
];
|
||||
// If using Admin_Manager, get the registered page hook slug.
|
||||
// For now, keep the simpler check, but ideally use the actual hook.
|
||||
$screen = get_current_screen();
|
||||
if (!$screen || strpos($screen->id, 'wpallstars') === false) {
|
||||
return; // Exit if not a WP Allstars page.
|
||||
}
|
||||
|
||||
|
||||
// Enqueue the specific JS file for color handling.
|
||||
wp_enqueue_script(
|
||||
'wpallstars-admin-colors-script', // More specific handle
|
||||
WPALLSTARS_URL . 'admin/js/wpallstars-admin-colors.js', // Use constant for URL
|
||||
array('jquery'),
|
||||
WPALLSTARS_VERSION, // Use constant for version
|
||||
true // Load in footer
|
||||
);
|
||||
|
||||
// Localize data needed by the script.
|
||||
wp_localize_script(
|
||||
'wpallstars-admin-colors-script', // Must match the script handle
|
||||
'wpallstarsAdminColorsData', // JavaScript object name
|
||||
array(
|
||||
'ajax_url' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce($this->ajax_nonce_action),
|
||||
'ajax_action' => 'wpallstars_update_admin_color_scheme', // The action hook name
|
||||
'l10n' => [ // Localization strings
|
||||
'saving' => __('Saving...', WPALLSTARS_TEXT_DOMAIN),
|
||||
'saved' => __('Saved', WPALLSTARS_TEXT_DOMAIN),
|
||||
'error' => __('Error', WPALLSTARS_TEXT_DOMAIN),
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the selected admin color scheme for the current user upon admin initialization.
|
||||
*
|
||||
* Checks if the user has the capability and if the setting is enabled.
|
||||
*/
|
||||
public function apply_user_admin_color_scheme() {
|
||||
// Ensure the current user has the capability to change schemes (usually 'manage_options' or similar).
|
||||
if (!current_user_can('manage_options')) { // Adjust capability if needed
|
||||
return;
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
if (!$user_id) {
|
||||
return; // Should not happen in admin_init, but good practice.
|
||||
}
|
||||
|
||||
// Check if the modern scheme override is enabled in settings.
|
||||
$scheme_to_apply = $this->is_modern_color_scheme_enabled()
|
||||
? $this->modern_scheme_slug
|
||||
: $this->default_scheme_slug;
|
||||
|
||||
// Get the user's currently saved color scheme preference.
|
||||
$current_user_scheme = get_user_meta($user_id, 'admin_color', true);
|
||||
|
||||
// Only update the user's meta if the desired scheme differs from their current one.
|
||||
// This prevents unnecessary database writes on every admin page load.
|
||||
if ($current_user_scheme !== $scheme_to_apply) {
|
||||
$this->update_user_color_scheme_preference($user_id, $scheme_to_apply);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a user's color scheme preference in their user meta.
|
||||
*
|
||||
* @param int $user_id The ID of the user to update.
|
||||
* @param string $scheme_slug The slug of the color scheme to set (e.g., 'modern', 'fresh').
|
||||
*/
|
||||
private function update_user_color_scheme_preference($user_id, $scheme_slug) {
|
||||
// WordPress handles validation internally, but ensure the scheme exists if crucial.
|
||||
// global $_wp_admin_css_colors;
|
||||
// if (!isset($_wp_admin_css_colors[$scheme_slug])) {
|
||||
// $scheme_slug = $this->default_scheme_slug; // Fallback to default
|
||||
// }
|
||||
|
||||
// Update the 'admin_color' user meta field.
|
||||
update_user_meta($user_id, 'admin_color', $scheme_slug);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the AJAX request to enable/disable the modern color scheme override.
|
||||
*
|
||||
* Verifies nonce, checks user capabilities, updates the option,
|
||||
* updates the current user's scheme immediately, and sends a JSON response.
|
||||
*/
|
||||
public function handle_ajax_color_scheme_update() {
|
||||
// 1. Verify Nonce for security.
|
||||
check_ajax_referer($this->ajax_nonce_action, 'nonce'); // Dies on failure
|
||||
|
||||
// 2. Check User Capabilities.
|
||||
if (!current_user_can('manage_options')) { // Ensure user can change this setting
|
||||
wp_send_json_error(array('message' => __('Insufficient permissions.', WPALLSTARS_TEXT_DOMAIN)), 403); // 403 Forbidden
|
||||
}
|
||||
|
||||
// 3. Sanitize and Validate Input.
|
||||
// Expecting 'enabled' to be 'true' or 'false' (as strings from JS).
|
||||
$is_enabled_input = isset($_POST['enabled']) ? sanitize_text_field($_POST['enabled']) : 'false';
|
||||
$is_enabled = ($is_enabled_input === 'true'); // Convert string 'true' to boolean true
|
||||
|
||||
// 4. Update the Option in the Database.
|
||||
$options = get_option($this->options_key, []);
|
||||
$options[$this->color_scheme_option_key] = $is_enabled ? 1 : 0; // Store as 1 or 0
|
||||
$update_success = update_option($this->options_key, $options);
|
||||
|
||||
// 5. Update Current User's Scheme Immediately for instant feedback.
|
||||
$user_id = get_current_user_id();
|
||||
$scheme_to_set = $is_enabled ? $this->modern_scheme_slug : $this->default_scheme_slug;
|
||||
$this->update_user_color_scheme_preference($user_id, $scheme_to_set);
|
||||
|
||||
// 6. Send JSON Response.
|
||||
if ($update_success) {
|
||||
wp_send_json_success(array(
|
||||
'message' => $is_enabled
|
||||
? __('Modern admin color scheme enabled.', WPALLSTARS_TEXT_DOMAIN)
|
||||
: __('Default admin color scheme restored.', WPALLSTARS_TEXT_DOMAIN),
|
||||
'new_state' => $is_enabled, // Send back the new state
|
||||
));
|
||||
} else {
|
||||
// Option update might have failed, or the value was unchanged.
|
||||
// Check if the value was actually unchanged.
|
||||
$current_db_options = get_option($this->options_key, []);
|
||||
$current_db_value = isset($current_db_options[$this->color_scheme_option_key]) ? (bool)$current_db_options[$this->color_scheme_option_key] : false;
|
||||
if ($current_db_value === $is_enabled) {
|
||||
wp_send_json_success(array(
|
||||
'message' => __('Setting unchanged.', WPALLSTARS_TEXT_DOMAIN),
|
||||
'new_state' => $is_enabled,
|
||||
'unchanged' => true
|
||||
));
|
||||
} else {
|
||||
wp_send_json_error(array('message' => __('Failed to save setting.', WPALLSTARS_TEXT_DOMAIN)), 500); // 500 Internal Server Error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the modern color scheme override is enabled in the plugin settings.
|
||||
*
|
||||
* @return bool True if enabled, false otherwise.
|
||||
*/
|
||||
public function is_modern_color_scheme_enabled() {
|
||||
$options = get_option($this->options_key, []);
|
||||
// Check if the specific key exists and is set to 1 (or true). Default to false if not set.
|
||||
return isset($options[$this->color_scheme_option_key]) && $options[$this->color_scheme_option_key] == 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
/**
|
||||
* Auto Upload Images functionality for WP Allstars Plugin.
|
||||
*
|
||||
* Automatically downloads external images found in post content upon saving
|
||||
* and uploads them to the WordPress media library, replacing the external URLs.
|
||||
*
|
||||
* @package WPALLSTARS
|
||||
* @subpackage Core
|
||||
* @since 0.2.0
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Class WPALLSTARS_Auto_Upload
|
||||
*
|
||||
* Manages the automatic uploading of external images embedded in post content.
|
||||
*/
|
||||
class WPALLSTARS_Auto_Upload {
|
||||
|
||||
/**
|
||||
* Initialize the hooks for the Auto Upload feature.
|
||||
*/
|
||||
public function __construct() {
|
||||
// Hook into content saving process. Priority 10 is standard.
|
||||
add_filter('content_save_pre', array($this, 'process_content_for_images'), 10, 1);
|
||||
|
||||
// Hook for logging errors, allowing other parts of the plugin or themes to hook in too.
|
||||
add_action('wpallstars_image_upload_error', array($this, 'log_upload_error'), 10, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process post content before saving to find and upload external images.
|
||||
*
|
||||
* Checks if the feature is enabled via settings before processing.
|
||||
*
|
||||
* @param string $content The raw post content being saved.
|
||||
* @return string Modified content with external image URLs replaced by local ones,
|
||||
* or the original content if the feature is disabled or no images are found.
|
||||
*/
|
||||
public function process_content_for_images($content) {
|
||||
// Retrieve workflow options, providing a default for 'auto_upload_images'
|
||||
$workflow_options = get_option('wpallstars_workflow_options', array('auto_upload_images' => 0)); // Default to disabled (0)
|
||||
|
||||
// Check if the 'auto_upload_images' setting is enabled (expecting '1' if enabled)
|
||||
if (empty($workflow_options['auto_upload_images']) || $workflow_options['auto_upload_images'] != '1') {
|
||||
return $content; // Feature disabled, return original content.
|
||||
}
|
||||
|
||||
// Regular expression to find <img> tags and capture their src attribute.
|
||||
// This pattern is case-insensitive (i) and handles single or double quotes.
|
||||
$pattern = '/<img[^>]+src=[\'"]([^\'"]+)[\'"][^>]*>/i';
|
||||
|
||||
// Use preg_replace_callback to process each found image URL individually.
|
||||
$modified_content = preg_replace_callback($pattern, array($this, 'replace_image_url_callback'), $content);
|
||||
|
||||
// Return the modified content, or the original if preg_replace_callback encountered an error.
|
||||
return (null === $modified_content) ? $content : $modified_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for preg_replace_callback. Processes a single image match.
|
||||
*
|
||||
* @param array $matches An array of matches from preg_replace_callback.
|
||||
* $matches[0] is the full <img> tag.
|
||||
* $matches[1] is the URL from the src attribute.
|
||||
* @return string The original <img> tag if the URL is local or upload fails,
|
||||
* or the modified <img> tag with the new local URL.
|
||||
*/
|
||||
private function replace_image_url_callback($matches) {
|
||||
// Ensure the URL capture group exists.
|
||||
if (empty($matches[1])) {
|
||||
return $matches[0]; // Return original tag if no URL found.
|
||||
}
|
||||
|
||||
$external_url = trim($matches[1]);
|
||||
|
||||
// Validate the URL format (basic check).
|
||||
if (filter_var($external_url, FILTER_VALIDATE_URL) === false) {
|
||||
// Optionally log invalid URL format if needed
|
||||
// $this->log_upload_error($external_url, 'Invalid URL format detected');
|
||||
return $matches[0]; // Invalid URL, skip.
|
||||
}
|
||||
|
||||
// Skip if the URL is already pointing to the local site.
|
||||
if ($this->is_local_image_url($external_url)) {
|
||||
return $matches[0]; // Already local, no need to process.
|
||||
}
|
||||
|
||||
try {
|
||||
// Attempt to upload the image.
|
||||
$local_url = $this->sideload_image($external_url);
|
||||
|
||||
// If upload is successful, replace the URL in the img tag.
|
||||
if ($local_url) {
|
||||
// Use str_replace for simple replacement within the matched tag.
|
||||
// This is generally safe as we're replacing the exact matched URL string.
|
||||
return str_replace($external_url, esc_url($local_url), $matches[0]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Trigger a WordPress action to log the error.
|
||||
// Pass the original external URL and the exception message.
|
||||
do_action('wpallstars_image_upload_error', esc_url($external_url), $e->getMessage());
|
||||
}
|
||||
|
||||
// Return the original <img> tag if the upload failed or an exception occurred.
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given image URL belongs to the local WordPress site.
|
||||
*
|
||||
* Compares the host of the image URL with the host of the site URL.
|
||||
*
|
||||
* @param string $url The image URL to check.
|
||||
* @return bool True if the URL is local, false otherwise.
|
||||
*/
|
||||
private function is_local_image_url($url) {
|
||||
// Get the host part of the site URL (e.g., '[www.example.com](www.example.com)').
|
||||
$site_host = parse_url(get_site_url(), PHP_URL_HOST);
|
||||
|
||||
// Get the host part of the image URL.
|
||||
$image_host = parse_url($url, PHP_URL_HOST);
|
||||
|
||||
// Return true if the hosts match, false otherwise.
|
||||
// Use strtolower for case-insensitive comparison.
|
||||
return !empty($site_host) && !empty($image_host) && strtolower($site_host) === strtolower($image_host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download an external image and upload it to the WordPress media library.
|
||||
*
|
||||
* Uses WordPress core functions download_url() and media_handle_sideload().
|
||||
*
|
||||
* @param string $external_url The URL of the external image to download.
|
||||
* @return string|false The local URL of the uploaded image on success, false on failure.
|
||||
* @throws Exception If downloading or uploading fails, or if the file type is invalid.
|
||||
*/
|
||||
private function sideload_image($external_url) {
|
||||
// Ensure required WordPress core files for media handling are loaded.
|
||||
require_once ABSPATH . 'wp-admin/includes/media.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/image.php'; // For potential image processing
|
||||
|
||||
$file_array = array();
|
||||
// Sanitize filename derived from the URL path.
|
||||
$file_array['name'] = sanitize_file_name(basename(parse_url($external_url, PHP_URL_PATH)));
|
||||
|
||||
// Download the file to a temporary location.
|
||||
// Set timeout to prevent long waits for unresponsive URLs.
|
||||
$timeout_seconds = 15;
|
||||
$temp_file_path = download_url($external_url, $timeout_seconds);
|
||||
|
||||
// Check for download errors.
|
||||
if (is_wp_error($temp_file_path)) {
|
||||
// Clean up temporary file if it exists, even on error
|
||||
if (file_exists($temp_file_path)) {
|
||||
@unlink($temp_file_path);
|
||||
}
|
||||
throw new Exception(sprintf('Failed to download image: %s', $temp_file_path->get_error_message()));
|
||||
}
|
||||
|
||||
// Check file type for security. Associate with the temporary file.
|
||||
$file_array['tmp_name'] = $temp_file_path;
|
||||
$wp_filetype = wp_check_filetype_and_ext($file_array['tmp_name'], $file_array['name']);
|
||||
|
||||
// Check if the file type is allowed by WordPress.
|
||||
if (empty($wp_filetype['ext']) || empty($wp_filetype['type']) || !in_array(strtolower($wp_filetype['ext']), get_allowed_mime_types()) && !in_array($wp_filetype['type'], get_allowed_mime_types())) {
|
||||
unlink($file_array['tmp_name']); // Clean up the temporary file.
|
||||
throw new Exception(sprintf('Invalid or disallowed file type detected: %s', $wp_filetype['type'] ?: 'Unknown'));
|
||||
}
|
||||
|
||||
|
||||
// Upload the file from the temporary location to the media library.
|
||||
// The post ID '0' indicates the attachment is not associated with any specific post.
|
||||
$attachment_id = media_handle_sideload($file_array, 0);
|
||||
|
||||
// Check for errors during the sideloading process.
|
||||
if (is_wp_error($attachment_id)) {
|
||||
unlink($file_array['tmp_name']); // Clean up the temporary file.
|
||||
throw new Exception(sprintf('Failed to upload image: %s', $attachment_id->get_error_message()));
|
||||
}
|
||||
|
||||
// Get the URL of the newly uploaded attachment.
|
||||
$local_url = wp_get_attachment_url($attachment_id);
|
||||
|
||||
// Check if a valid URL was returned.
|
||||
if (!$local_url) {
|
||||
// Attachment likely created, but URL failed. Try to clean up attachment? Difficult.
|
||||
// Best practice is often to leave the attachment and log the URL retrieval error.
|
||||
unlink($file_array['tmp_name']); // Still clean up temp file
|
||||
throw new Exception(sprintf('Failed to get attachment URL after upload (Attachment ID: %d)', $attachment_id));
|
||||
}
|
||||
|
||||
// Return the local URL on success.
|
||||
return $local_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log image upload errors using WordPress's error logging mechanism.
|
||||
*
|
||||
* Only logs if WP_DEBUG is enabled.
|
||||
*
|
||||
* @param string $failed_url The external URL that failed to upload.
|
||||
* @param string $error_message The specific error message.
|
||||
*/
|
||||
public function log_upload_error($failed_url, $error_message) {
|
||||
// Check if WordPress debugging is enabled.
|
||||
if (defined('WP_DEBUG') && WP_DEBUG === true) {
|
||||
error_log(sprintf(
|
||||
'[WPALLSTARS Auto Upload] Error: Failed to process image "%s". Reason: %s',
|
||||
esc_url_raw($failed_url), // Use raw URL for logging
|
||||
sanitize_text_field($error_message)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
<?php
|
||||
/**
|
||||
* WPALLSTARS Sync Guard
|
||||
*
|
||||
* Prevents accidental overwrites during content synchronization or updates.
|
||||
* Adds checks before saving posts or terms, potentially comparing modification dates
|
||||
* or using a locking mechanism to avoid data loss when multiple sources might update content.
|
||||
*
|
||||
* @package WPALLSTARS
|
||||
* @subpackage Core
|
||||
* @since 1.0.0 // Adjust version as needed
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Class WPALLSTARS_Sync_Guard
|
||||
*
|
||||
* Implements mechanisms to protect content from concurrent edits or overwrites
|
||||
* during synchronization processes.
|
||||
*/
|
||||
class WPALLSTARS_Sync_Guard {
|
||||
|
||||
/**
|
||||
* Option key for Sync Guard settings within the main options array.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $options_key = 'wpallstars_options';
|
||||
|
||||
/**
|
||||
* Key for the enable/disable setting within the options array.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $setting_key_enabled = 'sync_guard_enabled';
|
||||
|
||||
/**
|
||||
* Key for the sync guard mode (e.g., 'timestamp', 'lock').
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $setting_key_mode = 'sync_guard_mode';
|
||||
|
||||
/**
|
||||
* Meta key to store the last sync timestamp on a post/term.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $meta_key_last_sync = '_wpallstars_last_sync_timestamp';
|
||||
|
||||
/**
|
||||
* Meta key to store a lock indicator (e.g., user ID and timestamp).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $meta_key_lock = '_wpallstars_sync_lock';
|
||||
|
||||
/**
|
||||
* Lock timeout in seconds.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $lock_timeout = 300; // 5 minutes
|
||||
|
||||
/**
|
||||
* Constructor. Sets up hooks if the feature is enabled.
|
||||
*/
|
||||
public function __construct() {
|
||||
if ($this->is_enabled()) {
|
||||
// Hook into pre-save actions for posts and potentially terms
|
||||
// Priority 10 is default, allowing other plugins to modify data first.
|
||||
add_filter('wp_insert_post_data', array($this, 'check_post_sync_conflict'), 10, 3); // Use 3 args for postarr, update, WP_Error
|
||||
// Hook into post-save action to update meta or release locks.
|
||||
add_action('save_post', array($this, 'update_post_sync_meta'), 20, 2); // Run later to capture final state
|
||||
|
||||
// --- Term Hooks (Example - Not included in this edit for brevity) ---
|
||||
// --- Optional AJAX Lock Release (Not included in this edit for brevity) ---
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Sync Guard is enabled in settings.
|
||||
*
|
||||
* @return bool True if enabled, false otherwise.
|
||||
*/
|
||||
private function is_enabled() {
|
||||
$options = get_option($this->options_key, []);
|
||||
// Ensure the key exists and is explicitly set to '1' or true.
|
||||
return !empty($options[$this->setting_key_enabled]) && $options[$this->setting_key_enabled] == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configured sync guard mode from settings.
|
||||
*
|
||||
* @return string The mode ('timestamp', 'lock', or default 'timestamp').
|
||||
*/
|
||||
private function get_mode() {
|
||||
$options = get_option($this->options_key, []);
|
||||
$mode = isset($options[$this->setting_key_mode]) ? sanitize_key($options[$this->setting_key_mode]) : 'timestamp';
|
||||
// Ensure mode is one of the allowed values
|
||||
return in_array($mode, ['timestamp', 'lock'], true) ? $mode : 'timestamp'; // Default to timestamp
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for potential sync conflicts before saving post data.
|
||||
* Runs on the 'wp_insert_post_data' filter.
|
||||
*
|
||||
* @param array $data An array of slashed post data.
|
||||
* @param array $postarr An array of sanitized, but otherwise unmodified post data.
|
||||
* @param bool|WP_Error $update Whether this is an update. WP_Error if validation failed.
|
||||
* @return array|WP_Error The original $data or a WP_Error if a conflict is detected and blocking is configured.
|
||||
*/
|
||||
public function check_post_sync_conflict($data, $postarr, $update) {
|
||||
// --- Basic Checks ---
|
||||
// 1. Only act on updates (existing posts).
|
||||
// 2. Ignore if validation already failed ($update is WP_Error).
|
||||
// 3. Ensure we have a Post ID.
|
||||
// 4. Check if the post type is relevant.
|
||||
if (!$update || is_wp_error($update) || empty($postarr['ID']) || !$this->is_relevant_post_type($postarr['post_type'])) {
|
||||
return $data; // Pass through if not applicable
|
||||
}
|
||||
|
||||
$post_id = absint($postarr['ID']);
|
||||
$mode = $this->get_mode();
|
||||
$current_user_id = get_current_user_id(); // Can be 0 for system processes
|
||||
|
||||
// --- Timestamp Mode Logic ---
|
||||
if ($mode === 'timestamp') {
|
||||
$last_sync_time_str = get_post_meta($post_id, $this->meta_key_last_sync, true);
|
||||
$post_modified_gmt_str = isset($data['post_modified_gmt']) ? $data['post_modified_gmt'] : get_post_field('post_modified_gmt', $post_id);
|
||||
|
||||
// Convert to timestamps for comparison
|
||||
$last_sync_ts = !empty($last_sync_time_str) ? strtotime($last_sync_time_str) : 0;
|
||||
$post_modified_ts = !empty($post_modified_gmt_str) ? strtotime($post_modified_gmt_str) : 0;
|
||||
|
||||
// Check if a sync occurred *after* the last modification recorded in the database.
|
||||
// This implies an external update happened since the content being edited was loaded.
|
||||
if ($last_sync_ts > 0 && $post_modified_ts > 0 && $last_sync_ts > $post_modified_ts) {
|
||||
// Conflict detected: External sync is newer than the post's last known modification time.
|
||||
// Option 1: Block the save (disruptive) - Uncomment if needed
|
||||
/*
|
||||
return new WP_Error('sync_conflict_timestamp',
|
||||
__('Warning: This content appears to have been updated by an external sync process since you started editing. Saving now would overwrite those changes. Please reload the content.', WPALLSTARS_TEXT_DOMAIN)
|
||||
);
|
||||
*/
|
||||
|
||||
// Option 2: Allow save but log it (less disruptive)
|
||||
$log_message = sprintf(
|
||||
'[WPALLSTARS Sync Guard] Post ID %d: Potential timestamp conflict detected. Save allowed. Last Sync: %s, DB Post Modified: %s',
|
||||
$post_id,
|
||||
esc_html($last_sync_time_str),
|
||||
esc_html($post_modified_gmt_str)
|
||||
);
|
||||
error_log($log_message);
|
||||
}
|
||||
}
|
||||
// --- Lock Mode Logic ---
|
||||
elseif ($mode === 'lock') {
|
||||
$lock_data = get_post_meta($post_id, $this->meta_key_lock, true);
|
||||
|
||||
if (!empty($lock_data) && is_array($lock_data)) {
|
||||
$lock_time = isset($lock_data['time']) ? (int) $lock_data['time'] : 0;
|
||||
$lock_user = isset($lock_data['user']) ? (int) $lock_data['user'] : -1; // -1 for unknown/system lock owner
|
||||
|
||||
// Check if lock is expired
|
||||
if ((time() - $lock_time) > $this->lock_timeout) {
|
||||
$this->release_post_lock($post_id, 'timeout_expired');
|
||||
// Lock released due to timeout, proceed to acquire new lock below.
|
||||
}
|
||||
// Check if lock is held by someone else and not expired
|
||||
elseif ($lock_user !== $current_user_id) {
|
||||
$locked_by_user = ($lock_user > 0) ? get_userdata($lock_user) : null;
|
||||
$locked_by_name = $locked_by_user ? $locked_by_user->display_name : __('another process', WPALLSTARS_TEXT_DOMAIN);
|
||||
$time_ago = human_time_diff($lock_time);
|
||||
|
||||
$error_message = sprintf(
|
||||
// translators: %1$s: User display name or 'another process'. %2$s: Time duration (e.g., '5 minutes ago').
|
||||
__('Sync Conflict: This content is currently locked for editing by %1$s (since %2$s ago). Please try again later or ask them to finish.', WPALLSTARS_TEXT_DOMAIN),
|
||||
esc_html($locked_by_name),
|
||||
esc_html($time_ago)
|
||||
);
|
||||
// Block the save by returning a WP_Error
|
||||
return new WP_Error('sync_lock_conflict', $error_message);
|
||||
}
|
||||
// Else: Lock is held by the current user, allow save to proceed.
|
||||
}
|
||||
|
||||
// If we reached here (no conflict or lock expired), attempt to acquire or update the lock.
|
||||
// This ensures the lock is held throughout the save process.
|
||||
$this->acquire_post_lock($post_id, $current_user_id);
|
||||
}
|
||||
|
||||
// No conflict or conflict handled (e.g., logging), allow data to pass through.
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update sync-related meta data after a post is saved.
|
||||
* Runs on the 'save_post' action.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
public function update_post_sync_meta($post_id, $post) {
|
||||
// Prevent infinite loops and ensure post type is relevant
|
||||
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
|
||||
if (wp_is_post_revision($post_id)) return;
|
||||
if (!$this->is_relevant_post_type($post->post_type)) return;
|
||||
|
||||
$mode = $this->get_mode();
|
||||
|
||||
// Update timestamp after successful save (if in timestamp mode)
|
||||
if ($mode === 'timestamp') {
|
||||
// Update our custom meta field to reflect the latest save time.
|
||||
// This uses the post_modified_gmt from the saved post object.
|
||||
update_post_meta($post_id, $this->meta_key_last_sync, $post->post_modified_gmt);
|
||||
}
|
||||
// Release lock after successful save (if in lock mode)
|
||||
elseif ($mode === 'lock') {
|
||||
// Only release if the lock is held by the current user who initiated the save.
|
||||
$lock_data = get_post_meta($post_id, $this->meta_key_lock, true);
|
||||
$current_user_id = get_current_user_id();
|
||||
if (!empty($lock_data) && is_array($lock_data) && isset($lock_data['user']) && $lock_data['user'] === $current_user_id) {
|
||||
$this->release_post_lock($post_id, 'save_completed_by_user');
|
||||
}
|
||||
// Locks held by other users or expired locks should have been handled earlier or will time out.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquire or update a lock on a post for the current user/process.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @param int $user_id User ID acquiring the lock (0 for system/unknown).
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
private function acquire_post_lock($post_id, $user_id) {
|
||||
$lock_data = array(
|
||||
'user' => (int) $user_id,
|
||||
'time' => time(), // Current server time
|
||||
);
|
||||
// Use update_post_meta - it handles both adding and updating the meta key.
|
||||
$result = update_post_meta($post_id, $this->meta_key_lock, $lock_data);
|
||||
if (!$result) {
|
||||
error_log("[WPALLSTARS Sync Guard] Failed to acquire/update lock for Post ID {$post_id} by User ID {$user_id}.");
|
||||
}
|
||||
return (bool) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release a lock on a post.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @param string $reason Optional reason for logging purposes.
|
||||
* @return bool True if the meta key was deleted, false otherwise.
|
||||
*/
|
||||
private function release_post_lock($post_id, $reason = '') {
|
||||
$log_message = sprintf(
|
||||
'[WPALLSTARS Sync Guard] Releasing lock for Post ID %d. Reason: %s',
|
||||
absint($post_id),
|
||||
sanitize_text_field($reason)
|
||||
);
|
||||
error_log($log_message);
|
||||
// Deleting the meta key removes the lock.
|
||||
return delete_post_meta($post_id, $this->meta_key_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the post type is relevant for sync guarding.
|
||||
* Post types can be configured via the 'wpallstars_sync_guard_post_types' filter.
|
||||
*
|
||||
* @param string $post_type The post type slug.
|
||||
* @return bool True if the post type should be guarded, false otherwise.
|
||||
*/
|
||||
private function is_relevant_post_type($post_type) {
|
||||
// Default relevant post types
|
||||
$default_types = array('post', 'page');
|
||||
// Allow themes/plugins to filter the list of guarded post types
|
||||
$relevant_types = apply_filters('wpallstars_sync_guard_post_types', $default_types);
|
||||
// Ensure it's an array before checking
|
||||
return is_array($relevant_types) && in_array($post_type, $relevant_types, true);
|
||||
}
|
||||
|
||||
// --- Methods for Term Guarding (Example Structure - requires implementation) ---
|
||||
// Term guarding logic would go here, mirroring the post logic but using
|
||||
// term meta (get/update/delete_term_meta) and term-related hooks.
|
||||
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/**
|
||||
* WPALLSTARS UI Enhancements
|
||||
*
|
||||
* Responsible for enhancing the WordPress admin interface with improved UI components
|
||||
* like cards, panels, buttons, and responsive design elements.
|
||||
*
|
||||
* @package WPALLSTARS
|
||||
* @version v0.2.3.3
|
||||
*/
|
||||
|
||||
if (!defined('WPINC')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class WPALLSTARS_UI_Enhancements {
|
||||
/**
|
||||
* Constructor
|
||||
* Initialize hooks and settings
|
||||
*/
|
||||
public function __construct() {
|
||||
// Register scripts and styles
|
||||
add_action('admin_enqueue_scripts', array($this, 'enqueue_assets'));
|
||||
|
||||
// Add body class for enhanced UI
|
||||
add_filter('admin_body_class', array($this, 'add_body_class'));
|
||||
|
||||
// Initialize UI components
|
||||
$this->init_components();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue CSS and JavaScript assets
|
||||
*/
|
||||
public function enqueue_assets($hook) {
|
||||
// Only load on WPALLSTARS pages
|
||||
if (strpos($hook, 'wpallstars') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Already registered in main plugin file, but ensure they're enqueued
|
||||
wp_enqueue_style('wpallstars-admin');
|
||||
wp_enqueue_script('wpallstars-admin');
|
||||
|
||||
// Add UI enhancements script
|
||||
wp_enqueue_script(
|
||||
'wpallstars-ui-enhancements',
|
||||
WPALLSTARS_URL . 'admin/js/wpallstars-ui-enhancements.js',
|
||||
array('jquery', 'wpallstars-admin'),
|
||||
WPALLSTARS_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
// Add enhanced UI styles
|
||||
wp_enqueue_style(
|
||||
'wpallstars-ui-enhancements',
|
||||
WPALLSTARS_URL . 'admin/css/wpallstars-ui-enhancements.css',
|
||||
array('wpallstars-admin'),
|
||||
WPALLSTARS_VERSION
|
||||
);
|
||||
|
||||
// Localize script with settings
|
||||
wp_localize_script('wpallstars-ui-enhancements', 'wpallstarsUI', array(
|
||||
'ajaxurl' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce('wpallstars_ui_nonce'),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add body class for enhanced UI
|
||||
*/
|
||||
public function add_body_class($classes) {
|
||||
if (isset($_GET['page']) && strpos($_GET['page'], 'wpallstars') !== false) {
|
||||
$classes .= ' wpallstars-ui-enabled';
|
||||
}
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize UI components
|
||||
*/
|
||||
private function init_components() {
|
||||
// Add accordion functionality
|
||||
add_action('admin_footer', array($this, 'render_accordion_template'));
|
||||
|
||||
// Add card component
|
||||
add_action('admin_footer', array($this, 'render_card_template'));
|
||||
|
||||
// Add notification system
|
||||
add_action('admin_footer', array($this, 'render_notification_template'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Render accordion template
|
||||
*/
|
||||
public function render_accordion_template() {
|
||||
// Only on WPALLSTARS pages
|
||||
if (!isset($_GET['page']) || strpos($_GET['page'], 'wpallstars') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<script type="text/html" id="tmpl-wpallstars-accordion">
|
||||
<div class="wpallstars-accordion" role="tablist">
|
||||
<div class="wpallstars-accordion-header" role="tab" id="accordion-header-{{data.id}}" aria-expanded="false">
|
||||
<div class="wpallstars-accordion-title">{{data.title}}</div>
|
||||
<div class="wpallstars-accordion-icon"></div>
|
||||
</div>
|
||||
<div class="wpallstars-accordion-content" role="tabpanel" aria-labelledby="accordion-header-{{data.id}}">
|
||||
<div class="wpallstars-accordion-inner">
|
||||
{{{data.content}}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render card template
|
||||
*/
|
||||
public function render_card_template() {
|
||||
// Only on WPALLSTARS pages
|
||||
if (!isset($_GET['page']) || strpos($_GET['page'], 'wpallstars') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<script type="text/html" id="tmpl-wpallstars-card">
|
||||
<div class="wpallstars-card">
|
||||
<# if (data.header) { #>
|
||||
<div class="wpallstars-card-header">
|
||||
<# if (data.icon) { #>
|
||||
<div class="wpallstars-card-icon">{{{data.icon}}}</div>
|
||||
<# } #>
|
||||
<div class="wpallstars-card-title">{{data.header}}</div>
|
||||
</div>
|
||||
<# } #>
|
||||
<div class="wpallstars-card-content">
|
||||
{{{data.content}}}
|
||||
</div>
|
||||
<# if (data.footer) { #>
|
||||
<div class="wpallstars-card-footer">
|
||||
{{{data.footer}}}
|
||||
</div>
|
||||
<# } #>
|
||||
</div>
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render notification template
|
||||
*/
|
||||
public function render_notification_template() {
|
||||
// Only on WPALLSTARS pages
|
||||
if (!isset($_GET['page']) || strpos($_GET['page'], 'wpallstars') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<script type="text/html" id="tmpl-wpallstars-notification">
|
||||
<div class="wpallstars-notification wpallstars-notification-{{data.type}}">
|
||||
<div class="wpallstars-notification-icon"></div>
|
||||
<div class="wpallstars-notification-content">
|
||||
<# if (data.title) { #>
|
||||
<div class="wpallstars-notification-title">{{data.title}}</div>
|
||||
<# } #>
|
||||
<div class="wpallstars-notification-message">{{data.message}}</div>
|
||||
</div>
|
||||
<div class="wpallstars-notification-dismiss"></div>
|
||||
</div>
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WP ALLSTARS Plugin
|
||||
*
|
||||
* A comprehensive WordPress optimization and management tool designed to enhance
|
||||
* site performance, improve workflow, and provide recommendations for plugins and hosting.
|
||||
*
|
||||
* @package WP_ALLSTARS
|
||||
* @version v0.2.3.3
|
||||
*
|
||||
* Plugin Name: WP Allstars
|
||||
* Plugin URI: https://wpallstars.com
|
||||
* Description: A superstar stack of premium WordPress functionality, designed for SEO pros.
|
||||
* Author: Marcus Quinn
|
||||
* Author URI: https://wpallstars.com
|
||||
* Text Domain: wp-allstars
|
||||
* Domain Path: /languages
|
||||
* @version v0.2.3.3
|
||||
*
|
||||
* WP Allstars is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* any later version.
|
||||
* Version: v0.2.3.3 (Beta)
|
||||
*
|
||||
* WP Allstars is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with WP Allstars. If not, see https://www.gnu.org/licenses/gpl-2.0.html.
|
||||
*/
|
||||
|
||||
if (!defined('WPINC')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
define('WP_ALLSTARS_VERSION', 'v0.2.3.3');
|
||||
|
||||
/**
|
||||
* Load files safely by checking if they exist first
|
||||
*/
|
||||
function wp_allstars_require_if_exists($file) {
|
||||
if (file_exists($file)) {
|
||||
require_once $file;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for sync operations before loading the plugin
|
||||
*/
|
||||
// Simple sync detection - check for .syncing file
|
||||
if (file_exists(__DIR__ . '/.syncing')) {
|
||||
// Only load the minimal code needed for admin notice
|
||||
if (is_admin()) {
|
||||
add_action('admin_notices', function() {
|
||||
echo '<div class="notice notice-warning is-dismissible">';
|
||||
echo '<p><strong>WP Allstars:</strong> Plugin files are currently syncing. The plugin functionality is temporarily disabled to prevent errors. Please try again in a moment.</p>';
|
||||
echo '</div>';
|
||||
});
|
||||
}
|
||||
// Exit early to prevent loading other files
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the sync guard for future use and more advanced sync detection
|
||||
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'includes/class-wp-allstars-sync-guard.php');
|
||||
|
||||
/**
|
||||
* Plugin activation hook
|
||||
*/
|
||||
function wp_allstars_activate() {
|
||||
// Setup initial config
|
||||
}
|
||||
register_activation_hook(__FILE__, 'wp_allstars_activate');
|
||||
|
||||
// Core includes
|
||||
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'includes/class-wp-allstars-auto-upload.php');
|
||||
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'includes/class-wp-allstars-admin-colors.php');
|
||||
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'includes/class-wp-allstars-ui-enhancements.php');
|
||||
|
||||
// Admin includes
|
||||
if (is_admin()) {
|
||||
$admin_includes = array(
|
||||
'admin/includes/class-admin-manager.php',
|
||||
'admin/includes/class-settings-manager.php',
|
||||
'admin/includes/class-theme-manager.php',
|
||||
'admin/includes/class-workflow-manager.php',
|
||||
'admin/includes/class-tools-manager.php',
|
||||
'admin/includes/class-hosting-manager.php',
|
||||
'admin/includes/class-pro-plugins-manager.php',
|
||||
'admin/includes/class-plugin-manager.php',
|
||||
'admin/includes/class-free-plugins-manager.php',
|
||||
'admin/includes/class-readme-manager.php'
|
||||
);
|
||||
|
||||
foreach ($admin_includes as $file) {
|
||||
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . $file);
|
||||
}
|
||||
|
||||
// Settings and data
|
||||
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'admin/data/pro-plugins.php');
|
||||
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'admin/data/readme.php');
|
||||
|
||||
// Admin settings
|
||||
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'admin/settings.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto Upload feature initialization
|
||||
*
|
||||
* Initialize the Auto Upload feature when a user is logged in
|
||||
*/
|
||||
function wp_allstars_init_auto_upload() {
|
||||
// Only initialize for logged-in users
|
||||
if (is_user_logged_in()) {
|
||||
new WP_Allstars_Auto_Upload();
|
||||
}
|
||||
}
|
||||
add_action('init', 'wp_allstars_init_auto_upload');
|
||||
|
||||
/**
|
||||
* Initialize core features
|
||||
*/
|
||||
function wp_allstars_init_features() {
|
||||
// Initialize Admin Colors feature if the class exists
|
||||
if (class_exists('WP_Allstars_Admin_Colors')) {
|
||||
new WP_Allstars_Admin_Colors();
|
||||
}
|
||||
|
||||
// Initialize UI Enhancements if the class exists
|
||||
if (class_exists('WP_Allstars_UI_Enhancements')) {
|
||||
new WP_Allstars_UI_Enhancements();
|
||||
}
|
||||
}
|
||||
add_action('plugins_loaded', 'wp_allstars_init_features');
|
||||
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
/**
|
||||
* WPALLSTARS Plugin
|
||||
*
|
||||
* A comprehensive WordPress optimization and management tool designed to enhance
|
||||
* site performance, improve workflow, and provide recommendations for plugins and hosting.
|
||||
*
|
||||
* @package WPALLSTARS
|
||||
* @version 0.2.3.3
|
||||
*
|
||||
* Plugin Name: WP Allstars
|
||||
* Plugin URI: https://wpallstars.com
|
||||
* Description: A superstar stack of premium WordPress functionality, designed for SEO pros.
|
||||
* Author: Marcus Quinn
|
||||
* Author URI: https://wpallstars.com
|
||||
* Text Domain: wpallstars
|
||||
* Domain Path: /languages
|
||||
* Version: 0.2.3.3
|
||||
* License: GPLv2 or later
|
||||
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
if (!defined('WPINC')) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
// --- Constants ---
|
||||
define('WPALLSTARS_VERSION', '0.2.3.3');
|
||||
define('WPALLSTARS_PATH', plugin_dir_path(__FILE__));
|
||||
define('WPALLSTARS_URL', plugin_dir_url(__FILE__));
|
||||
define('WPALLSTARS_BASENAME', plugin_basename(__FILE__));
|
||||
define('WPALLSTARS_TEXT_DOMAIN', 'wpallstars'); // Consistent text domain constant
|
||||
|
||||
/**
|
||||
* Load files safely by checking if they exist first.
|
||||
*
|
||||
* @param string $file Full path to the file.
|
||||
* @return bool True if the file was loaded, false otherwise.
|
||||
*/
|
||||
function wpallstars_require_if_exists($file) {
|
||||
if (file_exists($file)) {
|
||||
require_once $file;
|
||||
return true;
|
||||
}
|
||||
// Optional: Add error logging here if a required file is missing
|
||||
// error_log('WP Allstars critical file missing: ' . $file);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for sync operations before loading the plugin.
|
||||
* Prevents errors during file synchronization (e.g., via Git or cloud storage).
|
||||
*/
|
||||
if (file_exists(WPALLSTARS_PATH . '.syncing')) {
|
||||
if (is_admin()) {
|
||||
add_action('admin_notices', function() {
|
||||
echo '<div class="notice notice-warning is-dismissible">';
|
||||
printf(
|
||||
'<p><strong>%s:</strong> %s</p>',
|
||||
esc_html__( 'WP Allstars', WPALLSTARS_TEXT_DOMAIN ),
|
||||
esc_html__( 'Plugin files are currently syncing. Functionality is temporarily disabled. Please try again shortly.', WPALLSTARS_TEXT_DOMAIN )
|
||||
);
|
||||
echo '</div>';
|
||||
});
|
||||
}
|
||||
return; // Exit early to prevent loading other files during sync
|
||||
}
|
||||
|
||||
// --- Core Includes ---
|
||||
// Load Sync Guard (if used for more advanced detection)
|
||||
wpallstars_require_if_exists(WPALLSTARS_PATH . 'includes/class-wpallstars-sync-guard.php');
|
||||
// Core features
|
||||
wpallstars_require_if_exists(WPALLSTARS_PATH . 'includes/class-wpallstars-auto-upload.php');
|
||||
wpallstars_require_if_exists(WPALLSTARS_PATH . 'includes/class-wpallstars-admin-colors.php');
|
||||
wpallstars_require_if_exists(WPALLSTARS_PATH . 'includes/class-wpallstars-ui-enhancements.php');
|
||||
|
||||
// --- Admin Includes ---
|
||||
if (is_admin() || (defined('DOING_AJAX') && DOING_AJAX)) { // Load admin for AJAX requests too
|
||||
$admin_includes = [
|
||||
'admin/includes/class-admin-manager.php',
|
||||
'admin/includes/class-settings-manager.php',
|
||||
'admin/includes/class-theme-manager.php',
|
||||
'admin/includes/class-workflow-manager.php',
|
||||
'admin/includes/class-pro-plugins-manager.php',
|
||||
'admin/includes/class-tools-manager.php',
|
||||
'admin/includes/class-hosting-manager.php',
|
||||
'admin/includes/class-plugin-manager.php', // Assuming this exists
|
||||
'admin/includes/class-free-plugins-manager.php',
|
||||
'admin/includes/class-readme-manager.php'
|
||||
];
|
||||
|
||||
foreach ($admin_includes as $relative_path) {
|
||||
// No need to anticipate renaming anymore, use the correct path directly
|
||||
wpallstars_require_if_exists(WPALLSTARS_PATH . $relative_path);
|
||||
}
|
||||
|
||||
// Data files (ensure these are still needed and paths are correct)
|
||||
wpallstars_require_if_exists(WPALLSTARS_PATH . 'admin/data/pro-plugins.php');
|
||||
wpallstars_require_if_exists(WPALLSTARS_PATH . 'admin/data/readme.php');
|
||||
|
||||
// Load admin settings initialization file (if it sets up hooks, etc.)
|
||||
// Deprecated: Settings should be handled by Settings_Manager and Admin_Manager
|
||||
// wpallstars_require_if_exists(WPALLSTARS_PATH . 'admin/settings.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin activation hook.
|
||||
* Used for setting up default options, database tables (if any), etc.
|
||||
*/
|
||||
function wpallstars_activate() {
|
||||
// Example: Set default options on first activation
|
||||
if (get_option('wpallstars_version') === false) {
|
||||
update_option('wpallstars_version', WPALLSTARS_VERSION);
|
||||
// Add other default options here if needed
|
||||
// update_option('wpallstars_options', ['feature_x_enabled' => 1]);
|
||||
}
|
||||
// Optional: Clear rewrite rules if custom post types or taxonomies are added
|
||||
// flush_rewrite_rules();
|
||||
}
|
||||
register_activation_hook(__FILE__, 'wpallstars_activate');
|
||||
|
||||
/**
|
||||
* Plugin deactivation hook.
|
||||
* Used for cleanup tasks if necessary.
|
||||
*/
|
||||
function wpallstars_deactivate() {
|
||||
// Example: Remove scheduled tasks
|
||||
// wp_clear_scheduled_hook('wpallstars_daily_task');
|
||||
// Optional: Clear rewrite rules
|
||||
// flush_rewrite_rules();
|
||||
}
|
||||
register_deactivation_hook(__FILE__, 'wpallstars_deactivate');
|
||||
|
||||
|
||||
/**
|
||||
* Load the plugin text domain for localization.
|
||||
*/
|
||||
function wpallstars_load_textdomain() {
|
||||
load_plugin_textdomain(
|
||||
WPALLSTARS_TEXT_DOMAIN,
|
||||
false,
|
||||
dirname(WPALLSTARS_BASENAME) . '/languages'
|
||||
);
|
||||
}
|
||||
add_action('plugins_loaded', 'wpallstars_load_textdomain');
|
||||
|
||||
|
||||
/**
|
||||
* Initialize core plugin features after plugins are loaded.
|
||||
* This ensures that all necessary WordPress functions and classes are available.
|
||||
*/
|
||||
function wpallstars_init_features() {
|
||||
// Initialize Core Features
|
||||
if (class_exists('WPALLSTARS_Admin_Colors')) {
|
||||
new WPALLSTARS_Admin_Colors();
|
||||
}
|
||||
if (class_exists('WPALLSTARS_UI_Enhancements')) {
|
||||
new WPALLSTARS_UI_Enhancements();
|
||||
}
|
||||
|
||||
// Initialize Admin Area (if in admin context or AJAX)
|
||||
if ((is_admin() || (defined('DOING_AJAX') && DOING_AJAX)) && class_exists('WPALLSTARS_Admin_Manager')) {
|
||||
WPALLSTARS_Admin_Manager::instance(); // Use singleton pattern if implemented
|
||||
}
|
||||
}
|
||||
add_action('plugins_loaded', 'wpallstars_init_features', 10); // Priority 10 is standard
|
||||
|
||||
|
||||
/**
|
||||
* Initialize Auto Upload feature later on 'init'.
|
||||
* This ensures the user is logged in and potentially allows other plugins to load first.
|
||||
*/
|
||||
function wpallstars_init_auto_upload() {
|
||||
// Only initialize for logged-in users
|
||||
if (is_user_logged_in() && class_exists('WPALLSTARS_Auto_Upload')) {
|
||||
new WPALLSTARS_Auto_Upload();
|
||||
}
|
||||
}
|
||||
add_action('init', 'wpallstars_init_auto_upload');
|
||||
|
||||
|
||||
/**
|
||||
* Add settings link on the plugins page.
|
||||
*
|
||||
* @param array $links Existing plugin action links.
|
||||
* @return array Modified plugin action links.
|
||||
*/
|
||||
function wpallstars_add_settings_link($links) {
|
||||
$settings_link = sprintf(
|
||||
'<a href="%s">%s</a>',
|
||||
esc_url(admin_url('admin.php?page=wpallstars-settings')), // Match the menu slug from Admin_Manager
|
||||
esc_html__( 'Settings', WPALLSTARS_TEXT_DOMAIN )
|
||||
);
|
||||
array_unshift($links, $settings_link); // Add link to the beginning
|
||||
return $links;
|
||||
}
|
||||
add_filter('plugin_action_links_' . WPALLSTARS_BASENAME, 'wpallstars_add_settings_link');
|
||||
|
||||
// --- End of Plugin ---
|
||||
Reference in New Issue
Block a user