File manager - Edit - /home/vblioqus/unfreezetiktok.com/wp-content/plugins/hummingbird-performance/core/modules/class-performance.php
Back
<?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' ); self::move_audits_without_score( $report ); return $report ? $report : false; } /** * Get last report scores. * * @since 3.18.0 * @return array|false */ public static function get_last_report_scores() { $report = self::get_last_report(); if ( ! $report || is_wp_error( $report ) ) { return false; } return array( 'mobile' => isset( $report->data->mobile->score ) ? $report->data->mobile->score : 0, 'desktop' => isset( $report->data->desktop->score ) ? $report->data->desktop->score : 0, ); } /** * 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 ); } /** * Get audits for MP. * * @since 3.9.0 * * @return array */ public static function get_audits_for_mp() { $audits = array( 'opportunities' => array( 'mobile' => self::get_audits_from_performance_test( 'mobile', 'opportunities' ), 'desktop' => self::get_audits_from_performance_test( 'desktop', 'opportunities' ), ), 'diagnostics' => array( 'mobile' => self::get_audits_from_performance_test( 'mobile', 'diagnostics' ), 'desktop' => self::get_audits_from_performance_test( 'desktop', 'diagnostics' ), ), 'passed' => array( 'mobile' => self::get_audits_from_performance_test( 'mobile', 'passed' ), 'desktop' => self::get_audits_from_performance_test( 'desktop', 'passed' ), ), ); return $audits; } /** * Get audits from the performance test. * * @since 3.9.0 * * @param string $device Device type. * @param string $audit_type Audit type. * * @return string */ public static function get_audits_from_performance_test( $device = 'desktop', $audit_type = 'opportunities' ) { $last_report = self::get_last_report(); $get_audits = isset( $last_report->data->$device->audits->$audit_type ) ? $last_report->data->$device->audits->$audit_type : array(); $performance_audit = array(); if ( ! empty( $get_audits ) ) { foreach ( $get_audits as $key => $value ) { $performance_audit[] = $key; } } return ! empty( $performance_audit ) ? $performance_audit : 'na'; } /** Get performance report error message if any. * * @since 3.9.0 * * @param object $report Performance report. * * @return bool */ public static function get_performance_report_error( $report ) { $error_details = ''; // Is that a report with errors? if ( is_wp_error( $report ) ) { $error_details = $report->get_error_data(); } elseif ( $report && is_null( $report->data->desktop->metrics ) ) { $error_details = "The performance test didn't return any results"; } return $error_details; } /** * Get LCP submetrics for MP. * * @since 3.9.0 * * @return array */ public static function get_lcp_submetrics_for_mp() { $lcp_submetrics = array( 'lcp_ttfb' => array( 'mobile' => self::get_lcp_submetrics( 'mobile', 'TTFB' ), 'desktop' => self::get_lcp_submetrics( 'desktop', 'TTFB' ), ), 'lcp_load_delay' => array( 'mobile' => self::get_lcp_submetrics( 'mobile', 'Load Delay' ), 'desktop' => self::get_lcp_submetrics( 'desktop', 'Load Delay' ), ), 'lcp_render_delay' => array( 'mobile' => self::get_lcp_submetrics( 'mobile', 'Render Delay' ), 'desktop' => self::get_lcp_submetrics( 'desktop', 'Render Delay' ), ), 'lcp_load_time' => array( 'mobile' => self::get_lcp_submetrics( 'mobile', 'Load Time' ), 'desktop' => self::get_lcp_submetrics( 'desktop', 'Load Time' ), ), 'lcp_element' => array( 'mobile' => self::get_lcp_submetrics( 'mobile', 'passed', true ), 'desktop' => self::get_lcp_submetrics( 'desktop', 'passed', true ), ), ); return $lcp_submetrics; } /** * Get the LCP submetrics. * * @since 3.9.0 * * @param string $device Device type. * @param string $phase Phase. * @param bool $lcp_element LCP element. * * @return string */ public static function get_lcp_submetrics( $device = 'desktop', $phase = 'TTFB', $lcp_element = false ) { $report = self::get_last_report(); $lcp = 'largest-contentful-paint-element'; $submetrics = ''; $lcp_snippet = ''; if ( ! empty( $report->data->$device->audits->opportunities->$lcp->details->items[1]->items ) ) { $submetrics = $report->data->$device->audits->opportunities->$lcp->details->items[1]->items; $lcp_snippet = $report->data->$device->audits->opportunities->$lcp->details->items[0]->items[0]->node; } elseif ( ! empty( $report->data->$device->audits->diagnostics->$lcp->details->items[1]->items ) ) { $submetrics = $report->data->$device->audits->diagnostics->$lcp->details->items[1]->items; $lcp_snippet = $report->data->$device->audits->diagnostics->$lcp->details->items[0]->items[0]->node; } elseif ( ! empty( $report->data->$device->audits->passed->$lcp->details->items[1]->items ) ) { $submetrics = $report->data->$device->audits->passed->$lcp->details->items[1]->items; $lcp_snippet = $report->data->$device->audits->passed->$lcp->details->items[0]->items[0]->node; } if ( true === $lcp_element ) { return ! empty( $lcp_snippet->nodeLabel ) && ! empty( $lcp_snippet->snippet ) ? $lcp_snippet->nodeLabel . $lcp_snippet->snippet : 'na'; } if ( empty( $submetrics ) ) { return 'na'; } foreach ( $submetrics as $submetric ) { if ( $phase === $submetric->phase ) { return $submetric->timing; } } return 'na'; } /** * Returns the core web vitals status. * * @since 3.10.0 * * @param string $device Device type. * * @return bool */ public static function core_web_vitals_status( $device = 'desktop' ) { $report = self::get_last_report(); $field_data = isset( $report->data->{$device}->field_data ) ? $report->data->{$device}->field_data : null; if ( empty( $field_data ) ) { return 'na'; } // Get the relevant metrics. $lcp = ! empty( $field_data->LARGEST_CONTENTFUL_PAINT_MS->percentile ) ? $field_data->LARGEST_CONTENTFUL_PAINT_MS->percentile : null; $inp = ! empty( $field_data->INTERACTION_TO_NEXT_PAINT->percentile ) ? $field_data->INTERACTION_TO_NEXT_PAINT->percentile : null; $cls = ! empty( $field_data->CUMULATIVE_LAYOUT_SHIFT_SCORE->percentile ) ? $field_data->CUMULATIVE_LAYOUT_SHIFT_SCORE->percentile / 100 : null; // Thresholds for passing Core Web Vitals. $lcp_pass = null === $lcp ? true : $lcp <= 2500; $inp_pass = null === $inp ? true : $inp <= 200; $cls_pass = null === $cls ? true : $cls <= 0.1; // Return true if all metrics pass, false otherwise. return $lcp_pass && $inp_pass && $cls_pass ? 'pass' : 'fail'; } /** * Move audits without a score to the `passed` object. * * @since 3.13.0 * * @param object $psi_response PSI response. */ public static function move_audits_without_score( &$psi_response ) { if ( ! isset( $psi_response->data ) ) { return; } foreach ( array( 'desktop', 'mobile' ) as $platform ) { if ( ! isset( $psi_response->data->$platform->audits ) ) { continue; } $audits = $psi_response->data->$platform->audits; if ( ! isset( $audits->passed ) ) { $audits->passed = new \stdClass(); } foreach ( array( 'diagnostics', 'opportunities' ) as $audit_type ) { if ( isset( $audits->$audit_type ) ) { foreach ( $audits->$audit_type as $key => $audit ) { if ( ! isset( $audit->score ) ) { $audits->passed->$key = $audit; unset( $audits->$audit_type->$key ); } } } } } } }
| ver. 1.4 |
Github
|
.
| PHP 8.2.30 | Generation time: 0 |
proxy
|
phpinfo
|
Settings