initial commit

This commit is contained in:
2024-04-29 13:12:44 +05:45
commit 34887303c5
19300 changed files with 5268802 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
<?php
if (!defined('ABSPATH')) die('No direct access allowed');
class WP_Optimize_Detect_Minify_Plugins {
/**
* Detect list of active most popular WordPress minify plugins.
*
* @return array
*/
public function get_active_minify_plugins() {
$active_minify_plugins = array();
foreach ($this->get_plugins() as $plugin_slug => $plugin_title) {
if ($this->is_plugin_active($plugin_slug) && $this->is_minify_active($plugin_slug)) {
$active_minify_plugins[$plugin_slug] = $plugin_title;
}
}
return $active_minify_plugins;
}
/**
* Get the plugins list
*
* @return array
*/
protected function get_plugins() {
return array(
'w3-total-cache' => 'W3 Total Cache',
'autoptimize' => 'Autoptimize',
'fast-velocity-minify' => 'Fast Velocity Minify',
);
}
/**
* Check if $plugin is active.
*
* @param string $plugin - plugin slug
*
* @return bool
*/
private function is_plugin_active($plugin) {
$status = WP_Optimize()->get_db_info()->get_plugin_status($plugin);
return $status['active'];
}
/**
* Check if minify feature is active
*
* @return bool
*/
public function is_minify_active($plugin_slug) {
switch ($plugin_slug) {
case 'w3-total-cache':
return (function_exists('w3tc_config') && w3tc_config()->get_boolean('minify.enabled'));
case 'autoptimize':
return ('on' == get_option('autoptimize_js', false) || 'on' == get_option('autoptimize_css', false) || 'on' == get_option('autoptimize_html', false));
case 'fast-velocity-minify':
return true;
}
}
/**
* Instance of WP_Optimize_Detect_Minify_Plugins.
*
* @return WP_Optimize_Detect_Minify_Plugins
*/
public static function get_instance() {
static $instance = null;
if (null === $instance) {
$instance = new self();
}
return $instance;
}
}

View File

@@ -0,0 +1,293 @@
<?php
if (!defined('ABSPATH')) die('No direct access allowed');
class WP_Optimize_Minify_Admin {
private $wp_version_required = '4.5';
/**
* Initialize, add actions and filters
*
* @return void
*/
public function __construct() {
if (WPO_MINIFY_PHP_VERSION_MET) {
// exclude processing for editors and administrators (fix editors)
add_action('wp_optimize_admin_page_wpo_minify_status', array($this, 'check_permissions_admin_notices'));
}
add_action('wp_optimize_admin_page_wpo_minify_status', array($this, 'admin_notices_activation_errors'));
add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));
// This function runs when WordPress updates or installs/remove something. Forces new cache
add_action('upgrader_process_complete', array('WP_Optimize_Minify_Cache_Functions', 'cache_increment'));
// This function runs when an active theme or plugin is updated
add_action('wpo_active_plugin_or_theme_updated', array('WP_Optimize_Minify_Cache_Functions', 'reset'));
add_action('upgrader_overwrote_package', array('WP_Optimize_Minify_Cache_Functions', 'reset'));
add_action('after_switch_theme', array('WP_Optimize_Minify_Cache_Functions', 'cache_increment'));
add_action('updraftcentral_version_updated', array('WP_Optimize_Minify_Cache_Functions', 'reset'));
add_action('elementor/editor/after_save', array('WP_Optimize_Minify_Cache_Functions', 'reset'));
add_action('fusion_cache_reset_after', array('WP_Optimize_Minify_Cache_Functions', 'reset'));
// Output asset preload placeholder, replaced by premium
add_action('wpo_minify_settings_tabs', array($this, 'output_assets_preload_placeholder'), 10, 1);
add_action('wp_optimize_register_admin_content', array($this, 'register_content'));
}
/**
* Register the content
*
* @return void
*/
public function register_content() {
add_action('wp_optimize_admin_page_wpo_minify_status', array($this, 'output_status'), 20);
add_action('wp_optimize_admin_page_wpo_minify_settings', array($this, 'output_settings'), 20);
add_action('wp_optimize_admin_page_wpo_minify_advanced', array($this, 'output_advanced'), 20);
add_action('wp_optimize_admin_page_wpo_minify_font', array($this, 'output_font_settings'), 20);
add_action('wp_optimize_admin_page_wpo_minify_css', array($this, 'output_css_settings'), 20);
add_action('wp_optimize_admin_page_wpo_minify_js', array($this, 'output_js_settings'), 20);
add_action('wp_optimize_admin_page_wpo_minify_preload', array($this, 'output_preload_settings'), 20);
}
/**
* Load scripts for controlling the admin pages
*
* @param string $hook
* @return void
*/
public function admin_enqueue_scripts($hook) {
$enqueue_version = (defined('WP_DEBUG') && WP_DEBUG) ? WPO_VERSION.'.'.time() : WPO_VERSION;
$min_or_not_internal = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '-'. str_replace('.', '-', WPO_VERSION). '.min';
if (preg_match('/wp\-optimize/i', $hook)) {
wp_enqueue_script('wp-optimize-min-js', WPO_PLUGIN_URL.'js/minify' . $min_or_not_internal . '.js', array('jquery', 'wp-optimize-admin-js'), $enqueue_version);
}
}
/**
* Conditionally runs upon the WP action admin_notices to display errors
*
* @return void
*/
public function admin_notices_activation_errors() {
global $wp_version;
include ABSPATH . WPINC . '/version.php';
$errors = array();
if (!WPO_MINIFY_PHP_VERSION_MET) {
$errors[] = sprintf(__('WP-Optimize Minify requires PHP 5.4 or higher. Youre using version %s.', 'wp-optimize'), PHP_VERSION);
}
if (!extension_loaded('mbstring')) {
$errors[] = __('WP-Optimize Minify requires the PHP mbstring module to be installed on the server; please ask your web hosting company for advice on how to enable it on your server.', 'wp-optimize');
}
if (version_compare($wp_version, $this->wp_version_required, '<')) {
$errors[] = sprintf(__('WP-Optimize Minify requires WordPress version %s or higher. Youre using version %s.', 'wp-optimize'), $this->wp_version_required, $wp_version);
}
foreach ($errors as $error) {
?>
<div class="notice notice-error wpo-warning">
<p><?php echo $error; ?></p>
</div>
<?php
}
}
/**
* Display an admin notice if the user has inadequate filesystem permissions
*
* @return void
*/
public function check_permissions_admin_notices() {
// get cache path
$cache_path = WP_Optimize_Minify_Cache_Functions::cache_path();
$cache_dir = $cache_path['cachedir'];
if (is_dir($cache_dir) && !is_writable($cache_dir)) {
$chmod = substr(sprintf('%o', fileperms($cache_dir)), -4);
?>
<div class="notice notice-error wpo-warning">
<p>
<?php printf(__('WP-Optimize Minify needs write permissions on the folder %s.', 'wp-optimize'), "<strong>".htmlspecialchars($cache_dir)."</strpmg>"); ?>
</p>
</div>
<div class="notice notice-error wpo-warning">
<p>
<?php printf(__('The current permissions for WP-Optimize Minify are chmod %s.', 'wp-optimize'), "<strong>$chmod</strong>"); ?>
</p>
</div>
<div class="notice notice-error wpo-warning">
<p>
<?php
printf(__('If you need something more than %s for it to work, then your server is probably misconfigured.', 'wp-optimize'), '<strong>775</strong>');
echo " ";
_e('Please contact your hosting provider.', 'wp-optimize');
?>
</p>
</div>
<?php
}
}
/**
* Minify - Outputs the status tab
*
* @return void
*/
public function output_status() {
if (!class_exists('WP_Optimize_Detect_Minify_Plugins')) {
require_once(WP_OPTIMIZE_MINIFY_DIR.'/class-wp-optimize-detect-minify-plugins.php');
}
$this->found_incompatible_plugins = WP_Optimize_Detect_Minify_Plugins::get_instance()->get_active_minify_plugins();
$wpo_minify_options = wp_optimize_minify_config()->get();
$cache_path = WP_Optimize_Minify_Cache_Functions::cache_path();
WP_Optimize()->include_template(
'minify/status-tab.php',
false,
array(
'wpo_minify_options' => $wpo_minify_options,
'show_information_notice' => !get_user_meta(get_current_user_id(), 'wpo-hide-minify-information-notice', true),
'cache_dir' => $cache_path['cachedir'],
'can_purge_the_cache' => WP_Optimize()->can_purge_the_cache(),
'active_minify_plugins' => apply_filters('wpo_minify_found_incompatible_plugins', $this->found_incompatible_plugins),
)
);
}
/**
* Minify - Outputs the font settings tab
*
* @return void
*/
public function output_font_settings() {
$wpo_minify_options = wp_optimize_minify_config()->get();
WP_Optimize()->include_template(
'minify/font-settings-tab.php',
false,
array(
'wpo_minify_options' => $wpo_minify_options
)
);
}
/**
* Minify - Outputs the CSS settings tab
*
* @return void
*/
public function output_css_settings() {
$wpo_minify_options = wp_optimize_minify_config()->get();
WP_Optimize()->include_template(
'minify/css-settings-tab.php',
false,
array(
'wpo_minify_options' => $wpo_minify_options
)
);
}
/**
* Minify - Outputs the JS settings tab
*
* @return void
*/
public function output_js_settings() {
$wpo_minify_options = wp_optimize_minify_config()->get();
WP_Optimize()->include_template(
'minify/js-settings-tab.php',
false,
array(
'wpo_minify_options' => $wpo_minify_options
)
);
}
/**
* Minify - Outputs the settings tab
*
* @return void
*/
public function output_settings() {
$wpo_minify_options = wp_optimize_minify_config()->get();
$url = parse_url(get_home_url());
WP_Optimize()->include_template(
'minify/settings-tab.php',
false,
array(
'wpo_minify_options' => $wpo_minify_options,
'default_protocol' => $url['scheme']
)
);
}
/**
* Minify - Outputs the settings tab
*
* @return void
*/
public function output_assets_preload_placeholder($wpo_minify_options) {
WP_Optimize()->include_template(
'minify/asset-preload.php',
false,
array(
'wpo_minify_options' => $wpo_minify_options
)
);
}
/**
* Minify - Outputs the preload tab
*
* @return void
*/
public function output_preload_settings() {
$wpo_minify_preloader = WP_Optimize_Minify_Preloader::instance();
$is_running = $wpo_minify_preloader->is_running();
$status = $wpo_minify_preloader->get_status_info();
if (!class_exists('WPO_Cache_Config')) require_once(WPO_PLUGIN_MAIN_PATH . '/cache/class-wpo-cache-config.php');
$cache_config = WPO_Cache_Config::instance();
WP_Optimize()->include_template(
'minify/preload-tab.php',
false,
array(
'is_cache_enabled' => $cache_config->get_option('enable_page_caching'),
'is_running' => $is_running,
'status_message' => isset($status['message']) ? $status['message'] : '',
)
);
}
/**
* Minify - Outputs the advanced tab
*
* @return void
*/
public function output_advanced() {
$wpo_minify_options = wp_optimize_minify_config()->get();
$files = false;
if (apply_filters('wpo_minify_status_show_files_on_load', true) && WPO_MINIFY_PHP_VERSION_MET) {
$files = WP_Optimize_Minify_Cache_Functions::get_cached_files();
}
// WP_Optimize_Minify_Functions is only loaded when Minify is active
if (class_exists('WP_Optimize_Minify_Functions')) {
$default_ignore = WP_Optimize_Minify_Functions::get_default_ignore();
$default_ie_blacklist = WP_Optimize_Minify_Functions::get_default_ie_blacklist();
} else {
$default_ignore = array();
$default_ie_blacklist = array();
}
WP_Optimize()->include_template(
'minify/advanced-tab.php',
false,
array(
'wpo_minify_options' => $wpo_minify_options,
'files' => $files,
'default_ignore' => $default_ignore,
'default_ie_blacklist' => $default_ie_blacklist
)
);
}
}

