400)); } if (version_compare(PHP_VERSION, '8.1', '<')) { wp_die(esc_html__('CommentMate requires PHP 8.1 or newer.', 'commentmate'), '', array('response' => 400)); } if (!function_exists('sodium_crypto_secretstream_xchacha20poly1305_init_push')) { wp_die(esc_html__('CommentMate requires the PHP Sodium extension.', 'commentmate'), '', array('response' => 400)); } if (version_compare(get_bloginfo('version'), '6.5', '<')) { wp_die(esc_html__('CommentMate requires WordPress 6.5 or newer.', 'commentmate'), '', array('response' => 400)); } if (!Database::install()) { wp_die(esc_html__('CommentMate could not create its required database tables. Check database permissions and retry activation.', 'commentmate'), '', array('response' => 500)); } Capabilities::install(); if (!Private_Storage::ensure_directory()) { wp_die(esc_html__('CommentMate could not create its private review-storage directory. Check filesystem permissions and retry activation.', 'commentmate'), '', array('response' => 500)); } if (!add_option('commentmate_version', COMMENTMATE_VERSION, '', false)) { update_option('commentmate_version', COMMENTMATE_VERSION, false); } // Default to final data removal only when the site owner uses WordPress's // normal plugin Delete action. Deactivation always preserves review data. add_option('commentmate_delete_data_on_uninstall', '1', '', false); Notification_Service::activate(); } /** * Deactivation deliberately preserves all review data; explicit cleanup or * uninstall is required to erase it. */ public static function deactivate(): void { wp_clear_scheduled_hook('commentmate_cleanup_cron'); Notification_Service::deactivate(); } public function boot(): void { if ($this->booted) { return; } $this->booted = true; add_action('admin_notices', array($this, 'https_notice')); if (!Database::maybe_upgrade()) { add_action('admin_notices', array($this, 'database_upgrade_notice')); return; } $this->record_running_version(); do_action('commentmate_loaded', COMMENTMATE_VERSION, 1); Notification_Service::register(); (new Compatibility_Service())->register(); (new Rest_Controller())->register(); (new Admin())->register(); add_action('init', array($this, 'protect_review_request'), 0); add_action('template_redirect', array($this, 'send_review_headers'), 0); add_filter('wp_robots', array($this, 'noindex_review_request')); add_action('wp_enqueue_scripts', array($this, 'enqueue_review_assets')); } /** * Sets the conventional cache-plugin flag as early as WordPress permits; * most cache plugins also honour the explicit headers sent later. */ public function protect_review_request(): void { if (!$this->is_review_request()) { return; } if (!defined('DONOTCACHEPAGE')) { define('DONOTCACHEPAGE', true); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound -- Established third-party page-cache opt-out protocol; the name must match cache plugins. } } public function send_review_headers(): void { if ($this->is_review_request()) { Security::send_no_cache_headers(); } } /** * @param array $robots * @return array */ public function noindex_review_request(array $robots): array { if ($this->is_review_request()) { $robots['noindex'] = true; $robots['nofollow'] = true; $robots['noarchive'] = true; } return $robots; } /** * Enqueues the locally bundled frontend only when review mode is explicitly * requested. Ordinary public visitors receive no CommentMate asset or layout * change. */ public function enqueue_review_assets(): void { if (!$this->is_review_request()) { return; } $relative_file = 'assets/build/commentmate.js'; $absolute_file = COMMENTMATE_PATH . $relative_file; if (!is_readable($absolute_file)) { return; } wp_enqueue_script( 'commentmate', COMMENTMATE_URL . $relative_file, array('wp-i18n'), COMMENTMATE_VERSION . '.' . (string) filemtime($absolute_file), true ); wp_set_script_translations('commentmate', 'commentmate', COMMENTMATE_PATH . 'languages'); wp_enqueue_style( 'commentmate-bridge', COMMENTMATE_URL . 'assets/styles/bridge.css', array(), COMMENTMATE_VERSION . '.' . (string) filemtime(COMMENTMATE_PATH . 'assets/styles/bridge.css') ); wp_localize_script( 'commentmate', 'CommentMateSettings', array( 'restUrl' => rest_url(Rest_Controller::NAMESPACE . '/'), 'pluginUrl' => COMMENTMATE_URL, 'reviewParam' => 'review', 'isMobile' => wp_is_mobile(), 'session' => null, // Only a site administrator receives a WordPress REST nonce. It is // never exposed to ordinary review guests and enables the owner-only // context view without reusing a share-link secret. 'admin' => Owner::can_manage_current_user() ? array( 'nonce' => wp_create_nonce('wp_rest'), ) : null, ) ); } /** Explain the HTTPS requirement only where administrators manage this plugin. */ public function https_notice(): void { if (is_ssl() || !current_user_can('manage_options')) { return; } $screen = get_current_screen(); if (null === $screen || (!in_array($screen->id, array('plugins', 'toplevel_page_commentmate'), true) && !str_starts_with($screen->id, 'commentmate_page_'))) { return; } ?>