Commit realizado el 12:13:52 08-04-2024

This commit is contained in:
Pagina Web Monito
2024-04-08 12:13:55 -04:00
commit 0c33094de9
7815 changed files with 1365694 additions and 0 deletions

View File

@@ -0,0 +1,210 @@
<?php
/**
* Workflow Base.
*
* @since 1.0.54
* @package RankMath
* @subpackage RankMath\modules
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Analytics\Workflow;
use RankMath\Helper;
use function has_filter;
use RankMath\Analytics\DB;
use RankMath\Traits\Hooker;
use function as_schedule_single_action;
defined( 'ABSPATH' ) || exit;
/**
* Base class.
*/
abstract class Base {
use Hooker;
/**
* Start fetching process.
*
* @param integer $days Number of days to fetch from past.
* @param string $action Action to perform.
* @return integer
*/
public function create_jobs( $days = 90, $action = 'console' ) {
$count = $this->add_data_pull( $days + 3, $action );
$time_gap = $this->get_schedule_gap();
Workflow::add_clear_cache( time() + ( $time_gap * ( $count + 1 ) ) );
update_option( 'rank_math_analytics_first_fetch', 'fetching' );
return $count;
}
/**
* Add data pull jobs.
*
* @param integer $days Number of days to fetch from past.
* @param string $action Action to perform.
* @return integer
*/
private function add_data_pull( $days, $action = 'console' ) {
$count = 1;
$start = Helper::get_midnight( time() + DAY_IN_SECONDS );
$interval = $this->get_data_interval();
$time_gap = $this->get_schedule_gap();
$hook = "get_{$action}_data";
if ( 1 === $interval ) {
for ( $current = 1; $current <= $days; $current++ ) {
$date = date_i18n( 'Y-m-d', $start - ( DAY_IN_SECONDS * $current ) );
if ( ! DB::date_exists( $date, $action ) ) {
$count++;
as_schedule_single_action(
time() + ( $time_gap * $count ),
'rank_math/analytics/' . $hook,
[ $date ],
'rank-math'
);
}
}
} else {
for ( $current = 1; $current <= $days; $current = $current + $interval ) {
for ( $j = 0; $j < $interval; $j++ ) {
$date = date_i18n( 'Y-m-d', $start - ( DAY_IN_SECONDS * ( $current + $j ) ) );
if ( ! DB::date_exists( $date, $action ) ) {
$count++;
as_schedule_single_action(
time() + ( $time_gap * $count ),
'rank_math/analytics/' . $hook,
[ $date ],
'rank-math'
);
}
}
}
}
return $count;
}
/**
* Get data interval.
*
* @return int
*/
private function get_data_interval() {
$is_custom = has_filter( 'rank_math/analytics/app_url' );
return $is_custom ? $this->do_filter( 'analytics/data_interval', 7 ) : 7;
}
/**
* Get schedule gap.
*
* @return int
*/
private function get_schedule_gap() {
return $this->do_filter( 'analytics/schedule_gap', 30 );
}
/**
* Check if google profile is updated.
*
* @param string $param Google profile param name.
* @param string $prev Previous profile data.
* @param string $new New posted profile data.
*
* @return boolean
*/
public function is_profile_updated( $param, $prev, $new ) {
if (
! is_null( $prev ) &&
! is_null( $new ) &&
isset( $prev[ $param ] ) &&
isset( $new[ $param ] ) &&
$prev[ $param ] === $new[ $param ]
) {
return false;
}
return true;
}
/**
* Function to get the dates.
*
* @param int $days Number of days.
*
* @return array
*/
public static function get_dates( $days = 90 ) {
$end = Helper::get_midnight( strtotime( '-1 day', time() ) );
$start = strtotime( '-' . $days . ' day', $end );
return [
'start_date' => date_i18n( 'Y-m-d', $start ),
'end_date' => date_i18n( 'Y-m-d', $end ),
];
}
/**
* Schedule single action
*
* @param int $days Number of days.
* @param string $action Name of the action hook.
* @param array $args Arguments to pass to callbacks when the hook triggers.
* @param string $group The group to assign this job to.
* @param boolean $unique Whether the action should be unique.
*/
public function schedule_single_action( $days = 90, $action = '', $args = [], $group = 'rank-math', $unique = false ) {
$timestamp = get_option( 'rank_math_analytics_last_single_action_schedule_time', time() );
$time_gap = $this->get_schedule_gap();
$dates = self::get_dates( $days );
// Get the analytics dates in which analytics data is actually available.
$days = apply_filters(
'rank_math/analytics/get_' . $action . '_days',
[
'start_date' => $dates['start_date'],
'end_date' => $dates['end_date'],
]
);
// No days then don't schedule the action.
if ( empty( $days ) ) {
return;
}
foreach ( $days as $day ) {
// Next schedule time.
$timestamp = $timestamp + $time_gap;
$args = wp_parse_args(
[
'start_date' => $day['start_date'],
'end_date' => $day['end_date'],
],
$args
);
as_schedule_single_action(
$timestamp,
'rank_math/analytics/get_' . $action . '_data',
$args,
$group,
$unique
);
}
Workflow::add_clear_cache( $timestamp );
// Update timestamp.
update_option( 'rank_math_analytics_last_single_action_schedule_time', $timestamp );
}
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* Google Search Console.
*
* @since 1.0.49
* @package RankMath
* @subpackage RankMath\Analytics
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Analytics\Workflow;
use Exception;
use RankMath\Helpers\DB;
use RankMath\Google\Console as GoogleConsole;
use function as_unschedule_all_actions;
defined( 'ABSPATH' ) || exit;
/**
* Console class.
*/
class Console extends Base {
/**
* Constructor.
*/
public function __construct() {
$this->create_tables();
// If console is not connected, ignore all no need to proceed.
if ( ! GoogleConsole::is_console_connected() ) {
return;
}
$this->action( 'rank_math/analytics/workflow/console', 'kill_jobs', 5, 0 );
$this->action( 'rank_math/analytics/workflow/create_tables', 'create_tables' );
$this->action( 'rank_math/analytics/workflow/console', 'create_tables', 6, 0 );
$this->action( 'rank_math/analytics/workflow/console', 'create_data_jobs', 10, 3 );
}
/**
* Unschedule all console data fetch action.
*
* Stop processing queue items, clear cronjob and delete all batches.
*/
public function kill_jobs() {
as_unschedule_all_actions( 'rank_math/analytics/get_console_data' );
}
/**
* Create tables.
*/
public function create_tables() {
global $wpdb;
$collate = $wpdb->get_charset_collate();
$table = 'rank_math_analytics_gsc';
// Early Bail!!
if ( DB::check_table_exists( $table ) ) {
return;
}
$schema = "CREATE TABLE {$wpdb->prefix}{$table} (
id bigint(20) unsigned NOT NULL auto_increment,
created timestamp NOT NULL,
query varchar(1000) NOT NULL,
page varchar(500) NOT NULL,
clicks mediumint(6) NOT NULL,
impressions mediumint(6) NOT NULL,
position double NOT NULL,
ctr double NOT NULL,
PRIMARY KEY (id),
KEY analytics_query (query(190)),
KEY analytics_page (page(190)),
KEY clicks (clicks),
KEY rank_position (position)
) $collate;";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
try {
dbDelta( $schema );
} catch ( Exception $e ) { // phpcs:ignore
// Will log.
}
// Make sure that collations match the objects table.
$objects_coll = DB::get_table_collation( 'rank_math_analytics_objects' );
DB::check_collation( $table, 'all', $objects_coll );
}
/**
* Create jobs to fetch data.
*
* @param integer $days Number of days to fetch from past.
* @param string $prev Previous saved value.
* @param string $new New posted value.
*/
public function create_data_jobs( $days, $prev, $new ) {
// Early bail if saved & new profile are same.
if ( ! $this->is_profile_updated( 'profile', $prev, $new ) ) {
return;
}
update_option( 'rank_math_analytics_first_fetch', 'fetching' );
// Fetch now.
$this->schedule_single_action( $days, 'console' );
}
}