View File

@@ -0,0 +1,495 @@
<?php
if (!defined('ABSPATH')) die('No direct access allowed');
if (!defined('WP_OPTIMIZE_MINIFY_DIR')) {
die('No direct access.');
}
if (!function_exists('wpo_delete_files')) {
include WPO_PLUGIN_MAIN_PATH.'cache/file-based-page-cache-functions.php';
}
class WP_Optimize_Minify_Cache_Functions {
/**
* Fix the permission bits on generated files
*
* @param String $file - full path to a file
*/
public static function fix_permission_bits($file) {
if (function_exists('stat')) {
if ($stat = stat(dirname($file))) {
$perms = $stat['mode'] & 0007777;
chmod($file, $perms);
clearstatcache();
return true;
}
}
// Get permissions from parent directory
$perms = 0777;
if (function_exists('stat')) {
if ($stat = stat(dirname($file))) {
$perms = $stat['mode'] & 0007777;
}
}
if (file_exists($file)) {
if (($perms & ~umask() != $perms)) {
$folder_parts = explode('/', substr($file, strlen(dirname($file)) + 1));
for ($i = 1, $c = count($folder_parts); $i <= $c; $i++) {
chmod(dirname($file) . '/' . implode('/', array_slice($folder_parts, 0, $i)), $perms);
}
}
}
return true;
}
/**
* Get cache directories and urls
*
* @return Array
*/
public static function cache_path() {
// get latest time stamp
$cache_time = wp_optimize_minify_config()->get('last-cache-update');
$cache_dir_url = WPO_CACHE_MIN_FILES_URL . "/$cache_time/assets";
$tmp_dir = WPO_CACHE_MIN_FILES_DIR . "/tmp";
$header_dir = WPO_CACHE_MIN_FILES_DIR . "/$cache_time/header";
$cache_dir = WPO_CACHE_MIN_FILES_DIR . "/$cache_time/assets";
// Create directories
$dirs = array($cache_dir, $tmp_dir, $header_dir);
foreach ($dirs as $target) {
$enabled = wp_optimize_minify_config()->get('enabled');
if (false === $enabled) break;
if (!is_dir($target) && !wp_mkdir_p($target)) {
error_log('WP_Optimize_Minify_Cache_Functions::cache_path(): The folder "'.$target.'" could not be created.');
}
}
return array(
'tmpdir' => $tmp_dir,
'cachedir' => $cache_dir,
'cachedirurl' => $cache_dir_url,
'headerdir' => $header_dir
);
}
/**
* Increment file names
*/
public static function cache_increment() {
$stamp = time();
wp_optimize_minify_config()->update(array(
'last-cache-update' => $stamp
));
return $stamp;
}
/**
* Reset the cache (Increment + purge temp files)
*/
public static function reset() {
self::cache_increment();
self::purge_temp_files();
}
/**
* Will delete temporary intermediate stuff but leave final css/js alone for compatibility
*
* @return Array
*/
public static function purge_temp_files() {
// get cache directories and urls
$cache_path = self::cache_path();
$tmp_dir = $cache_path['tmpdir'];
$header_dir = $cache_path['headerdir'];
// delete temporary directories only
if (is_dir($tmp_dir)) {
wpo_delete_files($tmp_dir, true);
}
if (is_dir($header_dir)) {
wpo_delete_files($header_dir, true);
}
/**
* Action triggered after purging temporary files
*/
do_action('wpo_min_after_purge_temp_files');
return array(
'tmpdir' => $tmp_dir,
'headerdir' => $header_dir,
);
}
/**
* Purge supported hosting and plugins
*
* @return string
*/
public static function purge_others() {
/**
* Action triggered before purging other plugins cache
*/
do_action('wpo_min_before_purge_others');
// WordPress default cache
if (function_exists('wp_cache_flush')) {
wp_cache_flush();
}
// Purge WP-Optimize
WP_Optimize()->get_page_cache()->purge();
// When plugins have a simple method, add them to the array ('Plugin Name' => 'method_name')
$others = array(
'WP Super Cache' => 'wp_cache_clear_cache',
'W3 Total Cache' => 'w3tc_pgcache_flush',
'WP Fastest Cache' => 'wpfc_clear_all_cache',
'WP Rocket' => 'rocket_clean_domain',
'Cachify' => 'cachify_flush_cache',
'Comet Cache' => array('comet_cache', 'clear'),
'SG Optimizer' => 'sg_cachepress_purge_cache',
'Pantheon' => 'pantheon_wp_clear_edge_all',
'Zen Cache' => array('zencache', 'clear'),
'Breeze' => array('Breeze_PurgeCache', 'breeze_cache_flush'),
'Swift Performance' => array('Swift_Performance_Cache', 'clear_all_cache'),
);
foreach ($others as $plugin => $method) {
if (is_callable($method)) {
call_user_func($method);
return sprintf(__('All caches from %s have also been purged.', 'wp-optimize'), '<strong>'.$plugin.'</strong>');
}
}
// Purge LiteSpeed Cache
if (is_callable(array('LiteSpeed_Cache_Tags', 'add_purge_tag'))) {
LiteSpeed_Cache_Tags::add_purge_tag('*');
return sprintf(__('All caches from %s have also been purged.', 'wp-optimize'), '<strong>LiteSpeed Cache</strong>');
}
// Purge Hyper Cache
if (class_exists('HyperCache')) {
do_action('autoptimize_action_cachepurged');
return sprintf(__('All caches from %s have also been purged.', 'wp-optimize'), '<strong>Hyper Cache</strong>');
}
// Purge Godaddy Managed WordPress Hosting (Varnish + APC)
if (class_exists('WPaaS\Plugin')) {
self::godaddy_request('BAN');
return sprintf(__('A cache purge request has been sent to %s. Please note that it may not work every time, due to cache rate limiting by your host.', 'wp-optimize'), '<strong>Go Daddy Varnish</strong>');
}
// purge cache enabler
if (has_action('ce_clear_cache')) {
do_action('ce_clear_cache');
return sprintf(__('All caches from %s have also been purged.', 'wp-optimize'), '<strong>Cache Enabler</strong>');
}
// Purge WP Engine
if (class_exists("WpeCommon")) {
if (method_exists('WpeCommon', 'purge_memcached')) {
WpeCommon::purge_memcached();
}
if (method_exists('WpeCommon', 'clear_maxcdn_cache')) {
WpeCommon::clear_maxcdn_cache();
}
if (method_exists('WpeCommon', 'purge_varnish_cache')) {
WpeCommon::purge_varnish_cache();
}
if (method_exists('WpeCommon', 'purge_memcached') || method_exists('WpeCommon', 'clear_maxcdn_cache') || method_exists('WpeCommon', 'purge_varnish_cache')) {
return sprintf(__('A cache purge request has been sent to %s. Please note that it may not work every time, due to cache rate limiting by your host.', 'wp-optimize'), '<strong>WP Engine</strong>');
}
}
// Purge Kinsta
global $kinsta_cache;
if (isset($kinsta_cache) && class_exists('\\Kinsta\\CDN_Enabler')) {
if (!empty($kinsta_cache->kinsta_cache_purge) && is_callable(array($kinsta_cache->kinsta_cache_purge, 'purge_complete_caches'))) {
$kinsta_cache->kinsta_cache_purge->purge_complete_caches();
return sprintf(__('A cache purge request was also sent to %s', 'wp-optimize'), '<strong>Kinsta</strong>');
}
}
// Purge Pagely
if (class_exists('PagelyCachePurge')) {
$purge_pagely = new PagelyCachePurge();
if (is_callable(array($purge_pagely, 'purgeAll'))) {
$purge_pagely->purgeAll();
return sprintf(__('A cache purge request was also sent to %s', 'wp-optimize'), '<strong>Pagely</strong>');
}
}
// Purge Pressidum
if (defined('WP_NINUKIS_WP_NAME') && class_exists('Ninukis_Plugin') && is_callable(array('Ninukis_Plugin', 'get_instance'))) {
$purge_pressidum = Ninukis_Plugin::get_instance();
if (is_callable(array($purge_pressidum, 'purgeAllCaches'))) {
$purge_pressidum->purgeAllCaches();
return sprintf(__('A cache purge request was also sent to %s', 'wp-optimize'), '<strong>Pressidium</strong>');
}
}
// Purge Savvii
if (defined('\Savvii\CacheFlusherPlugin::NAME_DOMAINFLUSH_NOW')) {
$purge_savvii = new \Savvii\CacheFlusherPlugin(); // phpcs:ignore PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound
if (is_callable(array($purge_savvii, 'domainflush'))) {
$purge_savvii->domainflush();
return sprintf(__('A cache purge request was also sent to %s', 'wp-optimize'), '<strong>Savvii</strong>');
}
}
/**
* Action triggered when purging other plugins cache, and nothing was triggered
*/
do_action('wpo_min_after_purge_others');
}
/**
* Purge all public files on uninstallation
* This will break cached pages that ref minified JS/CSS
*
* @return Boolean
*/
public static function purge() {
$log = '';
if (is_dir(WPO_CACHE_MIN_FILES_DIR)) {
if (wpo_delete_files(WPO_CACHE_MIN_FILES_DIR, true)) {
$log = "[Minify] files and folders are deleted recursively";
} else {
$log = "[Minify] recursive files and folders deletion unsuccessful";
}
if (wp_optimize_minify_config()->get('debug')) {
error_log($log);
}
}
return true;
}
/**
* Purge cache files older than 30 days
*
* @return array
*/
public static function purge_old() {
if (!class_exists('WP_Optimize_Minify_Config')) {
include_once WPO_PLUGIN_MAIN_PATH . '/minify/class-wp-optimize-minify-config.php';
}
$cache_time = wp_optimize_minify_config()->get('last-cache-update');
$cache_lifespan = wp_optimize_minify_config()->get('cache_lifespan');
/**
* Minify cache lifespan
*
* @param int The minify cache expiry timestamp
*/
$expires = apply_filters('wp_optimize_minify_cache_expiry_time', time() - 86400 * $cache_lifespan);
$log = array();
// get all directories that are a direct child of current directory
if (is_dir(WPO_CACHE_MIN_FILES_DIR) && is_writable(dirname(WPO_CACHE_MIN_FILES_DIR))) {
if ($handle = opendir(WPO_CACHE_MIN_FILES_DIR)) {
while (false !== ($d = readdir($handle))) {
if (strcmp($d, '.')==0 || strcmp($d, '..')==0) {
continue;
}
$log[] = "cache expiration time - $expires";
$log[] = "checking if cache has expired - $d";
if ($d != $cache_time && (is_numeric($d) && $d <= $expires)) {
$dir = WPO_CACHE_MIN_FILES_DIR.'/'.$d;
if (is_dir($dir)) {
$log[] = "deleting cache in $dir";
if (wpo_delete_files($dir, true)) {
$log[] = "files and folders are deleted recursively - $dir";
} else {
$log[] = "recursive files and folders deletion unsuccessful - $dir";
}
if (file_exists($dir)) {
if (rmdir($dir)) {
$log[] = "folder deleted successfully - $dir";
} else {
$log[] = "folder deletion unsuccessful - $dir";
}
}
}
}
}
closedir($handle);
}
}
if (wp_optimize_minify_config()->get('debug')) {
foreach ($log as $message) {
error_log($message);
}
}
return $log;
}
/**
* Get transients from the disk
*
* @return String|Boolean
*/
public static function get_transient($key) {
$cache_path = self::cache_path();
$tmp_dir = $cache_path['tmpdir'];
$f = $tmp_dir.'/'.$key.'.transient';
clearstatcache();
if (file_exists($f)) {
return file_get_contents($f);
} else {
return false;
}
}
/**
* Set cache on disk
*
* @param String $key
* @param Mixed $code
*
* @return Boolean
*/
public static function set_transient($key, $code) {
if (is_null($code) || empty($code)) {
return false;
}
$cache_path = self::cache_path();
$tmp_dir = $cache_path['tmpdir'];
$f = $tmp_dir.'/'.$key.'.transient';
file_put_contents($f, $code);
self::fix_permission_bits($f);
return true;
}
/**
* Get the cache size and count
*
* @param string $folder
* @return String
*/
public static function get_cachestats($folder) {
clearstatcache();
if (is_dir($folder)) {
$dir = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($folder, FilesystemIterator::SKIP_DOTS));
$size = 0;
$file_count = 0;
foreach ($dir as $file) {
$size += $file->getSize();
$file_count++;
}
return WP_Optimize()->format_size($size) . ' ('.$file_count.' files)';
} else {
return sprintf(__('Error: %s is not a directory!', 'wp-optimize'), $folder);
}
}
/**
* Purge GoDaddy Managed WordPress Hosting (Varnish)
*
* Source: https://github.com/wp-media/wp-rocket/blob/master/inc/3rd-party/hosting/godaddy.php
*
* @param String $method
* @param String|Null $url
*/
public static function godaddy_request($method, $url = null) {
$url = empty($url) ? home_url() : $url;
$host = parse_url($url, PHP_URL_HOST);
$url = set_url_scheme(str_replace($host, WPaas\Plugin::vip(), $url), 'http'); // phpcs:ignore PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound
wp_cache_flush();
update_option('gd_system_last_cache_flush', time()); // purge apc
wp_remote_request(esc_url_raw($url), array('method' => $method, 'blocking' => false, 'headers' => array('Host' => $host)));
}
/**
* List all cache files
*
* @param integer $stamp A timestamp
* @param boolean $use_cache If true, do not use transient value
* @return array
*/
public static function get_cached_files($stamp = 0, $use_cache = true) {
if ($use_cache && $files = get_transient('wpo_minify_get_cached_files')) {
return $files;
}
$cache_path = self::cache_path();
$cache_dir = $cache_path['cachedir'];
$size = self::get_cachestats($cache_dir);
$total_size = self::get_cachestats(WPO_CACHE_MIN_FILES_DIR);
$o = wp_optimize_minify_config()->get();
$cache_time = (0 == $o['last-cache-update']) ? __('Never.', 'wp-optimize') : self::format_date_time($o['last-cache-update']);
$return = array(
'js' => array(),
'css' => array(),
'stamp' => $stamp,
'cachesize' => esc_html($size),
'total_cache_size' => esc_html($total_size),
'cacheTime' => $cache_time,
'cachePath' => $cache_path['cachedir']
);
// Inspect directory with opendir, since glob might not be available in some systems
clearstatcache();
if (is_dir($cache_dir.'/') && $handle = opendir($cache_dir.'/')) {
while (false !== ($file = readdir($handle))) {
$file = $cache_dir.'/'.$file;
$ext = pathinfo($file, PATHINFO_EXTENSION);
if (in_array($ext, array('js', 'css'))) {
$log = false;
if (file_exists($file.'.json')) {
$log = json_decode(file_get_contents($file.'.json'));
}
$min_css = substr($file, 0, -4).'.min.css';
$minjs = substr($file, 0, -3).'.min.js';
$file_name = basename($file);
$file_url = trailingslashit($cache_path['cachedirurl']).$file_name;
if ('css' == $ext && file_exists($min_css)) {
$file_name = basename($min_css);
}
if ('js' == $ext && file_exists($minjs)) {
$file_name = basename($minjs);
}
$file_size = WP_Optimize()->format_size(filesize($file));
$uid = hash('adler32', $file_name);
array_push($return[$ext], array('uid' => $uid, 'filename' => $file_name, 'file_url' => $file_url, 'log' => $log, 'fsize' => $file_size));
}
}
closedir($handle);
}
set_transient('wpo_minify_get_cached_files', $return, DAY_IN_SECONDS);
return $return;
}
/**
* Format a timestamp using WP's date_format and time_format
*
* @param integer $timestamp - The timestamp
* @return string
*/
public static function format_date_time($timestamp) {
return WP_Optimize()->format_date_time($timestamp);
}
/**
* Format the log created when merging assets. Called via array_map
*
* @param array $files The files array, containing the 'log' object or array.
* @return array
*/
public static function format_file_logs($files) {
$files['log'] = WP_Optimize()->include_template(
'minify/cached-file-log.php',
true,
array(
'log' => $files['log']
)
);
return $files;
}
}

