*/ namespace RankMath\Analytics\Workflow; use Exception; use RankMath\Helper; use RankMath\Google\Api; use RankMath\Google\Console; use RankMath\Google\Url_Inspection; use RankMath\Analytics\DB; use RankMath\Traits\Cache; use RankMath\Traits\Hooker; use RankMath\Analytics\Stats; use RankMath\Analytics\Watcher; defined( 'ABSPATH' ) || exit; /** * Jobs class. */ class Jobs { use Hooker, Cache; /** * Main instance * * Ensure only one instance is loaded or can be loaded. * * @return Jobs */ public static function get() { static $instance; if ( is_null( $instance ) && ! ( $instance instanceof Jobs ) ) { $instance = new Jobs(); $instance->hooks(); } return $instance; } /** * Hooks. */ public function hooks() { $this->action( 'rank_math/analytics/flat_posts', 'do_flat_posts' ); $this->action( 'rank_math/analytics/flat_posts_completed', 'flat_posts_completed' ); add_action( 'rank_math/analytics/sync_sitemaps', [ Api::get(), 'sync_sitemaps' ] ); if ( Console::is_console_connected() ) { $this->action( 'rank_math/analytics/clear_cache', 'clear_cache', 99 ); // Fetch missing google data action. $this->action( 'rank_math/analytics/data_fetch', 'data_fetch' ); // Console data fetch. $this->filter( 'rank_math/analytics/get_console_days', 'get_console_days' ); $this->action( 'rank_math/analytics/get_console_data', 'get_console_data' ); $this->action( 'rank_math/analytics/handle_console_response', 'handle_console_response' ); // Inspections data fetch. $this->action( 'rank_math/analytics/get_inspections_data', 'get_inspections_data' ); } } /** * Fetch missing console data. */ public function data_fetch() { $this->check_for_missing_dates( 'console' ); } /** * Perform post check. */ public function flat_posts_completed() { $rows = DB::objects() ->selectCount( 'id' ) ->getVar(); Workflow::kill_workflows(); } /** * Add/update posts info from objects table. * * @param array $ids Posts ids to process. */ public function do_flat_posts( $ids ) { Inspections::kill_jobs(); foreach ( $ids as $id ) { Watcher::get()->update_post_info( $id ); } } /** * Clear cache. */ public function clear_cache() { global $wpdb; // Delete all useless data from console data table. $wpdb->get_results( "DELETE FROM {$wpdb->prefix}rank_math_analytics_gsc WHERE page NOT IN ( SELECT page from {$wpdb->prefix}rank_math_analytics_objects )" ); // Delete useless data from inspections table too. $wpdb->get_results( "DELETE FROM {$wpdb->prefix}rank_math_analytics_inspections WHERE page NOT IN ( SELECT page from {$wpdb->prefix}rank_math_analytics_objects )" ); delete_transient( 'rank_math_analytics_data_info' ); DB::purge_cache(); DB::delete_data_log(); $this->calculate_stats(); update_option( 'rank_math_analytics_last_updated', time() ); Workflow::do_workflow( 'inspections' ); } /** * Set the console start and end dates. * * @param array $args Args containing start and end date. */ public function get_console_days( $args = [] ) { set_time_limit( 300 ); $rows = Api::get()->get_search_analytics( [ 'start_date' => $args['start_date'], 'end_date' => $args['end_date'], 'dimensions' => [ 'date' ], ] ); if ( empty( $rows ) || is_wp_error( $rows ) ) { return []; } $empty_dates = get_option( 'rank_math_console_empty_dates', [] ); $dates = []; foreach ( $rows as $row ) { // Have at least few impressions. if ( $row['impressions'] ) { $date = $row['keys'][0]; if ( ! DB::date_exists( $date, 'console' ) && ! in_array( $date, $empty_dates, true ) ) { $dates[] = [ 'start_date' => $date, 'end_date' => $date, ]; } } } return $dates; } /** * Get console data. * * @param string $date Date to fetch data for. */ public function get_console_data( $date ) { set_time_limit( 300 ); $rows = Api::get()->get_search_analytics( [ 'start_date' => $date, 'end_date' => $date, 'dimensions' => [ 'query', 'page' ], ] ); if ( empty( $rows ) || is_wp_error( $rows ) ) { return; } $rows = \array_map( [ $this, 'normalize_query_page_data' ], $rows ); try { DB::add_query_page_bulk( $date, $rows ); // Clear the cache here. $this->cache_flush_group( 'rank_math_rest_keywords_rows' ); $this->cache_flush_group( 'rank_math_posts_rows_by_objects' ); $this->cache_flush_group( 'rank_math_analytics_summary' ); return $rows; } catch ( Exception $e ) {} // phpcs:ignore } /** * Handlle console response. * * @param array $data API request and response data. */ public function handle_console_response( $data = [] ) { if ( 200 !== $data['code'] ) { return; } if ( isset( $data['formatted_response']['rows'] ) && ! empty( $data['formatted_response']['rows'] ) ) { return; } if ( ! isset( $data['args']['startDate'] ) ) { return; } $dates = get_option( 'rank_math_console_empty_dates', [] ); if ( ! $dates ) { $dates = []; } $dates[] = $data['args']['startDate']; $dates[] = $data['args']['endDate']; $dates = array_unique( $dates ); update_option( 'rank_math_console_empty_dates', $dates ); } /** * Get inspection results from the API and store them in the database. * * @param string $page URI to fetch data for. */ public function get_inspections_data( $page ) { // If the option is disabled, don't fetch data. if ( ! \RankMath\Analytics\Url_Inspection::is_enabled() ) { return; } $inspection = Url_Inspection::get()->get_inspection_data( $page ); if ( empty( $inspection ) ) { return; } try { DB::store_inspection( $inspection ); } catch ( Exception $e ) {} // phpcs:ignore } /** * Check for missing dates. * * @param string $action Action to perform. */ public function check_for_missing_dates( $action ) { $days = Helper::get_settings( 'general.console_caching_control', 90 ); Workflow::do_workflow( $action, $days, null, null ); } /** * Calculate stats. */ private function calculate_stats() { $ranges = [ '-7 days', '-15 days', '-30 days', '-3 months', '-6 months', '-1 year', ]; foreach ( $ranges as $range ) { Stats::get()->set_date_range( $range ); Stats::get()->get_top_keywords(); } } /** * Normalize console data. * * @param array $row Single row item. * * @return array */ protected function normalize_query_page_data( $row ) { $row = $this->normalize_data( $row ); $row['query'] = $row['keys'][0]; $row['page'] = $row['keys'][1]; unset( $row['keys'] ); return $row; } /** * Normalize console data. * * @param array $row Single row item. * * @return array */ private function normalize_data( $row ) { $row['ctr'] = round( $row['ctr'] * 100, 2 ); $row['position'] = round( $row['position'], 2 ); return $row; } }