xpath_engine = $xpath_engine; $this->options_repository = $options_repository; $this->logger = $logger; } /** * Initialize output buffering. */ public function init(): void { // Start output buffering for frontend add_action('template_redirect', [$this, 'start_output_buffering']); // Start output buffering for admin pages add_action('admin_init', [$this, 'start_output_buffering']); } /** * Start output buffering. */ public function start_output_buffering(): void { if (!$this->should_process_output()) { return; } // Start output buffering for processing HTML // Note: WordPress and other plugins may already have buffers active, // but we can still add our own buffer to the stack ob_start([$this, 'process_output']); } /** * Process the output buffer content. * * @param string $content * @return string */ public function process_output(string $content): string { if (empty($content) || $this->is_xml_content($content)) { return $content; } try { $rules = $this->options_repository->get_active_rules(); // Check if selection mode is active (from sessionStorage via JavaScript) $is_selection_mode = $this->is_selection_mode_active(); // Debug: log HTML size and check for WBCR $has_wbcr = strpos($content, 'id="WBCR"') !== false; $this->logger->debug('Output buffer received HTML', [ 'size' => strlen($content), 'has_wbcr' => $has_wbcr, 'has_wpbody' => strpos($content, 'id="wpbody-content"') !== false ]); return $this->xpath_engine->process_html($content, $rules, $is_selection_mode); } catch (\Exception $e) { // Log error but don't break the page if ($this->logger) { $this->logger->error('Error processing output', ['message' => $e->getMessage()]); } else { error_log('AdsDestroyer: Error processing output - ' . $e->getMessage()); } return $content; } } /** * Check if output processing should be enabled. * * @return bool */ private function should_process_output(): bool { // Allow processing admin pages for block hiding // This enables hiding blocks on admin pages when rules are created there // Don't process AJAX requests if (wp_doing_ajax()) { return false; } // Don't process REST API requests if (defined('REST_REQUEST') && REST_REQUEST) { return false; } // Don't process if no rules are configured $rules = $this->options_repository->get_active_rules(); if (empty($rules)) { return false; } return true; } /** * Check if content is XML (not HTML). * * @param string $content * @return bool */ private function is_xml_content(string $content): bool { $trimmed = trim($content); return str_starts_with($trimmed, '