| Current Path : /home/krobertfnz/www/wp-content/plugins/wp-hummingbird/core/modules/ |
| Current File : /home/krobertfnz/www/wp-content/plugins/wp-hummingbird/core/modules/class-performance.php |
<?php
/**
* Performance module.
*
* @package Hummingbird
*/
namespace Hummingbird\Core\Modules;
use Hummingbird\Core\Module;
use Hummingbird\Core\Settings;
use Hummingbird\Core\Traits\Module as ModuleContract;
use Hummingbird\Core\Utils;
use WP_Error;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class Performance
*/
class Performance extends Module {
use ModuleContract;
/**
* Initializes the module. Always executed even if the module is deactivated.
*
* Do not use __construct in subclasses, use init() instead
*/
public function init() {
add_action( 'wphb_init_performance_scan', array( $this, 'on_init_performance_scan' ) );
}
/**
* Implement abstract parent method for clearing cache.
*
* @since 1.7.1
*/
public function clear_cache() {
Settings::delete( 'wphb-last-report' );
Settings::delete( 'wphb-stop-report' );
delete_transient( 'wphb-doing-report' );
}
/**
* Initializes the Performance Scan
*
* @since 1.7.1 Removed static property.
*/
public function init_scan() {
// Clear the cache.
$this->clear_cache();
// Start the test.
self::set_doing_report();
Utils::get_api()->performance->ping();
// Clear dismissed report.
if ( self::report_dismissed() ) {
self::dismiss_report( false );
}
do_action( 'wphb_init_performance_scan' );
}
/**
* Do a cron scan.
*
* @return array|mixed|object|WP_Error
*/
public static function cron_scan() {
// Start the test.
self::set_doing_report();
$api = Utils::get_api();
$report = $api->performance->check();
// Stop the test.
self::set_doing_report( false );
// Return the results.
return $report;
}
/**
* Return the last Performance scan done data
*
* @return bool|mixed|WP_Error Data of the last scan or false of there's not such data
*/
public static function get_last_report() {
$report = Settings::get( 'wphb-last-report' );
return $report ? $report : false;
}
/**
* Check if WP Hummingbird is currently doing a Performance Scan
*
* @return false|int Timestamp when the report started, false if there's no report being executed
*/
public static function is_doing_report() {
return (bool) Settings::get( 'wphb-stop-report' ) ? false : get_transient( 'wphb-doing-report' );
}
/**
* Start a new Performance Scan
*
* It sets the new status for the report
*
* @param bool $status If set to true, it will start a new Performance Report, otherwise it will stop the current one.
*/
public static function set_doing_report( $status = true ) {
if ( ! $status ) {
delete_transient( 'wphb-doing-report' );
Settings::update( 'wphb-stop-report', true, false );
return;
}
// Set time when we started the report.
set_transient( 'wphb-doing-report', time(), 300 ); // save for 5 minutes.
Settings::delete( 'wphb-stop-report' );
}
/**
* Get the latest report from server
*
* @return void
*/
public static function refresh_report() {
self::set_doing_report( false );
self::dismiss_report( false );
$results = Utils::get_api()->performance->results();
$skip_db = false;
if ( is_wp_error( $results ) ) {
$error_message = $results->get_error_message();
if ( 200 === $results->get_error_code() && 'Performance Results not found' === $error_message ) {
$skip_db = true;
$message = __( 'Whoops, looks like we were unable to grab your test results this time round. Please wait a few moments and try again...', 'wphb' );
} else {
$message = __( "The performance test didn't return any results. This could be because you're on a local website (which we can't access) or something went wrong trying to connect with the testing API. Give it another go and if the problem persists, please open a ticket with our support team.", 'wphb' );
}
// It's an actual error.
$results = new WP_Error( 'performance-error', $message, array( 'details' => $error_message ) );
}
/**
* Fires after getting the latest report.
*
* @since 1.9.2
*
* @see https://developers.google.com/speed/docs/insights/v4/reference/pagespeedapi/runpagespeed
*
* @param object $report Object with report data.
*/
if ( isset( $results->data ) && ! is_wp_error( $results->data ) ) {
do_action( 'wphb_get_performance_report', $results->data );
}
if ( $skip_db ) {
return;
}
// Only save reports from Performance module.
Settings::update( 'wphb-last-report', $results, false );
}
/**
* Check if time enough has passed to make another test ( 5 minutes )
*
* @param bool|wp_error|array|object $last_report Last report.
*
* @return bool|integer True if a new test is available or the time in minutes remaining for next test
*/
public static function can_run_test( $last_report = false ) {
if ( ! $last_report || is_wp_error( $last_report ) ) {
$last_report = self::get_last_report();
}
$current_gmt_time = time();
if ( $last_report && ! is_wp_error( $last_report ) ) {
$data_time = $last_report->data->time;
if ( ( $data_time + 300 ) < $current_gmt_time ) {
return true;
} else {
$remaining = ceil( ( ( $data_time + 300 ) - $current_gmt_time ) / 60 );
return absint( $remaining );
}
}
return true;
}
/**
* Set last report dismissed status to true
*
* @since 1.8
*
* @param bool $dismiss Enable or disable dismissed report status.
*
* @return bool
*/
public static function dismiss_report( $dismiss ) {
Settings::update_setting( 'dismissed', (bool) $dismiss, 'performance' );
if ( (bool) $dismiss ) {
// Ignore report in the Hub.
$api = Utils::get_api();
$results = $api->performance->ignore();
if ( is_wp_error( $results ) ) {
return $results->get_error_message();
}
}
return true;
}
/**
* Return whether the last report was dismissed
*
* @since 1.8
*
* @param bool|wp_error|array|object $last_report Last report.
* @return bool True if user dismissed report or false of there's no site option
*/
public static function report_dismissed( $last_report = false ) {
if ( Settings::get_setting( 'dismissed', 'performance' ) ) {
return true;
}
if ( ! $last_report || is_wp_error( $last_report ) ) {
$last_report = self::get_last_report();
}
if ( isset( $last_report->data->ignored ) && $last_report->data->ignored ) {
return true;
}
return false;
}
/**
* Get the class for a specific type. Used to select proper icons and styles.
*
* @since 2.0.0
*
* @param int $score Score value.
* @param string $type Type of item. Accepts: score, icon.
*
* @return string
*/
public static function get_impact_class( $score = 0, $type = 'score' ) {
if ( ! in_array( $type, array( 'score', 'icon' ), true ) ) {
return '';
}
// Make this method universal - either use 1 as a 100%, or 100 as 100%.
if ( 0 < $score && 1 >= $score && is_float( $score ) ) {
$score = $score * 100;
}
$impact_score_class = 'error';
$impact_icon_class = 'warning-alert';
if ( 90 <= (int) $score ) {
$impact_score_class = 'success';
$impact_icon_class = 'check-tick';
} elseif ( 50 <= (int) $score ) {
$impact_score_class = 'warning';
$impact_icon_class = 'warning-alert';
}
return 'score' === $type ? $impact_score_class : $impact_icon_class;
}
/**
* Get the lowest score from a list of audits and return the appropriate class.
*
* @since 2.0.0
*
* @param array $audits Array with audits.
*
* @return string
*/
public static function get_audits_class( $audits ) {
if ( is_null( $audits ) ) {
return 'warning';
}
$lowest_score = 1;
foreach ( $audits as $audit ) {
if ( ! isset( $audit->score ) ) {
continue;
}
if ( $lowest_score > $audit->score ) {
$lowest_score = $audit->score;
}
}
return self::get_impact_class( $lowest_score );
}
/**
* Triggered when a performance scan is initialized
*/
public function on_init_performance_scan() {
if ( Utils::is_member() ) {
return;
}
$options = $this->get_options();
$options['reports'] = false;
$this->update_options( $options );
}
/**
* Return audits mapped to metrics that they affect.
*
* @since 3.1.0
*
* @return array
*/
public static function get_maps() {
return array(
'fcp' => array(
'server-response-time',
'render-blocking-resources',
'redirects',
'critical-request-chains',
'uses-text-compression',
'uses-rel-preconnect',
'uses-rel-preload',
'font-display',
'unminified-javascript',
'unminified-css',
'unused-css-rules',
),
'lcp' => array(
'server-response-time',
'render-blocking-resources',
'redirects',
'critical-request-chains',
'uses-text-compression',
'uses-rel-preconnect',
'uses-rel-preload',
'font-display',
'unminified-javascript',
'unminified-css',
'unused-css-rules',
'largest-contentful-paint-element',
'preload-lcp-image',
'unused-javascript',
'efficient-animated-content',
'total-byte-weight',
),
'tbt' => array(
'long-tasks',
'third-party-summary',
'third-party-facades',
'bootup-time',
'mainthread-work-breakdown',
'dom-size',
'duplicated-javascript',
'legacy-javascript',
),
'cls' => array(
'layout-shift-elements',
'non-composited-animations',
'unsized-images',
),
);
}
/**
* Return relevant metric IDs based on audit ID.
*
* @since 3.1.0
*
* @param string $audit Audit ID.
*
* @return string Metric IDs, separated with a space.
*/
public static function get_relevant_metrics( $audit ) {
$metrics = array();
foreach ( self::get_maps() as $metric => $audits ) {
if ( ! in_array( $audit, $audits, true ) ) {
continue;
}
$metrics[] = $metric;
}
return implode( ' ', $metrics );
}
}