boot(); } return self::$instance; } /** * Capability required to manage AriConsent. * * @return string */ public static function capability() { /** * Filters the capability needed to manage AriConsent. * * @param string $capability Default 'manage_options'. */ return (string) apply_filters( 'ariconsent_capability', 'manage_options' ); } /** * Registers hooks. Nothing here calls translation functions, so it is safe before `init`. */ private function boot() { add_filter( 'lang_dir_for_domain', array( self::class, 'translation_dir' ), 10, 3 ); add_action( 'init', array( $this, 'init' ), 0 ); add_action( 'rest_api_init', array( Rest::class, 'register_routes' ) ); add_action( ConsentLog::CRON_HOOK, array( ConsentLog::class, 'purge_expired' ) ); WpConsentApi::register(); Health::register(); Multilingual::register(); CachePurge::register(); Cli::register(); if ( is_admin() ) { Admin\Admin::register(); Admin\Setup::register(); } /** * Fires after AriConsent has loaded. Extensions (such as AriConsent Pro) hook in here. */ do_action( 'ariconsent_loaded' ); } /** * Runs on init: upgrades and front-end hooks. WordPress loads the translations by itself. */ public function init() { Installer::maybe_upgrade(); add_shortcode( 'ariconsent_declaration', array( Declaration::class, 'shortcode' ) ); add_shortcode( 'ariconsent_settings', array( Declaration::class, 'settings_link_shortcode' ) ); if ( ! self::is_frontend_request() || ! Settings::get()['enabled'] ) { return; } add_action( 'wp_head', array( ConsentMode::class, 'print_defaults' ), -1000 ); add_action( 'wp_head', array( ConsentMode::class, 'print_microsoft_defaults' ), -1000 ); add_action( 'wp_head', array( Guard::class, 'print_guard' ), -999 ); add_action( 'wp_enqueue_scripts', array( Banner::class, 'enqueue' ) ); add_action( 'wp_body_open', array( Banner::class, 'print_markup' ), 1 ); add_action( 'wp_footer', array( Banner::class, 'print_markup' ), 1 ); // Fallback for themes without wp_body_open. add_action( 'template_redirect', array( Blocker::class, 'start' ), -1000 ); add_filter( 'wp_script_attributes', array( self::class, 'script_attributes' ) ); add_filter( 'wp_inline_script_attributes', array( self::class, 'script_attributes' ) ); } /** * Points WordPress at the translations shipped in languages/ when it has no WordPress.org * language pack for the locale, so a Norwegian, Swedish, Danish or Finnish site shows its own * language from the first day. WordPress only asks when it found no pack itself, so a pack from * translate.wordpress.org always wins once one exists. * * @param string|false $path Directory WordPress found, or false. * @param string $domain Text domain. * @param string $locale Locale. * @return string|false */ public static function translation_dir( $path, $domain, $locale ) { if ( 'ariconsent' !== $domain || false !== $path ) { return $path; } $dir = ARICONSENT_DIR . 'languages/'; if ( is_readable( $dir . 'ariconsent-' . $locale . '.l10n.php' ) || is_readable( $dir . 'ariconsent-' . $locale . '.mo' ) ) { return $dir; } return $path; } /** * Attributes that tell page optimisers to leave a script exactly where and as it is. * The consent defaults and the guard must run before every other script; if an optimiser * defers, combines or rewrites them, trackers can run first. * Autoptimize: data-noptimize. LiteSpeed Cache: data-no-optimize, data-no-defer. * Cloudflare Rocket Loader: data-cfasync. WP Rocket: nowprocket. Jetpack Boost: data-jetpack-boost. * PageSpeed: data-pagespeed-no-defer. * * @return array */ public static function no_optimize_attributes() { return array( 'data-cfasync' => 'false', 'data-noptimize' => '1', 'data-no-optimize' => '1', 'data-no-defer' => '1', 'data-pagespeed-no-defer' => true, 'data-jetpack-boost' => 'ignore', 'nowprocket' => true, ); } /** * Adds the no-optimise attributes to the banner script and its configuration. * * @param array $attributes Script tag attributes. * @return array */ public static function script_attributes( $attributes ) { if ( isset( $attributes['id'] ) && in_array( $attributes['id'], array( 'ariconsent-js', 'ariconsent-js-before' ), true ) ) { $attributes += self::no_optimize_attributes(); } return $attributes; } /** * Whether this request renders a public page (not admin, REST, AJAX, cron, feeds or the customizer). * * @return bool */ public static function is_frontend_request() { if ( is_admin() || wp_doing_ajax() || wp_doing_cron() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || ( defined( 'WP_CLI' ) && WP_CLI ) ) { return false; } if ( isset( $_SERVER['REQUEST_URI'] ) && false !== strpos( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), '/wp-json/' ) ) { return false; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only check for page builder preview modes. if ( isset( $_GET['elementor-preview'] ) || isset( $_GET['et_fb'] ) || isset( $_GET['bricks'] ) || isset( $_GET['fl_builder'] ) ) { return false; } /** * Filters whether AriConsent runs on this request. * * @param bool $run Whether to run. */ return (bool) apply_filters( 'ariconsent_run_on_request', true ); } }