View File

@@ -0,0 +1,162 @@
<?php
/**
* Google Search Console.
*
* @since 1.0.49
* @package RankMath
* @subpackage RankMath\Analytics
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Analytics\Workflow;
use Exception;
use RankMath\Helpers\DB;
use RankMath\Traits\Hooker;
use RankMath\Analytics\DB as AnalyticsDB;
use RankMath\Analytics\Url_Inspection;
use RankMath\Google\Console;
use function as_unschedule_all_actions;
defined( 'ABSPATH' ) || exit;
/**
* Inspections class.
*/
class Inspections {
use Hooker;
/**
* API Limit.
* 600 requests per minute, 2000 per day.
* We can ignore the per-minute limit, since we will use a few seconds delay after each request.
*/
const API_LIMIT = 2000;
/**
* Interval between requests.
*/
const REQUEST_GAP_SECONDS = 7;
/**
* Constructor.
*/
public function __construct() {
$this->create_tables();
// If console is not connected, ignore all, no need to proceed.
if ( ! Console::is_console_connected() ) {
return;
}
$this->action( 'rank_math/analytics/workflow/create_tables', 'create_tables' );
$this->action( 'rank_math/analytics/workflow/inspections', 'create_tables', 6, 0 );
$this->action( 'rank_math/analytics/workflow/inspections', 'create_data_jobs', 10, 0 );
}
/**
* Unschedule all inspections data fetch action.
*
* Stop processing queue items, clear cronjob and delete all batches.
*/
public static function kill_jobs() {
as_unschedule_all_actions( 'rank_math/analytics/get_inspections_data' );
}
/**
* Create tables.
*/
public function create_tables() {
global $wpdb;
$collate = $wpdb->get_charset_collate();
$table = 'rank_math_analytics_inspections';
// Early Bail!!
if ( DB::check_table_exists( $table ) ) {
return;
}
$schema = "CREATE TABLE {$wpdb->prefix}{$table} (
id bigint(20) unsigned NOT NULL auto_increment,
page varchar(500) NOT NULL,
created timestamp NOT NULL,
index_verdict varchar(64) NOT NULL, /* PASS, PARTIAL, FAIL, NEUTRAL, VERDICT_UNSPECIFIED */
indexing_state varchar(64) NOT NULL, /* INDEXING_ALLOWED, BLOCKED_BY_META_TAG, BLOCKED_BY_HTTP_HEADER, BLOCKED_BY_ROBOTS_TXT, INDEXING_STATE_UNSPECIFIED */
coverage_state text NOT NULL, /* String, e.g. 'Submitted and indexed'. */
page_fetch_state varchar(64) NOT NULL, /* SUCCESSFUL, SOFT_404, BLOCKED_ROBOTS_TXT, NOT_FOUND, ACCESS_DENIED, SERVER_ERROR, REDIRECT_ERROR, ACCESS_FORBIDDEN, BLOCKED_4XX, INTERNAL_CRAWL_ERROR, INVALID_URL, PAGE_FETCH_STATE_UNSPECIFIED */
robots_txt_state varchar(64) NOT NULL, /* ALLOWED, DISALLOWED, ROBOTS_TXT_STATE_UNSPECIFIED */
mobile_usability_verdict varchar(64) NOT NULL, /* PASS, PARTIAL, FAIL, NEUTRAL, VERDICT_UNSPECIFIED */
mobile_usability_issues longtext NOT NULL, /* JSON */
rich_results_verdict varchar(64) NOT NULL, /* PASS, PARTIAL, FAIL, NEUTRAL, VERDICT_UNSPECIFIED */
rich_results_items longtext NOT NULL, /* JSON */
last_crawl_time timestamp NOT NULL,
crawled_as varchar(64) NOT NULL, /* DESKTOP, MOBILE, CRAWLING_USER_AGENT_UNSPECIFIED */
google_canonical text NOT NULL, /* Google-chosen canonical URL. */
user_canonical text NOT NULL, /* Canonical URL declared on-page. */
sitemap text NOT NULL, /* Sitemap URL. */
referring_urls longtext NOT NULL, /* JSON */
raw_api_response longtext NOT NULL, /* JSON */
PRIMARY KEY (id),
KEY analytics_object_page (page(190)),
KEY created (created),
KEY index_verdict (index_verdict),
KEY page_fetch_state (page_fetch_state),
KEY robots_txt_state (robots_txt_state),
KEY mobile_usability_verdict (mobile_usability_verdict),
KEY rich_results_verdict (rich_results_verdict)
) $collate;";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
try {
dbDelta( $schema );
} catch ( Exception $e ) { // phpcs:ignore
// Will log.
}
// Make sure that collations match the objects table.
$objects_coll = DB::get_table_collation( 'rank_math_analytics_objects' );
DB::check_collation( $table, 'all', $objects_coll );
}
/**
* Create jobs to fetch data.
*/
public function create_data_jobs() {
// If there are jobs left from the previous queue, don't create new jobs.
if ( as_has_scheduled_action( 'rank_math/analytics/get_inspections_data' ) ) {
return;
}
// If the option is disabled, don't create jobs.
if ( ! Url_Inspection::is_enabled() ) {
return;
}
$inspections_table = AnalyticsDB::inspections()->table;
$objects_table = AnalyticsDB::objects()->table;
$objects = AnalyticsDB::objects()
->select( [ "$objects_table.id", "$objects_table.page", "$inspections_table.created" ] )
->leftJoin( $inspections_table, "$inspections_table.page", "$objects_table.page" )
->where( "$objects_table.is_indexable", 1 )
->orderBy( "$inspections_table.created", 'ASC' )
->get();
$count = 0;
foreach ( $objects as $object ) {
$count++;
$time = time() + ( $count * self::REQUEST_GAP_SECONDS );
if ( $count > self::API_LIMIT ) {
$delay_days = floor( $count / self::API_LIMIT );
$time = strtotime( "+{$delay_days} days", $time );
}
as_schedule_single_action( $time, 'rank_math/analytics/get_inspections_data', [ $object->page ], 'rank-math' );
}
}
}

