BossBey File Manager
PHP:
8.2.30
OS:
Linux
User:
imagivibe
Root
/
home
/
imagivibe
/
www
/
wp-content
/
plugins
/
sg-cachepress
/
core
/
Front_End_Optimization
📤 Upload
📝 New File
📁 New Folder
Close
Editing: Front_End_Optimization.php
<?php namespace SiteGround_Optimizer\Front_End_Optimization; use SiteGround_Optimizer\Supercacher\Supercacher; use SiteGround_Optimizer\File_Cacher\File_Cacher; use SiteGround_Helper\Helper_Service; use SiteGround_Optimizer\Helper\Helper; /** * SG Front_End_Optimization main plugin class */ class Front_End_Optimization { /** * The dir where the minified styles and scripts will be saved. * * @since 5.0.0 * * @var string|null Path to assets dir. */ public $assets_dir = null; /** * Limit of assets dir in bytes. * * @since 5.6.0 * * @var int Bytes. */ const LIMIT = 1000000000; /** * Script handles that shouldn't be loaded async. * * @since 5.0.0 * * @var array Array of script handles that shouldn't be loaded async. */ private $blacklisted_async_scripts = array( 'moxiejs', 'wc-square', 'wc-braintree', 'wc-authorize-net-cim', 'sv-wc-payment-gateway-payment-form', 'paypal-checkout-sdk', 'uncode-app', 'uncode-plugins', 'uncode-init', 'lodash', 'wp-api-fetch', 'wp-i18n', 'wp-polyfill', 'wp-url', 'wp-hooks', 'houzez-google-map-api', 'wpascript', 'wc-square', ); /** * Array containing all script handle regex' that should be excluded. * * @since 7.1.0 * * @var array Array containing all script handle regex' that should be excluded. */ private $blacklisted_async_regex = array( 'sv-wc-payment-gateway-payment-form-v', // Authorize.NET payment gateway payment form script. ); /** * The singleton instance. * * @since 5.1.0 * * @var \Front_End_Optimization The singleton instance. */ private static $instance; /** * Create a {@link Supercacher} instance. * * @since 5.0.0 */ public function __construct() { // Set the assets dir path. $this->set_assets_directory_path(); self::$instance = $this; $this->blacklisted_async_scripts = array_merge( $this->blacklisted_async_scripts, get_option( 'siteground_optimizer_async_javascript_exclude', array() ) ); } /** * Get the singleton instance. * * @since 5.1.0 * * @return \Front_End_Optimization The singleton instance. */ public static function get_instance() { if ( null == self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Set the assets directory. * * @since 5.1.0 */ private function set_assets_directory_path() { // Bail if the assets dir has been set. if ( null !== $this->assets_dir ) { return; } $uploads_dir = Helper_Service::get_uploads_dir(); // Build the assets dir name. $directory = $uploads_dir . '/siteground-optimizer-assets'; // Check if directory exists and try to create it if not. $is_directory_created = ! is_dir( $directory ) ? $this->create_directory( $directory ) : true; // Set the assets dir. if ( $is_directory_created ) { $this->assets_dir = trailingslashit( $directory ); } } /** * Create directory. * * @since 5.1.0 * * @param string $directory The new directory path. * * @return bool True is the directory is created. * False on failure. */ public function create_directory( $directory ) { // Create the directory and return the result. $is_directory_created = wp_mkdir_p( $directory ); // Bail if cannot create temp dir. if ( false === $is_directory_created ) { // translators: `$directory` is the name of directory that should be created. error_log( sprintf( 'Cannot create directory: %s.', $directory ) ); } return $is_directory_created; } /** * Get the original filepath by file handle. * * @since 5.1.0 * * @param string $original File handle. * * @return string Original filepath. */ public static function get_original_filepath( $original ) { $home_url = Helper_Service::get_site_url(); // Get the home_url from database. Some plugins like qtranslate for example, // modify the home_url, which result to wrong replacement with ABSPATH for resources loaded via link. // Very ugly way to handle resources without protocol. $result = wp_parse_url( $home_url ); $replace = $result['scheme'] . '://'; $new = preg_replace( '~^https?:\/\/|^\/\/~', $replace, $original ); // Get the filepath to original file. if ( @strpos( $new, $home_url ) !== false ) { $original_filepath = str_replace( $home_url, ABSPATH, $new ); } else { $original_filepath = untrailingslashit( ABSPATH ) . $new; } return $original_filepath; } /** * Return the path to assets dir. * * @since 5.1.0 * * @return string Path to assets dir. */ public function get_assets_dir() { return $this->assets_dir; } /** * Prepare scripts to be included async. * * @since 5.1.0 */ public function prepare_scripts_for_async_load() { global $wp_scripts; // Bail if the scripts object is empty. if ( ! is_object( $wp_scripts ) || is_user_logged_in() ) { return; } $scripts = wp_clone( $wp_scripts ); $scripts->all_deps( $scripts->queue ); $excluded_scripts = apply_filters( 'sgo_js_async_exclude', $this->blacklisted_async_scripts ); // Remove excluded script handles using regex. foreach( $this->blacklisted_async_regex as $regex ) { $excluded_scripts = array_merge( $excluded_scripts, Helper::get_script_handle_regex( $regex, $scripts->to_do ) ); } // Get groups of handles. foreach ( $scripts->to_do as $handle ) { // We don't want to load footer scripts asynchronous. if ( in_array( $handle, $excluded_scripts ) || empty( $wp_scripts->registered[ $handle ]->src ) ) { continue; } $wp_scripts->registered[ $handle ]->src = add_query_arg( 'siteground-async', 1, $wp_scripts->registered[ $handle ]->src ); } } /** * Load all scripts async. * This function adds async attr to all scripts. * * @since 5.1.0 * * @param string $tag The <script> tag for the enqueued script. * @param string $handle The script's registered handle. * @param string $src Script src. */ public function add_async_attribute( $tag, $handle, $src ) { // Bail if we do not find the argument. if ( @strpos( $src, 'siteground-async=1' ) === false ) { return $tag; } // Add the async attribute and replace the & and ? with their proper representation. $tag = str_replace( array( '<script ', '-siteground-async', $src, '?#038;', '#038;', '&', ), array( '<script defer ', '', remove_query_arg( 'siteground-async', $src ), '?', '&', '&', ), $tag ); // Match the async argument and replace it with the proper symbol, depending of the position of the argument. $tag = preg_replace_callback( '/([\?&])siteground-async=1(&|$|\b)/', function( $matches ) { return empty( $matches[2] ) ? '' : $matches[1]; }, $tag ); return $tag; } /** * Remove query strings from static resources. * * @since 5.0.0 * * @param string $src The source URL of the enqueued style. * * @return string $src The modified src if there are query strings, the initial src otherwise. */ public static function remove_query_strings( $src ) { // Get the host. $host = wp_parse_url( $src, PHP_URL_HOST ); // Bail if the host is empty. if ( empty( $host ) ) { return $src; } // Skip all external sources. if ( @strpos( Helper_Service::get_home_url(), $host ) === false ) { return $src; } $exclude_list = apply_filters( 'sgo_rqs_exclude', array() ); if ( ! empty( $exclude_list ) && preg_match( '~' . implode( '|', $exclude_list ) . '~', $src ) ) { return $src; } return remove_query_arg( array( 'ver', 'version', 'v', 'mts', 'nomtcache', 'generated', 'timestamp', 'cache', ), html_entity_decode( $src ) ); } /** * Get styles and scripts loaded on the site. * * @since 5.2.0 * * @return arary $data Array of all styles and scripts loaded on the site. */ public function get_assets() { // Get the global varialbes. global $wp; global $wp_styles; global $wp_scripts; // Pre-load Woocommerce functionality, if needed. if ( function_exists( '\WC' ) && defined( '\WC_ABSPATH' ) ) { include_once \WC_ABSPATH . 'includes/wc-cart-functions.php'; include_once \WC_ABSPATH . 'includes/class-wc-cart.php'; if ( is_null( WC()->cart ) ) { wc_load_cart(); } } // Remove the jet popup action to prevent fatal errros. remove_all_actions( 'elementor/editor/after_enqueue_styles', 10 ); ob_start(); // Call the action to load the assets. do_action( 'wp', $wp ); do_action( 'wp_enqueue_scripts' ); do_action( 'elementor/editor/after_enqueue_styles' ); ob_get_clean(); // Build the assets data. return array( 'scripts' => $this->get_assets_data( $wp_scripts ), 'styles' => $this->get_assets_data( $wp_styles ), ); } /** * Get assets data (styles/scripts) * * @since 5.2.0 * * @param object $assets The global styles/scripts obejct. * * @return array $data. Array of styles/scripts data. */ private function get_assets_data( $assets ) { $excludes = array( 'moxiejs', 'elementor-frontend', ); // Init the data array. $data = array( 'header' => array(), 'default' => array(), 'non_minified' => array(), ); // CLone the global assets object. $items = wp_clone( $assets ); $items->all_deps( $items->queue ); // Loop through all assets and push them to data array. foreach ( $items->to_do as $index => $handle ) { if ( in_array( $handle, $excludes ) || // Do not include excluded assets. ! is_bool( @strpos( $handle, 'siteground' ) ) || ! is_string( $items->registered[ $handle ]->src ) // Do not include asset without source. ) { continue; } if ( 1 !== $items->groups[ $handle ] ) { $data['header'][] = $this->get_asset_data( $items->registered[ $handle ] ); } if ( @strpos( $items->registered[ $handle ]->src, '.min.' ) === false ) { $data['non_minified'][] = $this->get_asset_data( $items->registered[ $handle ] ); } $data['default'][] = $this->get_asset_data( $items->registered[ $handle ] ); } // Finally return the assets data. return $data; } /** * Get single asset data. * * @since 5.2.0 * * @param object $item The asset object. * * @return array The asset data. */ public function get_asset_data( $item ) { // Strip the protocol from the src because some assets are loaded without protocol. $src = preg_replace( '~https?://~', '', Front_End_Optimization::remove_query_strings( $item->src ) ); // Do regex match to the the plugin name and shorten src link. preg_match( '~wp-content(/(.*?)/(.*?)/.*)~', $src, $matches ); // Push everything in the data array. $data = array( 'value' => $item->handle, // The handle. 'title' => ! empty( $matches[1] ) ? $matches[1] : $item->src, // The assets src. 'group' => ! empty( $matches[2] ) ? substr( $matches[2], 0, -1 ) : __( 'others', 'siteground-optimizer' ), // Get the group name. 'name' => ! empty( $matches[3] ) ? $this->get_plugin_info( $matches[3] ) : false, // The name of the parent( plugin or theme name ). ); $data['group_title'] = empty( $data['name'] ) ? $data['group'] : $data['group'] . ': ' . $data['name']; return $data; } /** * Get information about specific plugin. * * @since 5.2.0 * * @param string $path Path to the plugin. * @param string $field The field we want to retrieve. * * @return string The specific plugin field. */ private function get_plugin_info( $path, $field = 'name' ) { // Get active plugins. $active_plugins = get_option( 'active_plugins' ); // Check if the path is presented in the active plugins. foreach ( $active_plugins as $plugin_file ) { if ( false === @strpos( $plugin_file, $path ) ) { continue; } // Get the plugin data from the main plugin file. $plugin = get_file_data( WP_PLUGIN_DIR . '/' . $plugin_file, array( $field => 'Plugin Name' ) ); } // Return the date from plugin file. if ( ! empty( $plugin[ $field ] ) ) { return $plugin[ $field ]; } // Otherwise return the path. return $path; } /** * Check the size of the assets dir. * * @since 5.6.0 */ public function check_assets_dir() { // Bail if the size is smaller that the limit. if ( self::LIMIT > $this->get_directory_size( $this->assets_dir ) ) { return; } Supercacher::delete_assets(); Supercacher::purge_cache(); Supercacher::flush_memcache(); File_Cacher::get_instance()->purge_everything(); } /** * Return the total size of a directory in bytes. * * @since 5.6.0 * * @param string $directory The directory which size to calculate. * * @return int $size The total size of the directory. */ public static function get_directory_size( $directory ) { // Init the size. $size = 0; // Bail if the directory doesn't exists. if ( ! file_exists( $directory ) ) { return false; } // Init the iterator. // We create this variable for code readability. // Otherwise the foreach below looks very ugly. $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $directory, \FilesystemIterator::SKIP_DOTS ) ); // Loop through all sub-directories and files // and calculate the size of the directory. foreach ( $iterator as $object ) { // Increase the `size` by adding the current object size. $size += $object->getSize(); } // Finally return the total size of the directory. return $size; } }
Save
Cancel