View File

@@ -0,0 +1,210 @@
<?php
if (!defined('ABSPATH')) die('No direct access allowed');
if (!class_exists('WP_Optimize_Minify_Config')) require_once(dirname(__FILE__) . '/class-wp-optimize-minify-config.php');
if (!class_exists('WP_Optimize_Minify_Preloader')) require_once(dirname(__FILE__) . '/class-wpo-minify-preloader.php');
/**
* All cache commands that are intended to be available for calling from any sort of control interface (e.g. wp-admin, UpdraftCentral) go in here. All public methods should either return the data to be returned, or a WP_Error with associated error code, message and error data.
*/
class WP_Optimize_Minify_Commands {
/**
* List all cache files
*
* @param array $data - The $_POST data
* @return array
*/
public function get_minify_cached_files($data = array()) {
if (!WPO_MINIFY_PHP_VERSION_MET) return array('error' => __('WP-Optimize Minify requires a higher PHP version', 'wp-optimize'));
$stamp = isset($data['stamp']) ? $data['stamp'] : 0;
$files = WP_Optimize_Minify_Cache_Functions::get_cached_files($stamp, false);
$files['js'] = array_map(array('WP_Optimize_Minify_Cache_Functions', 'format_file_logs'), $files['js']);
$files['css'] = array_map(array('WP_Optimize_Minify_Cache_Functions', 'format_file_logs'), $files['css']);
return $files;
}
/**
* Removes the entire cache dir.
* Use with caution, as cached html may still reference those files.
*
* @return array
*/
public function purge_all_minify_cache() {
if (!WPO_MINIFY_PHP_VERSION_MET) return array('error' => __('WP-Optimize Minify requires a higher PHP version', 'wp-optimize'));
WP_Optimize_Minify_Cache_Functions::purge();
WP_Optimize_Minify_Cache_Functions::cache_increment();
$others = WP_Optimize_Minify_Cache_Functions::purge_others();
$files = $this->get_minify_cached_files();
$message = array(
__('The minification cache was deleted.', 'wp-optimize'),
strip_tags($others, '<strong>'),
);
$message = array_filter($message);
return array(
'success' => true,
'message' => implode("\n", $message),
'files' => $files
);
}
/**
* Forces a new Cache to be built
*
* @return array
*/
public function minify_increment_cache() {
if (!WPO_MINIFY_PHP_VERSION_MET) return array('error' => __('WP-Optimize Minify requires a higher PHP version', 'wp-optimize'));
WP_Optimize_Minify_Cache_Functions::cache_increment();
$files = $this->get_minify_cached_files();
return array(
'success' => true,
'files' => $files
);
}
/**
* Purge the cache
*
* @return array
*/
public function purge_minify_cache() {
if (!WPO_MINIFY_PHP_VERSION_MET) return array('error' => __('WP-Optimize Minify requires a higher PHP version', 'wp-optimize'));
if (!WP_Optimize()->can_purge_the_cache()) return array('error' => __('You do not have permission to purge the cache', 'wp-optimize'));
// deletes temp files and old caches incase CRON isn't working
WP_Optimize_Minify_Cache_Functions::cache_increment();
if (wp_optimize_minify_config()->always_purge_everything()) {
WP_Optimize_Minify_Cache_Functions::purge();
$state = array();
$old = array();
} else {
$state = WP_Optimize_Minify_Cache_Functions::purge_temp_files();
$old = WP_Optimize_Minify_Cache_Functions::purge_old();
}
$others = WP_Optimize_Minify_Cache_Functions::purge_others();
$files = $this->get_minify_cached_files();
$notice = array(
__('All caches from WP-Optimize Minify have been purged.', 'wp-optimize'),
strip_tags($others, '<strong>'),
);
$notice = array_filter($notice);
$notice = json_encode($notice); // encode
return array(
'result' => 'caches cleared',
'others' => $others,
'state' => $state,
'message' => $notice,
'old' => $old,
'files' => $files
);
}
/**
* Save options to the config
*
* @param array $data
* @return array
*/
public function save_minify_settings($data) {
$new_data = array();
foreach ($data as $key => $value) {
if ('true' === $value) {
$new_data[$key] = true;
} elseif ('false' === $value) {
$new_data[$key] = false;
} else {
$new_data[$key] = $value;
}
}
if (isset($data['minify_advanced_tab'])) {
// Make sure that empty settings are still saved
if (!isset($new_data['ignore_list'])) $new_data['ignore_list'] = array();
if (!isset($new_data['blacklist'])) $new_data['blacklist'] = array();
}
/**
* Filters the data before saving it
*
* @param array $new_data - The original data
* @return array The data, altered or not
*/
$new_data = apply_filters('wpo_save_minify_settings', $new_data);
if (!class_exists('WP_Optimize_Minify_Config')) return array(
'success' => false,
'message' => "WP_Optimize_Minify_Config class doesn't exist",
);
$working = wp_optimize_minify_config()->update($new_data);
if (!$working) {
return array(
'success' => false,
'error' => 'failed to save'
);
}
$purged = $this->purge_minify_cache();
return array(
'success' => true,
'files' => $purged['files']
);
}
/**
* Hide the information notice for the current user
*
* @return array
*/
public function hide_minify_notice() {
return array(
'success' => update_user_meta(get_current_user_id(), 'wpo-hide-minify-information-notice', true)
);
}
/**
* Get the current status
*
* @return array
*/
public function get_status() {
$config = wp_optimize_minify_config()->get();
return array(
'enabled' => $config['enabled'],
'js' => $config['enable_js'],
'css' => $config['enable_css'],
'html' => $config['html_minification'],
'stats' => $this->get_minify_cached_files()
);
}
/**
* Run minify preload action.
*
* @return void|array - Doesn't return anything if run() is successfull (Run() prints a JSON object and closed browser connection) or an array if failed.
*/
public function run_minify_preload() {
return WP_Optimize_Minify_Preloader::instance()->run('manual');
}
/**
* Cancel minify preload action.
*
* @return array
*/
public function cancel_minify_preload() {
WP_Optimize_Minify_Preloader::instance()->cancel_preload();
return WP_Optimize_Minify_Preloader::instance()->get_status_info();
}
/**
* Get status of minify preload.
*
* @return array
*/
public function get_minify_preload_status() {
return WP_Optimize_Minify_Preloader::instance()->get_status_info();
}
}

