*/ namespace RankMath\SEO_Analysis; use Rollbar\Rollbar; use RankMath\Helper; use RankMath\Traits\Ajax; use RankMath\Traits\Hooker; use Rollbar\Payload\Level; use MyThemeShop\Helpers\Str; use MyThemeShop\Helpers\Param; defined( 'ABSPATH' ) || exit; /** * SEO_Analyzer class. */ class SEO_Analyzer { use Ajax, Hooker; /** * Rank Math SEO Checkup API. * * @var string */ private $api_url = ''; /** * Url to analyze. * * @var string */ public $analyse_url = ''; /** * Sub-page url to analyze. * * @var string */ public $analyse_subpage = false; /** * Hold analysis results. * * @var array */ public $results = []; /** * Hold any api error. * * @var array */ private $api_error = ''; /** * Hold local test data. * * @var array */ private $local_tests = []; /** * The Constructor. */ public function __construct() { $this->api_url = $this->do_filter( 'seo_analysis/api_endpoint', 'https://rankmath.com/analyze/v2/json/' ); $this->analyse_url = get_home_url(); if ( ! empty( $_REQUEST['u'] ) && $this->is_allowed_url( Param::request( 'u' ) ) ) { $this->analyse_url = Param::request( 'u' ); $this->analyse_subpage = true; } $this->maybe_clear_storage(); if ( ! $this->analyse_subpage ) { $this->get_results_from_storage(); $this->local_tests = $this->do_filter( 'seo_analysis/tests', [] ); } $this->ajax( 'analyze', 'analyze_me' ); } /** * Output results. */ public function display() { if ( empty( $this->results ) ) { return; } $this->display_graphs(); $this->display_results(); } /** * Output graphs */ private function display_graphs() { $data = $this->get_graph_metrices(); extract( $data ); // phpcs:ignore $max = max( $statuses['ok'], $statuses['warning'], $statuses['fail'] ); ?>
/100
analyse_subpage ) : ?>
0, 'fail' => 0, 'info' => 0, 'warning' => 0, ]; foreach ( $this->results as $id => $result ) { if ( ! is_object( $result ) || 'info' === $result->get_status() || $result->is_excluded() ) { continue; } $statuses[ $result->get_status() ]++; $total++; if ( 'ok' !== $result->get_status() ) { continue; } $percent = $percent + $result->get_score(); } $grade = $this->get_graph_grade( $percent ); return compact( 'total', 'percent', 'statuses', 'grade' ); } /** * Format grade result. * * @param int $percent Total percentage. * * @return string */ private function get_graph_grade( $percent ) { if ( $percent < 70 ) { return 'average'; } if ( $percent < 50 ) { return 'bad'; } return 'good'; } /** * Output results in tables. */ private function display_results() { foreach ( $this->sort_results_by_category() as $category => $results ) : $label = $this->get_category_label( $category ); ?>
results = get_option( 'rank_math_seo_analysis_results' ); $this->build_results(); } /** * Clear stored results if needed. */ private function maybe_clear_storage() { if ( '1' === Param::request( 'clear_results' ) ) { delete_option( 'rank_math_seo_analysis_results' ); wp_safe_redirect( remove_query_arg( 'clear_results' ) ); exit; } } /** * Convert result into object. */ private function build_results() { if ( ! is_array( $this->results ) ) { return; } foreach ( $this->results as $id => $result ) { $this->results[ $id ] = new Result( $id, $result, $this->analyse_subpage ); } } /** * Analyze page. */ public function analyze_me() { check_ajax_referer( 'rank-math-ajax-nonce', 'security' ); $this->has_cap_ajax( 'site_analysis' ); if ( ! $this->run_api_tests() ) { error_log( $this->api_error ); Rollbar::log( Level::WARNING, $this->api_error ); /* translators: API error */ echo '

' . sprintf( __( 'API Error: %s', 'rank-math' ), $this->api_error ) . '

'; } if ( ! $this->analyse_subpage ) { $this->run_local_tests(); $this->run_social_tests(); update_option( 'rank_math_seo_analysis_results', $this->results ); } $this->build_results(); $this->display(); die; } /** * Run test through rank math api. * * @return boolean */ private function run_api_tests() { $response = $this->get_api_results(); if ( false === $response ) { return false; } $this->process_api_results( $response ); return true; } /** * Process results as needed. * * @return boolean */ private function process_api_results( $response ) { foreach ( $response as $id => $results ) { $this->results[ $id ] = wp_parse_args( $results, [ 'test_id' => $id, 'api_test' => true, ] ); } return true; } /** * Get API results. * * @return bool|array */ private function get_api_results() { $api_url = add_query_arg( [ 'u' => $this->analyse_url, 'ak' => $this->get_api_key(), 'locale' => get_locale(), 'is_subpage' => $this->analyse_subpage, ], $this->api_url ); $request = wp_remote_get( $api_url, [ 'timeout' => 20 ] ); if ( is_wp_error( $request ) ) { $this->api_error = strip_tags( $request->get_error_message() ); return false; } $response = wp_remote_retrieve_body( $request ); $response = json_decode( $response, true ); if ( ! is_array( $response ) ) { return false; } if ( 200 !== absint( wp_remote_retrieve_response_code( $request ) ) ) { $this->api_error = join( ', ', $response['errors'] ); return false; } return $response; } /** * Run local site tests. */ private function run_local_tests() { foreach ( $this->local_tests as $id => $test ) { $this->results[ $id ] = array_merge( [ 'test_id' => $id, 'api_test' => false, 'title' => $test['title'], 'description' => $test['description'], 'how_to_fix' => $test['how_to_fix'], 'category' => $test['category'], 'info' => [], ], call_user_func( $test['callback'], $this ) ); } } /** * Run Social SEO Tests */ private function run_social_tests() { $social_seo = [ 'facebook' => [ 'name' => esc_html__( 'Facebook', 'rank-math' ), 'title' => esc_html__( 'Facebook Connected', 'rank-math' ), ], 'instagram' => [ 'name' => esc_html__( 'Instagram', 'rank-math' ), 'title' => esc_html__( 'Instagram Connected', 'rank-math' ), ], 'linkedin' => [ 'name' => esc_html__( 'Linkedin', 'rank-math' ), 'title' => esc_html__( 'Linkedin Connected', 'rank-math' ), ], 'twitter' => [ 'name' => esc_html__( 'Twitter', 'rank-math' ), 'title' => esc_html__( 'Twitter Connected', 'rank-math' ), ], 'youtube' => [ 'name' => esc_html__( 'Youtube', 'rank-math' ), 'title' => esc_html__( 'Youtube Connected', 'rank-math' ), ], ]; /* translators: link to social option setting */ $fix_content = sprintf( __( 'Add Social Schema to your website by linking your social profiles here.', 'rank-math' ), Helper::get_admin_url( 'options-titles#setting-panel-social' ) ); foreach ( $social_seo as $id => $social ) { $found = Helper::get_settings( 'titles.social_url_' . $id ); $id = $id . '_connected'; $this->results[ $id ] = [ 'test_id' => $id, 'api_test' => false, 'title' => $social['title'], 'category' => 'social', 'info' => [], 'status' => $found ? 'ok' : 'fail', /* translators: social name */ 'message' => $found ? sprintf( esc_html__( 'Your website has a %s page connected to it.', 'rank-math' ), $social['name'] ) : sprintf( esc_html__( 'Your website has no %s connected to it.', 'rank-math' ), $social['name'] ), 'fix' => $found ? null : $fix_content, ]; } } /** * Check if it is a valid URL on this site. * * @param string $url Check url if it is allowed. * @return bool */ private function is_allowed_url( $url ) { $home = get_home_url(); if ( strpos( $url, $home ) !== 0 ) { return false; } // wp-admin pages are not allowed. if ( strpos( substr( $url, strlen( $home ) ), '/wp-admin' ) === 0 ) { return false; } return true; } /** * Sort results by category. * * @return array */ private function sort_results_by_category() { $data = []; foreach ( $this->results as $result ) { if ( ! is_object( $result ) ) { continue; } $category = $result->get_category(); if ( ! isset( $data[ $category ] ) ) { $data[ $category ] = []; } $data[ $category ][ $result->get_id() ] = $result; } return $data; } /** * Get category label by slug. * * @param string $category Current category slug. * @return string */ private function get_category_label( $category ) { $category_map = [ 'advanced' => esc_html__( 'Advanced SEO', 'rank-math' ), 'basic' => esc_html__( 'Basic SEO', 'rank-math' ), 'performance' => esc_html__( 'Performance', 'rank-math' ), 'security' => esc_html__( 'Security', 'rank-math' ), 'social' => esc_html__( 'Social SEO', 'rank-math' ), ]; return isset( $category_map[ $category ] ) ? $category_map[ $category ] : ''; } /** * Get api key for rank math api. * * @return string */ private function get_api_key() { return 'xxx-xxxx-xxxxxxxxx'; } }