View File

@@ -0,0 +1,322 @@
<?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;
}
}

View File

@@ -0,0 +1,176 @@
<?php
/**
* Authentication workflow.
*
* @since 1.0.55
* @package RankMath
* @subpackage RankMath\Analytics
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Analytics\Workflow;
use RankMath\Helper;
use RankMath\Google\Api;
use RankMath\Traits\Hooker;
use RankMath\Helpers\Str;
use RankMath\Helpers\Param;
use RankMath\Helpers\Security;
use RankMath\Analytics\DB;
use RankMath\Google\Permissions;
use RankMath\Google\Authentication;
defined( 'ABSPATH' ) || exit;
/**
* OAuth class.
*/
class OAuth {
use Hooker;
/**
* Constructor.
*/
public function __construct() {
$this->action( 'admin_init', 'process_oauth' );
$this->action( 'admin_init', 'reconnect_google' );
}
/**
* OAuth reply back
*/
public function process_oauth() {
$process_oauth = Param::get( 'process_oauth', 0, FILTER_VALIDATE_INT );
$access_token = Param::get( 'access_token', '', FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_BACKTICK );
$security = Param::get( 'rankmath_security', '', FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_BACKTICK );
// Early Bail!!
if ( empty( $security ) || ( $process_oauth < 1 && empty( $access_token ) ) ) {
return;
}
if ( ! wp_verify_nonce( $security, 'rank_math_oauth_token' ) ) {
wp_nonce_ays( 'rank_math_oauth_token' );
die();
}
$redirect = false;
// Backward compatibility.
if ( ! empty( $process_oauth ) ) {
$redirect = $this->get_tokens_from_server();
}
// New version.
if ( ! empty( $access_token ) ) {
$redirect = $this->get_tokens_from_url();
}
// Remove possible admin notice if we have new access token.
delete_option( 'rankmath_google_api_failed_attempts_data' );
delete_option( 'rankmath_google_api_reconnect' );
Permissions::fetch();
if ( ! empty( $redirect ) ) {
Helper::redirect( $redirect );
exit;
}
}
/**
* Reconnect Google.
*/
public function reconnect_google() {
if ( ! isset( $_GET['reconnect'] ) || 'google' !== $_GET['reconnect'] ) {
return;
}
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rank_math_reconnect_google' ) ) {
wp_nonce_ays( 'rank_math_reconnect_google' );
die();
}
if ( ! Helper::has_cap( 'analytics' ) ) {
return;
}
$rows = DB::objects()
->selectCount( 'id' )
->getVar();
if ( empty( $rows ) ) {
delete_option( 'rank_math_analytics_installed' );
}
Api::get()->revoke_token();
Workflow::kill_workflows();
wp_redirect( Authentication::get_auth_url() ); // phpcs:ignore
die();
}
/**
* Get access token from url.
*
* @return string
*/
private function get_tokens_from_url() {
$data = [
'access_token' => urldecode( Param::get( 'access_token', '', FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_BACKTICK ) ),
'refresh_token' => urldecode( Param::get( 'refresh_token', '', FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_BACKTICK ) ),
'expire' => urldecode( Param::get( 'expire', 0, FILTER_VALIDATE_INT ) ),
];
Authentication::tokens( $data );
$current_request = remove_query_arg(
[
'access_token',
'refresh_token',
'expire',
'security',
]
);
return $current_request;
}
/**
* Get access token from rankmath server.
*
* @return string
*/
private function get_tokens_from_server() {
// Bail if the user is not authenticated at all yet.
$id = Param::get( 'process_oauth', 0, FILTER_VALIDATE_INT );
if ( $id < 1 ) {
return;
}
$response = wp_remote_get( Authentication::get_auth_app_url() . '/get.php?id=' . $id );
if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
return;
}
$response = wp_remote_retrieve_body( $response );
if ( empty( $response ) ) {
return;
}
$response = \json_decode( $response, true );
unset( $response['id'] );
// Save new token.
Authentication::tokens( $response );
$redirect = Security::remove_query_arg_raw( [ 'process_oauth', 'security' ] );
if ( Str::contains( 'rank-math-options-general', $redirect ) ) {
$redirect .= '#setting-panel-analytics';
}
Helper::remove_notification( 'rank_math_analytics_reauthenticate' );
return $redirect;
}
}

