options['general']['caching_compatibility']; // if it is enabled allow immediately if ( $db_cc ) return true; // check caching compatibility before it is saved, needed when we change caching_compatibility from false to true if ( ! ( isset( $_POST['save_cookie_notice_options'], $_POST['action'], $_POST['_wpnonce'], $_POST['option_page'], $_POST['cookie_notice_options'] ) && $_POST['option_page'] === 'cookie_notice_options' && wp_verify_nonce( $_POST['_wpnonce'], 'cookie_notice_options-options' ) !== false ) ) return false; // check availability of caching compatibility itself if ( ! isset( $_POST['cookie_notice_options']['caching_compatibility'] ) ) return false; // get active caching plugins $active_plugins = cn_get_active_caching_plugins(); // return caching compatibility on the fly return ! empty( $active_plugins ); } /** * Load additional modules. * * @return void */ public function load_modules() { // caching compatibility enabled? if ( $this->is_caching_compatibility() && Cookie_Notice()->get_status() === 'active' ) { // autoptimize if ( cn_is_plugin_active( 'autoptimize' ) ) include_once( COOKIE_NOTICE_PATH . 'includes/modules/autoptimize/autoptimize.php' ); // breeze if ( cn_is_plugin_active( 'breeze' ) ) include_once( COOKIE_NOTICE_PATH . 'includes/modules/breeze/breeze.php' ); // hummingbird if ( cn_is_plugin_active( 'hummingbird' ) ) include_once( COOKIE_NOTICE_PATH . 'includes/modules/hummingbird/hummingbird.php' ); // litespeed cache if ( cn_is_plugin_active( 'litespeed' ) ) include_once( COOKIE_NOTICE_PATH . 'includes/modules/litespeed-cache/litespeed-cache.php' ); // speedycache if ( cn_is_plugin_active( 'speedycache' ) ) include_once( COOKIE_NOTICE_PATH . 'includes/modules/speedycache/speedycache.php' ); // speed optimizer if ( cn_is_plugin_active( 'speedoptimizer' ) ) include_once( COOKIE_NOTICE_PATH . 'includes/modules/speed-optimizer/speed-optimizer.php' ); // wp fastest cache if ( cn_is_plugin_active( 'wpfastestcache' ) ) include_once( COOKIE_NOTICE_PATH . 'includes/modules/wp-fastest-cache/wp-fastest-cache.php' ); // wp-optimize if ( cn_is_plugin_active( 'wpoptimize' ) ) include_once( COOKIE_NOTICE_PATH . 'includes/modules/wp-optimize/wp-optimize.php' ); // wp rocket if ( cn_is_plugin_active( 'wprocket' ) ) include_once( COOKIE_NOTICE_PATH . 'includes/modules/wp-rocket/wp-rocket.php' ); // wp super cache if ( cn_is_plugin_active( 'wpsupercache' ) ) include_once( COOKIE_NOTICE_PATH . 'includes/modules/wp-super-cache/wp-super-cache.php' ); } } /** * Load plugin defaults. * * @return void */ public function load_defaults() { // set tabs $this->tabs = [ 'settings' => __( 'Cookie Consent', 'cookie-notice' ), 'privacy-consent' => __( 'Privacy Consent', 'cookie-notice' ), 'consent-logs' => __( 'Consent Logs', 'cookie-notice' ) ]; // get first default tab $first_tab = array_key_first( $this->tabs ); // sanitize current tab $tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : $first_tab; // set current tab $this->current_tab = ! empty( $tab ) && array_key_exists( $tab, $this->tabs ) ? $tab : $first_tab; if ( $this->current_tab === 'consent-logs' ) { $this->sections = [ 'cookie' => __( 'Cookie Consent Logs', 'cookie-notice' ), 'privacy' => __( 'Privacy Consent Logs', 'cookie-notice' ) ]; // check section $section = isset( $_GET['section'] ) ? sanitize_key( $_GET['section'] ) : ''; if ( ! $section || ! array_key_exists( $section, $this->sections ) ) $section = array_key_first( $this->sections ); $this->current_section = $section; } $this->parameters = [ 'page_type' => __( 'Page Type', 'cookie-notice' ), 'page' => __( 'Page', 'cookie-notice' ), 'post_type' => __( 'Post Type', 'cookie-notice' ), 'post_type_archive' => __( 'Post Type Archive', 'cookie-notice' ), 'user_type' => __( 'User Type', 'cookie-notice' ), 'taxonomy_archive' => __( 'Taxonomy Archive', 'cookie-notice' ) ]; $this->operators = [ 'equal' => __( 'is equal to', 'cookie-notice' ), 'not_equal' => __( 'is not equal to', 'cookie-notice' ) ]; $this->conditional_display_types = [ 'hide' => __( 'Hide the banner', 'cookie-notice' ), 'show' => __( 'Show the banner', 'cookie-notice' ) ]; $this->positions = [ 'top' => __( 'Top', 'cookie-notice' ), 'bottom' => __( 'Bottom', 'cookie-notice' ) ]; $this->styles = [ 'none' => __( 'None', 'cookie-notice' ), 'wp-default' => __( 'Light', 'cookie-notice' ), 'bootstrap' => __( 'Dark', 'cookie-notice' ) ]; $this->revoke_opts = [ 'automatic' => __( 'Automatic', 'cookie-notice' ), 'manual' => __( 'Manual', 'cookie-notice' ) ]; $this->links = [ 'page' => __( 'Page link', 'cookie-notice' ), 'custom' => __( 'Custom link', 'cookie-notice' ) ]; $this->link_targets = [ '_blank', '_self' ]; $this->link_positions = [ 'banner' => __( 'Banner', 'cookie-notice' ), 'message' => __( 'Message', 'cookie-notice' ) ]; $this->colors = [ 'text' => __( 'Text color', 'cookie-notice' ), 'button' => __( 'Button color', 'cookie-notice' ), 'bar' => __( 'Bar color', 'cookie-notice' ) ]; $this->times = apply_filters( 'cn_cookie_expiry', [ 'hour' => [ __( 'An hour', 'cookie-notice' ), HOUR_IN_SECONDS ], 'day' => [ __( '1 day', 'cookie-notice' ), DAY_IN_SECONDS ], 'week' => [ __( '1 week', 'cookie-notice' ), WEEK_IN_SECONDS ], 'month' => [ __( '1 month', 'cookie-notice' ), MONTH_IN_SECONDS ], '3months' => [ __( '3 months', 'cookie-notice' ), 7862400 ], '6months' => [ __( '6 months', 'cookie-notice' ), 15811200 ], 'year' => [ __( '1 year', 'cookie-notice' ), YEAR_IN_SECONDS ], 'infinity' => [ __( 'infinity', 'cookie-notice' ), 2147483647 ] ] ); $this->effects = [ 'none' => __( 'None', 'cookie-notice' ), 'fade' => __( 'Fade', 'cookie-notice' ), 'slide' => __( 'Slide', 'cookie-notice' ) ]; $this->script_placements = [ 'header' => __( 'Header', 'cookie-notice' ), 'footer' => __( 'Footer', 'cookie-notice' ) ]; $this->level_names = [ 1 => [ 1 => __( 'Private', 'cookie-notice' ), 2 => __( 'Balanced', 'cookie-notice' ), 3 => __( 'Personalized', 'cookie-notice' ) ], 2 => [ 1 => __( 'Silver', 'cookie-notice' ), 2 => __( 'Gold', 'cookie-notice' ), 3 => __( 'Platinum', 'cookie-notice' ) ], 3 => [ 1 => __( 'Reject All', 'cookie-notice' ), 2 => __( 'Accept Some', 'cookie-notice' ), 3 => __( 'Accept All', 'cookie-notice' ) ] ]; $this->text_strings = [ 'saveBtnText' => __( 'Save my preferences', 'cookie-notice' ), 'privacyBtnText' => __( 'Privacy policy', 'cookie-notice' ), 'dontSellBtnText' => __( 'Do Not Sell', 'cookie-notice' ), 'customizeBtnText' => __( 'Preferences', 'cookie-notice' ), 'headingText' => __( "Your data is your property and we support your right to privacy and transparency.", 'cookie-notice' ), 'bodyText' => __( "To provide you the best experience on our website, we use cookies or similar technologies. Select a data access level to decide for which purposes we may use and share your data.", 'cookie-notice' ), 'levelBodyText_1' => __( 'Highest level of privacy. Data accessed for necessary site operations only. Data shared with 3rd parties to ensure the site is secure and works on your device.', 'cookie-notice' ), 'levelBodyText_2' => __( 'Balanced experience. Data accessed for content personalisation and site optimisation. Data shared with 3rd parties may be used to track and store your preferences for this site.', 'cookie-notice' ), 'levelBodyText_3' => __( 'Highest level of personalisation. Data accessed to make ads and media more relevant. Data shared with 3rd parties may be use to track you on this site and other sites you visit.', 'cookie-notice' ), 'levelNameText_1' => $this->level_names[1][1], 'levelNameText_2' => $this->level_names[1][2], 'levelNameText_3' => $this->level_names[1][3], 'monthText' => __( 'month', 'cookie-notice' ), 'monthsText' => __( 'months', 'cookie-notice' ) ]; // get main instance $cn = Cookie_Notice(); // set default text strings $cn->defaults['general']['message_text'] = __( 'We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.', 'cookie-notice' ); $cn->defaults['general']['accept_text'] = __( 'Ok', 'cookie-notice' ); $cn->defaults['general']['refuse_text'] = __( 'No', 'cookie-notice' ); $cn->defaults['general']['revoke_message_text'] = __( 'You can revoke your consent any time using the Revoke consent button.', 'cookie-notice' ); $cn->defaults['general']['revoke_text'] = __( 'Revoke consent', 'cookie-notice' ); $cn->defaults['general']['see_more_opt']['text'] = __( 'Privacy policy', 'cookie-notice' ); // set translation strings on plugin activation if ( ! empty( $cn->options['general']['translate'] ) ) { $cn->options['general']['translate'] = false; $cn->options['general']['message_text'] = $cn->defaults['general']['message_text']; $cn->options['general']['accept_text'] = $cn->defaults['general']['accept_text']; $cn->options['general']['refuse_text'] = $cn->defaults['general']['refuse_text']; $cn->options['general']['revoke_message_text'] = $cn->defaults['general']['revoke_message_text']; $cn->options['general']['revoke_text'] = $cn->defaults['general']['revoke_text']; $cn->options['general']['see_more_opt']['text'] = $cn->defaults['general']['see_more_opt']['text']; if ( $cn->is_network_admin() ) update_site_option( 'cookie_notice_options', $cn->options['general'] ); else update_option( 'cookie_notice_options', $cn->options['general'] ); } // WPML >= 3.2 if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) { $this->register_wpml_strings(); // WPML and Polylang compatibility } elseif ( function_exists( 'icl_register_string' ) ) { icl_register_string( 'Cookie Notice', 'Message in the notice', $cn->options['general']['message_text'] ); icl_register_string( 'Cookie Notice', 'Button text', $cn->options['general']['accept_text'] ); icl_register_string( 'Cookie Notice', 'Refuse button text', $cn->options['general']['refuse_text'] ); icl_register_string( 'Cookie Notice', 'Revoke message text', $cn->options['general']['revoke_message_text'] ); icl_register_string( 'Cookie Notice', 'Revoke button text', $cn->options['general']['revoke_text'] ); icl_register_string( 'Cookie Notice', 'Privacy policy text', $cn->options['general']['see_more_opt']['text'] ); icl_register_string( 'Cookie Notice', 'Custom link', $cn->options['general']['see_more_opt']['link'] ); } } /** * Add submenu. * * @return void */ public function admin_menu_options() { if ( current_action() === 'network_admin_menu' && ! Cookie_Notice()->is_plugin_network_active() ) return; $cap = apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ); add_menu_page( __( 'Compliance by Hu-manity.co', 'cookie-notice' ), __( 'Compliance', 'cookie-notice' ), $cap, 'cookie-notice', [ $this, 'options_page' ], 'none', '99.300' ); // React mode: no submenus — React owns in-page tab navigation. // Legacy mode: three submenus matching the PHP tab structure. if ( Cookie_Notice()->options['general']['ui_mode'] === 'legacy' ) { add_submenu_page( 'cookie-notice', __( 'Compliance - Cookie Consent', 'cookie-notice' ), __( 'Cookie Consent', 'cookie-notice' ), $cap, 'cookie-notice', [ $this, 'options_page' ] ); add_submenu_page( 'cookie-notice', __( 'Compliance - Privacy Consent', 'cookie-notice' ), $this->mark_new( __( 'Privacy Consent', 'cookie-notice' ) ), $cap, 'cookie-notice&tab=privacy-consent', [ $this, 'options_page' ] ); add_submenu_page( 'cookie-notice', __( 'Compliance - Consent Logs', 'cookie-notice' ), __( 'Consent Logs', 'cookie-notice' ), $cap, 'cookie-notice&tab=consent-logs', [ $this, 'options_page' ] ); // highlight submenus add_filter( 'submenu_file', [ $this, 'submenu_file' ], 10, 2 ); } } /** * Adds an indicator to mark a new menu item. * * @return string */ private function mark_new( $title ) { return sprintf( '%s %s', $title, __( 'NEW!', 'cookie-notice' ) ); } /** * Highlight submenu items. * * @param string|null $submenu_file * @param string $parent_file * @return string|null */ public function submenu_file( $submenu_file, $parent_file ) { if ( $parent_file === 'cookie-notice' ) { $tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'settings'; if ( $tab !== 'settings' ) return 'cookie-notice&tab=' . $tab; } return $submenu_file; } /** * Options page output. * * @return void */ public function options_page() { // get main instance $cn = Cookie_Notice(); // get cookie compliance status $status = $cn->get_status(); $ui_mode = $cn->options['general']['ui_mode']; echo '

