Files
Instagram-Gallery-Sync-Pro/includes/class-admin.php

535 lines
18 KiB
PHP

<?php
/**
* Admin Class
*
* Handles all admin functionality including settings pages and AJAX handlers.
*
* @package Instagram_Gallery_Sync_Pro
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
/**
* Class IGSP_Admin
*/
class IGSP_Admin
{
/**
* Settings page slug
*
* @var string
*/
const PAGE_SLUG = 'instagram-gallery-sync-pro';
/**
* Initialize admin
*
* @return void
*/
public function init()
{
// Add admin menu
add_action('admin_menu', array($this, 'add_admin_menu'));
// Register settings
add_action('admin_init', array($this, 'register_settings'));
// Enqueue admin assets
add_action('admin_enqueue_scripts', array($this, 'enqueue_assets'));
// AJAX handlers
add_action('wp_ajax_igsp_manual_sync', array($this, 'ajax_manual_sync'));
add_action('wp_ajax_igsp_clear_cache', array($this, 'ajax_clear_cache'));
add_action('wp_ajax_igsp_reset_data', array($this, 'ajax_reset_data'));
add_action('wp_ajax_igsp_get_sync_status', array($this, 'ajax_get_sync_status'));
add_action('wp_ajax_igsp_clear_logs', array($this, 'ajax_clear_logs'));
add_action('wp_ajax_igsp_delete_post', array($this, 'ajax_delete_post'));
add_action('wp_ajax_igsp_toggle_post', array($this, 'ajax_toggle_post'));
add_action('wp_ajax_igsp_add_manual_post', array($this, 'ajax_add_manual_post'));
// Add settings link to plugins page
add_filter('plugin_action_links_' . IGSP_PLUGIN_BASENAME, array($this, 'add_settings_link'));
}
/**
* Add admin menu
*
* @return void
*/
public function add_admin_menu()
{
add_menu_page(
__('Instagram Gallery', 'instagram-gallery-sync-pro'),
__('Instagram Gallery', 'instagram-gallery-sync-pro'),
'manage_options',
self::PAGE_SLUG,
array($this, 'render_settings_page'),
'dashicons-instagram',
30
);
}
/**
* Register settings
*
* @return void
*/
public function register_settings()
{
// Instagram settings
register_setting('igsp_instagram_settings', 'igsp_username', 'sanitize_text_field');
register_setting('igsp_instagram_settings', 'igsp_max_images', 'absint');
register_setting('igsp_instagram_settings', 'igsp_save_locally', 'sanitize_text_field');
register_setting('igsp_instagram_settings', 'igsp_image_quality', 'sanitize_text_field');
register_setting('igsp_instagram_settings', 'igsp_sync_interval', 'sanitize_text_field');
// Layout settings
register_setting('igsp_layout_settings', 'igsp_layout_type', 'sanitize_text_field');
register_setting('igsp_layout_settings', 'igsp_layout_type_tablet', 'sanitize_text_field');
register_setting('igsp_layout_settings', 'igsp_layout_type_mobile', 'sanitize_text_field');
register_setting('igsp_layout_settings', 'igsp_columns_desktop', 'absint');
register_setting('igsp_layout_settings', 'igsp_columns_tablet', 'absint');
register_setting('igsp_layout_settings', 'igsp_columns_mobile', 'absint');
register_setting('igsp_layout_settings', 'igsp_spacing', 'absint');
register_setting('igsp_layout_settings', 'igsp_padding', 'absint');
register_setting('igsp_layout_settings', 'igsp_aspect_ratio', 'sanitize_text_field');
register_setting('igsp_layout_settings', 'igsp_object_fit', 'sanitize_text_field');
register_setting('igsp_layout_settings', 'igsp_border_radius', 'absint');
register_setting('igsp_layout_settings', 'igsp_hover_effect', 'sanitize_text_field');
// Slider settings
register_setting('igsp_layout_settings', 'igsp_slider_autoplay', 'sanitize_text_field');
register_setting('igsp_layout_settings', 'igsp_slider_delay', 'absint');
register_setting('igsp_layout_settings', 'igsp_slider_pause_hover', 'sanitize_text_field');
// Display settings
register_setting('igsp_display_settings', 'igsp_display_limit', 'absint');
register_setting('igsp_display_settings', 'igsp_order', 'sanitize_text_field');
register_setting('igsp_display_settings', 'igsp_show_caption', 'sanitize_text_field');
register_setting('igsp_display_settings', 'igsp_caption_position', 'sanitize_text_field');
register_setting('igsp_display_settings', 'igsp_show_instagram_btn', 'sanitize_text_field');
register_setting('igsp_display_settings', 'igsp_instagram_btn_text', 'sanitize_text_field');
register_setting('igsp_display_settings', 'igsp_link_behavior', 'sanitize_text_field');
register_setting('igsp_display_settings', 'igsp_lightbox', 'sanitize_text_field');
register_setting('igsp_display_settings', 'igsp_lazy_loading', 'sanitize_text_field');
register_setting('igsp_display_settings', 'igsp_loader_type', 'sanitize_text_field');
// Styling settings
register_setting('igsp_styling_settings', 'igsp_primary_color', 'sanitize_hex_color');
register_setting('igsp_styling_settings', 'igsp_hover_color', 'sanitize_hex_color');
register_setting('igsp_styling_settings', 'igsp_text_color', 'sanitize_hex_color');
register_setting('igsp_styling_settings', 'igsp_caption_font_size', 'absint');
register_setting('igsp_styling_settings', 'igsp_custom_css', array($this, 'sanitize_css'));
register_setting('igsp_styling_settings', 'igsp_css_prefix', 'sanitize_text_field');
// Advanced settings
register_setting('igsp_advanced_settings', 'igsp_debug_mode', 'sanitize_text_field');
register_setting('igsp_advanced_settings', 'igsp_cache_duration', 'absint');
register_setting('igsp_advanced_settings', 'igsp_request_timeout', 'absint');
register_setting('igsp_advanced_settings', 'igsp_user_agent', 'sanitize_text_field');
register_setting('igsp_advanced_settings', 'igsp_proxy_host', 'sanitize_text_field');
register_setting('igsp_advanced_settings', 'igsp_proxy_port', 'absint');
register_setting('igsp_advanced_settings', 'igsp_auto_delete_days', 'absint');
}
/**
* Sanitize CSS input
*
* @param string $css CSS string
* @return string
*/
public function sanitize_css($css)
{
// Remove any script tags
$css = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $css);
// Remove javascript: URLs
$css = preg_replace('/javascript\s*:/i', '', $css);
// Remove expression()
$css = preg_replace('/expression\s*\(/i', '', $css);
// Remove behavior: (IE specific)
$css = preg_replace('/behavior\s*:/i', '', $css);
return wp_strip_all_tags($css);
}
/**
* Enqueue admin assets
*
* @param string $hook Current page hook
* @return void
*/
public function enqueue_assets($hook)
{
if (strpos($hook, self::PAGE_SLUG) === false) {
return;
}
// Admin CSS
wp_enqueue_style(
'igsp-admin-style',
IGSP_PLUGIN_URL . 'admin/css/admin-style.css',
array(),
IGSP_VERSION . '.' . time()
);
// WordPress components
wp_enqueue_style('wp-color-picker');
// WordPress Media Library
wp_enqueue_media();
// Admin JS
wp_enqueue_script(
'igsp-admin-script',
IGSP_PLUGIN_URL . 'admin/js/admin-script.js',
array('jquery', 'wp-color-picker', 'media-upload'),
IGSP_VERSION . '.' . time(),
true
);
// AJAX Sync JS
wp_enqueue_script(
'igsp-ajax-sync',
IGSP_PLUGIN_URL . 'admin/js/ajax-sync.js',
array('jquery'),
IGSP_VERSION . '.' . time(),
true
);
// Localize script
wp_localize_script('igsp-admin-script', 'igspAdmin', array(
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('igsp_admin_nonce'),
'strings' => array(
'syncing' => __('Syncing...', 'instagram-gallery-sync-pro'),
'syncComplete' => __('Sync complete!', 'instagram-gallery-sync-pro'),
'syncError' => __('Sync failed. Check logs for details.', 'instagram-gallery-sync-pro'),
'confirmReset' => __('Are you sure? This will delete ALL Instagram data including images. This action cannot be undone.', 'instagram-gallery-sync-pro'),
'confirmClearLogs' => __('Are you sure you want to clear all logs?', 'instagram-gallery-sync-pro'),
'confirmDeletePost' => __('Are you sure you want to delete this post?', 'instagram-gallery-sync-pro'),
'processing' => __('Processing...', 'instagram-gallery-sync-pro'),
'done' => __('Done!', 'instagram-gallery-sync-pro'),
'postAdded' => __('Post added successfully!', 'instagram-gallery-sync-pro'),
'postDeleted' => __('Post deleted.', 'instagram-gallery-sync-pro'),
'selectImage' => __('Select Image', 'instagram-gallery-sync-pro'),
'useImage' => __('Use this image', 'instagram-gallery-sync-pro'),
),
));
}
/**
* Render settings page
*
* @return void
*/
public function render_settings_page()
{
// Check permissions
if (!current_user_can('manage_options')) {
wp_die(__('You do not have sufficient permissions to access this page.', 'instagram-gallery-sync-pro'));
}
include IGSP_PLUGIN_DIR . 'admin/views/settings-page.php';
}
/**
* Add settings link to plugins page
*
* @param array $links Existing links
* @return array
*/
public function add_settings_link($links)
{
$settings_link = sprintf(
'<a href="%s">%s</a>',
admin_url('admin.php?page=' . self::PAGE_SLUG),
__('Settings', 'instagram-gallery-sync-pro')
);
array_unshift($links, $settings_link);
return $links;
}
/**
* AJAX: Manual sync
*
* @return void
*/
public function ajax_manual_sync()
{
check_ajax_referer('igsp_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'instagram-gallery-sync-pro')));
}
$cron = new IGSP_Cron();
$result = $cron->manual_sync();
if ($result['success']) {
wp_send_json_success($result);
} else {
wp_send_json_error($result);
}
}
/**
* AJAX: Clear cache
*
* @return void
*/
public function ajax_clear_cache()
{
check_ajax_referer('igsp_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'instagram-gallery-sync-pro')));
}
igsp()->clear_transients();
wp_send_json_success(array('message' => __('Cache cleared successfully.', 'instagram-gallery-sync-pro')));
}
/**
* AJAX: Reset all data
*
* @return void
*/
public function ajax_reset_data()
{
check_ajax_referer('igsp_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'instagram-gallery-sync-pro')));
}
// Delete all posts from database
$database = new IGSP_Database();
$database->delete_all_posts();
// Clear all images
$image_handler = new IGSP_Image_Handler();
$image_handler->clear_all_images();
// Clear logs
$logger = new IGSP_Logger();
$logger->clear_logs();
// Clear transients
igsp()->clear_transients();
// Reset last sync
update_option('igsp_last_sync', '');
wp_send_json_success(array('message' => __('All data has been reset.', 'instagram-gallery-sync-pro')));
}
/**
* AJAX: Get sync status
*
* @return void
*/
public function ajax_get_sync_status()
{
check_ajax_referer('igsp_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'instagram-gallery-sync-pro')));
}
$cron = new IGSP_Cron();
$status = $cron->get_sync_status();
wp_send_json_success($status);
}
/**
* AJAX: Clear logs
*
* @return void
*/
public function ajax_clear_logs()
{
check_ajax_referer('igsp_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'instagram-gallery-sync-pro')));
}
$logger = new IGSP_Logger();
$logger->clear_logs();
wp_send_json_success(array('message' => __('Logs cleared successfully.', 'instagram-gallery-sync-pro')));
}
/**
* Get current tab
*
* @return string
*/
public function get_current_tab()
{
return isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'instagram';
}
/**
* Get tabs configuration
*
* @return array
*/
public function get_tabs()
{
return array(
'instagram' => array(
'title' => __('Instagram', 'instagram-gallery-sync-pro'),
'icon' => 'dashicons-instagram',
),
'posts' => array(
'title' => __('Posts', 'instagram-gallery-sync-pro'),
'icon' => 'dashicons-images-alt2',
),
'layout' => array(
'title' => __('Layout', 'instagram-gallery-sync-pro'),
'icon' => 'dashicons-grid-view',
),
'display' => array(
'title' => __('Display', 'instagram-gallery-sync-pro'),
'icon' => 'dashicons-visibility',
),
'styling' => array(
'title' => __('Styling', 'instagram-gallery-sync-pro'),
'icon' => 'dashicons-art',
),
'advanced' => array(
'title' => __('Advanced', 'instagram-gallery-sync-pro'),
'icon' => 'dashicons-admin-generic',
),
);
}
/**
* AJAX: Delete single post
*
* @return void
*/
public function ajax_delete_post()
{
check_ajax_referer('igsp_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'instagram-gallery-sync-pro')));
}
$post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
if (!$post_id) {
wp_send_json_error(array('message' => __('Invalid post ID.', 'instagram-gallery-sync-pro')));
}
$database = new IGSP_Database();
$result = $database->delete_post($post_id);
if ($result) {
// Clear gallery cache
igsp()->clear_transients();
wp_send_json_success(array('message' => __('Post deleted successfully.', 'instagram-gallery-sync-pro')));
} else {
wp_send_json_error(array('message' => __('Failed to delete post.', 'instagram-gallery-sync-pro')));
}
}
/**
* AJAX: Toggle post active/inactive
*
* @return void
*/
public function ajax_toggle_post()
{
check_ajax_referer('igsp_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'instagram-gallery-sync-pro')));
}
$post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
if (!$post_id) {
wp_send_json_error(array('message' => __('Invalid post ID.', 'instagram-gallery-sync-pro')));
}
$database = new IGSP_Database();
$result = $database->toggle_post_active($post_id);
if ($result) {
$post = $database->get_post($post_id);
igsp()->clear_transients();
wp_send_json_success(array(
'message' => __('Post status updated.', 'instagram-gallery-sync-pro'),
'is_active' => (bool) $post->is_active,
));
} else {
wp_send_json_error(array('message' => __('Failed to update post status.', 'instagram-gallery-sync-pro')));
}
}
/**
* AJAX: Add manual post
*
* @return void
*/
public function ajax_add_manual_post()
{
check_ajax_referer('igsp_admin_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'instagram-gallery-sync-pro')));
}
$attachment_id = isset($_POST['attachment_id']) ? absint($_POST['attachment_id']) : 0;
$post_url = isset($_POST['post_url']) ? esc_url_raw($_POST['post_url']) : '';
$caption = isset($_POST['caption']) ? wp_kses_post($_POST['caption']) : '';
$posted_at = isset($_POST['posted_at']) ? sanitize_text_field($_POST['posted_at']) : '';
if (!$attachment_id) {
wp_send_json_error(array('message' => __('Please select an image.', 'instagram-gallery-sync-pro')));
}
// Copy from Media Library to plugin upload directory
$image_handler = new IGSP_Image_Handler();
$image_result = $image_handler->save_from_media_library($attachment_id);
if (is_wp_error($image_result)) {
wp_send_json_error(array('message' => $image_result->get_error_message()));
}
// Insert into database
$database = new IGSP_Database();
$result = $database->insert_manual_post(array(
'image_local_path' => $image_result['local_path'],
'image_thumbnail_path' => $image_result['thumbnail_path'],
'post_url' => $post_url,
'caption' => $caption,
'posted_at' => $posted_at,
'file_size' => $image_result['file_size'],
'image_width' => $image_result['width'],
'image_height' => $image_result['height'],
));
if ($result) {
igsp()->clear_transients();
wp_send_json_success(array('message' => __('Post added successfully!', 'instagram-gallery-sync-pro')));
} else {
wp_send_json_error(array('message' => __('Failed to add post.', 'instagram-gallery-sync-pro')));
}
}
}