View File

@@ -0,0 +1,152 @@
<?php
/**
* Install objects.
*
* @since 1.0.49
* @package RankMath
* @subpackage RankMath\modules
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Analytics\Workflow;
use Exception;
use RankMath\Helper;
use RankMath\Helpers\DB;
use RankMath\Traits\Hooker;
defined( 'ABSPATH' ) || exit;
/**
* Objects class.
*/
class Objects extends Base {
use Hooker;
/**
* Constructor.
*/
public function __construct() {
$done = \boolval( get_option( 'rank_math_analytics_installed' ) );
if ( $done ) {
return;
}
$this->create_tables();
$this->create_data_job();
$this->flat_posts();
update_option( 'rank_math_analytics_installed', true );
}
/**
* Create tables.
*/
public function create_tables() {
global $wpdb;
$collate = $wpdb->get_charset_collate();
$table = 'rank_math_analytics_objects';
// Early Bail!!
if ( DB::check_table_exists( $table ) ) {
return;
}
$schema = "CREATE TABLE {$wpdb->prefix}{$table} (
id bigint(20) unsigned NOT NULL auto_increment,
created timestamp NOT NULL,
title text NOT NULL,
page varchar(500) NOT NULL,
object_type varchar(100) NOT NULL,
object_subtype varchar(100) NOT NULL,
object_id bigint(20) unsigned NOT NULL,
primary_key varchar(255) NOT NULL,
seo_score tinyint NOT NULL default 0,
page_score tinyint NOT NULL default 0,
is_indexable tinyint(1) NOT NULL default 1,
schemas_in_use varchar(500),
desktop_interactive double default 0,
desktop_pagescore double default 0,
mobile_interactive double default 0,
mobile_pagescore double default 0,
pagespeed_refreshed timestamp,
PRIMARY KEY (id),
KEY analytics_object_page (page(190))
) $collate;";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
try {
dbDelta( $schema );
} catch ( Exception $e ) { // phpcs:ignore
// Will log.
}
}
/**
* Create jobs to fetch data.
*/
public function create_data_job() {
// Clear old schedule.
wp_clear_scheduled_hook( 'rank_math/analytics/get_analytics' );
// Add action for scheduler.
$task_name = 'rank_math/analytics/data_fetch';
$fetch_gap = apply_filters( 'rank_math/analytics/fetch_gap', 7, 'objects' );
// Schedule new action only when there is no existing action.
if ( false === as_next_scheduled_action( $task_name ) ) {
$schedule_in_minute = wp_rand( 3, defined( 'RANK_MATH_PRO_FILE' ) ? 1380 : 4320 );
$time_to_schedule = ( strtotime( 'tomorrow' ) + ( $schedule_in_minute * MINUTE_IN_SECONDS ) );
as_schedule_recurring_action(
$time_to_schedule,
DAY_IN_SECONDS * $fetch_gap,
$task_name,
[],
'rank-math'
);
}
}
/**
* Flat posts
*/
public function flat_posts() {
$post_types = $this->do_filter( 'analytics/post_types', Helper::get_accessible_post_types() );
unset( $post_types['attachment'] );
$ids = get_posts(
[
'post_type' => array_keys( $post_types ),
'post_status' => 'publish',
'fields' => 'ids',
'posts_per_page' => -1,
]
);
$counter = 0;
$chunks = \array_chunk( $ids, 50 );
foreach ( $chunks as $chunk ) {
$counter++;
as_schedule_single_action(
time() + ( 60 * ( $counter / 2 ) ),
'rank_math/analytics/flat_posts',
[ $chunk ],
'rank-math'
);
}
// Check for posts.
as_schedule_single_action(
time() + ( 60 * ( ( $counter + 1 ) / 2 ) ),
'rank_math/analytics/flat_posts_completed',
[],
'rank-math'
);
// Clear cache.
Workflow::add_clear_cache( time() + ( 60 * ( ( $counter + 2 ) / 2 ) ) );
}
}

