plugin_url = plugin_dir_url(dirname(__FILE__));
$this->init();
}
public function init() {
// Check if frontend widget is enabled
if ($this->is_widget_enabled()) {
add_action('wp_enqueue_scripts', [$this, 'enqueue_frontend_scripts']);
add_action('wp_footer', [$this, 'render_widget_template']);
}
}
/**
* Check if frontend widget is enabled
*/
private function is_widget_enabled() {
return (bool) get_option('acb_frontend_widget_enabled', true);
}
/**
* Enqueue frontend scripts and styles
*/
public function enqueue_frontend_scripts() {
// Only load on frontend pages
if (is_admin()) {
return;
}
// Enqueue frontend widget styles
wp_enqueue_style(
'acb-frontend-widget-style',
esc_url($this->plugin_url . 'build/frontend-index.css'),
[],
'1.0.0'
);
wp_enqueue_style(
'font-awesome',
esc_url($this->plugin_url . 'assets/library/all.min.css'),
[],
'5.15.4'
);
// Enqueue frontend widget script
wp_enqueue_script(
'acb-frontend-widget-script',
esc_url($this->plugin_url . 'build/frontend-index.js'),
['jquery', 'wp-element'],
'1.0.0',
true
);
// Pass Firebase config and nonces to frontend
$firebase_config = get_option('acb_firebase_config', []);
// Sanitize Firebase config before passing to frontend
$sanitized_config = $this->sanitize_firebase_config($firebase_config);
wp_localize_script('acb-frontend-widget-script', 'acb_firebase_config', $sanitized_config);
wp_localize_script('acb-frontend-widget-script', 'acb_firebase_nonce', wp_create_nonce('acb_firebase_nonce'));
wp_localize_script('acb-frontend-widget-script', 'ajaxurl', esc_url(admin_url('admin-ajax.php')));
}
/**
* Sanitize Firebase config for frontend use
*/
private function sanitize_firebase_config($config) {
if (!is_array($config)) {
return [];
}
$sanitized = [];
$allowed_keys = ['apiKey', 'authDomain', 'projectId', 'storageBucket', 'messagingSenderId', 'appId'];
foreach ($allowed_keys as $key) {
if (isset($config[$key])) {
$sanitized[$key] = sanitize_text_field($config[$key]);
}
}
return $sanitized;
}
/**
* Render widget template in footer
*/
public function render_widget_template() {
// Only render if widget is enabled
if (!$this->is_widget_enabled()) {
return;
}
// Get widget settings with proper sanitization
$widget_position = sanitize_text_field(get_option('acb_widget_position', 'bottom-right'));
$widget_title = sanitize_text_field(get_option('acb_widget_title', 'Chat Support'));
$widget_description = sanitize_text_field(get_option('acb_widget_description', 'Need help? Chat with our team!'));
// Validate position value
$allowed_positions = ['bottom-right', 'bottom-left', 'top-right', 'top-left'];
if (!in_array($widget_position, $allowed_positions, true)) {
$widget_position = 'bottom-right';
}
?>
(bool) get_option('acb_frontend_widget_enabled', false),
'position' => sanitize_text_field(get_option('acb_widget_position', 'bottom-right')),
'title' => sanitize_text_field(get_option('acb_widget_title', 'Chat Support')),
'description' => sanitize_text_field(get_option('acb_widget_description', 'Need help? Chat with our team!')),
'show_on_pages' => sanitize_text_field(get_option('acb_widget_show_on_pages', 'all')),
'exclude_pages' => sanitize_textarea_field(get_option('acb_widget_exclude_pages', '')),
];
}
/**
* Save widget settings with proper validation and sanitization
*/
public static function save_widget_settings($settings) {
// Verify nonce if this is an AJAX request
if (wp_doing_ajax()) {
if (!wp_verify_nonce($_POST['nonce'] ?? '', 'acb_widget_settings_nonce')) {
wp_send_json_error(['message' => 'Invalid security token']);
return false;
}
}
// Check user capabilities
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'Insufficient permissions']);
return false;
}
// Validate and sanitize input
if (!is_array($settings)) {
wp_send_json_error(['message' => 'Invalid settings format']);
return false;
}
// Sanitize enabled setting
$enabled = isset($settings['enabled']) ? (bool) $settings['enabled'] : false;
update_option('acb_frontend_widget_enabled', $enabled);
// Sanitize and validate position
$position = sanitize_text_field($settings['position'] ?? 'bottom-right');
$allowed_positions = ['bottom-right', 'bottom-left', 'top-right', 'top-left'];
if (!in_array($position, $allowed_positions, true)) {
$position = 'bottom-right';
}
update_option('acb_widget_position', $position);
// Sanitize text fields
$title = sanitize_text_field($settings['title'] ?? 'Chat Support');
$title = wp_unslash($title); // Remove slashes if any
if (strlen($title) > 100) { // Limit title length
$title = substr($title, 0, 100);
}
update_option('acb_widget_title', $title);
$description = sanitize_textarea_field($settings['description'] ?? 'Need help? Chat with our team!');
$description = wp_unslash($description); // Remove slashes if any
if (strlen($description) > 500) { // Limit description length
$description = substr($description, 0, 500);
}
update_option('acb_widget_description', $description);
// Sanitize show_on_pages
$show_on_pages = sanitize_text_field($settings['show_on_pages'] ?? 'all');
$allowed_show_options = ['all', 'specific', 'exclude'];
if (!in_array($show_on_pages, $allowed_show_options, true)) {
$show_on_pages = 'all';
}
update_option('acb_widget_show_on_pages', $show_on_pages);
// Sanitize exclude_pages
$exclude_pages = sanitize_textarea_field($settings['exclude_pages'] ?? '');
$exclude_pages = wp_unslash($exclude_pages); // Remove slashes if any
// Validate page IDs if provided
if (!empty($exclude_pages)) {
$page_ids = array_map('trim', explode(',', $exclude_pages));
$valid_page_ids = [];
foreach ($page_ids as $page_id) {
$page_id = absint($page_id); // Ensure positive integer
if ($page_id > 0) {
$valid_page_ids[] = $page_id;
}
}
$exclude_pages = implode(',', $valid_page_ids);
}
update_option('acb_widget_exclude_pages', $exclude_pages);
// Send success response for AJAX requests
if (wp_doing_ajax()) {
wp_send_json_success(['message' => 'Settings saved successfully']);
}
return true;
}
/**
* Check if widget should be displayed on current page
*/
private function should_display_widget() {
$show_on_pages = get_option('acb_widget_show_on_pages', 'all');
$exclude_pages = get_option('acb_widget_exclude_pages', '');
$current_page_id = get_the_ID();
// If excluding specific pages
if (!empty($exclude_pages) && $current_page_id) {
$excluded_ids = array_map('absint', explode(',', $exclude_pages));
if (in_array($current_page_id, $excluded_ids, true)) {
return false;
}
}
// Additional display logic can be added here
return true;
}
/**
* AJAX handler for widget settings
*/
public static function ajax_save_widget_settings() {
// This method would be called via AJAX
// The nonce verification is handled in save_widget_settings()
$settings = $_POST['settings'] ?? [];
// Unslash the entire settings array
$settings = wp_unslash($settings);
self::save_widget_settings($settings);
}
}