You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
323 lines
7.0 KiB
PHTML
323 lines
7.0 KiB
PHTML
8 months ago
|
<?php
|
||
|
/**
|
||
|
* Jobs.
|
||
|
*
|
||
|
* @since 1.0.54
|
||
|
* @package RankMath
|
||
|
* @subpackage RankMath\modules
|
||
|
* @author Rank Math <support@rankmath.com>
|
||
|
*/
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
}
|