View File

@@ -0,0 +1,161 @@
<?php
/**
* Workflow.
*
* @since 1.0.54
* @package RankMath
* @subpackage RankMath\modules
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Analytics\Workflow;
use RankMath\Traits\Hooker;
use function as_enqueue_async_action;
use function as_unschedule_all_actions;
defined( 'ABSPATH' ) || exit;
/**
* Workflow class.
*/
class Workflow {
use Hooker;
/**
* Main instance
*
* Ensure only one instance is loaded or can be loaded.
*
* @return Workflow
*/
public static function get() {
static $instance;
if ( is_null( $instance ) && ! ( $instance instanceof Workflow ) ) {
$instance = new Workflow();
$instance->hooks();
}
return $instance;
}
/**
* Hooks.
*/
public function hooks() {
// Common.
$this->action( 'rank_math/analytics/workflow', 'maybe_first_install', 5, 0 );
$this->action( 'rank_math/analytics/workflow', 'start_workflow', 10, 4 );
$this->action( 'rank_math/analytics/workflow/create_tables', 'create_tables_only', 5 );
// Console.
$this->action( 'rank_math/analytics/workflow/console', 'init_console_workflow', 5, 0 );
// Inspections.
$this->action( 'rank_math/analytics/workflow/inspections', 'init_inspections_workflow', 5, 0 );
}
/**
* Maybe first install.
*/
public function maybe_first_install() {
new Objects();
}
/**
* Init Console workflow
*/
public function init_console_workflow() {
new Console();
}
/**
* Init Inspections workflow.
*/
public function init_inspections_workflow() {
new Inspections();
}
/**
* Create tables only.
*/
public function create_tables_only() {
( new Objects() )->create_tables();
( new Inspections() )->create_tables();
new Console();
}
/**
* Service workflow
*
* @param string $action Action to perform.
* @param integer $days Number of days to fetch from past.
* @param string $prev Previous saved value.
* @param string $new New posted value.
*/
public function start_workflow( $action, $days = 0, $prev = null, $new = null ) {
do_action(
'rank_math/analytics/workflow/' . $action,
$days,
$prev,
$new
);
}
/**
* Service workflow
*
* @param string $action Action to perform.
* @param integer $days Number of days to fetch from past.
* @param string $prev Previous saved value.
* @param string $new New posted value.
*/
public static function do_workflow( $action, $days = 0, $prev = null, $new = null ) {
as_enqueue_async_action(
'rank_math/analytics/workflow',
[
$action,
$days,
$prev,
$new,
],
'rank-math'
);
}
/**
* Kill all workflows
*
* Stop processing queue items, clear cronjob and delete all batches.
*/
public static function kill_workflows() {
as_unschedule_all_actions( 'rank_math/analytics/workflow' );
as_unschedule_all_actions( 'rank_math/analytics/clear_cache' );
as_unschedule_all_actions( 'rank_math/analytics/get_console_data' );
as_unschedule_all_actions( 'rank_math/analytics/get_analytics_data' );
as_unschedule_all_actions( 'rank_math/analytics/get_adsense_data' );
as_unschedule_all_actions( 'rank_math/analytics/get_inspections_data' );
do_action( 'rank_math/analytics/clear_cache' );
}
/**
* Add clear cache job.
*
* @param int $time Timestamp to add job for.
*/
public static function add_clear_cache( $time ) {
as_unschedule_all_actions( 'rank_math/analytics/clear_cache' );
as_schedule_single_action(
$time,
'rank_math/analytics/clear_cache',
[],
'rank-math'
);
delete_option( 'rank_math_analytics_last_single_action_schedule_time' );
}
}