options_repository = $options_repository; } /** * Initialize admin bar functionality. */ public function init(): void { add_action('admin_bar_menu', [$this, 'add_admin_bar_button'], 999); add_action('wp_enqueue_scripts', [$this, 'enqueue_admin_bar_assets']); add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_bar_assets']); // Initialize pointer/tooltip for first-time users add_action('admin_enqueue_scripts', [$this, 'enqueue_pointer_scripts']); add_action('wp_ajax_adsd_dismiss_pointer', [$this, 'handle_dismiss_pointer']); } /** * Add toggle button to admin bar. * * @param \WP_Admin_Bar $wp_admin_bar */ public function add_admin_bar_button(\WP_Admin_Bar $wp_admin_bar): void { // Only show button in admin area, not on frontend if (!is_admin()) { return; } if (!$this->can_user_access_selection_mode()) { return; } $is_active = $this->is_selection_mode_active(); // Generate URL with or without selection mode parameter $current_url = $this->get_current_url(); $href = $is_active ? $this->remove_selection_mode_param($current_url) : $this->add_selection_mode_param($current_url); $button_title = $is_active ? __('Exit selection mode', 'ads-destroyer') : __('Disable ad', 'ads-destroyer'); // Tooltip text with helpful description $tooltip = $is_active ? esc_attr__('Exit selection mode', 'ads-destroyer') : esc_attr__('Click to hide any elements in the admin area: ads, notices, confidential information, menus, and more', 'ads-destroyer'); $wp_admin_bar->add_node([ 'id' => 'adsd-toggle', 'title' => esc_html($button_title), 'href' => $href, 'meta' => [ 'title' => $tooltip, 'class' => $is_active ? 'adsd-selection-active' : '', ], ]); } /** * Enqueue admin bar assets. */ public function enqueue_admin_bar_assets(): void { if (!$this->can_user_access_selection_mode()) { return; } // Only load assets if selection mode is active OR we're on admin pages (settings page) $is_selection_mode_active = $this->is_selection_mode_active(); $is_admin_page = is_admin(); if (!$is_selection_mode_active && !$is_admin_page) { return; } // Enqueue CSS file for overlay styles wp_enqueue_style( 'adsd-style', plugin_dir_url(\ADSD_PLUGIN_FILE) . 'build/css/style.min.css', [], ADSD_PLUGIN_VERSION ); wp_enqueue_script( 'adsd-app', plugin_dir_url(\ADSD_PLUGIN_FILE) . 'build/js/app.js', ['jquery'], ADSD_PLUGIN_VERSION, true ); wp_localize_script('adsd-app', 'adsdData', [ 'ajaxUrl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('adsd_selection_mode'), 'isActive' => $is_selection_mode_active, 'strings' => [ 'enable' => __('Enable Selection Mode', 'ads-destroyer'), 'disable' => __('Disable Selection Mode', 'ads-destroyer'), 'selecting' => __('Selecting...', 'ads-destroyer'), ], ]); // Also create ADSD_CONFIG for compatibility with REST API wp_localize_script('adsd-app', 'ADSD_CONFIG', [ 'rest_url' => rest_url('adsd/v1'), 'nonce' => wp_create_nonce('wp_rest'), 'is_active' => $is_selection_mode_active, ]); } /** * Check if user can access selection mode. * * @return bool */ private function can_user_access_selection_mode(): bool { $allowed_roles = $this->options_repository->get_option('allowed_roles', ['administrator']); $user = wp_get_current_user(); if (!$user || !$user->ID) { return false; } return !empty(array_intersect($user->roles, $allowed_roles)); } /** * Check if selection mode is currently active. * * @return bool */ private function is_selection_mode_active(): bool { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- URL parameter check, not form submission return isset($_GET['adsd_selection_mode_active']) && sanitize_text_field(wp_unslash($_GET['adsd_selection_mode_active'])) === '1'; } /** * Get current URL. * * @return string */ private function get_current_url(): string { // Use WordPress function to get current URL $request_uri = isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : ''; return home_url($request_uri); } /** * Add selection mode parameter to URL. * * @param string $url * @return string */ private function add_selection_mode_param(string $url): string { return add_query_arg('adsd_selection_mode_active', '1', $url); } /** * Remove selection mode parameter from URL. * * @param string $url * @return string */ private function remove_selection_mode_param(string $url): string { return remove_query_arg('adsd_selection_mode_active', $url); } /** * Get button title based on state. * * @param bool $is_active * @return string */ private function get_button_title(bool $is_active): string { return __('Disable ad', 'ads-destroyer'); } /** * Enqueue WordPress pointer scripts for tooltip guide. * * @since 1.0.24 */ public function enqueue_pointer_scripts(): void { // Only show to users who can access selection mode if (!$this->can_user_access_selection_mode()) { return; } // Allow forcing pointer display via URL parameter (for testing) // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- URL parameter check, not form submission $force_pointer = isset($_GET['adsd_show_pointer']) && sanitize_text_field(wp_unslash($_GET['adsd_show_pointer'])) === '1'; // Check if user has already seen the pointer $dismissed_pointers = get_user_meta(get_current_user_id(), 'dismissed_wp_pointers', true); $dismissed_pointers = explode(',', (string) $dismissed_pointers); $pointer_id = 'adsd_admin_bar_pointer_v124'; // If user already dismissed this pointer and not forcing, don't show it if (!$force_pointer && in_array($pointer_id, $dismissed_pointers, true)) { return; } // Enqueue WordPress pointer scripts and styles wp_enqueue_style('wp-pointer'); wp_enqueue_script('wp-pointer'); // Add inline script to initialize the pointer add_action('admin_print_footer_scripts', function() use ($pointer_id) { $this->render_pointer_script($pointer_id); }); } /** * Render pointer JavaScript. * * @since 1.0.24 * @param string $pointer_id Unique pointer identifier */ private function render_pointer_script(string $pointer_id): void { $pointer_content = '
' . esc_html__('Click this button to hide any elements in the admin area: ads, notices, confidential information, menus, and more.', 'ads-destroyer') . '
'; $pointer_content .= '' . esc_html__('How it works:', 'ads-destroyer') . '
'; $pointer_content .= '