' . esc_html__( 'Compliance by Hu-manity.co', 'cookie-notice' ) . '

'; if ( $ui_mode === 'react' ) { echo '
'; } // get current tab $tab = $this->current_tab; if ( $ui_mode === 'legacy' ) { $base_url = $cn->is_network_admin() ? network_admin_url( 'admin.php?page=cookie-notice' ) : admin_url( 'admin.php?page=cookie-notice' ); echo ' '; } // end if ui_mode === 'legacy' echo '
'; } /** * Display options page. * * @return array */ private function display_options_page( $tab = '' ) { // get main instance $cn = Cookie_Notice(); // multisite? if ( is_multisite() ) { // network admin? if ( $cn->is_network_admin() ) { $class = ( $cn->is_plugin_network_active() && ! $cn->options['general']['global_override'] ? 'cn-options-disabled' : ( $tab === 'privacy-consent' ? 'cn-options-privacy-disabled cn-options-submit-disabled' : '' ) ); $page = 'admin.php?page=cookie-notice'; $input = ''; // single network site } else { $class = ( $cn->is_plugin_network_active() && $cn->network_options['general']['global_override'] ? ( $tab === 'privacy-consent' ? 'cn-options-compliance-disabled' : 'cn-options-disabled cn-options-submit-disabled' ) : '' ); $page = 'options.php'; $input = ''; } // single site } else { $class = ''; $page = 'options.php'; $input = ''; } if ( $tab === 'privacy-consent' ) $option = 'cookie_notice_privacy_consent'; elseif ( $tab === 'settings' ) $option = 'cookie_notice_options'; echo '
'; settings_fields( $option ); if ( $input !== '' ) { echo wp_kses( $input, [ 'input' => [ 'type' => true, 'name' => true, 'value' => true ] ] ); } echo '
'; do_settings_sections( $option ); $other_attributes = []; // get cookie compliance status $status = $cn->get_status(); // disabled save / reset if compliance inactive if ( $tab === 'privacy-consent' && ( $status !== 'active' || $cn->is_network_admin() ) ) $other_attributes = array( 'disabled' => true ); echo '

'; submit_button( '', 'primary', 'save_' . $option, false, $other_attributes ); echo ' '; submit_button( esc_html__( 'Reset to defaults', 'cookie-notice' ), 'secondary cn-reset-settings', 'reset_' . $option, false, $other_attributes ); echo '

