Files
2026-04-28 15:13:50 +02:00

137 lines
4.2 KiB
PHP

<?php
namespace AIOSEO\Plugin\Pro\SearchStatistics;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\SearchStatistics as CommonSearchStatistics;
use AIOSEO\Plugin\Pro\Models\SearchStatistics as SearchStatisticsModels;
/**
* Handles the Inspection Result scan.
*
* @since 4.5.0
*/
class UrlInspection {
/**
* Fetches the inspection results for the given paths.
*
* @since 4.8.2
*
* @param array $paths The paths to fetch the inspection results for.
* @param boolean $force Whether to force fetching from Google API.
* @return array An array containing the inspection results for the given paths.
*/
public function fetchInspectionResults( $paths = [], $force = false ) {
$pathsWithResult = array_map( '__return_null', array_flip( $paths ) );
$quotaExceededCacheKey = 'search_statistics_url_inspection_quota_exceeded';
$quotaExceeded = ! empty( aioseo()->core->cache->get( $quotaExceededCacheKey ) );
$output = [
'quotaExceeded' => $quotaExceeded,
'pathsWithResult' => $pathsWithResult,
'pathsWithoutResult' => [],
'error' => null
];
$batchSize = (int) apply_filters( 'aioseo_search_statistics_url_inspection_batch_size', 50 );
$objects = aioseo()->core->db->start( 'aioseo_search_statistics_objects' )
->whereIn( 'object_path_hash', array_map( 'sha1', array_map( 'sanitize_text_field', array_unique( $paths ) ) ) )
->orderBy( 'inspection_result_date ASC' )
->limit( $batchSize )
->run()
->models( 'AIOSEO\\Plugin\\Pro\\Models\\SearchStatistics\\WpObject' );
$objects = aioseo()->searchStatistics->helpers->setRowKey( $objects, 'object_path' );
// First, collect all paths that need inspection.
foreach ( $objects as $object ) {
if ( ! SearchStatisticsModels\WpObject::isInspectionResultValid( $object ) || true === $force ) {
$output['pathsWithoutResult'][] = $object->object_path;
} else {
$output['pathsWithResult'][ $object->object_path ] = $object->inspection_result;
}
}
// If there are no paths that need inspection, or we don't have enough quota, return early.
if ( empty( $output['pathsWithoutResult'] ) || $output['quotaExceeded'] ) {
return $output;
}
$api = new CommonSearchStatistics\Api\Request( 'google-search-console/url-inspection/', [ 'paths' => $output['pathsWithoutResult'] ], 'GET' );
$response = $api->request();
if (
is_wp_error( $response ) ||
empty( $response['data'] ) ||
! empty( $response['error'] )
) {
$output['error'] = $response;
return $output;
}
if ( ! empty( $response['quotaExceeded'] ) ) {
$output['quotaExceeded'] = true;
aioseo()->core->cache->update( $quotaExceededCacheKey, true, aioseo()->searchStatistics->helpers->getNext8Am() - time() );
}
foreach ( $response['data'] as $path => $result ) {
if (
empty( $result ) ||
! in_array( $path, $output['pathsWithoutResult'], true )
) {
continue;
}
$output['pathsWithResult'][ $path ] = $result;
SearchStatisticsModels\WpObject::update( [
'id' => $objects[ $path ]->id ?? null,
'inspection_result' => $result,
'inspection_result_date' => current_time( 'mysql' ),
] );
}
return $output;
}
/**
* Gets the inspection result for the given path.
* Returning null will force it to be fetched again on the front-end.
*
* @since 4.5.5
*
* @param string $path The path to get the inspection result for.
* @return object|null The inspection result object or null if the object needs to be fetched again.
*/
public function get( $path ) {
$wpObject = SearchStatisticsModels\WpObject::getObject( $path );
// Returning null for the scenarios below will force the object to be fetched again.
if ( ! SearchStatisticsModels\WpObject::isInspectionResultValid( $wpObject ) ) {
return null;
}
return $wpObject->inspection_result;
}
/**
* Resets all the inspection_results and force scanning again.
*
* @since 4.5.0
*
* @return void
*/
public function reset() {
aioseo()->core->db->update( 'aioseo_search_statistics_objects as asso' )
->set(
[
'inspection_result' => null,
'inspection_result_date' => null
]
)
->run();
}
}