plugin_name = $plugin_name; $this->version = $version; $this->load_dependencies(); } /** * Load the required dependencies for this plugin. * * Include the following files that make up the plugin: * * - Siteimprove_Loader. Orchestrates the hooks of the plugin. * - Siteimprove_I18n. Defines internationalization functionality. * - Siteimprove_Admin. Defines all hooks for the admin area. * - Siteimprove_Public. Defines all hooks for the public side of the site. * * Create an instance of the loader which will be used to register the hooks * with WordPress. * * @access private */ private function load_dependencies() { require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/class-siteimprove-admin-settings.php'; $this->settings = new Siteimprove_Admin_Settings(); } /** * Register the stylesheets for the admin area. */ public function enqueue_styles() { wp_enqueue_style( 'siteimprove_admin_css', plugin_dir_url( __FILE__ ) . 'css/siteimprove-admin.css', array(), $this->version, 'all' ); } /** * Register the stylesheets for the preview area. */ public function enqueue_preview_styles() { global $wp_query; $prepublish_allowed = intval( get_option( 'siteimprove_prepublish_allowed', 0 ) ); $prepublish_enabled = intval( get_option( 'siteimprove_prepublish_enabled', 0 ) ); if ( ( $wp_query->is_preview() || $wp_query->is_singular() || is_front_page() ) && 1 === $prepublish_allowed && 1 === $prepublish_enabled ) { wp_enqueue_style( 'siteimprove_preview_css', plugin_dir_url( __FILE__ ) . 'css/siteimprove-preview.css', array(), $this->version, 'all' ); } } /** * Register the JavaScript for the admin area. */ public function enqueue_scripts() { wp_enqueue_script( 'siteimprove_admin_js', plugin_dir_url( __FILE__ ) . 'js/siteimprove-admin.js', array( 'jquery' ), $this->version, false ); } /** * Gutenberg script for adding buttons to its editor such as Recheck */ public function gutenberg_siteimprove_plugin() { global $post; if ( $post && $post->ID ) { $permalink = get_permalink( $post->ID ); if ( $permalink ) { $this->siteimprove_add_js( $permalink, 'siteimprove_input' ); if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log( 'Siteimprove Debug: Gutenberg - Post ID: ' . $post->ID ); error_log( 'Siteimprove Debug: Gutenberg - Permalink: ' . $permalink ); } } } wp_enqueue_script( 'gutenberg-siteimprove-plugin', plugin_dir_url( __FILE__ ) . 'js/siteimprove-gutenberg.js', array( 'wp-plugins', 'wp-edit-post', 'wp-element', 'siteimprove' ), $this->version, false ); $post_id = $post ? $post->ID : 0; $url = $post_id ? get_permalink( $post_id ) : ''; $si_js_args = array( 'token' => get_option( 'siteimprove_token' ), 'text' => __( 'Siteimprove Recheck', 'siteimprove' ), 'url' => $url, ); wp_localize_script( 'gutenberg-siteimprove-plugin', 'siteimprove_gutenberg_recheck', $si_js_args ); } /** * Initial actions. */ public function siteimprove_init() { global $pagenow; if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log( 'Siteimprove Debug: Current page: ' . $pagenow ); error_log( 'Siteimprove Debug: GET params: ' . print_r( $_GET, true ) ); } $urls = get_transient( 'siteimprove_url_' . get_current_user_id() ); if ( ! wp_doing_ajax() && ! empty( $urls ) ) { if ( is_array( $urls ) && count( $urls ) > 1 ) { $url = esc_url( home_url() ); $method = 'siteimprove_recrawl'; } else { $url = array_pop( $urls ); $method = 'siteimprove_recheck'; } delete_transient( 'siteimprove_url_' . get_current_user_id() ); $this->siteimprove_add_js( $url, $method ); } switch ( $pagenow ) { case 'post.php': $post_id = ! empty( $_GET['post'] ) ? (int) $_GET['post'] : 0; $permalink = $post_id ? get_permalink( $post_id ) : false; if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log( 'Siteimprove Debug: Post ID: ' . $post_id ); error_log( 'Siteimprove Debug: Permalink: ' . $permalink ); error_log( 'Siteimprove Debug: Token: ' . get_option( 'siteimprove_token', 'NOT_SET' ) ); error_log( 'Siteimprove Debug: User can edit posts: ' . ( current_user_can( 'edit_posts' ) ? 'yes' : 'no' ) ); } if ( $permalink && current_user_can( 'edit_posts' ) ) { $this->siteimprove_add_js( get_permalink( $post_id ), 'siteimprove_input' ); // Only display recheck button in published posts. if ( get_post_status( $post_id ) === 'publish' ) { $this->siteimprove_add_js( get_permalink( $post_id ), 'siteimprove_recheck_button' ); } } break; case 'term.php': case 'edit-tags.php': $tag_id = ! empty( $_GET['tag_ID'] ) ? (int) $_GET['tag_ID'] : 0; $taxonomy = ! empty( $_GET['taxonomy'] ) ? sanitize_key( $_GET['taxonomy'] ) : ''; if ( ( 'term.php' === $pagenow || ( 'edit-tags.php' === $pagenow && ! empty( $_GET['action'] ) && 'edit' === $_GET['action'] ) ) && current_user_can( 'manage_categories' ) ) { $term_link = get_term_link( (int) $tag_id, $taxonomy ); if ( ! is_wp_error( $term_link ) ) { $this->siteimprove_add_js( $term_link, 'siteimprove_input' ); $this->siteimprove_add_js( $term_link, 'siteimprove_recheck_button' ); } } break; default: $host = isset( $_SERVER['HTTP_HOST'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : ''; $request = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; $this->siteimprove_add_js( $host . $request, 'siteimprove_domain' ); } } /** * Include siteimprove js. * * @param string $url Url of the included js file. * @param string $type Type/Handle of resource being included to localize the script correctly. * @return void */ private function siteimprove_add_js( $url, $type ) { $file_name = get_option( 'siteimprove_overlayjs_file', 'overlay-v2-dev.js' ); $disabled_new_version = get_option( 'siteimprove_disable_new_version' ); $pattern = '/^[a-zA-Z_\d-]+.js/'; $nonce = wp_create_nonce( 'siteimprove_nonce' ); if ( ! empty( $file_name ) ) { if ( preg_match( $pattern, $file_name ) ) { $overlay_path = Siteimprove::JS_LIBRARY_URL . $file_name; } else { $overlay_path = $file_name; } } else { if ( $disabled_new_version ) { $overlay_path = Siteimprove::JS_LIBRARY_URL . 'overlay-latest.js'; } else { $overlay_path = Siteimprove::JS_LIBRARY_URL . 'overlay-v1.js'; } } if ( isset( $_GET['si_preview_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['si_preview_nonce'] ) ), 'siteimprove_nonce' ) ) { return; } else { wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/siteimprove.js', array( 'jquery' ), $this->version, false ); /* Pass any server-side vars down to JS. These will be exposed as php_vars.variablename for example */ $jsarray = array( 'prepublish_allowed' => intval( get_option( 'siteimprove_prepublish_allowed', 0 ) ), 'prepublish_enabled' => intval( get_option( 'siteimprove_prepublish_enabled', 0 ) ), 'has_api_key' => intval( strlen( get_option( 'siteimprove_api_key', 0 ) ) > 0 ), ); wp_localize_script( $this->plugin_name, 'php_vars', $jsarray ); wp_enqueue_script( 'siteimprove_overlay', $overlay_path, array(), $this->version, true ); } $public_url = get_option( 'siteimprove_public_url' ); $ignore_segments = get_option( 'siteimprove_ignore_path_segments' ); // Parse the URL to get its components. $parsed_url = wp_parse_url( $url ); $path = isset( $parsed_url['path'] ) ? $parsed_url['path'] : ''; // Apply path segment filtering if configured. if ( ! empty( $ignore_segments ) && ! empty( $path ) ) { // Split the ignore segments by comma and trim whitespace. $segments_to_ignore = array_map( 'trim', explode( ',', $ignore_segments ) ); // Split the path into segments. $path_segments = array_filter( explode( '/', $path ) ); // Remove segments that should be ignored. $filtered_segments = array(); foreach ( $path_segments as $segment ) { if ( ! in_array( $segment, $segments_to_ignore, true ) ) { $filtered_segments[] = $segment; } } // Reconstruct the path. $path = '/' . implode( '/', $filtered_segments ); } // Apply public URL transformation if configured. if ( ! empty( $public_url ) ) { $public_url = rtrim( $public_url, '/' ); $normalized_path = '/' . ltrim( $path, '/' ); $query_string = isset( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : ''; $url = $public_url . $normalized_path . $query_string; } else { // If no public URL is set, reconstruct the URL with the filtered path. $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] . '://' : ''; $host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : ''; $port = isset( $parsed_url['port'] ) ? ':' . $parsed_url['port'] : ''; $query = isset( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : ''; $fragment = isset( $parsed_url['fragment'] ) ? '#' . $parsed_url['fragment'] : ''; $url = $scheme . $host . $port . $path . $query . $fragment; } $is_content_page = is_preview() || is_singular() || is_front_page(); $si_js_args = array( 'token' => get_option( 'siteimprove_token' ), 'txt' => __( 'Siteimprove Recheck', 'siteimprove' ), 'url' => $url, 'version' => $disabled_new_version, 'is_content_page' => $is_content_page, 'nonce' => $nonce, ); wp_localize_script( $this->plugin_name, esc_js( $type ), $si_js_args ); // Adding translation strings. wp_localize_script( $this->plugin_name, 'siteimprove_plugin_text', array( 'loading' => __( 'Loading... Please wait.', 'siteimprove' ), 'prepublish_activate_running' => __( 'We are now activating prepublish for your website... Please keep the current page open while the process is running.', 'siteimprove' ), 'prepublish_feature_ready' => __( 'Prepublish feature is already enabled for the current website. To use it please go to the preview of any page/post or content that you want to check and click the button Siteimprove Prepublish Check located on the top bar of the admin panel.', 'siteimprove' ), 'prepublish_activation_error' => __( 'Error activating prepublish. Please contact support team.', 'siteimprove' ), ) ); } /** * Register settings form section. */ public function siteimprove_settings() { $this->settings->register_section(); } /** * Register menu page. */ public function siteimprove_settings_page() { $this->settings->register_menu(); } /** * Register action for token requests. */ public function siteimprove_request_token() { $this->settings->request_token(); } /** * Register action for prepublish feature check after manual activation on the admin panel side * * @return void */ public function siteimprove_check_prepublish_activation() { $this->settings->check_prepublish_activation(); } /** * Register action for prepublish feature manual activation made on the admin panel side * * @return void */ public function siteimprove_prepublish_manual_activation() { $this->settings->prepublish_manual_activation(); } /** * Save in session post url. * * @param integer $post_ID WordPress Post ID. * @return void */ public function siteimprove_save_session_url_post( $post_ID ) { if ( ! wp_is_post_revision( $post_ID ) && ! wp_is_post_autosave( $post_ID ) ) { $urls = get_transient( 'siteimprove_url_' . get_current_user_id() ); $urls[] = get_permalink( $post_ID ); set_transient( 'siteimprove_url_' . get_current_user_id(), $urls, 900 ); } } /** * Save in session term url. * * @param integer $term_id WordPress Term ID. * @param mixed $tt_id WordPress parameter added for hook compatibility. * @param mixed $taxonomy WordPress taxonomy. * @return void */ public function siteimprove_save_session_url_term( $term_id, $tt_id, $taxonomy ) { $urls = get_transient( 'siteimprove_url_' . get_current_user_id() ); $urls[] = get_term_link( (int) $term_id, $taxonomy ); set_transient( 'siteimprove_url_' . get_current_user_id(), $urls, 900 ); } /** * Save in session product url. * * @param string $new_status WordPress post status. * @param string $old_status WordPress post status. * @param object $post WordPress Post Object. * @return void */ public function siteimprove_save_session_url_product( $new_status, $old_status, $post ) { if ( 'publish' === $new_status && ! empty( $post->ID ) && in_array( $post->post_type, array( 'product' ), true ) ) { $urls = get_transient( 'siteimprove_url_' . get_current_user_id() ); $urls[] = get_permalink( $post->ID ); set_transient( 'siteimprove_url_' . get_current_user_id(), $urls, 900 ); } } /** * Include js in frontend pages. */ public function siteimprove_wp_head() { $user = wp_get_current_user(); $allowed_roles = array( 'shop_manager', 'contributor', 'author', 'editor', 'administrator', ); if ( array_intersect( $allowed_roles, $user->roles ) ) { $type = $this->get_current_page_type(); switch ( $type ) { case 'front': case 'home': case 'page': case 'single': case 'category': case 'tag': case 'tax': $this->siteimprove_add_js( get_permalink(), 'siteimprove_input' ); break; default: $host = isset( $_SERVER['HTTP_HOST'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : ''; $request = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; $this->siteimprove_add_js( $host . $request, 'siteimprove_domain' ); } } } /** * Return current page type. */ protected function get_current_page_type() { global $wp_query; $loop = 'notfound'; if ( $wp_query->is_page ) { $loop = is_front_page() ? 'front' : 'page'; } elseif ( $wp_query->is_home ) { $loop = 'home'; } elseif ( $wp_query->is_single ) { $loop = ( $wp_query->is_attachment ) ? 'attachment' : 'single'; } elseif ( $wp_query->is_category ) { $loop = 'category'; } elseif ( $wp_query->is_tag ) { $loop = 'tag'; } elseif ( $wp_query->is_tax ) { $loop = 'tax'; } elseif ( $wp_query->is_archive ) { if ( $wp_query->is_day ) { $loop = 'day'; } elseif ( $wp_query->is_month ) { $loop = 'month'; } elseif ( $wp_query->is_year ) { $loop = 'year'; } elseif ( $wp_query->is_author ) { $loop = 'author'; } else { $loop = 'archive'; } } elseif ( $wp_query->is_search ) { $loop = 'search'; } elseif ( $wp_query->is_404 ) { $loop = 'notfound'; } return $loop; } /** * Adds the prepublish menu item on the top bar when user is * in preview mode so he can send the content to prepublish. * * @param WP_Admin_Bar $admin_bar WordPress Admin Bar Object. * @return void */ public function add_prepublish_toolbar_item( WP_Admin_Bar $admin_bar ) { global $pagenow; $prepublish_allowed = intval( get_option( 'siteimprove_prepublish_allowed', 0 ) ); $prepublish_enabled = intval( get_option( 'siteimprove_prepublish_enabled', 0 ) ); $has_api_key = intval( strlen( get_option( 'siteimprove_api_key', 0 ) ) > 0 ); if ( ( is_preview() || is_singular() || is_front_page() ) && 1 === $prepublish_allowed && 1 === $prepublish_enabled && 1 === $has_api_key ) { $prepublish_button = ' '; $admin_bar->add_menu( array( 'id' => 'siteimprove-trigger-contentcheck', 'title' => $prepublish_button . __( 'Prepublish', 'siteimprove' ), 'group' => null, 'href' => '#', 'meta' => array( 'title' => __( 'Siteimprove Prepublish', 'siteimprove' ), 'class' => 'siteimprove-trigger-contentcheck', ), ) ); } } }