'; } /** * Display options sidebar HTML. * * @return void */ public function display_options_sidebar() { // get main instance $cn = Cookie_Notice(); // get cookie compliance status $status = $cn->get_status(); // get subscription $subscription = $cn->get_subscription(); echo ' '; } /** * Register plugin settings. * * @return void */ public function register_settings() { // register settings register_setting( 'cookie_notice_options', 'cookie_notice_options', [ $this, 'validate_options' ] ); // get main instance $cn = Cookie_Notice(); $status = $cn->get_status(); // this is no longer used if ( $cn->is_network_admin() ) $cb = ''; elseif ( $cn->is_plugin_network_active() && $cn->network_options['general']['global_override'] ) $cb = [ $this, 'cn_network_section' ]; else $cb = ''; if ( is_multisite() ) { if ( $cn->is_plugin_network_active() && ( ( $cn->is_network_admin() && ! $cn->network_options['general']['global_override'] ) || ( ! $cn->is_network_admin() && $cn->network_options['general']['global_override'] ) ) ) $this->allow_consent_logs = false; else $this->allow_consent_logs = true; } else $this->allow_consent_logs = true; add_settings_section( 'cookie_notice_consent_logs_status', esc_html__( 'Compliance Integration', 'cookie-notice' ), '', 'cookie_notice_consent_logs', [ 'before_section' => '
', 'after_section' => '
', 'section_class' => 'cn-section-container compliance-section' ] ); add_settings_field( 'cn_consent_logs_status', esc_html__( 'Compliance Status', 'cookie-notice' ), [ $this, 'cn_consent_logs_status' ], 'cookie_notice_consent_logs', 'cookie_notice_consent_logs_status' ); add_settings_section( 'cookie_notice_consent_logs', esc_html__( 'Consent Logs', 'cookie-notice' ), [ $this, 'cn_consent_logs_section' ], 'cookie_notice_consent_logs', [ 'before_section' => '
', 'after_section' => '
', 'section_class' => 'cn-section-container logs-section' ] ); // multisite? if ( is_multisite() ) { // network admin? if ( $cn->is_network_admin() ) { // network section add_settings_section( 'cookie_notice_network', esc_html__( 'Network Settings', 'cookie-notice' ), '', 'cookie_notice_options', [ 'before_section' => '
', 'after_section' => '
', 'section_class' => 'cn-section-container network-section' ] ); add_settings_field( 'cn_global_override', esc_html__( 'Global Settings Override', 'cookie-notice' ), [ $this, 'cn_global_override' ], 'cookie_notice_options', 'cookie_notice_network' ); add_settings_field( 'cn_global_cookie', esc_html__( 'Global Cookie', 'cookie-notice' ), [ $this, 'cn_global_cookie' ], 'cookie_notice_options', 'cookie_notice_network' ); } elseif ( $cn->is_plugin_network_active() && $cn->network_options['general']['global_override'] ) { // network section add_settings_section( 'cookie_notice_network', esc_html__( 'Network Settings', 'cookie-notice' ), [ $this, 'cn_network_section' ], 'cookie_notice_options', [ 'before_section' => '
', 'after_section' => '
', 'section_class' => 'cn-section-container network-section' ] ); add_settings_field( 'cn_dummy', '', '__return_empty_string', 'cookie_notice_options', 'cookie_notice_network' ); // get default status data $default_data = $cn->defaults['data']; // get real status of current site, not network since global_override is on $status_data = get_option( 'cookie_notice_status', $default_data ); // old status format? if ( ! is_array( $status_data ) ) { // old value saved as string if ( is_string( $status_data ) && $cn->check_status( $status_data ) ) { // update status $default_data['status'] = $status_data; } // set data $status_data = $default_data; } // get valid status $status = $cn->check_status( $status_data['status'] ); } } // compliance enabled if ( $status === 'active' ) { // compliance section add_settings_section( 'cookie_notice_compliance', esc_html__( 'Compliance Integration', 'cookie-notice' ), '', 'cookie_notice_options', [ 'before_section' => '
', 'after_section' => '
', 'section_class' => 'cn-section-container compliance-section' ] ); add_settings_field( 'cn_app_status', esc_html__( 'Compliance Status', 'cookie-notice' ), [ $this, 'cn_app_status' ], 'cookie_notice_options', 'cookie_notice_compliance' ); add_settings_field( 'cn_app_id', esc_html__( 'App ID', 'cookie-notice' ), [ $this, 'cn_app_id' ], 'cookie_notice_options', 'cookie_notice_compliance' ); add_settings_field( 'cn_app_key', esc_html__( 'App Key', 'cookie-notice' ), [ $this, 'cn_app_key' ], 'cookie_notice_options', 'cookie_notice_compliance' ); // configuration section add_settings_section( 'cookie_notice_configuration', esc_html__( 'Cookie Consent Settings', 'cookie-notice' ), '', 'cookie_notice_options', [ 'before_section' => '
', 'after_section' => '
', 'section_class' => 'cn-section-container misc-section' ] ); add_settings_field( 'cn_app_blocking', esc_html__( 'Autoblocking', 'cookie-notice' ), [ $this, 'cn_app_blocking' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_excluded_handles', esc_html__( 'Excluded Script Handles', 'cookie-notice' ), [ $this, 'cn_excluded_handles' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_sync_config', esc_html__( 'Pull Configuration', 'cookie-notice' ), [ $this, 'cn_sync_config' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_refuse_code', esc_html__( 'Scripts', 'cookie-notice' ), [ $this, 'cn_refuse_code' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_caching_compatibility', esc_html__( 'Caching Compatibility', 'cookie-notice' ), [ $this, 'cn_caching_compatibility' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_app_purge_cache', esc_html__( 'Purge Cache', 'cookie-notice' ), [ $this, 'cn_app_purge_cache' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_conditional_display', esc_html__( 'Conditional Display', 'cookie-notice' ), [ $this, 'cn_conditional_display' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_bot_detection', esc_html__( 'Bot Detection', 'cookie-notice' ), [ $this, 'cn_bot_detection' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_amp_support', esc_html__( 'AMP Support', 'cookie-notice' ), [ $this, 'cn_amp_support' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_debug_mode', esc_html__( 'Debug Mode', 'cookie-notice' ), [ $this, 'cn_debug_mode' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_deactivation_delete', esc_html__( 'Deactivation', 'cookie-notice' ), [ $this, 'cn_deactivation_delete' ], 'cookie_notice_options', 'cookie_notice_configuration' ); // compliance disabled } else { // compliance section add_settings_section( 'cookie_notice_compliance', esc_html__( 'Compliance Integration', 'cookie-notice' ), '', 'cookie_notice_options', [ 'before_section' => '
', 'after_section' => '
', 'section_class' => 'cn-section-container compliance-section' ] ); add_settings_field( 'cn_app_status', esc_html__( 'Compliance status', 'cookie-notice' ), [ $this, 'cn_app_status' ], 'cookie_notice_options', 'cookie_notice_compliance' ); add_settings_field( 'cn_app_id', esc_html__( 'App ID', 'cookie-notice' ), [ $this, 'cn_app_id' ], 'cookie_notice_options', 'cookie_notice_compliance' ); add_settings_field( 'cn_app_key', esc_html__( 'App Key', 'cookie-notice' ), [ $this, 'cn_app_key' ], 'cookie_notice_options', 'cookie_notice_compliance' ); // configuration section add_settings_section( 'cookie_notice_configuration', esc_html__( 'Notice Settings', 'cookie-notice' ), '', 'cookie_notice_options', [ 'before_section' => '
', 'after_section' => '
', 'section_class' => 'cn-section-container notice-section' ] ); add_settings_field( 'cn_message_text', esc_html__( 'Message', 'cookie-notice' ), [ $this, 'cn_message_text' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_accept_text', esc_html__( 'Button text', 'cookie-notice' ), [ $this, 'cn_accept_text' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_see_more', esc_html__( 'Privacy policy', 'cookie-notice' ), [ $this, 'cn_see_more' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_refuse_opt', esc_html__( 'Refuse consent', 'cookie-notice' ), [ $this, 'cn_refuse_opt' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_revoke_opt', esc_html__( 'Revoke consent', 'cookie-notice' ), [ $this, 'cn_revoke_opt' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_app_blocking', esc_html__( 'Autoblocking', 'cookie-notice' ), [ $this, 'cn_app_blocking' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_refuse_code', esc_html__( 'Script blocking', 'cookie-notice' ), [ $this, 'cn_refuse_code' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_pro_features_locked', esc_html__( 'Pro Features', 'cookie-notice' ), [ $this, 'cn_pro_features_locked' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_redirection', esc_html__( 'Reloading', 'cookie-notice' ), [ $this, 'cn_redirection' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_on_scroll', esc_html__( 'On scroll', 'cookie-notice' ), [ $this, 'cn_on_scroll' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_on_click', esc_html__( 'On click', 'cookie-notice' ), [ $this, 'cn_on_click' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_time', esc_html__( 'Accepted expiry', 'cookie-notice' ), [ $this, 'cn_time' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_time_rejected', esc_html__( 'Rejected expiry', 'cookie-notice' ), [ $this, 'cn_time_rejected' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_conditional_display', esc_html__( 'Conditional display', 'cookie-notice' ), [ $this, 'cn_conditional_display' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_script_placement', esc_html__( 'Script placement', 'cookie-notice' ), [ $this, 'cn_script_placement' ], 'cookie_notice_options', 'cookie_notice_configuration' ); add_settings_field( 'cn_deactivation_delete', esc_html__( 'Deactivation', 'cookie-notice' ), [ $this, 'cn_deactivation_delete' ], 'cookie_notice_options', 'cookie_notice_configuration' ); // design section add_settings_section( 'cookie_notice_design', esc_html__( 'Notice Design', 'cookie-notice' ), '', 'cookie_notice_options', [ 'before_section' => '
', 'after_section' => '
', 'section_class' => 'cn-section-container design-section' ] ); add_settings_field( 'cn_position', esc_html__( 'Position', 'cookie-notice' ), [ $this, 'cn_position' ], 'cookie_notice_options', 'cookie_notice_design' ); add_settings_field( 'cn_hide_effect', esc_html__( 'Animation', 'cookie-notice' ), [ $this, 'cn_hide_effect' ], 'cookie_notice_options', 'cookie_notice_design' ); add_settings_field( 'cn_colors', esc_html__( 'Colors', 'cookie-notice' ), [ $this, 'cn_colors' ], 'cookie_notice_options', 'cookie_notice_design' ); add_settings_field( 'cn_css_class', esc_html__( 'Button class', 'cookie-notice' ), [ $this, 'cn_css_class' ], 'cookie_notice_options', 'cookie_notice_design' ); } } /** * Network settings override option. * * @return void */ public function cn_global_override() { echo '

' . esc_html__( 'Every site in the network will use the same settings. Site administrators will not be able to change them.', 'cookie-notice' ) . '

'; } /** * Network cookie acceptance option. * * @return void */ public function cn_global_cookie() { $multi_folders = is_multisite() && ! is_subdomain_install(); // multisite with path-based network? if ( $multi_folders ) $desc = __( 'This option works only for domain-based networks.', 'cookie-notice' ); else $desc = ''; echo ' '; } /** * Network settings section. * * @return void */ public function cn_network_section() { echo '

' . esc_html__( 'Global network settings override is active. Every site will use the same network settings. Please contact super administrator if you want to have more control over the settings.', 'cookie-notice' ) . '

'; } /** * Consent logs section. * * @return void */ public function cn_consent_logs_section() { if ( ! $this->allow_consent_logs ) return; echo '
'; } /** * Compliance status. * * @return void */ public function cn_app_status() { // get main instance $cn = Cookie_Notice(); // get cookie compliance status $app_status = $cn->get_status(); // get threshold status $threshold_exceeded = $cn->threshold_exceeded(); switch ( $app_status ) { case 'active': echo '
' . esc_html__( 'Consent Banner', 'cookie-notice' ) . ': ' . esc_html__( 'Active', 'cookie-notice' ) . '
' . esc_html__( 'Autoblocking', 'cookie-notice' ) . ': ' . esc_html__( 'Active', 'cookie-notice' ) . '
' . esc_html__( 'Cookie Categories', 'cookie-notice' ) . ': ' . esc_html__( 'Active', 'cookie-notice' ) . '
' . esc_html__( 'Cookie Consent Storage', 'cookie-notice' ) . ': ' . esc_html__( 'Active', 'cookie-notice' ) . '
' . esc_html__( 'Log in & Configure', 'cookie-notice' ) . '

' . esc_html__( 'Log in to the Compliance by Hu-manity.co dashboard to explore, configure and manage its functionalities.', 'cookie-notice' ) . '

'; break; case 'pending': echo '
' . esc_html__( 'Consent Banner', 'cookie-notice' ) . ': ' . esc_html__( 'Active', 'cookie-notice' ) . '
' . esc_html__( 'Autoblocking', 'cookie-notice' ) . ': ' . esc_html__( 'Pending', 'cookie-notice' ) . '
' . esc_html__( 'Cookie Categories', 'cookie-notice' ) . ': ' . esc_html__( 'Pending', 'cookie-notice' ) . '
' . esc_html__( 'Cookie Consent Storage', 'cookie-notice' ) . ': ' . esc_html__( 'Pending', 'cookie-notice' ) . '
' . esc_html__( 'Log in & Configure', 'cookie-notice' ) . '

' . esc_html__( 'Log in to the Compliance by Hu-manity.co web application and complete the setup process.', 'cookie-notice' ) . '

'; break; default: if ( $cn->is_network_admin() ) $url = network_admin_url( 'admin.php?page=cookie-notice' ); else $url = admin_url( 'admin.php?page=cookie-notice' ); echo '
' . esc_html__( 'Consent Banner', 'cookie-notice' ) . ': ' . esc_html__( 'Active', 'cookie-notice' ) . '
' . esc_html__( 'Autoblocking', 'cookie-notice' ) . ': ' . esc_html__( 'Inactive', 'cookie-notice' ) . '
' . esc_html__( 'Cookie Categories', 'cookie-notice' ) . ': ' . esc_html__( 'Inactive', 'cookie-notice' ) . '
' . esc_html__( 'Cookie Consent Storage', 'cookie-notice' ) . ': ' . esc_html__( 'Inactive', 'cookie-notice' ) . '
' . esc_html__( 'Try Compliance by Hu-manity.co free', 'cookie-notice' ) . '

' . sprintf( esc_html__( 'Sign up to %s and add GDPR, CCPA and other international data privacy laws compliance features.', 'cookie-notice' ), 'Compliance by Hu-manity.co' ) . '

'; break; } } /** * Compliance status. * * @return void */ public function cn_consent_logs_status() { // get main instance $cn = Cookie_Notice(); // get cookie compliance status $app_status = $cn->get_status(); if ( $cn->is_network_admin() ) $url = network_admin_url( 'admin.php?page=cookie-notice' ); else $url = admin_url( 'admin.php?page=cookie-notice' ); switch ( $app_status ) { case 'active': echo '
' . esc_html__( 'Cookie Consent Logs', 'cookie-notice' ) . ': ' . esc_html__( 'Active', 'cookie-notice' ) . '
' . esc_html__( 'Privacy Consent Logs', 'cookie-notice' ) . ': ' . esc_html__( 'Active', 'cookie-notice' ) . '
' . esc_html__( 'Log in & Configure', 'cookie-notice' ) . '

' . esc_html__( 'Log in to the Compliance by Hu-manity.co dashboard to explore, configure and manage its functionalities.', 'cookie-notice' ) . '

'; break; case 'pending': echo '
' . esc_html__( 'Cookie Consent Logs', 'cookie-notice' ) . ': ' . esc_html__( 'Pending', 'cookie-notice' ) . '
' . esc_html__( 'Privacy Consent Logs', 'cookie-notice' ) . ': ' . esc_html__( 'Pending', 'cookie-notice' ) . '
' . esc_html__( 'Log in & Configure', 'cookie-notice' ) . '

' . esc_html__( 'Log in to the Compliance by Hu-manity.co web application and complete the setup process.', 'cookie-notice' ) . '

'; break; default: echo '
' . '' . esc_html__( 'Cookie Consent Logs', 'cookie-notice' ) . ': ' . esc_html__( 'Inactive', 'cookie-notice' ) . '
' . esc_html__( 'Privacy Consent Logs', 'cookie-notice' ) . ': ' . esc_html__( 'Inactive', 'cookie-notice' ) . '
' . esc_html__( 'Try Compliance by Hu-manity.co free', 'cookie-notice' ) . '

' . sprintf( esc_html__( 'Sign up to %s and enable Privacy Consent support.', 'cookie-notice' ), 'Compliance by Hu-manity.co' ) . '

'; } } /** * App ID option. * * @return void */ public function cn_app_id() { echo '

' . esc_html__( 'Enter your Compliance by Hu-manity.co application ID.', 'cookie-notice' ) . '

'; } /** * App key option. * * @return void */ public function cn_app_key() { echo '

' . esc_html__( 'Enter your Compliance by Hu-manity.co application secret key.', 'cookie-notice' ) . '

'; } /** * App autoblocking option. * * @return void */ public function cn_app_blocking() { // get main instance $cn = Cookie_Notice(); $threshold_exceeded = $cn->threshold_exceeded(); echo '
' . ( $threshold_exceeded ? '

* ' . esc_html__( 'This option has been temporarily disabled because your website has reached the usage limit for the Compliance by Hu-manity.co Free Plan. It will become available again when the current visits cycle resets or you upgrade your website to a Professional plan.', 'cookie-notice' ) . '

' : '' ) . '
'; } /** * Excluded script handles textarea. * * @return void */ public function cn_excluded_handles() { $cn = Cookie_Notice(); $value = ! empty( $cn->options['general']['excluded_handles'] ) ? implode( "\n", $cn->options['general']['excluded_handles'] ) : ''; echo '

' . esc_html__( 'Enter WordPress script handles to exclude from autoblocking, one per line. These scripts will be marked as Essential (Category 1) so they are never blocked.', 'cookie-notice' ) . '

'; } /** * Sync configuration option. * * @return void */ public function cn_sync_config() { // get main instance $cn = Cookie_Notice(); $threshold_exceeded = $cn->threshold_exceeded(); $network = $cn->is_network_options(); // get last sync timestamp if ( $network ) $blocking = get_site_option( 'cookie_notice_app_blocking', [] ); else $blocking = get_option( 'cookie_notice_app_blocking', [] ); $last_synced = ! empty( $blocking['lastUpdated'] ) ? $blocking['lastUpdated'] : ''; $last_synced_display = $last_synced ? sprintf( esc_html__( 'Last synced (UTC): %s', 'cookie-notice' ), date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $last_synced ) ) ) : esc_html__( 'Not synced yet', 'cookie-notice' ); echo '
' . $last_synced_display . '

' . esc_html__( 'Manually pull the latest configuration including autoblocking. Configuration syncs automatically every 24 hours.', 'cookie-notice' ) . '

'; } /** * Purge cache option. * * @return void */ public function cn_app_purge_cache() { echo '
' . esc_html__( 'Purge Cache', 'cookie-notice' ) . '

' . esc_html__( 'Click the Purge Cache button to refresh the app configuration.', 'cookie-notice' ) . '

'; } /** * Conditional display option. * * @return void */ public function cn_conditional_display() { // get main instance $cn = Cookie_Notice(); echo '
options['general']['conditional_active'] ) ? ' style="display: none"' : '' ) . ' class="cn_fieldset_content">

' . esc_html__( 'Determine what should happen when the following conditions are met.', 'cookie-notice' ) . '

'; // get allowed html $allowed_html = wp_kses_allowed_html( 'post' ); $allowed_html['select'] = [ 'name' => true, 'class' => true ]; $allowed_html['option'] = [ 'value' => true, 'selected' => true ]; $allowed_html['optgroup'] = [ 'label' => true ]; add_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] ); echo wp_kses( $this->conditional_display( $cn->options['general']['conditional_rules'] ), $allowed_html ); remove_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] ); echo '
'; } /** * Debug mode option. * * @return void */ public function cn_debug_mode() { echo '
'; } /** * AMP support option. * * @return void */ public function cn_amp_support() { $amp_enabled = cn_is_plugin_active( 'amp' ); echo '

' . ( ! $amp_enabled ? esc_html__( 'No compatible Google AMP plugins found.', 'cookie-notice' ) : esc_html__( 'Allows you to activate consent banner support for Google AMP.', 'cookie-notice' ) ) . '

'; } /** * Bot detection option. * * @return void */ public function cn_bot_detection() { echo '
'; } /** * Caching compatibility option. * * @return void */ public function cn_caching_compatibility() { // get main instance $cn = Cookie_Notice(); $plugins_html = ''; // get active caching plugins $active_plugins = cn_get_active_caching_plugins(); if ( ! empty( $active_plugins ) ) { $active_plugins_html = []; $plugins_html .= '

' . esc_html__( 'Currently detected active caching plugins', 'cookie-notice' ) . ': '; foreach ( $active_plugins as $plugin ) { $active_plugins_html[] = '' . esc_html( $plugin ) . ''; } $plugins_html .= implode( ', ', $active_plugins_html ) . '.

'; } else $plugins_html .= '

' . esc_html__( 'No compatible cache plugins found.', 'cookie-notice' ) . '

'; echo '
' . $plugins_html . '
'; } /** * Cookie notice message option. * * @return void */ public function cn_message_text() { echo '

' . esc_html__( 'Enter the cookie notice message.', 'cookie-notice' ) . '

'; } /** * Accept cookie label option. * * @return void */ public function cn_accept_text() { echo '

' . esc_html__( 'The text of the option to accept the notice and make it disappear.', 'cookie-notice' ) . '

'; } /** * Toggle third party non functional cookies option. * * @return void */ public function cn_refuse_opt() { // get main instance $cn = Cookie_Notice(); echo '
options['general']['refuse_opt'] ) ? ' style="display: none"' : '' ) . ' class="cn_fieldset_content">

' . esc_html__( 'The text of the button to refuse the consent.', 'cookie-notice' ) . '

'; } /** * Non functional cookies code option. * * @return void */ public function cn_refuse_code() { // get main instance $cn = Cookie_Notice(); $active = ! empty( $cn->options['general']['refuse_code'] ) && empty( $cn->options['general']['refuse_code_head'] ) ? 'body' : 'head'; echo '

' . esc_html__( 'The code to be used in your site header, before the closing head tag.', 'cookie-notice' ) . '

' . esc_html__( 'The code to be used in your site footer, before the closing body tag.', 'cookie-notice' ) . '

' . esc_html__( 'Enter non functional cookies Javascript code here (for e.g. Google Analitycs) to be used after the visitor consent is given.', 'cookie-notice' ) . '

'; } /** * Pro features locked callout (inactive/BASIC tier). * Shows Cookie Categories and Analytics as disabled with upgrade CTA. * * @return void */ public function cn_pro_features_locked() { // get main instance $cn = Cookie_Notice(); $base_url = $cn->is_network_admin() ? network_admin_url( 'admin.php?page=cookie-notice' ) : admin_url( 'admin.php?page=cookie-notice' ); $welcome_url = ( $cn->options['general']['ui_mode'] === 'react' ) ? add_query_arg( [ 'cn_react_welcome' => '1' ], $base_url ) : add_query_arg( [ 'welcome' => '1' ], $base_url ); echo '

' . esc_html__( 'Group cookies by purpose and let users consent selectively.', 'cookie-notice' ) . '

' . esc_html__( 'Track consent rates, view logs, and generate compliance reports.', 'cookie-notice' ) . '

' . esc_html__( 'Connect your site to unlock →', 'cookie-notice' ) . '

'; } /** * Revoke cookies option. * * @return void */ public function cn_revoke_opt() { // get main instance $cn = Cookie_Notice(); echo '
options['general']['revoke_cookies'] ? '' : ' style="display: none"' ) . ' class="cn_fieldset_content">

' . esc_html__( 'Enter the revoke message.', 'cookie-notice' ) . '

' . esc_html__( 'The text of the button to revoke the consent.', 'cookie-notice' ) . '

'; foreach ( $this->revoke_opts as $value => $label ) { echo ' '; } echo '

' . sprintf( esc_html__( 'Select the method for displaying the revoke button - automatic (in the banner) or manual using %s[cookies_revoke]%s shortcode.', 'cookie-notice' ), '', '' ) . '

'; } /** * Redirection on cookie accept option. * * @return void */ public function cn_redirection() { echo '
'; } /** * Privacy policy link option. * * @global string $wp_version * * @return void */ public function cn_see_more() { // get main instance $cn = Cookie_Notice(); // get published pages $pages = get_pages( [ 'sort_order' => 'ASC', 'sort_column' => 'post_title', 'hierarchical' => 0, 'child_of' => 0, 'parent' => -1, 'offset' => 0, 'post_type' => 'page', 'post_status' => 'publish' ] ); echo '
options['general']['see_more'] ) ? ' style="display: none"' : '' ) . ' class="cn_fieldset_content">

' . esc_html__( 'The text of the privacy policy button.', 'cookie-notice' ) . '

' . esc_html__( 'Select where to redirect user for more information.', 'cookie-notice' ) . '

options['general']['see_more_opt']['link_type'] === 'custom' ? ' style="display: none"' : '' ) . '>

' . esc_html__( 'Select from one of your site\'s pages.', 'cookie-notice' ) . '

'; global $wp_version; if ( version_compare( $wp_version, '4.9.6', '>=' ) ) { echo ' '; } echo '
'; } /** * Expiration time option. * * @return void */ public function cn_time() { echo '

' . esc_html__( 'The amount of time that the cookie should be stored for when user accepts the notice.', 'cookie-notice' ) . '

'; } /** * Expiration time option. * * @return void */ public function cn_time_rejected() { echo '

' . esc_html__( 'The amount of time that the cookie should be stored for when the user doesn\'t accept the notice.', 'cookie-notice' ) . '

'; } /** * Script placement option. * * @return void */ public function cn_script_placement() { echo '
'; foreach ( $this->script_placements as $value => $label ) { echo ' '; } echo '

' . esc_html__( 'Select where all the plugin scripts should be placed.', 'cookie-notice' ) . '

'; } /** * Position option. * * @return void */ public function cn_position() { echo '
'; foreach ( $this->positions as $value => $label ) { echo ' '; } echo '

' . esc_html__( 'Select location for the notice.', 'cookie-notice' ) . '

'; } /** * Animation effect option. * * @return void */ public function cn_hide_effect() { echo '
'; foreach ( $this->effects as $value => $label ) { echo ' '; } echo '

' . esc_html__( 'Select the animation style.', 'cookie-notice' ) . '

'; } /** * On scroll option. * * @return void */ public function cn_on_scroll() { // get main instance $cn = Cookie_Notice(); echo '
options['general']['on_scroll'] ) ? ' style="display: none"' : '' ) . ' class="cn_fieldset_content"> px

