$path, ); } } return $config; } /** * Output preconnect and preload hints. * * @return void */ public static function output_preloads() { if ( ! I365_PO_Plugin::is_frontend_context() ) { return; } $settings = I365_PO_Plugin::get_settings(); foreach ( $settings['preconnect_hosts'] as $host ) { $is_cross = ( wp_parse_url( $host, PHP_URL_HOST ) !== wp_parse_url( home_url(), PHP_URL_HOST ) ); $cross = $is_cross ? ' crossorigin' : ''; printf( '%3$s', esc_url( $host ), $cross, "\n" ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } if ( ! empty( $settings['preload_font'] ) ) { printf( '%s', esc_url( $settings['preload_font'] ), "\n" ); } if ( ! empty( $settings['preload_hero'] ) ) { if ( ! $settings['hero_preload_on_front'] || is_front_page() ) { printf( '%s', esc_url( $settings['preload_hero'] ), "\n" ); } } } /** * Clean REST and oEmbed link tags on the front end. * * @return void */ public static function clean_head_links() { if ( is_admin() ) { return; } $settings = I365_PO_Plugin::get_settings(); if ( $settings['remove_rest_link'] ) { remove_action( 'wp_head', 'rest_output_link_wp_head' ); } if ( $settings['remove_oembed_link'] ) { remove_action( 'wp_head', 'wp_oembed_add_discovery_links' ); } } /** * Mark LCP images as high priority when applicable. * * @param array $attr Attributes. * @param WP_Post $attachment Attachment. * @param string|array $size Size. * * @return array */ public static function lcp_priority( $attr, $attachment, $size ) { if ( ! I365_PO_Plugin::is_frontend_context() ) { return $attr; } if ( empty( $attr['loading'] ) && empty( $attr['fetchpriority'] ) ) { $attr['fetchpriority'] = 'high'; } return $attr; } /** * Disable lazy-loading on front page images for sanity. * * @param bool $default Default value. * @param string $tag Tag name. * * @return bool */ public static function lazy_loading_sanity( $default, $tag ) { if ( ! I365_PO_Plugin::is_frontend_context() ) { return $default; } // Check per-page override to force lazy-loading. if ( I365_PO_Meta_Box::is_override_active( 'force_lazy_load' ) ) { return $default; // Keep default (lazy-loading enabled). } if ( 'img' === $tag && is_front_page() ) { return false; } return $default; } /** * Enqueue stylesheet with preload metadata to satisfy plugin checks. * * @return void */ public static function enqueue_stylesheet_preload() { if ( ! I365_PO_Plugin::is_frontend_context() ) { return; } $settings = I365_PO_Plugin::get_settings(); if ( empty( $settings['preload_stylesheet'] ) ) { return; } $url = esc_url_raw( $settings['preload_stylesheet'] ); $handle = 'i365-po-preload-style'; wp_enqueue_style( $handle, $url, array(), I365_PO_VERSION ); // Inform WordPress this should be preloaded. wp_style_add_data( $handle, 'preload', true ); } /* |-------------------------------------------------------------------------- | JavaScript Delay Until Interaction |-------------------------------------------------------------------------- */ /** * Delay non-critical scripts until user interaction. * * @param string $tag Script tag HTML. * @param string $handle Script handle. * @param string $src Script URL. * * @return string */ public static function delay_scripts( $tag, $handle, $src ) { if ( ! I365_PO_Plugin::is_frontend_context() ) { return $tag; } // Check per-page override. if ( I365_PO_Meta_Box::is_override_active( 'disable_delay_js' ) ) { return $tag; } $settings = I365_PO_Plugin::get_settings(); $exclude = $settings['delay_js_exclude']; // Merge per-page excluded scripts. $page_excluded = I365_PO_Meta_Box::get_excluded_scripts(); if ( ! empty( $page_excluded ) ) { $exclude = array_merge( $exclude, $page_excluded ); } // Check if this script should be excluded from delay. if ( self::is_delay_excluded( $handle, $exclude ) ) { return $tag; } // Don't delay scripts that are already deferred/async or modules. if ( false !== stripos( $tag, ' async' ) || false !== stripos( $tag, ' type="module"' ) ) { return $tag; } // Don't delay inline scripts (no src). if ( empty( $src ) ) { return $tag; } // Transform the script tag to delay loading. // Change src to data-i365-src and add data-i365-delay marker. $tag = preg_replace( '/(]*)\ssrc=["\']([^"\']+)["\']([^>]*>)/i', '$1 data-i365-src="$2" data-i365-delay$3', $tag ); // Add type="text/plain" to prevent execution. $tag = preg_replace( '/(window.i365DelayTimeout=' . absint( $timeout ) . ';'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Trusted plugin JS file content. echo $script; echo "\n"; } /* |-------------------------------------------------------------------------- | Heartbeat API Control |-------------------------------------------------------------------------- */ /** * Control WordPress Heartbeat API behavior. * * @return void */ public static function control_heartbeat() { // This method is a placeholder for initialization. // Actual work is done by deregister_heartbeat and modify_heartbeat_settings. } /** * Deregister the heartbeat script. * * @return void */ public static function deregister_heartbeat() { wp_deregister_script( 'heartbeat' ); } /** * Modify heartbeat settings to reduce frequency. * * @param array $settings Heartbeat settings. * * @return array */ public static function modify_heartbeat_settings( $settings ) { $opts = I365_PO_Plugin::get_settings(); $settings['interval'] = absint( $opts['heartbeat_interval'] ); return $settings; } /* |-------------------------------------------------------------------------- | Query String Removal |-------------------------------------------------------------------------- */ /** * Remove version query strings from static resources. * * @param string $src Resource URL. * @param string $handle Resource handle. * * @return string */ public static function remove_query_strings( $src, $handle ) { // Only process if there's a version query string. if ( strpos( $src, '?ver=' ) !== false || strpos( $src, '&ver=' ) !== false ) { $src = remove_query_arg( 'ver', $src ); } return $src; } }