View File

@@ -0,0 +1,197 @@
<?php
if (!defined('ABSPATH')) die('No direct access allowed');
/**
* Handles cache configuration and related I/O
*/
if (!class_exists('WP_Optimize_Minify_Config')) :
class WP_Optimize_Minify_Config {
static protected $_instance = null;
private $_options = array();
/**
* Construct
*
* @return void
*/
private function __construct() {
}
/**
* Getter to see if Minify is enabled
*
* @return bool
*/
public function is_enabled() {
return $this->get('enabled');
}
/**
* Removes all Minify settings from the Database if 'preserve_settings_on_uninstall' is false
*
* @return void
*/
public function purge() {
if (!$this->get('preserve_settings_on_uninstall')) {
if (is_multisite()) {
delete_site_option('wpo_minify_config');
} else {
delete_option('wpo_minify_config');
}
}
}
/**
* Get config from file or cache
*
* @param string $option - An option name
* @param mixed $default - A default for the option
* @return array|string
*/
public function get($option = null, $default = false) {
if (empty($this->_options)) {
if (is_multisite()) {
$config = get_site_option('wpo_minify_config', array());
} else {
$config = get_option('wpo_minify_config', array());
}
$this->_options = wp_parse_args($config, $this->get_defaults());
}
if ($option && isset($this->_options[$option])) {
return $this->_options[$option];
} elseif ($option) {
return $default;
}
return $this->_options;
}
/**
* Update the config
*
* @param array $config - The new configuration array
* @return boolean
*/
public function update($config) {
$prev_settings = $this->get();
$prev_settings = wp_parse_args($prev_settings, $this->get_defaults());
$new_settings = wp_parse_args($config, $prev_settings);
$this->_options = $new_settings;
if (is_multisite()) {
update_site_option('wpo_minify_config', $new_settings);
} else {
update_option('wpo_minify_config', $new_settings);
}
return true;
}
/**
* Return defaults
*
* @return array
*/
public function get_defaults() {
$defaults = array(
// dev tab checkboxes
'debug' => false,
'enabled_css_preload' => false,
'enabled_js_preload' => false,
'hpreconnect' => '',
'hpreload' => '',
'loadcss' => false,
'remove_css' => false,
'critical_path_css' => '',
'critical_path_css_is_front_page' => '',
// settings tab checkboxes
'preserve_settings_on_uninstall' => true,
'disable_when_logged_in' => false,
'default_protocol' => 'dynamic', // dynamic, http, https
'html_minification' => true,
'clean_header_one' => false,
'emoji_removal' => true,
'merge_google_fonts' => true,
'enable_display_swap' => true,
'remove_googlefonts' => false,
'gfonts_method' => 'inherit', // inline, async, exclude
'fawesome_method' => 'inherit', // inline, async, exclude
'enable_css' => true,
'enable_css_minification' => true,
'enable_merging_of_css' => true,
'remove_print_mediatypes' => false,
'inline_css' => false,
'enable_js' => true,
'enable_js_minification' => true,
'enable_merging_of_js' => true,
'enable_defer_js' => 'individual',
'defer_js_type' => 'defer',
'defer_jquery' => true,
'enable_js_trycatch' => false,
'exclude_defer_login' => true,
'cdn_url' => '',
'cdn_force' => false,
'async_css' => '',
'async_js' => '',
'disable_css_inline_merge' => true,
'ualist' => array('x11.*fox\/54', 'oid\s4.*xus.*ome\/62', 'x11.*ome\/62', 'oobot', 'ighth', 'tmetr', 'eadles', 'ingdo'),
'blacklist' => array(),
'ignore_list' => array(),
'exclude_js' => '',
'exclude_css' => '',
'edit_default_exclutions' => false,
'merge_allowed_urls' => '',
// internal
'enabled' => false,
'last-cache-update' => 0,
'plugin_version' => '0.0.0',
'cache_lifespan' => 30,
'merge_inline_extra_css_js' => true,
);
return apply_filters('wpo_minify_defaults', $defaults);
}
/**
* Check whether everything should be purged instead of just incremented
*
* @return boolean
*/
public function always_purge_everything() {
/**
* Filters the result of always_purge_everything
*
* @return boolean
*/
return apply_filters('wpo_minify_always_purge_everything', 0 === intval($this->get('cache_lifespan')) || (defined('WPO_ADVANCED_CACHE') && defined('WP_CACHE') && WP_CACHE));
}
/**
* Get the instance
*
* @return WP_Optimize_Minify_Config
*/
public static function get_instance() {
if (!self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
}
/**
* Get WPO Minify instance
*
* @return WP_Optimize_Minify_Config
*/
function wp_optimize_minify_config() {
return WP_Optimize_Minify_Config::get_instance();
}
endif;

View File

@@ -0,0 +1,298 @@
<?php
if (!defined('ABSPATH')) die('No direct access allowed');
class WP_Optimize_Minify_Fonts {
private static $fonts = array();
private static $subsets = array();
/**
* Get a list of Google fonts
*
* @return Array
*/
public static function get_google_fonts() {
// https://www.googleapis.com/webfonts/v1/webfonts?sort=alpha
$google_fonts_file = WPO_PLUGIN_MAIN_PATH.'google-fonts.json';
if (is_file($google_fonts_file) && is_readable($google_fonts_file)) {
return json_decode(file_get_contents($google_fonts_file), true);
}
return array();
}
/**
* Check if the google font exist or not
*
* @param string $font
* @return boolean
*/
public static function concatenate_google_fonts_allowed($font) {
$gfonts_whitelist = self::get_google_fonts();
// normalize
$font = str_ireplace('+', ' ', strtolower($font));
return in_array($font, $gfonts_whitelist);
}
/**
* Concatenates Google Fonts tags (http://fonts.googleapis.com/css?...)
*
* @param array $gfonts_array
* @return string|boolean
*/
public static function concatenate_google_fonts($gfonts_array) {
// Loop through fonts array
foreach ($gfonts_array as $font) {
self::parse_font_url($font);
}
self::convert_v1_font_specs_to_v2();
$merge = self::build();
$config = wp_optimize_minify_config();
/**
* Filters wether to add display=swap to Google fonts urls
*
* @param boolean $display - Default to true
*/
if (apply_filters('wpo_minify_gfont_display_swap', $config->get('enable_display_swap'))) {
/**
* Filters the value of the display parameter.
*
* @param string $display_value - Default to 'swap'. https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display
*/
$merge.= '&display='.apply_filters('wpo_minify_gfont_display_type', 'swap');
}
if (!empty($merge)) return 'https://fonts.googleapis.com/css2?' . $merge;
return false;
}
/**
* Parses font url based on whether it is API version 1 or 2
*/
private static function parse_font_url($font) {
if (false !== strpos($font, 'css?')) {
self::parse_font_api1_url($font);
} else {
self::parse_font_api2_url($font);
}
}
/**
* Parses google font api version 1 url
*/
private static function parse_font_api1_url($font) {
parse_str(parse_url(rtrim($font, '|'), PHP_URL_QUERY), $font_elements);
// Process each font family
foreach (explode('|', $font_elements['family']) as $font_family) {
// Separate font and sizes
$font_family = explode(':', $font_family);
// if the family wasn't added yet
if (!in_array($font_family[0], array_keys(self::$fonts))) {
self::$fonts[$font_family[0]]['specs'] = isset($font_family[1]) ? explode(',', rtrim($font_family[1], ',')) : array();
} else {
// if the family was already added, and this new one has weights, merge with previous
if (isset($font_family[1])) {
if (isset(self::$fonts[$font_family[0]]['version']) && 'V2' == self::$fonts[$font_family[0]]['version']) {
self::$fonts[$font_family[0]]['specs'] = explode(',', rtrim($font_family[1], ','));
} else {
self::$fonts[$font_family[0]]['specs'] = array_merge(self::$fonts[$font_family[0]]['specs'], explode(',', rtrim($font_family[1], ',')));
}
}
}
self::$fonts[$font_family[0]]['version'] = 'V1';
}
// Add subsets
if (isset($font_elements['subset'])) {
self::$subsets = array_merge(self::$subsets, explode(',', $font_elements['subset']));
}
}
/**
* Parses google font api version 2 url
*/
private static function parse_font_api2_url($font) {
$parsed_url = parse_url($font, PHP_URL_QUERY);
$query_elements = explode('&', $parsed_url);
foreach ($query_elements as $element) {
$family_str = str_replace('family=', '', $element);
$family = explode(':', $family_str);
if (!empty($family)) {
$font_name = $family[0];
$font_elements = isset($family[1]) ? explode('@', $family[1]) : '';
if (!empty($font_elements) && !empty($font_elements[0]) && !empty($font_elements[1])) {
$font_styles = $font_elements[0];
$font_units = explode(',', $font_elements[1]);
}
} else {
$font_name = $family_str;
continue;
}
if (!isset(self::$fonts[$font_name])) {
self::$fonts[$font_name]['specs'] = array(
'wght' => array(),
'ital' => array(),
'ital,wght' => array(),
);
}
if (!isset(self::$fonts[$font_name]['version'])) {
self::$fonts[$font_name]['version'] = 'V2';
}
if (isset($font_styles) && isset($font_units) && isset($font_elements[1])) {
$font_units = explode(';', $font_elements[1]);
switch ($font_styles) {
case 'wght':
foreach ($font_units as $font_unit) {
if (!in_array($font_unit, self::$fonts[$font_name]['specs']['wght'])) {
array_push(self::$fonts[$font_name]['specs']['wght'], $font_unit);
}
}
break;
case 'ital':
foreach ($font_units as $font_unit) {
if (!in_array($font_unit, self::$fonts[$font_name]['specs']['ital'])) {
array_push(self::$fonts[$font_name]['specs']['ital'], $font_unit);
}
}
break;
case 'ital,wght':
foreach ($font_units as $font_unit) {
if (!in_array($font_unit, self::$fonts[$font_name]['specs']['ital,wght'])) {
array_push(self::$fonts[$font_name]['specs']['ital,wght'], $font_unit);
}
}
break;
}
}
}
}
/**
* Converts google font api version 1 font specification into API V2
*/
private static function convert_v1_font_specs_to_v2() {
foreach (self::$fonts as $font_name => $font_details) {
if ('V2' == $font_details['version']) continue;
if (0 == count($font_details['specs'])) {
self::$fonts[$font_name]['specs'] = array(
'wght' => array(),
'ital' => array(),
'ital,wght' => array(),
);
} else {
foreach ($font_details['specs'] as $key => $detail) {
if (is_array($detail)) $detail = implode('', $detail);
switch ($detail) {
case 'i':
unset(self::$fonts[$font_name]['specs'][$key]);
self::$fonts[$font_name]['specs']['ital'] = array(1);
break;
case 'b':
unset(self::$fonts[$font_name]['specs'][$key]);
self::$fonts[$font_name]['specs']['wght'] = array();
break;
case 'bi':
unset(self::$fonts[$font_name]['specs'][$key]);
self::$fonts[$font_name]['specs']['ital'] = array('0;1');
break;
default:
unset(self::$fonts[$font_name]['specs'][$key]);
if (!isset(self::$fonts[$font_name]['specs']['ital,wght'])) {
self::$fonts[$font_name]['specs']['ital,wght'] = array();
}
if (false !== strpos($detail, 'i')) {
$detail = str_replace(array('italic', 'i'), '', $detail);
$detail = '' === $detail ? 400 : $detail;
array_push(self::$fonts[$font_name]['specs']['ital,wght'], '1,' . $detail);
} else {
$detail = 'regular' === $detail ? 400 : $detail;
array_push(self::$fonts[$font_name]['specs']['ital,wght'], '0,' . $detail);
}
break;
}
}
}
}
}
/**
* Build valid Google font api 2 url string
*
* @return string $result Url string
*/
private static function build() {
$result = '';
foreach (self::$fonts as $font_name => $font_details) {
if ('display=swap' == $font_name) continue;
if ('' != $result) {
$result .= '&';
}
$result .= 'family=' . str_replace(' ', '+', $font_name);
$result .= self::specs_to_string($font_details['specs']);
}
return $result;
}
/**
* Converts font specifications into a valid google font api2 url string
*
* @param array $font_specs Font style and weight specifications
*
* @return string
*/
private static function specs_to_string($font_specs) {
$result = array();
$weights = isset($font_specs['wght']) && count($font_specs['wght']);
$italic_weights = isset($font_specs['ital']) && count($font_specs['ital']);
$all_weights = isset($font_specs['ital,wght']) && count($font_specs['ital,wght']);
// Nothing is set, return
if (!$weights && !$italic_weights && !$all_weights) {
return '';
}
// Italic only
if ($italic_weights && !$weights && !$all_weights) {
if ('1' == $font_specs['ital'][0]) {
return ':ital@1';
} elseif ('0;1' == $font_specs['ital'][0]) {
return ':ital@0;1';
}
}
foreach ($font_specs as $style => $units) {
switch ($style) {
case 'wght':
foreach ($units as $unit) {
$multiple_units = explode(',', $unit);
if (count($multiple_units) > 0) {
foreach ($multiple_units as $single_unit) {
array_push($result, '0,' . $single_unit);
}
} else {
array_push($result, '0,' . $unit);
}
}
break;
case 'ital':
foreach ($units as $unit) {
array_push($result, 1 == $unit ? '1,400' : $unit);
}
break;
case 'ital,wght':
foreach ($units as $unit) {
array_push($result, $unit);
}
break;
}
}
sort($result);
return ':ital,wght@' . implode(';', array_unique($result));
}
}

View File

@@ -0,0 +1,170 @@
<?php
if (!defined('ABSPATH')) die('No direct access allowed');
if (!class_exists('WP_Optimize_Minify_Functions')) {
include WP_OPTIMIZE_MINIFY_DIR.'/class-wp-optimize-minify-functions.php';
}
class WP_Optimize_Minify_Print {
/**
* Load the script using loadAsync JavaScript
*
* @param string $href
* @param boolean $print
* @return string|void
*/
public static function async_script($href, $print = true) {
$wpo_minify_options = wp_optimize_minify_config()->get();
$tag = '<script>if (!navigator.userAgent.match(/'.implode('|', $wpo_minify_options['ualist']).'/i)){' . "\n";
$tag .= " loadAsync('$href', null);" . "\n";
$tag .= '}</script>' . "\n";
if ($print) {
echo $tag;
} else {
return $tag;
}
}
/**
* Print a style that will be loaded async using 'preload'
*
* @param string $href
* @param string $media
* @return void
*/
public static function async_style($href, $media = 'all') {
echo '<link rel="preload" href="'.$href.'" as="style" media="'.$media.'" onload="this.onload=null;this.rel=\'stylesheet\'" />' . "\n";
// fix for firefox not supporting preload
echo '<link rel="stylesheet" href="'.$href.'" media="'.$media.'" />' . "\n";
echo '<noscript><link rel="stylesheet" href="'.$href.'" media="'.$media.'" /></noscript>' . "\n";
echo '<!--[if IE]><link rel="stylesheet" href="'.$href.'" media="'.$media.'" /><![endif]-->' . "\n";
}
/**
* Print a style that will be loaded by JS
*
* @param string $href
* @return void
*/
public static function exclude_style($href) {
$wpo_minify_options = wp_optimize_minify_config()->get();
// make a stylesheet, hide from PageSpeedIndex
$cssguid = 'wpo_min'.hash('adler32', $href);
echo '<script>if (!navigator.userAgent.match(/'.implode('|', $wpo_minify_options['ualist']).'/i)){' . "\n";
echo ' var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$href.'",'.$cssguid.'.onload=function() {'.$cssguid.'.media="all"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');' . "\n";
echo '}</script>' . "\n";
}
/**
* Inline a single style
*
* @param string $handle
* @param string $href
* @return boolean
*/
public static function inline_style($handle, $href) {
$wpo_minify_options = wp_optimize_minify_config()->get();
// font awesome processing, inline
// download, minify, cache
$tkey = 'css-'.hash('adler32', $href).'.css';
$json = WP_Optimize_Minify_Cache_Functions::get_transient($tkey);
if (false === $json) {
$json = WP_Optimize_Minify_Functions::download_and_minify($href, null, $wpo_minify_options['enable_css_minification'], 'css', $handle);
if ($wpo_minify_options['debug']) {
echo "<!-- wpo_min DEBUG: Uncached file processing now for $href -->" . "\n";
}
WP_Optimize_Minify_Cache_Functions::set_transient($tkey, $json);
}
// decode
$res = json_decode($json, true);
// add font-display
// https://developers.google.com/web/updates/2016/02/font-display
$res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
// inline css or fail
if (false != $res['status']) {
echo '<style type="text/css" media="all">' . "\n";
echo $res['code'] . "\n";
echo '</style>' . "\n";
return true;
} else {
return false;
}
}
/**
* Print a normal style tag pointing the href
*
* @param string $href
* @return void
*/
public static function style($href) {
echo '<link rel="stylesheet" href="'.$href.'" media="all">' . "\n";
}
/**
* Write header
*
* @param string $file
* @param string $headers
* @return void
*/
public static function write_header($file, $headers) {
file_put_contents($file, $headers);
WP_Optimize_Minify_Cache_Functions::fix_permission_bits($file);
}
/**
* Write CSS
*
* @param string $file
* @param string $code
* @param string $log
* @return void
*/
public static function write_combined_asset($file, $code, $log) {
file_put_contents($file.'.json', json_encode($log));
file_put_contents($file, $code);
// permissions
WP_Optimize_Minify_Cache_Functions::fix_permission_bits($file.'.json');
WP_Optimize_Minify_Cache_Functions::fix_permission_bits($file);
if (function_exists('gzencode')) {
file_put_contents($file.'.gz', gzencode(file_get_contents($file), 9));
WP_Optimize_Minify_Cache_Functions::fix_permission_bits($file.'.gz');
}
// brotli static support
if (function_exists('brotli_compress')) {
file_put_contents($file.'.br', brotli_compress(file_get_contents($file), 11));
WP_Optimize_Minify_Cache_Functions::fix_permission_bits($file.'.br');
}
}
/**
* Load async scripts with callback
*
* @return void
*/
public static function add_load_async() {
$min_or_not_internal = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '-'. str_replace('.', '-', WPO_VERSION). '.min';
$contents = file_get_contents(trailingslashit(WPO_PLUGIN_MAIN_PATH) . "js/loadAsync$min_or_not_internal.js");
echo "<script>$contents</script>\n";
}
/**
* Defer CSS globally from the header (order matters)
* Dev: https://www.filamentgroup.com/lab/async-css.html
*
* @return void
*/
public static function add_load_css() {
$min_or_not_internal = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '-'. str_replace('.', '-', WPO_VERSION). '.min';
$contents = file_get_contents(trailingslashit(WPO_PLUGIN_MAIN_PATH) . "js/loadCSS$min_or_not_internal.js");
echo "<script>$contents</script>" . "\n";
}
}

View File

@@ -0,0 +1,259 @@
<?php
if (!defined('ABSPATH')) die('No direct access allowed');
define('WP_OPTIMIZE_MINIFY_VERSION', '2.6.5');
define('WP_OPTIMIZE_MINIFY_DIR', dirname(__FILE__));
if (!defined('WP_OPTIMIZE_SHOW_MINIFY_ADVANCED')) define('WP_OPTIMIZE_SHOW_MINIFY_ADVANCED', false);
class WP_Optimize_Minify {
/**
* Constructor - Initialize actions and filters
*
* @return void
*/
public function __construct() {
if (!class_exists('WP_Optimize_Minify_Commands')) include_once(WPO_PLUGIN_MAIN_PATH . 'minify/class-wp-optimize-minify-commands.php');
$this->minify_commands = new WP_Optimize_Minify_Commands();
if (!class_exists('WP_Optimize_Minify_Config')) {
include WP_OPTIMIZE_MINIFY_DIR.'/class-wp-optimize-minify-config.php';
}
$this->enabled = wp_optimize_minify_config()->is_enabled();
$this->load_admin();
// Don't run the rest if PHP requirement isn't met
if (!WPO_MINIFY_PHP_VERSION_MET) return;
add_filter('wpo_cache_admin_bar_menu_items', array($this, 'admin_bar_menu'), 30, 1);
if (WP_Optimize::is_premium()) {
$this->load_premium();
}
/**
* Directory that stores the cache, including gzipped files and mobile specifc cache
*/
if (!defined('WPO_CACHE_MIN_FILES_DIR')) define('WPO_CACHE_MIN_FILES_DIR', untrailingslashit(WP_CONTENT_DIR).'/cache/wpo-minify');
if (!defined('WPO_CACHE_MIN_FILES_URL')) define('WPO_CACHE_MIN_FILES_URL', untrailingslashit(WP_CONTENT_URL).'/cache/wpo-minify');
if (!class_exists('WP_Optimize_Minify_Cache_Functions')) {
include WP_OPTIMIZE_MINIFY_DIR.'/class-wp-optimize-minify-cache-functions.php';
}
$this->load_frontend();
// cron job to delete old wpo_min cache
add_action('wpo_minify_purge_old_cache', array('WP_Optimize_Minify_Cache_Functions', 'purge_old'));
// front-end actions; skip on certain post_types or if there are specific keys on the url or if editor or admin
// Handle minify cache purging.
add_action('wp_loaded', array($this, 'handle_purge_minify_cache'));
}
/**
* Admin toolbar processing
*
* @param array $menu_items
* @return array
*/
public function admin_bar_menu($menu_items) {
$wpo_minify_options = wp_optimize_minify_config()->get();
if (!$wpo_minify_options['enabled'] || !current_user_can('manage_options') || !($wpo_minify_options['enable_css'] || $wpo_minify_options['enable_js'])) return $menu_items;
$act_url = remove_query_arg('wpo_minify_cache_purged');
$cache_path = WP_Optimize_Minify_Cache_Functions::cache_path();
$cache_size_info = '<h4>'.__('Minify cache', 'wp-optimize').'</h4><span><span class="label">'.__('Cache size:', 'wp-optimize').'</span> <span class="stats">'.esc_html(WP_Optimize_Minify_Cache_Functions::get_cachestats($cache_path['cachedir'])).'</span></span>';
$menu_items[] = array(
'id' => 'wpo_minify_cache_stats',
'title' => $cache_size_info,
'meta' => array(
'class' => 'wpo-cache-stats',
),
'parent' => 'wpo_purge_cache',
);
$menu_items[] = array(
'parent' => 'wpo_purge_cache',
'id' => 'purge_minify_cache',
'title' => __('Purge minify cache', 'wp-optimize'),
'href' => add_query_arg('_wpo_purge_minify_cache', wp_create_nonce('wpo_purge_minify_cache'), $act_url),
);
return $menu_items;
}
/**
* Check if purge single page action sent and purge cache.
*/
public function handle_purge_minify_cache() {
$wpo_minify_options = wp_optimize_minify_config()->get();
if (!$wpo_minify_options['enabled'] || !current_user_can('manage_options')) return;
if (isset($_GET['wpo_minify_cache_purged'])) {
if (is_admin()) {
add_action('admin_notices', array($this, 'notice_purge_minify_cache_success'));
return;
} else {
$message = __('Minify cache purged', 'wp-optmize');
printf('<script>alert("%s");</script>', $message);
return;
}
}
if (!isset($_GET['_wpo_purge_minify_cache'])) return;
if (wp_verify_nonce($_GET['_wpo_purge_minify_cache'], 'wpo_purge_minify_cache')) {
$success = false;
// Purge minify
$results = $this->minify_commands->purge_minify_cache();
if ("caches cleared" == $results['result']) $success = true;
// remove nonce from url and reload page.
wp_redirect(add_query_arg('wpo_minify_cache_purged', $success, remove_query_arg('_wpo_purge_minify_cache')));
exit;
}
}
/**
* Load the admin class
*
* @return void
*/
private function load_admin() {
if (!is_admin()) return;
if (!class_exists('WP_Optimize_Minify_Admin')) {
include WP_OPTIMIZE_MINIFY_DIR.'/class-wp-optimize-minify-admin.php';
}
new WP_Optimize_Minify_Admin();
}
/**
* Load the frontend class
*
* @return void
*/
private function load_frontend() {
if ($this->enabled) {
if (!class_exists('WP_Optimize_Minify_Front_End')) {
include WP_OPTIMIZE_MINIFY_DIR.'/class-wp-optimize-minify-front-end.php';
}
new WP_Optimize_Minify_Front_End();
}
}
/**
* Load the premium class
*
* @return void
*/
private function load_premium() {
if (!class_exists('WP_Optimize_Minify_Premium')) {
include WP_OPTIMIZE_MINIFY_DIR.'/class-wp-optimize-minify-premium.php';
}
$this->premium = new WP_Optimize_Minify_Premium();
}
/**
* Run during activation
* Increment cache first as it will save files to that dir
*
* @return void
*/
public function plugin_activate() {
// increment cache time
if (class_exists('WP_Optimize_Minify_Cache_Functions')) {
WP_Optimize_Minify_Cache_Functions::cache_increment();
}
// old cache purge event cron
wp_clear_scheduled_hook('wpo_minify_purge_old_cache');
if (!wp_next_scheduled('wpo_minify_purge_old_cache')) {
wp_schedule_event(time() + 86400, 'daily', 'wpo_minify_purge_old_cache');
}
}
/**
* Run during plugin deactivation
*
* @return void
*/
public function plugin_deactivate() {
if (defined('WPO_MINIFY_PHP_VERSION_MET') && !WPO_MINIFY_PHP_VERSION_MET) return;
if (class_exists('WP_Optimize_Minify_Cache_Functions')) {
WP_Optimize_Minify_Cache_Functions::purge_temp_files();
WP_Optimize_Minify_Cache_Functions::purge_old();
WP_Optimize_Minify_Cache_Functions::purge_others();
}
// old cache purge event cron
wp_clear_scheduled_hook('wpo_minify_purge_old_cache');
}
/**
* Run during plugin uninstall
*
* @return void
*/
public function plugin_uninstall() {
if (defined('WPO_MINIFY_PHP_VERSION_MET') && !WPO_MINIFY_PHP_VERSION_MET) return;
// remove options from DB
if (!function_exists('wp_optimize_minify_config')) {
include WP_OPTIMIZE_MINIFY_DIR.'/class-wp-optimize-minify-config.php';
}
wp_optimize_minify_config()->purge();
// remove minified files
if (class_exists('WP_Optimize_Minify_Cache_Functions')) {
WP_Optimize_Minify_Cache_Functions::purge();
WP_Optimize_Minify_Cache_Functions::purge_others();
}
}
/**
* Shows success notice for purge minify cache
*/
public function notice_purge_minify_cache_success() {
$this->show_notice(__('The minify cache was successfully purged.', 'wp-optimize'), 'success');
}
/**
* Show notification in WordPress admin.
*
* @param string $message HTML (no further escaping is performed)
* @param string $type error, warning, success, or info
*/
public function show_notice($message, $type) {
global $current_screen;
if ($current_screen && is_callable(array($current_screen, 'is_block_editor')) && $current_screen->is_block_editor()) :
?>
<script>
window.addEventListener('load', function() {
(function(wp) {
if (window.wp && wp.hasOwnProperty('data') && 'function' == typeof wp.data.dispatch) {
wp.data.dispatch('core/notices').createNotice(
'<?php echo $type; ?>',
'<?php echo $message; ?>',
{
isDismissible: true,
}
);
}
})(window.wp);
});
</script>
<?php else : ?>
<div class="notice wpo-notice notice-<?php echo $type; ?> is-dismissible">
<p><?php echo $message; ?></p>
</div>
<?php
endif;
}
}

View File

@@ -0,0 +1,56 @@
<?php
if (!defined('ABSPATH')) die('Access denied.');
if (!class_exists('Updraft_Task_1_2')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task.php');
if (!class_exists('WP_Optimize_Minify_Preloader')) require_once(dirname(__FILE__) . '/class-wpo-minify-preloader.php');
class WP_Optimize_Minify_Load_Url_Task extends Updraft_Task_1_2 {
/**
* Default options.
*/
public function get_default_options() {
return array();
}
/**
* Run preload http requests with different user-agent values to cache pages for different devices.
*
* @return bool
*/
public function run() {
$url = $this->get_option('url');
if (empty($url)) return;
$minify_preloader = WP_Optimize_Minify_Preloader::instance();
// load pages with different user-agents values.
$minify_preloader->preload_desktop($url);
$minify_preloader->preload_amp($url);
if (defined('WP_CLI') && WP_CLI) {
WP_CLI::log($url);
}
/**
* Action triggered after preloading a single url
*
* @param string $url The url to preload
* @param object $minify_preloader Minify preloader instance
*/
do_action('wpoptimize_after_minify_preload_url', $url, $minify_preloader);
/**
* Allows to change the delay between each URL preload, to reduce server load.
*
* @param integer $preload_delay The delay between each request in microseconds (1000000 = 1 second).
*/
usleep(apply_filters('wpoptimize_minify_preload_delay', 500000));
return true;
}
}

View File

@@ -0,0 +1,166 @@
<?php
if (!defined('ABSPATH')) die('No direct access allowed');
if (!class_exists('WP_Optimize_Minify_Load_Url_Task')) require_once(dirname(__FILE__) . '/class-wpo-minify-load-url-task.php');
if (!class_exists('WP_Optimize_Preloader')) require_once(WPO_PLUGIN_MAIN_PATH . 'includes/class-wpo-preloader.php');
class WP_Optimize_Minify_Preloader extends WP_Optimize_Preloader {
protected $preload_type = 'minify';
protected $task_type = 'minify-load-url-task';
static protected $_instance = null;
/**
* WP_Optimize_Page_Cache_Preloader constructor.
*/
public function __construct() {
parent::__construct();
add_filter('cron_schedules', array($this, 'cron_add_intervals'));
}
/**
* Check if minify is active.
*
* @return bool
*/
public function is_option_active() {
if (!function_exists('wp_optimize_minify_config')) {
include_once WPO_PLUGIN_MAIN_PATH . '/minify/class-wp-optimize-minify-config.php';
}
return wp_optimize_minify_config()->get('enabled');
}
/**
* Add intervals to cron schedules.
*
* @param array $schedules
*
* @return array
*/
public function cron_add_intervals($schedules) {
$interval = $this->get_continue_preload_cron_interval();
$schedules['wpo_minify_preload_continue_interval'] = array(
'interval' => $interval,
'display' => round($interval / 60, 1).' minutes'
);
return $schedules;
}
/**
* Create tasks (WP_Optimize_Load_Url_Task) for preload all urls from site.
*
* @param string $type The preload type (currently: scheduled, manual)
* @return void
*/
public function create_tasks_for_preload_site_urls($type = 'manual') {
$urls = $this->get_site_urls();
if (!empty($urls)) {
$this->log(__('Minify: Creating tasks for preload site urls.', 'wp-optimize'));
foreach ($urls as $url) {
if (wpo_url_in_exceptions($url)) continue;
// this description is being used for internal purposes.
$description = 'Preload - '.$url;
$options = array('url' => $url, 'preload_type' => $type, 'anonymous_user_allowed' => (defined('DOING_CRON') && DOING_CRON) || (defined('WP_CLI') && WP_CLI));
WP_Optimize_Minify_Load_Url_Task::create_task($this->task_type, $description, $options, 'WP_Optimize_Minify_Load_Url_Task');
}
$this->log(__('Minify: Tasks for preload site urls created.', 'wp-optimize'));
}
}
/**
* Instance of WP_Optimize_Minify_Preloader.
*
* @return WP_Optimize_Minify_Preloader
*/
public static function instance() {
if (empty(self::$_instance)) {
self::$_instance = new WP_Optimize_Minify_Preloader();
}
return self::$_instance;
}
/**
* Option disabled error message
*
* @return array
*/
protected function get_option_disabled_error() {
return array(
'success' => false,
'error' => __('Minify is disabled.', 'wp-optimize')
);
}
/**
* Get preload already running error message
*
* @return array
*/
protected function get_preload_already_running_error() {
return array(
'success' => false,
'error' => __('Probably minify preload is running already.', 'wp-optimize')
);
}
protected function get_preload_data() {
$cache_path = WP_Optimize_Minify_Cache_Functions::cache_path();
$cache_dir = $cache_path['cachedir'];
$minify_cache_data = array();
$minify_cache_data['size'] = esc_html(WP_Optimize_Minify_Cache_Functions::get_cachestats($cache_dir));
$minify_cache_data['total_size'] = esc_html(WP_Optimize_Minify_Cache_Functions::get_cachestats(WPO_CACHE_MIN_FILES_DIR));
return $minify_cache_data;
}
protected function get_preloading_message($minify_cache_data) {
return array(
'done' => false,
'message' => __('Loading URLs...', 'wp-optimize'),
'size' => WP_Optimize()->format_size($minify_cache_data['size']),
'total_size' => $minify_cache_data['total_size']
);
}
protected function get_last_preload_message($minify_cache_data, $last_preload_time_str) {
return array(
'done' => true,
'message' => sprintf(__('Last preload finished at %s', 'wp-optimize'), $last_preload_time_str),
'size' => WP_Optimize()->format_size($minify_cache_data['size']),
'total_size' => $minify_cache_data['total_size']
);
}
protected function get_preload_success_message($minify_cache_data) {
return array(
'done' => true,
'size' => WP_Optimize()->format_size($minify_cache_data['size']),
'total_size' => $minify_cache_data['total_size']
);
}
protected function get_preload_progress_message($minify_cache_data, $preloaded_message, $preload_resuming_in) {
return array(
'done' => false,
'message' => $preloaded_message,
'size' => WP_Optimize()->format_size($minify_cache_data['size']),
'total_size' => $minify_cache_data['total_size'],
'resume_in' => $preload_resuming_in
);
}
}
WP_Optimize_Minify_Preloader::instance();