' . esc_html__( 'Number of pixels user has to scroll to accept the notice and make it disappear.', 'cookie-notice' ) . '

'; } /** * On click option. * * @return void */ public function cn_on_click() { echo '
'; } /** * Delete plugin data on deactivation option. * * @return void */ public function cn_deactivation_delete() { echo '
'; } /** * CSS style option. * * @return void */ public function cn_css_class() { echo '

' . esc_html__( 'Enter additional button CSS classes separated by spaces.', 'cookie-notice' ) . '

'; } /** * Colors option. * * @return void */ public function cn_colors() { // get main instance $cn = Cookie_Notice(); echo '
'; foreach ( $this->colors as $value => $label ) { echo '

'; } echo '

'; echo '
'; } /** Check whether htaccess file has Content Security Policy directives with hu-manity.co domain. * * @return bool */ private function check_htaccess() { if ( ! function_exists( 'get_home_path' ) ) require_once ABSPATH . 'wp-admin/includes/file.php'; $htaccess_file = get_home_path() . '.htaccess'; // whether htaccess file is readable $file_readable = false; // whether csp fetch directives are valid $valid_directives = true; // empty string = not found, false = invalid, true = valid $fetch_directives = [ 'img' => '', 'connect' => '', 'script' => '', 'style' => '', 'default' => '' ]; // htaccess exists and its readable? if ( is_readable( $htaccess_file ) ) { // read file $file_data = file( $htaccess_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ); // operable file? if ( $file_data !== false ) { $file_readable = true; $default_directive = ''; // check every line foreach ( $file_data as $file_line ) { $trimmed_line = trim( $file_line ); // skip comment lines if ( substr( $trimmed_line, 0, 1 ) !== "#" ) { $csp_position = strpos( $trimmed_line, 'Content-Security-Policy' ); // found csp? if ( $csp_position !== false ) { $after_csp_line = substr( $trimmed_line, $csp_position + 23 ); // get directives $directives = explode( ';', trim( $after_csp_line ) ); foreach ( $directives as $directive ) { // get source expression list values $values = explode( ' ', trim( $directive ), 2 ); // img-src directive if ( strpos( $values[0], 'img-src' ) !== false ) { // expression list exists and its valid? if ( isset( $values[1] ) && strpos( $values[1], 'data:' ) !== false ) $fetch_directives['img'] = true; else $fetch_directives['img'] = false; } // style-src directive if ( strpos( $values[0], 'style-src' ) !== false ) { // expression list exists and its valid? if ( isset( $values[1] ) && strpos( $values[1], '\'unsafe-inline\'' ) !== false ) $fetch_directives['style'] = true; else $fetch_directives['style'] = false; } // connect-src directive if ( strpos( $values[0], 'connect-src' ) !== false ) { // expression list exists and its valid? if ( isset( $values[1] ) && strpos( $values[1], '*.hu-manity.co' ) !== false ) $fetch_directives['connect'] = true; else $fetch_directives['connect'] = false; } // script-src directive if ( strpos( $values[0], 'script-src' ) !== false ) { // expression list exists and its valid? if ( isset( $values[1] ) && strpos( $values[1], '\'unsafe-inline\'' ) !== false && strpos( $values[1], '*.hu-manity.co' ) !== false ) $fetch_directives['script'] = true; else $fetch_directives['script'] = false; } // default-src directive if ( strpos( $values[0], 'default-src' ) !== false ) { if ( isset( $values[1] ) ) $default_directive = $values[1]; } } } } } // check default-src directive as last if ( $default_directive ) { if ( ! $fetch_directives['img'] ) $condition1 = strpos( $default_directive, 'data:' ) !== false; else $condition1 = true; if ( ! $fetch_directives['style'] ) $condition2 = strpos( $default_directive, '\'unsafe-inline\'' ) !== false; else $condition2 = true; if ( ! $fetch_directives['connect'] ) $condition3 = strpos( $default_directive, '*.hu-manity.co' ) !== false; else $condition3 = true; if ( ! $fetch_directives['script'] ) $condition4 = $condition2 && $condition3; else $condition4 = true; if ( $condition1 && $condition2 && $condition3 && $condition4 ) $fetch_directives['default'] = true; else $fetch_directives['default'] = false; } } } foreach ( $fetch_directives as $directive ) { // check whether directive is valid if ( is_bool( $directive ) && ! $directive ) { $valid_directives = false; break; } } return $file_readable && ! $valid_directives; } /** * Check whether to display admin notices. * * @return void */ public function check_notices() { global $pagenow; // get main instance $cn = Cookie_Notice(); $allow_notice = false; if ( is_multisite() && $cn->is_plugin_network_active() ) { if ( $cn->is_network_admin() ) { if ( $cn->network_options['general']['global_override'] ) $allow_notice = true; } elseif ( ! $cn->network_options['general']['global_override'] ) $allow_notice = true; } else $allow_notice = true; // display notice? if ( $allow_notice && $pagenow === 'admin.php' && isset( $_GET['page'] ) && $_GET['page'] === 'cookie-notice' && $cn->get_status() === 'active' && $cn->options['general']['csp_notice'] ) { add_settings_error( 'cn_cookie_notice_options', 'cookie_notice_csp_warning', esc_html__( "It looks like some of the Consent Security Policy (CSP) records in your website's .htaccess file may be causing Compliance by Hu-manity.co loading problems. Make sure you allow loading of Compliance by Hu-manity.co resources by adding the following record:", 'cookie-notice') . '
' . esc_html__( "img-src data:; style-src 'unsafe-inline'; connect-src *.hu-manity.co; script-src 'unsafe-inline' *.hu-manity.co" ) . '', 'error' ); } } /** * Validate options. * * @param array $input * * @return array */ public function validate_options( $input ) { if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) ) return $input; // get main instance $cn = Cookie_Notice(); $is_network = $cn->is_network_admin(); if ( isset( $_POST['save_cookie_notice_options'] ) ) { // app id $input['app_id'] = isset( $input['app_id'] ) ? sanitize_key( $input['app_id'] ) : $cn->defaults['general']['app_id']; // app key $input['app_key'] = isset( $input['app_key'] ) ? sanitize_key( $input['app_key'] ) : $cn->defaults['general']['app_key']; // set app status if ( ! empty( $input['app_id'] ) && ! empty( $input['app_key'] ) ) { $app_data = $cn->welcome_api->get_app_config( $input['app_id'], true, false ); if ( $cn->check_status( $app_data['status'] ) === 'active' && $cn->options['general']['app_id'] !== $input['app_id'] ) { // get_app_analytics requires fresh app data $this->analytics_app_data = [ 'id' => $input['app_id'], 'key' => $input['app_key'] ]; // update analytics data $cn->welcome_api->get_app_analytics( $input['app_id'], true, false ); $this->analytics_app_data = []; } } else { if ( $is_network ) update_site_option( 'cookie_notice_status', $cn->defaults['data'] ); else update_option( 'cookie_notice_status', $cn->defaults['data'] ); } // app blocking — checkbox: absent from POST when unchecked. // If not submitted at all, preserve the existing DB value instead of defaulting // to false. This prevents a legacy form save from zeroing out a value that was // set via the React path (field partition: app_blocking is plugin-owned but the // legacy form does not always render the checkbox, e.g. when connected). See #2272. if ( isset( $input['app_blocking'] ) ) { // Checkbox was present in the form — honour the submitted value, but // cap it to false when threshold is exceeded. $input['app_blocking'] = ! $cn->threshold_exceeded(); } else { // Checkbox absent (unchecked or not rendered) — preserve DB value to avoid // silently clobbering a React-written true. The preservation loop below // would normally handle this, but it runs after this block and only fills // keys missing from $input entirely. Since we must not add app_blocking to // $input here (the loop checks array_key_exists), we skip setting it and // let the loop restore it from the DB. unset( $input['app_blocking'] ); } // excluded script handles $input['excluded_handles'] = isset( $input['excluded_handles'] ) ? array_values( array_filter( array_map( 'sanitize_text_field', explode( "\n", $input['excluded_handles'] ) ) ) ) : $cn->defaults['general']['excluded_handles']; // conditional display $input['conditional_active'] = isset( $input['conditional_active'] ); $input['conditional_display'] = isset( $input['conditional_display'] ) ? sanitize_key( $input['conditional_display'] ) : $cn->defaults['general']['conditional_display']; if ( ! in_array( $input['conditional_display'], array_keys( $this->conditional_display_types ), true ) ) $input['conditional_display'] = $cn->defaults['general']['conditional_display']; if ( ! empty( $input['conditional_rules'] ) && is_array( $input['conditional_rules'] ) ) { $group_id = $rule_id = 1; $rules = []; foreach ( $input['conditional_rules'] as $group_number => $group ) { // skips template data or empty groups if ( (int) $group_number <= 0 || empty( $group ) ) continue; foreach ( $group as $rule ) { $param = sanitize_key( $rule['param'] ); $operator = sanitize_key( $rule['operator'] ); // do not sanitize value for taxonomy archive if ( $param === 'taxonomy_archive' ) $value = $rule['value']; else $value = sanitize_key( $rule['value'] ); if ( $this->check_rule( $param, $operator, $value ) ) { $rules[$group_id][$rule_id++] = [ 'param' => $param, 'operator' => $operator, 'value' => $value ]; } } $rule_id = 1; $group_id++; } $input['conditional_rules'] = $rules; } else $input['conditional_rules'] = []; // bot detection $input['bot_detection'] = isset( $input['bot_detection'] ); // debug mode $input['debug_mode'] = isset( $input['debug_mode'] ); // ui_mode is managed exclusively by maybe_switch_ui_mode() via nonce-gated // query param. It must not be processed here — the #2153 preservation loop // carries the existing DB value through. See #2155. // amp support $input['amp_support'] = isset( $input['amp_support'] ) && cn_is_plugin_active( 'amp' ); // get active caching plugins $active_plugins = cn_get_active_caching_plugins(); // caching compatibility $input['caching_compatibility'] = isset( $input['caching_compatibility'] ) && ! empty( $active_plugins ); // display csp notice? if ( $cn->get_status() === 'active' ) $input['csp_notice'] = $this->check_htaccess(); else $input['csp_notice'] = false; // position if ( isset( $input['position'] ) ) { $input['position'] = sanitize_key( $input['position'] ); if ( ! array_key_exists( $input['position'], $this->positions ) ) $input['position'] = $cn->defaults['general']['position']; } else $input['position'] = $cn->defaults['general']['position']; // text color if ( isset( $input['colors']['text'] ) ) { $input['colors']['text'] = sanitize_hex_color( $input['colors']['text'] ); if ( empty( $input['colors']['text'] ) ) $input['colors']['text'] = $cn->defaults['general']['colors']['text']; } else $input['colors']['text'] = $cn->defaults['general']['colors']['text']; // button color if ( isset( $input['colors']['button'] ) ) { $input['colors']['button'] = sanitize_hex_color( $input['colors']['button'] ); if ( empty( $input['colors']['button'] ) ) $input['colors']['button'] = $cn->defaults['general']['colors']['button']; } else $input['colors']['button'] = $cn->defaults['general']['colors']['button']; // bar color if ( isset( $input['colors']['bar'] ) ) { $input['colors']['bar'] = sanitize_hex_color( $input['colors']['bar'] ); if ( empty( $input['colors']['bar'] ) ) $input['colors']['bar'] = $cn->defaults['general']['colors']['bar']; } else $input['colors']['bar'] = $cn->defaults['general']['colors']['bar']; // bar opacity $input['colors']['bar_opacity'] = isset( $input['colors']['bar_opacity'] ) ? (int) $input['colors']['bar_opacity'] : $cn->defaults['general']['colors']['bar_opacity']; if ( $input['colors']['bar_opacity'] < 50 || $input['colors']['bar_opacity'] > 100 ) $input['colors']['bar_opacity'] = $cn->defaults['general']['colors']['bar_opacity']; // message text if ( isset( $input['message_text'] ) ) { add_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] ); $input['message_text'] = wp_kses_post( trim( $input['message_text'] ) ); remove_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] ); if ( $input['message_text'] === '' ) $input['message_text'] = $cn->defaults['general']['message_text']; } else $input['message_text'] = $cn->defaults['general']['message_text']; // accept button text if ( isset( $input['accept_text'] ) ) { $input['accept_text'] = sanitize_text_field( $input['accept_text'] ); if ( $input['accept_text'] === '' ) $input['accept_text'] = $cn->defaults['general']['accept_text']; } else $input['accept_text'] = $cn->defaults['general']['accept_text']; // refuse button text if ( isset( $input['refuse_text'] ) ) { $input['refuse_text'] = sanitize_text_field( $input['refuse_text'] ); if ( $input['refuse_text'] === '' ) $input['refuse_text'] = $cn->defaults['general']['refuse_text']; } else $input['refuse_text'] = $cn->defaults['general']['refuse_text']; // revoke message text if ( isset( $input['revoke_message_text'] ) ) { add_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] ); $input['revoke_message_text'] = wp_kses_post( trim( $input['revoke_message_text'] ) ); remove_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] ); if ( $input['revoke_message_text'] === '' ) $input['revoke_message_text'] = $cn->defaults['general']['revoke_message_text']; } else $input['revoke_message_text'] = $cn->defaults['general']['revoke_message_text']; // revoke button text if ( isset( $input['revoke_text'] ) ) { $input['revoke_text'] = sanitize_text_field( $input['revoke_text'] ); if ( $input['revoke_text'] === '' ) $input['revoke_text'] = $cn->defaults['general']['revoke_text']; } else $input['revoke_text'] = $cn->defaults['general']['revoke_text']; // refuse consent $input['refuse_opt'] = isset( $input['refuse_opt'] ); // revoke consent $input['revoke_cookies'] = isset( $input['revoke_cookies'] ); // revoke consent type if ( isset( $input['revoke_cookies_opt'] ) ) { $input['revoke_cookies_opt'] = sanitize_key( $input['revoke_cookies_opt'] ); if ( ! array_key_exists( $input['revoke_cookies_opt'], $this->revoke_opts ) ) $input['revoke_cookies_opt'] = $cn->defaults['general']['revoke_cookies_opt']; } else $input['revoke_cookies_opt'] = $cn->defaults['general']['revoke_cookies_opt']; // body refuse code if ( isset( $input['refuse_code'] ) ) $input['refuse_code'] = wp_kses( trim( $input['refuse_code'] ), $cn->get_allowed_html( 'body' ) ); else $input['refuse_code'] = $cn->defaults['general']['refuse_code']; // head refuse code if ( isset( $input['refuse_code_head'] ) ) $input['refuse_code_head'] = wp_kses( trim( $input['refuse_code_head'] ), $cn->get_allowed_html( 'head' ) ); else $input['refuse_code_head'] = $cn->defaults['general']['refuse_code_head']; // css button class(es) if ( isset( $input['css_class'] ) ) { $input['css_class'] = trim( $input['css_class'] ); if ( $input['css_class'] !== '' ) { // more than 1 class? if ( strpos( $input['css_class'], ' ' ) !== false ) { // get unique valid html classes $input['css_class'] = array_unique( array_filter( array_map( 'sanitize_html_class', explode( ' ', $input['css_class'] ) ) ) ); if ( ! empty( $input['css_class'] ) ) $input['css_class'] = implode( ' ', $input['css_class'] ); else $input['css_class'] = $cn->defaults['general']['css_class']; // single class } else $input['css_class'] = sanitize_html_class( $input['css_class'] ); } } else $input['css_class'] = $cn->defaults['general']['css_class']; // accepted expiry if ( isset( $input['time'] ) ) { $input['time'] = sanitize_key( $input['time'] ); if ( ! array_key_exists( $input['time'], $this->times ) ) $input['time'] = $cn->defaults['general']['time']; } else $input['time'] = $cn->defaults['general']['time']; // rejected expiry if ( isset( $input['time_rejected'] ) ) { $input['time_rejected'] = sanitize_key( $input['time_rejected'] ); if ( ! array_key_exists( $input['time_rejected'], $this->times ) ) $input['time_rejected'] = $cn->defaults['general']['time_rejected']; } else $input['time_rejected'] = $cn->defaults['general']['time_rejected']; // script placement if ( isset( $input['script_placement'] ) ) { $input['script_placement'] = sanitize_key( $input['script_placement'] ); if ( ! array_key_exists( $input['script_placement'], $this->script_placements ) ) $input['script_placement'] = $cn->defaults['general']['script_placement']; } else $input['script_placement'] = $cn->defaults['general']['script_placement']; // hide effect if ( isset( $input['hide_effect'] ) ) { $input['hide_effect'] = sanitize_key( $input['hide_effect'] ); if ( ! array_key_exists( $input['hide_effect'], $this->effects ) ) $input['hide_effect'] = $cn->defaults['general']['hide_effect']; } else $input['hide_effect'] = $cn->defaults['general']['hide_effect']; // reloading $input['redirection'] = isset( $input['redirection'] ); // on scroll $input['on_scroll'] = isset( $input['on_scroll'] ); // on scroll offset $input['on_scroll_offset'] = isset( $input['on_scroll_offset'] ) ? (int) $input['on_scroll_offset'] : $cn->defaults['general']['on_scroll_offset']; if ( $input['on_scroll_offset'] < 0 ) $input['on_scroll_offset'] = 0; // on click $input['on_click'] = isset( $input['on_click'] ); // deactivation $input['deactivation_delete'] = isset( $input['deactivation_delete'] ); // privacy policy $input['see_more'] = isset( $input['see_more'] ); // privacy policy link text if ( isset( $input['see_more_opt']['text'] ) ) { $input['see_more_opt']['text'] = sanitize_text_field( $input['see_more_opt']['text'] ); if ( $input['see_more_opt']['text'] === '' ) $input['see_more_opt']['text'] = $cn->defaults['general']['see_more_opt']['text']; } else $input['see_more_opt']['text'] = $cn->defaults['general']['see_more_opt']['text']; // privacy policy link type if ( isset( $input['see_more_opt']['link_type'] ) ) { $input['see_more_opt']['link_type'] = sanitize_key( $input['see_more_opt']['link_type'] ); if ( ! array_key_exists( $input['see_more_opt']['link_type'], $this->links ) ) $input['see_more_opt']['link_type'] = $cn->defaults['general']['see_more_opt']['link_type']; } else $input['see_more_opt']['link_type'] = $cn->defaults['general']['see_more_opt']['link_type']; if ( $input['see_more_opt']['link_type'] === 'custom' ) $input['see_more_opt']['link'] = $input['see_more'] && isset( $input['see_more_opt']['link'] ) ? esc_url_raw( $input['see_more_opt']['link'] ) : ''; elseif ( $input['see_more_opt']['link_type'] === 'page' ) { $input['see_more_opt']['id'] = $input['see_more'] && isset( $input['see_more_opt']['id'] ) ? (int) $input['see_more_opt']['id'] : 0; $input['see_more_opt']['sync'] = isset( $input['see_more_opt']['sync'] ); if ( $input['see_more_opt']['sync'] ) update_option( 'wp_page_for_privacy_policy', $input['see_more_opt']['id'] ); } // privacy policy link target if ( isset( $input['link_target'] ) ) { $input['link_target'] = sanitize_key( $input['link_target'] ); if ( ! in_array( $input['link_target'], $this->link_targets, true ) ) $input['link_target'] = $cn->defaults['general']['link_target']; } else $input['link_target'] = $cn->defaults['general']['link_target']; // policy policy link position if ( isset( $input['link_position'] ) ) { $input['link_position'] = sanitize_key( $input['link_position'] ); if ( ! array_key_exists( $input['link_position'], $this->link_positions ) ) $input['link_position'] = $cn->defaults['general']['link_position']; } else $input['link_position'] = $cn->defaults['general']['link_position']; // message link position? if ( $input['see_more'] && $input['link_position'] === 'message' && strpos( $input['message_text'], '[cookies_policy_link' ) === false ) $input['message_text'] .= ' [cookies_policy_link]'; // notice data $input['update_version'] = $cn->options['general']['update_version']; $input['update_notice'] = $cn->options['general']['update_notice']; $input['review_notice'] = $cn->options['general']['review_notice']; $input['review_notice_delay'] = $cn->options['general']['review_notice_delay']; $input['translate'] = false; // WPML >= 3.2 if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) { do_action( 'wpml_register_single_string', 'Cookie Notice', 'Message in the notice', $input['message_text'] ); do_action( 'wpml_register_single_string', 'Cookie Notice', 'Button text', $input['accept_text'] ); do_action( 'wpml_register_single_string', 'Cookie Notice', 'Refuse button text', $input['refuse_text'] ); do_action( 'wpml_register_single_string', 'Cookie Notice', 'Revoke message text', $input['revoke_message_text'] ); do_action( 'wpml_register_single_string', 'Cookie Notice', 'Revoke button text', $input['revoke_text'] ); do_action( 'wpml_register_single_string', 'Cookie Notice', 'Privacy policy text', $input['see_more_opt']['text'] ); if ( $input['see_more_opt']['link_type'] === 'custom' ) do_action( 'wpml_register_single_string', 'Cookie Notice', 'Custom link', $input['see_more_opt']['link'] ); } // Preserve any keys in the current DB options that validate_options() does not // explicitly process (e.g. displayType, ui_mode, update_delay_date, // update_threshold_date, update_notice_diss). Without this, WordPress's register_setting() // replaces the entire cookie_notice_options row with $input, silently dropping these fields // on every legacy form save. See #2153. // Re-read from DB here (not from constructor snapshot) to avoid overwriting concurrent // React changes made in another tab after this page loaded. See #2181. $current_db_options = $is_network ? (array) get_site_option( 'cookie_notice_options', [] ) : (array) get_option( 'cookie_notice_options', [] ); foreach ( $current_db_options as $key => $value ) { if ( ! array_key_exists( $key, $input ) ) { $input[ $key ] = $value; } } add_settings_error( 'cn_cookie_notice_options', 'save_cookie_notice_options', esc_html__( 'Settings saved.', 'cookie-notice' ), 'updated' ); } elseif ( isset( $_POST['reset_cookie_notice_options'] ) ) { $input = $cn->defaults['general']; add_settings_error( 'cn_cookie_notice_options', 'reset_cookie_notice_options', esc_html__( 'Settings restored to defaults.', 'cookie-notice' ), 'updated' ); // network area? if ( $is_network ) { // set app data update_site_option( 'cookie_notice_status', $cn->defaults['data'] ); } else { // set app data update_option( 'cookie_notice_status', $cn->defaults['data'] ); } } do_action( 'cn_configuration_updated', 'settings', $input ); return $input; } /** * Validate network options. * * @return void */ public function validate_network_options() { if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) ) return; // get main instance $cn = Cookie_Notice(); // global network page? if ( $cn->is_network_admin() && isset( $_POST['cn-network-settings'] ) ) { // network settings if ( ! empty( $_POST['cookie_notice_options'] ) && check_admin_referer( 'cookie_notice_options-options', '_wpnonce' ) !== false ) { if ( isset( $_POST['save_cookie_notice_options'] ) ) { // need to force it early for get_app_config and get_app_analytics $cn->network_options['general']['global_override'] = true; // validate options $data = $this->validate_options( $_POST['cookie_notice_options'] ); // check network settings $data['global_override'] = isset( $_POST['cookie_notice_options']['global_override'] ); $data['global_cookie'] = isset( $_POST['cookie_notice_options']['global_cookie'] ); $data['update_notice_diss'] = $cn->options['general']['update_notice_diss']; // set real value $cn->network_options['general']['global_override'] = $data['global_override']; if ( $data['global_override'] && ! $cn->options['general']['update_notice_diss'] ) $data['update_notice'] = true; else $data['update_notice'] = false; // update database update_site_option( 'cookie_notice_options', $data ); // update settings $cn->options['general'] = $cn->network_options['general'] = $cn->multi_array_merge( $cn->defaults['general'], get_site_option( 'cookie_notice_options', $cn->defaults['general'] ) ); } elseif ( isset( $_POST['reset_cookie_notice_options'] ) ) { $cn->defaults['general']['update_notice'] = false; $cn->defaults['general']['update_notice_diss'] = false; // silent options validation $this->validate_options( $cn->defaults['general'] ); // update database update_site_option( 'cookie_notice_options', $cn->defaults['general'] ); // update settings $cn->options['general'] = $cn->network_options['general'] = $cn->defaults['general']; } } // update status of cookie compliance $cn->set_status_data(); } } /** * Load scripts and styles - admin. * * @return void */ public function admin_enqueue_scripts( $page ) { // get main instance $cn = Cookie_Notice(); $is_network = $cn->is_network_admin(); if ( $page === 'toplevel_page_cookie-notice' ) { $ui_mode = $cn->options['general']['ui_mode']; wp_enqueue_script( 'cookie-notice-admin', COOKIE_NOTICE_URL . '/js/admin' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [ 'jquery', 'wp-color-picker' ], $cn->defaults['version'] ); // prepare script data $script_data = [ 'ajaxURL' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'cn-purge-cache' ), 'nonceSyncConfig' => wp_create_nonce( 'cookie-notice-welcome' ), 'nonceConditional' => wp_create_nonce( 'cn-get-group-values' ), 'nonceCookieConsentLogs' => wp_create_nonce( 'cn-get-cookie-consent-logs' ), 'noncePrivacyConsentLogs' => wp_create_nonce( 'cn-get-privacy-consent-logs' ), 'noncePrivacyConsent' => wp_create_nonce( 'cn-privacy-consent-set-form-status' ), 'consentLogsTemplate' => $cn->consent_logs->get_single_row_template(), 'consentLogsError' => $cn->consent_logs->get_error_template(), 'settingsTab' => $this->current_tab, 'settingsSection' => $this->current_section, 'network' => $cn->is_network_admin(), 'resetToDefaults' => esc_html__( 'Are you sure you want to reset these settings to defaults?', 'cookie-notice' ), 'privacyConsentSources' => $cn->privacy_consent->get_sources() ]; wp_add_inline_script( 'cookie-notice-admin', 'var cnArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' ); wp_enqueue_style( 'wp-color-picker' ); // React admin bundle. // In CN_DEV_MODE use the file's mtime as the version so every deploy // busts the browser cache automatically (the plugin version string only // changes on official releases, causing stale bundles during testing). $react_js_path = COOKIE_NOTICE_PATH . 'assets/react-admin/cn-admin-react.js'; $react_css_path = COOKIE_NOTICE_PATH . 'assets/react-admin/cn-admin-react.css'; $react_ver = ( defined( 'CN_DEV_MODE' ) && CN_DEV_MODE && file_exists( $react_js_path ) ) ? filemtime( $react_js_path ) : $cn->defaults['version']; if ( $ui_mode === 'react' ) { wp_enqueue_script( 'cookie-notice-react-admin', COOKIE_NOTICE_URL . '/assets/react-admin/cn-admin-react.js', [], $react_ver, true ); wp_enqueue_style( 'cookie-notice-react-admin', COOKIE_NOTICE_URL . '/assets/react-admin/cn-admin-react.css', [], $react_ver ); // Pull fresh config from Designer API before localizing data. // Ensures the React UI starts with the latest state, even if // changes were made in the Admin Portal since the last cron sync. if ( ! empty( $cn->options['general']['app_id'] ) ) { $cn->welcome_api->get_app_config( '', true ); } // Re-apply dev tier override — get_app_config() calls // set_status_data() which re-reads from DB, overwriting // the in-memory override set during init. $cn->maybe_apply_dev_tier_override(); // Read notification rules from shared JSON config. $cn_rules_json = file_get_contents( COOKIE_NOTICE_PATH . 'includes/notifications.json' ); $cn_rules_data = $cn_rules_json !== false ? json_decode( $cn_rules_json, true ) : null; $cn_notification_rules = is_array( $cn_rules_data ) ? ( $cn_rules_data['rules'] ?? [] ) : []; wp_localize_script( 'cookie-notice-react-admin', 'cnReactData', [ 'ajaxURL' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'cn_react_nonce' ), 'welcomeNonce' => wp_create_nonce( 'cookie-notice-welcome' ), 'configureNonce' => wp_create_nonce( 'cn_api_configure' ), 'registerNonce' => wp_create_nonce( 'cn_api_register' ), 'loginNonce' => wp_create_nonce( 'cn_api_login' ), 'paymentNonce' => wp_create_nonce( 'cn_api_payment' ), 'uiMode' => $ui_mode, 'network' => $cn->is_network_admin(), 'status' => $cn->get_status(), 'subscription' => $cn->get_subscription(), 'app_id' => $cn->options['general']['app_id'], 'version' => $cn->defaults['version'], 'options' => $cn->options['general'], 'siteUrl' => home_url(), 'devMode' => defined( 'CN_DEV_MODE' ) && CN_DEV_MODE && current_user_can( 'manage_options' ), 'welcomeDismissedAt' => get_option( 'cookie_notice_welcome_dismissed', '' ), 'setupWizardComplete' => (bool) get_option( 'cookie_notice_setup_wizard_complete', false ), 'selectedLaws' => $cn->is_network_admin() ? get_site_option( 'cookie_notice_app_regulations', [] ) : get_option( 'cookie_notice_app_regulations', [] ), 'wpPages' => array_map( function( $p ) { return [ 'id' => $p->ID, 'title' => $p->post_title ]; }, get_pages( [ 'sort_column' => 'post_title' ] ) ?: [] ), 'siteLocale' => get_locale(), 'detectedPlugins' => cn_detect_active_plugins(), 'bannerDesign' => $is_network ? get_site_option( 'cookie_notice_app_design', [] ) : get_option( 'cookie_notice_app_design', [] ), 'displayType' => $cn->options['general']['displayType'] ?? 'floating', 'appUrl' => Cookie_Notice()->get_url( 'host' ), 'lastSynced' => ( function() use ( $is_network ) { $blocking = $is_network ? get_site_option( 'cookie_notice_app_blocking', [] ) : get_option( 'cookie_notice_app_blocking', [] ); return ! empty( $blocking['lastUpdated'] ) ? $blocking['lastUpdated'] : ''; } )(), 'purgeNonce' => wp_create_nonce( 'cn-purge-cache' ), 'notificationRules' => $cn_notification_rules, 'ruleParams' => array_map( function( $label, $key ) { return [ 'value' => $key, 'label' => $label ]; }, $this->parameters, array_keys( $this->parameters ) ), 'ruleOperators' => array_map( function( $label, $key ) { return [ 'value' => $key, 'label' => $label ]; }, $this->operators, array_keys( $this->operators ) ), ] ); } } wp_enqueue_style( 'cookie-notice-admin', COOKIE_NOTICE_URL . '/css/admin' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css', [], $cn->defaults['version'] ); if ( $this->current_tab === 'consent-logs' ) { // pagination script wp_enqueue_script( 'cookie-notice-admin-pagination', COOKIE_NOTICE_URL . '/assets/pagination/pagination.js', [ 'jquery' ], '2.6.0' ); wp_enqueue_style( 'cookie-notice-admin-pagination', COOKIE_NOTICE_URL . '/assets/pagination/pagination.css', [], '2.6.0' ); } } /** * Load admin style inline, for menu icon only. * * @return void */ public function admin_print_styles() { echo ' '; } /** * Register WPML (>= 3.2) strings if needed. * * @global object $wpdb * * @return void */ private function register_wpml_strings() { // get main instance $cn = Cookie_Notice(); global $wpdb; // prepare strings $strings = [ 'Message in the notice' => $cn->options['general']['message_text'], 'Button text' => $cn->options['general']['accept_text'], 'Refuse button text' => $cn->options['general']['refuse_text'], 'Revoke message text' => $cn->options['general']['revoke_message_text'], 'Revoke button text' => $cn->options['general']['revoke_text'], 'Privacy policy text' => $cn->options['general']['see_more_opt']['text'], 'Custom link' => $cn->options['general']['see_more_opt']['link'] ]; // get query results $results = $wpdb->get_col( $wpdb->prepare( "SELECT name FROM " . $wpdb->prefix . "icl_strings WHERE context = %s", 'Cookie Notice' ) ); // check results foreach( $strings as $string => $value ) { // string does not exist? if ( ! in_array( $string, $results, true ) ) { // register string do_action( 'wpml_register_single_string', 'Cookie Notice', $string, $value ); } } } /** * Display errors and notices. * * @global string $pagenow * * @return void */ public function settings_errors() { global $pagenow; // force display notices in top menu settings page if ( $pagenow === 'options-general.php' ) return; settings_errors( 'cn_cookie_notice_options' ); } /** * Save compliance config caching. * * @return void */ public function ajax_purge_cache() { // valid nonce? if ( ! check_ajax_referer( 'cn-purge-cache', 'nonce' ) ) exit; // check capability if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) ) exit; // request for new config data Cookie_Notice()->welcome_api->get_app_config( '', true ); // force new config on frontend if ( Cookie_Notice()->is_network_options() ) set_site_transient( 'cookie_notice_config_update', current_time( 'timestamp', true ), 600 ); else set_transient( 'cookie_notice_config_update', current_time( 'timestamp', true ), 600 ); exit; } /** * Generate conditions. * * @param array $groups * @return string */ public function conditional_display( $groups ) { $group_template = ' %s

' . esc_html__( 'or', 'cookie-notice' ) . '

'; $rule_template = ' '; $html = sprintf( $group_template, ' class="rules-group" id="rules-group-template" style="display: none"', sprintf( $rule_template, ' class="rule_template"', $this->prepare_parameters(), $this->prepare_operators(), $this->prepare_values( 'page_type' ) ) ) . ' '; return $html; } /** * Prepare condition parameters. * * @param string $selected * @return string */ public function prepare_parameters( $selected = 'page_type' ) { $html = ''; foreach ( $this->parameters as $id => $element ) { $html .= ''; } return $html; } /** * Prepare condition operators. * * @param string $selected * @return string */ public function prepare_operators( $selected = 'equal' ) { $html = ''; foreach ( $this->operators as $id => $operator ) { $html .= ''; } return $html; } /** * Prepare condition values. * * @param string $type * @param string $selected * @return string */ public function prepare_values( $type = '', $selected = '' ) { $type = sanitize_key( $type ); if ( $type !== 'taxonomy_archive' ) $selected = sanitize_key( $selected ); $html = ''; switch ( sanitize_key( $type ) ) { case 'page': $pages = $this->get_pages(); if ( ! empty( $pages ) ) { foreach ( $pages as $page_id => $page_title ) { $html .= ''; } } break; case 'page_type': $page_types = $this->get_page_types(); if ( ! empty( $page_types ) ) { foreach ( $page_types as $page_type => $label ) { $html .= ''; } } break; case 'post_type': $post_types = $this->get_post_types(); if ( ! empty( $post_types ) ) { foreach ( $post_types as $post_type => $label ) { $html .= ''; } } break; case 'user_type': $user_types = $this->get_user_types(); if ( ! empty( $user_types ) ) { foreach ( $user_types as $user_type => $username ) { $html .= ''; } } break; case 'post_type_archive': $post_type_archives = $this->get_post_type_archives(); if ( ! empty( $post_type_archives ) ) { foreach ( $post_type_archives as $post_type => $archive_name ) { $html .= ''; } } else $html .= ''; break; case 'taxonomy_archive': $terms = $this->get_terms(); if ( ! empty( $terms ) ) { foreach ( $terms as $taxonomy => $data ) { $html .= ''; foreach ( $data['terms'] as $term_id => $term_name ) { $value = $term_id . '|' . $taxonomy; $html .= ''; } $html .= ''; } } else $html .= ''; } return $html; } /** * Check condition rule. * * @param string $type * @param string $operator * @param string $value * @return bool */ public function check_rule( $type = '', $operator = '', $value = '' ) { if ( ! isset( $this->operators[$operator] ) ) return false; switch( $type ) { case 'page': $pages = $this->get_pages(); $valid_rule = ! empty( $pages[$value] ); break; case 'page_type': $page_types = $this->get_page_types(); $valid_rule = ! empty( $page_types[$value] ); break; case 'post_type': $post_types = $this->get_post_types(); $valid_rule = ! empty( $post_types[$value] ); break; case 'user_type': $user_types = $this->get_user_types(); $valid_rule = ! empty( $user_types[$value] ); break; case 'post_type_archive': $post_type_archives = $this->get_post_type_archives(); $valid_rule = ! empty( $post_type_archives[$value] ); break; case 'taxonomy_archive': // check value if ( strpos( $value, '|' ) !== false ) { // explode it $values = explode( '|', $value ); // 2 chunks? if ( count( $values ) === 2 ) { // get term $term = get_term( (int) $values[0], $values[1] ); $valid_rule = ! ( is_wp_error( $term ) || ! $term ); } else $valid_rule = false; } else $valid_rule = false; break; default: $valid_rule = false; } return $valid_rule; } /** * Get page types. * * @return array */ public function get_pages() { $pages = []; // default arguments $args = [ 'post_type' => 'page', 'post__not_in' => [], 'nopaging' => true, 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'asc', 'suppress_filters' => false, 'no_found_rows' => true, 'cache_results' => false, 'post_status' => [ 'publish', 'private', 'future' ] ]; // get static home pages $homepage = (int) get_option( 'page_for_posts', 0 ); $posts_page = (int) get_option( 'page_on_front', 0 ); // check homepage if ( $homepage > 0 ) $args['post__not_in'][] = $homepage; // check posts page if ( $posts_page > 0 ) $args['post__not_in'][] = $posts_page; $query = new WP_Query( $args ); if ( ! empty( $query->posts ) ) { foreach ( $query->posts as $page ) { $page_id = (int) $page->ID; $pages[$page_id] = trim( $page->post_title ) === '' ? sprintf( __( 'Untitled Page %d', 'cookie-notice' ), $page_id ) : $page->post_title; } } return $pages; } /** * Get page types. * * @return array */ public function get_page_types() { return [ 'front' => __( 'Front Page', 'cookie-notice' ), 'home' => __( 'Home Page', 'cookie-notice' ) ]; } /** * Get user types. * * @return array */ public function get_user_types() { return [ 'logged_in' => __( 'Logged in', 'cookie-notice' ), 'guest' => __( 'Guest', 'cookie-notice' ) ]; } /** * Get public post types. * * @return array */ public function get_post_types() { // get public post types $post_types = get_post_types( [ 'public' => true ], 'objects', 'and' ); $data = []; if ( ! empty( $post_types ) ) { foreach ( $post_types as $key => $post_type ) { $data[$key] = $post_type->labels->singular_name; } } asort( $data, SORT_STRING ); return $data; } /** * Get public post type archives. * * @return array */ public function get_post_type_archives() { // get public post types with archives $post_types = get_post_types( [ 'has_archive' => true, 'public' => true ], 'objects', 'and' ); $archives = []; if ( ! empty( $post_types ) ) { foreach ( $post_types as $key => $post_type ) { $archives[$key] = $post_type->labels->name; } } // sort archives alphabetically asort( $archives, SORT_STRING ); return $archives; } /** * Get public terms. * * @return array */ public function get_terms() { // get all public taxonomies $taxonomies = get_taxonomies( [ 'public' => true ], 'objects', 'and' ); // get all terms associated with specified taxonomies $terms = get_terms( [ 'taxonomy' => array_keys( $taxonomies ), 'hide_empty' => false, 'order' => 'asc', 'orderby' => 'name' ] ); $sorted = []; foreach ( $taxonomies as $slug => $taxonomy ) { $sorted[$slug] = [ 'label' => $taxonomy->label, 'terms' => [] ]; } foreach ( $terms as $term ) { $sorted[$term->taxonomy]['terms'][$term->term_id] = $term->name; } return $sorted; } /** * Get group rule values. * * @return void */ public function get_group_rule_values() { if ( isset( $_POST['action'], $_POST['cn_param'], $_POST['cn_nonce'] ) && wp_verify_nonce( $_POST['cn_nonce'], 'cn-get-group-values' ) !== false && current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) ) { echo wp_json_encode( [ 'select' => $this->prepare_values( sanitize_key( $_POST['cn_param'] ) ) ] ); } exit; } /** * Get fresh cookie compliance credentials for analytics. * * @return array */ public function get_analytics_app_data() { return $this->analytics_app_data; } /** * Add new properties to style safe list. * * @param array $styles * @return array */ public function allow_style_attributes( $styles ) { $styles[] = 'display'; return $styles; } }