Version Description
- Sep 2 2020 =
-
CCSS Fixed an issue where dynamically generated CSS failed with
TypeError: Cannot read property type of undefined
. - Page Optimize Fixed CSS optimization compatibility for CSS dynamically generated with PHP.
- Page Optimize Added the ability to defer JS even when the resource is excluded from other JS optimizations. (@slr1979)
- ESI Added support for ESI last paramater inline value.
- 3rd YITH Wishlist, when cached for the first time, will no longer send sub requests.
Download this release
Release Info
Developer | LiteSpeedTech |
Plugin | LiteSpeed Cache |
Version | 3.4.1 |
Comparing to | |
See all releases |
Code changes from version 3.4 to 3.4.1
- litespeed-cache.php +2 -2
- readme.txt +8 -1
- src/admin.cls.php +30 -35
- src/avatar.cls.php +93 -107
- src/cdn.cls.php +1 -2
- src/css.cls.php +2 -1
- src/esi.cls.php +21 -13
- src/htaccess.cls.php +285 -312
- src/media.cls.php +231 -254
- src/object.lib.php +145 -175
- src/optimize.cls.php +10 -1
- src/optimizer.cls.php +30 -6
- src/tag.cls.php +77 -91
- src/tool.cls.php +51 -59
- src/vary.cls.php +118 -137
- thirdparty/yith-wishlist.cls.php +54 -40
litespeed-cache.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: LiteSpeed Cache
|
4 |
* Plugin URI: https://www.litespeedtech.com/products/cache-plugins/wordpress-acceleration
|
5 |
* Description: High-performance page caching and site optimization from LiteSpeed
|
6 |
-
* Version: 3.4
|
7 |
* Author: LiteSpeed Technologies
|
8 |
* Author URI: https://www.litespeedtech.com
|
9 |
* License: GPLv3
|
@@ -33,7 +33,7 @@ if ( class_exists( 'LiteSpeed\Core' ) || defined( 'LSCWP_DIR' ) ) {
|
|
33 |
return;
|
34 |
}
|
35 |
|
36 |
-
! defined( 'LSCWP_V' ) && define( 'LSCWP_V', '3.4' );
|
37 |
|
38 |
! defined( 'LSCWP_CONTENT_DIR' ) && define( 'LSCWP_CONTENT_DIR', WP_CONTENT_DIR ) ;
|
39 |
! defined( 'LSCWP_DIR' ) && define( 'LSCWP_DIR', __DIR__ . '/' ) ;// Full absolute path '/var/www/html/***/wp-content/plugins/litespeed-cache/' or MU
|
3 |
* Plugin Name: LiteSpeed Cache
|
4 |
* Plugin URI: https://www.litespeedtech.com/products/cache-plugins/wordpress-acceleration
|
5 |
* Description: High-performance page caching and site optimization from LiteSpeed
|
6 |
+
* Version: 3.4.1
|
7 |
* Author: LiteSpeed Technologies
|
8 |
* Author URI: https://www.litespeedtech.com
|
9 |
* License: GPLv3
|
33 |
return;
|
34 |
}
|
35 |
|
36 |
+
! defined( 'LSCWP_V' ) && define( 'LSCWP_V', '3.4.1' );
|
37 |
|
38 |
! defined( 'LSCWP_CONTENT_DIR' ) && define( 'LSCWP_CONTENT_DIR', WP_CONTENT_DIR ) ;
|
39 |
! defined( 'LSCWP_DIR' ) && define( 'LSCWP_DIR', __DIR__ . '/' ) ;// Full absolute path '/var/www/html/***/wp-content/plugins/litespeed-cache/' or MU
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: LiteSpeedTech
|
|
3 |
Tags: caching, optimize, performance, pagespeed, seo, speed, image optimize, compress, object cache, redis, memcached, database cleaner
|
4 |
Requires at least: 4.0
|
5 |
Tested up to: 5.5
|
6 |
-
Stable tag: 3.4
|
7 |
License: GPLv3
|
8 |
License URI: http://www.gnu.org/licenses/gpl.html
|
9 |
|
@@ -245,6 +245,13 @@ The vast majority of plugins and themes are compatible with LiteSpeed Cache. The
|
|
245 |
|
246 |
== Changelog ==
|
247 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
= 3.4 - Aug 26 2020 =
|
249 |
* 🌱**LQIP** New setting **LQIP Excludes**.
|
250 |
* 🌱**LQIP** Added a Clear LQIP Queue button.
|
3 |
Tags: caching, optimize, performance, pagespeed, seo, speed, image optimize, compress, object cache, redis, memcached, database cleaner
|
4 |
Requires at least: 4.0
|
5 |
Tested up to: 5.5
|
6 |
+
Stable tag: 3.4.1
|
7 |
License: GPLv3
|
8 |
License URI: http://www.gnu.org/licenses/gpl.html
|
9 |
|
245 |
|
246 |
== Changelog ==
|
247 |
|
248 |
+
= 3.4.1 - Sep 2 2020 =
|
249 |
+
* 🐞**CCSS** Fixed an issue where dynamically generated CSS failed with `TypeError: Cannot read property type of undefined`.
|
250 |
+
* 🐞**Page Optimize** Fixed CSS optimization compatibility for CSS dynamically generated with PHP.
|
251 |
+
* **Page Optimize** Added the ability to defer JS even when the resource is excluded from other JS optimizations. (@slr1979)
|
252 |
+
* **ESI** Added support for ESI last paramater inline value.
|
253 |
+
* **3rd** YITH Wishlist, when cached for the first time, will no longer send sub requests.
|
254 |
+
|
255 |
= 3.4 - Aug 26 2020 =
|
256 |
* 🌱**LQIP** New setting **LQIP Excludes**.
|
257 |
* 🌱**LQIP** Added a Clear LQIP Queue button.
|
src/admin.cls.php
CHANGED
@@ -8,17 +8,16 @@
|
|
8 |
* @subpackage LiteSpeed_Cache/admin
|
9 |
* @author LiteSpeed Technologies <info@litespeedtech.com>
|
10 |
*/
|
11 |
-
namespace LiteSpeed
|
12 |
|
13 |
-
defined( 'WPINC' ) || exit
|
14 |
|
15 |
-
class Admin extends Instance
|
16 |
-
{
|
17 |
const PAGE_EDIT_HTACCESS = 'litespeed-edit-htaccess';
|
18 |
|
19 |
-
protected static $_instance
|
20 |
-
private $__cfg
|
21 |
-
private $display
|
22 |
|
23 |
/**
|
24 |
* Initialize the class and set its properties.
|
@@ -26,41 +25,40 @@ class Admin extends Instance
|
|
26 |
*
|
27 |
* @since 1.0.0
|
28 |
*/
|
29 |
-
protected function __construct()
|
30 |
-
{
|
31 |
// Define LSCWP_MU_PLUGIN if is mu-plugins
|
32 |
if ( defined( 'WPMU_PLUGIN_DIR' ) && dirname( LSCWP_DIR ) == WPMU_PLUGIN_DIR ) {
|
33 |
-
define( 'LSCWP_MU_PLUGIN', true )
|
34 |
}
|
35 |
|
36 |
// Additional litespeed assets on admin display
|
37 |
// Also register menu
|
38 |
-
$this->display = Admin_Display::get_instance()
|
39 |
|
40 |
-
$this->__cfg = Conf::get_instance()
|
41 |
|
42 |
// initialize admin actions
|
43 |
-
add_action( 'admin_init', array( $this, 'admin_init' ) )
|
44 |
// add link to plugin list page
|
45 |
-
add_filter( 'plugin_action_links_' . LSCWP_BASENAME, array( $this->display, 'add_plugin_links' ) )
|
46 |
|
47 |
if ( defined( 'LITESPEED_ON' ) ) {
|
48 |
// register purge_all actions
|
49 |
-
$purge_all_events = Conf::val( Base::O_PURGE_HOOK_ALL )
|
50 |
|
51 |
// purge all on upgrade
|
52 |
if ( Conf::val( Base::O_PURGE_ON_UPGRADE ) ) {
|
53 |
-
$purge_all_events[] = 'upgrader_process_complete'
|
54 |
-
$purge_all_events[] = 'admin_action_do-plugin-upgrade'
|
55 |
}
|
56 |
foreach ( $purge_all_events as $event ) {
|
57 |
// Don't allow hook to update_option bcos purge_all will cause infinite loop of update_option
|
58 |
if ( in_array( $event, array( 'update_option' ) ) ) {
|
59 |
-
continue
|
60 |
}
|
61 |
-
add_action( $event, __NAMESPACE__ . '\Purge::purge_all' )
|
62 |
}
|
63 |
-
// add_filter( 'upgrader_pre_download', 'Purge::filter_with_purge_all' )
|
64 |
}
|
65 |
}
|
66 |
|
@@ -77,13 +75,13 @@ class Admin extends Instance
|
|
77 |
|
78 |
// Terminate if user doesn't have the access to settings
|
79 |
if( is_network_admin() ) {
|
80 |
-
$capability = 'manage_network_options'
|
81 |
}
|
82 |
else {
|
83 |
-
$capability = 'manage_options'
|
84 |
}
|
85 |
if ( ! current_user_can($capability) ) {
|
86 |
-
return
|
87 |
}
|
88 |
|
89 |
// Save setting from admin settings page
|
@@ -92,14 +90,14 @@ class Admin extends Instance
|
|
92 |
// Add privacy policy
|
93 |
// @since 2.2.6
|
94 |
if ( function_exists( 'wp_add_privacy_policy_content' ) ) {
|
95 |
-
wp_add_privacy_policy_content( Core::PLUGIN_NAME, Doc::privacy_policy() )
|
96 |
}
|
97 |
|
98 |
-
do_action( 'litspeed_after_admin_init' )
|
99 |
|
100 |
if ( Router::esi_enabled() ) {
|
101 |
-
add_action( 'in_widget_form', array( $this->display, 'show_widget_edit' ), 100, 3 )
|
102 |
-
add_filter( 'widget_update_callback', __NAMESPACE__ . '\Admin_Settings::validate_widget_save', 10, 4 )
|
103 |
}
|
104 |
}
|
105 |
|
@@ -108,8 +106,7 @@ class Admin extends Instance
|
|
108 |
*
|
109 |
* @since 1.1.0
|
110 |
*/
|
111 |
-
private function _proceed_admin_action()
|
112 |
-
{
|
113 |
// handle actions
|
114 |
switch ( Router::get_action() ) {
|
115 |
|
@@ -142,13 +139,12 @@ class Admin extends Instance
|
|
142 |
* @param string $input The input string to clean.
|
143 |
* @return string The cleaned up input.
|
144 |
*/
|
145 |
-
public static function cleanup_text( $input )
|
146 |
-
{
|
147 |
if ( is_array( $input ) ) {
|
148 |
-
return array_map( __CLASS__ . '::cleanup_text', $input )
|
149 |
}
|
150 |
|
151 |
-
return stripslashes( trim( $input ) )
|
152 |
}
|
153 |
|
154 |
/**
|
@@ -159,8 +155,7 @@ class Admin extends Instance
|
|
159 |
* @access public
|
160 |
* @global string $pagenow
|
161 |
*/
|
162 |
-
public static function redirect( $url = false )
|
163 |
-
{
|
164 |
global $pagenow;
|
165 |
|
166 |
if ( ! empty( $_GET[ '_litespeed_ori' ] ) ) {
|
8 |
* @subpackage LiteSpeed_Cache/admin
|
9 |
* @author LiteSpeed Technologies <info@litespeedtech.com>
|
10 |
*/
|
11 |
+
namespace LiteSpeed;
|
12 |
|
13 |
+
defined( 'WPINC' ) || exit;
|
14 |
|
15 |
+
class Admin extends Instance {
|
|
|
16 |
const PAGE_EDIT_HTACCESS = 'litespeed-edit-htaccess';
|
17 |
|
18 |
+
protected static $_instance;
|
19 |
+
private $__cfg;// cfg instance
|
20 |
+
private $display;
|
21 |
|
22 |
/**
|
23 |
* Initialize the class and set its properties.
|
25 |
*
|
26 |
* @since 1.0.0
|
27 |
*/
|
28 |
+
protected function __construct() {
|
|
|
29 |
// Define LSCWP_MU_PLUGIN if is mu-plugins
|
30 |
if ( defined( 'WPMU_PLUGIN_DIR' ) && dirname( LSCWP_DIR ) == WPMU_PLUGIN_DIR ) {
|
31 |
+
define( 'LSCWP_MU_PLUGIN', true );
|
32 |
}
|
33 |
|
34 |
// Additional litespeed assets on admin display
|
35 |
// Also register menu
|
36 |
+
$this->display = Admin_Display::get_instance();
|
37 |
|
38 |
+
$this->__cfg = Conf::get_instance();
|
39 |
|
40 |
// initialize admin actions
|
41 |
+
add_action( 'admin_init', array( $this, 'admin_init' ) );
|
42 |
// add link to plugin list page
|
43 |
+
add_filter( 'plugin_action_links_' . LSCWP_BASENAME, array( $this->display, 'add_plugin_links' ) );
|
44 |
|
45 |
if ( defined( 'LITESPEED_ON' ) ) {
|
46 |
// register purge_all actions
|
47 |
+
$purge_all_events = Conf::val( Base::O_PURGE_HOOK_ALL );
|
48 |
|
49 |
// purge all on upgrade
|
50 |
if ( Conf::val( Base::O_PURGE_ON_UPGRADE ) ) {
|
51 |
+
$purge_all_events[] = 'upgrader_process_complete';
|
52 |
+
$purge_all_events[] = 'admin_action_do-plugin-upgrade';
|
53 |
}
|
54 |
foreach ( $purge_all_events as $event ) {
|
55 |
// Don't allow hook to update_option bcos purge_all will cause infinite loop of update_option
|
56 |
if ( in_array( $event, array( 'update_option' ) ) ) {
|
57 |
+
continue;
|
58 |
}
|
59 |
+
add_action( $event, __NAMESPACE__ . '\Purge::purge_all' );
|
60 |
}
|
61 |
+
// add_filter( 'upgrader_pre_download', 'Purge::filter_with_purge_all' );
|
62 |
}
|
63 |
}
|
64 |
|
75 |
|
76 |
// Terminate if user doesn't have the access to settings
|
77 |
if( is_network_admin() ) {
|
78 |
+
$capability = 'manage_network_options';
|
79 |
}
|
80 |
else {
|
81 |
+
$capability = 'manage_options';
|
82 |
}
|
83 |
if ( ! current_user_can($capability) ) {
|
84 |
+
return;
|
85 |
}
|
86 |
|
87 |
// Save setting from admin settings page
|
90 |
// Add privacy policy
|
91 |
// @since 2.2.6
|
92 |
if ( function_exists( 'wp_add_privacy_policy_content' ) ) {
|
93 |
+
wp_add_privacy_policy_content( Core::PLUGIN_NAME, Doc::privacy_policy() );
|
94 |
}
|
95 |
|
96 |
+
do_action( 'litspeed_after_admin_init' );
|
97 |
|
98 |
if ( Router::esi_enabled() ) {
|
99 |
+
add_action( 'in_widget_form', array( $this->display, 'show_widget_edit' ), 100, 3 );
|
100 |
+
add_filter( 'widget_update_callback', __NAMESPACE__ . '\Admin_Settings::validate_widget_save', 10, 4 );
|
101 |
}
|
102 |
}
|
103 |
|
106 |
*
|
107 |
* @since 1.1.0
|
108 |
*/
|
109 |
+
private function _proceed_admin_action() {
|
|
|
110 |
// handle actions
|
111 |
switch ( Router::get_action() ) {
|
112 |
|
139 |
* @param string $input The input string to clean.
|
140 |
* @return string The cleaned up input.
|
141 |
*/
|
142 |
+
public static function cleanup_text( $input ) {
|
|
|
143 |
if ( is_array( $input ) ) {
|
144 |
+
return array_map( __CLASS__ . '::cleanup_text', $input );
|
145 |
}
|
146 |
|
147 |
+
return stripslashes( trim( $input ) );
|
148 |
}
|
149 |
|
150 |
/**
|
155 |
* @access public
|
156 |
* @global string $pagenow
|
157 |
*/
|
158 |
+
public static function redirect( $url = false ) {
|
|
|
159 |
global $pagenow;
|
160 |
|
161 |
if ( ! empty( $_GET[ '_litespeed_ori' ] ) ) {
|
src/avatar.cls.php
CHANGED
@@ -7,20 +7,19 @@
|
|
7 |
* @subpackage LiteSpeed/inc
|
8 |
* @author LiteSpeed Technologies <info@litespeedtech.com>
|
9 |
*/
|
10 |
-
namespace LiteSpeed
|
11 |
|
12 |
-
defined( 'WPINC' ) || exit
|
13 |
|
14 |
-
class Avatar extends Base
|
15 |
-
|
16 |
-
protected static $_instance ;
|
17 |
|
18 |
-
const TYPE_GENERATE = 'generate'
|
19 |
|
20 |
-
private $_conf_cache_ttl
|
21 |
-
private $_tb
|
22 |
|
23 |
-
private $_avatar_realtime_gen_dict = array()
|
24 |
protected $_summary;
|
25 |
|
26 |
/**
|
@@ -29,19 +28,18 @@ class Avatar extends Base
|
|
29 |
* @since 1.4
|
30 |
* @access protected
|
31 |
*/
|
32 |
-
protected function __construct()
|
33 |
-
{
|
34 |
if ( ! Conf::val( Base::O_DISCUSS_AVATAR_CACHE ) ) {
|
35 |
-
return
|
36 |
}
|
37 |
|
38 |
-
Debug2::debug2( '[Avatar] init' )
|
39 |
|
40 |
-
$this->_tb = Data::get_instance()->tb( 'avatar' )
|
41 |
|
42 |
-
$this->_conf_cache_ttl = Conf::val( Base::O_DISCUSS_AVATAR_CACHE_TTL )
|
43 |
|
44 |
-
add_filter( 'get_avatar_url', array( $this, 'crawl_avatar' ) )
|
45 |
|
46 |
$this->_summary = self::get_summary();
|
47 |
}
|
@@ -52,13 +50,12 @@ class Avatar extends Base
|
|
52 |
* @since 3.0
|
53 |
* @access public
|
54 |
*/
|
55 |
-
public static function need_db()
|
56 |
-
{
|
57 |
if ( Conf::val( Base::O_DISCUSS_AVATAR_CACHE ) ) {
|
58 |
-
return true
|
59 |
}
|
60 |
|
61 |
-
return false
|
62 |
}
|
63 |
/**
|
64 |
* Get gravatar URL from DB and regenarate
|
@@ -66,29 +63,28 @@ class Avatar extends Base
|
|
66 |
* @since 3.0
|
67 |
* @access public
|
68 |
*/
|
69 |
-
public function serve_satic( $md5 )
|
70 |
-
|
71 |
-
global $wpdb ;
|
72 |
|
73 |
-
Debug2::debug( '[Avatar] is avatar request' )
|
74 |
|
75 |
if ( strlen( $md5 ) !== 32 ) {
|
76 |
-
Debug2::debug( '[Avatar] wrong md5 ' . $md5 )
|
77 |
-
return
|
78 |
}
|
79 |
|
80 |
-
$q = "SELECT url FROM `$this->_tb` WHERE md5=%s"
|
81 |
-
$url = $wpdb->get_var( $wpdb->prepare( $q, $md5 ) )
|
82 |
|
83 |
if ( ! $url ) {
|
84 |
-
Debug2::debug( '[Avatar] no matched url for md5 ' . $md5 )
|
85 |
-
return
|
86 |
}
|
87 |
|
88 |
-
$url = $this->_generate( $url )
|
89 |
|
90 |
-
wp_redirect( $url )
|
91 |
-
exit
|
92 |
}
|
93 |
|
94 |
/**
|
@@ -97,39 +93,38 @@ class Avatar extends Base
|
|
97 |
* @since 3.0
|
98 |
* @access public
|
99 |
*/
|
100 |
-
public function crawl_avatar( $url )
|
101 |
-
{
|
102 |
if ( ! $url ) {
|
103 |
-
return $url
|
104 |
}
|
105 |
|
106 |
// Check if its already in dict or not
|
107 |
if ( ! empty( $this->_avatar_realtime_gen_dict[ $url ] ) ) {
|
108 |
-
Debug2::debug2( '[Avatar] already in dict [url] ' . $url )
|
109 |
|
110 |
-
return $this->_avatar_realtime_gen_dict[ $url ]
|
111 |
}
|
112 |
|
113 |
-
$realpath = $this->_realpath( $url )
|
114 |
if ( file_exists( $realpath ) && time() - filemtime( $realpath ) <= $this->_conf_cache_ttl ) {
|
115 |
-
Debug2::debug2( '[Avatar] cache file exists [url] ' . $url )
|
116 |
-
return $this->_rewrite( $url )
|
117 |
}
|
118 |
|
119 |
if ( ! strpos( $url, 'gravatar.com' ) ) {
|
120 |
-
return $url
|
121 |
}
|
122 |
|
123 |
// Send request
|
124 |
if ( ! empty( $this->_summary[ 'curr_request' ] ) && time() - $this->_summary[ 'curr_request' ] < 300 ) {
|
125 |
-
Debug2::debug2( '[Avatar] Bypass generating due to interval limit [url] ' . $url )
|
126 |
-
return $url
|
127 |
}
|
128 |
|
129 |
// Generate immediately
|
130 |
-
$this->_avatar_realtime_gen_dict[ $url ] = $this->_generate( $url )
|
131 |
|
132 |
-
return $this->_avatar_realtime_gen_dict[ $url ]
|
133 |
}
|
134 |
|
135 |
/**
|
@@ -138,9 +133,8 @@ class Avatar extends Base
|
|
138 |
* @since 3.0
|
139 |
* @access public
|
140 |
*/
|
141 |
-
public static function has_cache()
|
142 |
-
|
143 |
-
return is_dir( LITESPEED_STATIC_DIR . '/avatar' ) ;
|
144 |
}
|
145 |
|
146 |
/**
|
@@ -149,9 +143,8 @@ class Avatar extends Base
|
|
149 |
* @since 3.0
|
150 |
* @access private
|
151 |
*/
|
152 |
-
private function _mkdir()
|
153 |
-
|
154 |
-
mkdir( LITESPEED_STATIC_DIR . '/avatar', 0755, true ) ;
|
155 |
}
|
156 |
|
157 |
/**
|
@@ -160,8 +153,7 @@ class Avatar extends Base
|
|
160 |
* @since 3.0
|
161 |
* @access public
|
162 |
*/
|
163 |
-
public function queue_count()
|
164 |
-
{
|
165 |
global $wpdb;
|
166 |
|
167 |
// If var not exists, mean table not exists // todo: not true
|
@@ -180,8 +172,7 @@ class Avatar extends Base
|
|
180 |
*
|
181 |
* @since 3.0
|
182 |
*/
|
183 |
-
private function _rewrite( $url )
|
184 |
-
{
|
185 |
return LITESPEED_STATIC_URL . '/avatar/' . md5( $url ) . '.jpg';
|
186 |
}
|
187 |
|
@@ -191,8 +182,7 @@ class Avatar extends Base
|
|
191 |
* @since 3.0
|
192 |
* @access private
|
193 |
*/
|
194 |
-
private function _realpath( $url )
|
195 |
-
{
|
196 |
return LITESPEED_STATIC_DIR . '/avatar/' . md5( $url ) . '.jpg';
|
197 |
}
|
198 |
|
@@ -202,16 +192,15 @@ class Avatar extends Base
|
|
202 |
* @since 3.0
|
203 |
* @access public
|
204 |
*/
|
205 |
-
public function rm_cache_folder()
|
206 |
-
{
|
207 |
if ( file_exists( LITESPEED_STATIC_DIR . '/avatar' ) ) {
|
208 |
-
File::rrmdir( LITESPEED_STATIC_DIR . '/avatar' )
|
209 |
}
|
210 |
|
211 |
// Clear avatar summary
|
212 |
-
self::save_summary( array() )
|
213 |
|
214 |
-
Debug2::debug2( '[Avatar] Cleared avatar queue' )
|
215 |
}
|
216 |
|
217 |
/**
|
@@ -220,32 +209,31 @@ class Avatar extends Base
|
|
220 |
* @since 3.0
|
221 |
* @access public
|
222 |
*/
|
223 |
-
public static function cron( $force = false )
|
224 |
-
|
225 |
-
global $wpdb ;
|
226 |
|
227 |
$_instance = self::get_instance();
|
228 |
if ( ! $_instance->queue_count() ) {
|
229 |
-
Debug2::debug( '[Avatar] no queue' )
|
230 |
-
return
|
231 |
}
|
232 |
|
233 |
// For cron, need to check request interval too
|
234 |
if ( ! $force ) {
|
235 |
if ( ! empty( $_instance->_summary[ 'curr_request' ] ) && time() - $_instance->_summary[ 'curr_request' ] < 300 ) {
|
236 |
-
Debug2::debug( '[Avatar] curr_request too close' )
|
237 |
-
return
|
238 |
}
|
239 |
}
|
240 |
|
241 |
-
$q = "SELECT url FROM `$_instance->_tb` WHERE dateline < %d ORDER BY id DESC LIMIT %d"
|
242 |
-
$q = $wpdb->prepare( $q, array( time() - $_instance->_conf_cache_ttl, apply_filters( 'litespeed_avatar_limit', 30 ) ) )
|
243 |
|
244 |
-
$list = $wpdb->get_results( $q )
|
245 |
-
Debug2::debug( '[Avatar] cron job [count] ' . count( $list ) )
|
246 |
|
247 |
foreach ( $list as $v ) {
|
248 |
-
Debug2::debug( '[Avatar] cron job [url] ' . $v->url )
|
249 |
|
250 |
$_instance->_generate( $v->url );
|
251 |
}
|
@@ -257,52 +245,51 @@ class Avatar extends Base
|
|
257 |
* @since 3.0
|
258 |
* @access private
|
259 |
*/
|
260 |
-
private function _generate( $url )
|
261 |
-
|
262 |
-
global $wpdb ;
|
263 |
|
264 |
// Record the data
|
265 |
|
266 |
-
$file = $this->_realpath( $url )
|
267 |
|
268 |
// Update request status
|
269 |
-
$this->_summary[ 'curr_request' ] = time()
|
270 |
-
self::save_summary()
|
271 |
|
272 |
// Generate
|
273 |
if ( ! self::has_cache() ) {
|
274 |
-
$this->_mkdir()
|
275 |
}
|
276 |
-
$response = wp_remote_get( $url, array( 'timeout' => 180, 'stream' => true, 'filename' => $file ) )
|
277 |
|
278 |
-
Debug2::debug( '[Avatar] _generate [url] ' . $url )
|
279 |
|
280 |
// Parse response data
|
281 |
if ( is_wp_error( $response ) ) {
|
282 |
-
$error_message = $response->get_error_message()
|
283 |
-
file_exists( $file ) && unlink( $file )
|
284 |
-
Debug2::debug( '[Avatar] failed to get: ' . $error_message )
|
285 |
-
return $url
|
286 |
}
|
287 |
|
288 |
// Save summary data
|
289 |
-
$this->_summary[ 'last_spent' ] = time() - $this->_summary[ 'curr_request' ]
|
290 |
-
$this->_summary[ 'last_request' ] = $this->_summary[ 'curr_request' ]
|
291 |
-
$this->_summary[ 'curr_request' ] = 0
|
292 |
-
self::save_summary()
|
293 |
|
294 |
// Update DB
|
295 |
-
$md5 = md5( $url )
|
296 |
-
$q = "UPDATE `$this->_tb` SET dateline=%d WHERE md5=%s"
|
297 |
-
$existed = $wpdb->query( $wpdb->prepare( $q, array( time(), $md5 ) ) )
|
298 |
if ( ! $existed ) {
|
299 |
-
$q = "INSERT INTO `$this->_tb` SET url=%s, md5=%s, dateline=%d"
|
300 |
-
$wpdb->query( $wpdb->prepare( $q, array( $url, $md5, time() ) ) )
|
301 |
}
|
302 |
|
303 |
-
Debug2::debug( '[Avatar] saved avatar ' . $file )
|
304 |
|
305 |
-
return $this->_rewrite( $url )
|
306 |
}
|
307 |
|
308 |
/**
|
@@ -311,22 +298,21 @@ class Avatar extends Base
|
|
311 |
* @since 3.0
|
312 |
* @access public
|
313 |
*/
|
314 |
-
public static function handler()
|
315 |
-
|
316 |
-
$instance = self::get_instance() ;
|
317 |
|
318 |
-
$type = Router::verify_type()
|
319 |
|
320 |
switch ( $type ) {
|
321 |
case self::TYPE_GENERATE :
|
322 |
-
self::cron( true )
|
323 |
-
break
|
324 |
|
325 |
default:
|
326 |
-
break
|
327 |
}
|
328 |
|
329 |
-
Admin::redirect()
|
330 |
}
|
331 |
|
332 |
}
|
7 |
* @subpackage LiteSpeed/inc
|
8 |
* @author LiteSpeed Technologies <info@litespeedtech.com>
|
9 |
*/
|
10 |
+
namespace LiteSpeed;
|
11 |
|
12 |
+
defined( 'WPINC' ) || exit;
|
13 |
|
14 |
+
class Avatar extends Base {
|
15 |
+
protected static $_instance;
|
|
|
16 |
|
17 |
+
const TYPE_GENERATE = 'generate';
|
18 |
|
19 |
+
private $_conf_cache_ttl;
|
20 |
+
private $_tb;
|
21 |
|
22 |
+
private $_avatar_realtime_gen_dict = array();
|
23 |
protected $_summary;
|
24 |
|
25 |
/**
|
28 |
* @since 1.4
|
29 |
* @access protected
|
30 |
*/
|
31 |
+
protected function __construct() {
|
|
|
32 |
if ( ! Conf::val( Base::O_DISCUSS_AVATAR_CACHE ) ) {
|
33 |
+
return;
|
34 |
}
|
35 |
|
36 |
+
Debug2::debug2( '[Avatar] init' );
|
37 |
|
38 |
+
$this->_tb = Data::get_instance()->tb( 'avatar' );
|
39 |
|
40 |
+
$this->_conf_cache_ttl = Conf::val( Base::O_DISCUSS_AVATAR_CACHE_TTL );
|
41 |
|
42 |
+
add_filter( 'get_avatar_url', array( $this, 'crawl_avatar' ) );
|
43 |
|
44 |
$this->_summary = self::get_summary();
|
45 |
}
|
50 |
* @since 3.0
|
51 |
* @access public
|
52 |
*/
|
53 |
+
public static function need_db() {
|
|
|
54 |
if ( Conf::val( Base::O_DISCUSS_AVATAR_CACHE ) ) {
|
55 |
+
return true;
|
56 |
}
|
57 |
|
58 |
+
return false;
|
59 |
}
|
60 |
/**
|
61 |
* Get gravatar URL from DB and regenarate
|
63 |
* @since 3.0
|
64 |
* @access public
|
65 |
*/
|
66 |
+
public function serve_satic( $md5 ) {
|
67 |
+
global $wpdb;
|
|
|
68 |
|
69 |
+
Debug2::debug( '[Avatar] is avatar request' );
|
70 |
|
71 |
if ( strlen( $md5 ) !== 32 ) {
|
72 |
+
Debug2::debug( '[Avatar] wrong md5 ' . $md5 );
|
73 |
+
return;
|
74 |
}
|
75 |
|
76 |
+
$q = "SELECT url FROM `$this->_tb` WHERE md5=%s";
|
77 |
+
$url = $wpdb->get_var( $wpdb->prepare( $q, $md5 ) );
|
78 |
|
79 |
if ( ! $url ) {
|
80 |
+
Debug2::debug( '[Avatar] no matched url for md5 ' . $md5 );
|
81 |
+
return;
|
82 |
}
|
83 |
|
84 |
+
$url = $this->_generate( $url );
|
85 |
|
86 |
+
wp_redirect( $url );
|
87 |
+
exit;
|
88 |
}
|
89 |
|
90 |
/**
|
93 |
* @since 3.0
|
94 |
* @access public
|
95 |
*/
|
96 |
+
public function crawl_avatar( $url ) {
|
|
|
97 |
if ( ! $url ) {
|
98 |
+
return $url;
|
99 |
}
|
100 |
|
101 |
// Check if its already in dict or not
|
102 |
if ( ! empty( $this->_avatar_realtime_gen_dict[ $url ] ) ) {
|
103 |
+
Debug2::debug2( '[Avatar] already in dict [url] ' . $url );
|
104 |
|
105 |
+
return $this->_avatar_realtime_gen_dict[ $url ];
|
106 |
}
|
107 |
|
108 |
+
$realpath = $this->_realpath( $url );
|
109 |
if ( file_exists( $realpath ) && time() - filemtime( $realpath ) <= $this->_conf_cache_ttl ) {
|
110 |
+
Debug2::debug2( '[Avatar] cache file exists [url] ' . $url );
|
111 |
+
return $this->_rewrite( $url );
|
112 |
}
|
113 |
|
114 |
if ( ! strpos( $url, 'gravatar.com' ) ) {
|
115 |
+
return $url;
|
116 |
}
|
117 |
|
118 |
// Send request
|
119 |
if ( ! empty( $this->_summary[ 'curr_request' ] ) && time() - $this->_summary[ 'curr_request' ] < 300 ) {
|
120 |
+
Debug2::debug2( '[Avatar] Bypass generating due to interval limit [url] ' . $url );
|
121 |
+
return $url;
|
122 |
}
|
123 |
|
124 |
// Generate immediately
|
125 |
+
$this->_avatar_realtime_gen_dict[ $url ] = $this->_generate( $url );
|
126 |
|
127 |
+
return $this->_avatar_realtime_gen_dict[ $url ];
|
128 |
}
|
129 |
|
130 |
/**
|
133 |
* @since 3.0
|
134 |
* @access public
|
135 |
*/
|
136 |
+
public static function has_cache() {
|
137 |
+
return is_dir( LITESPEED_STATIC_DIR . '/avatar' );
|
|
|
138 |
}
|
139 |
|
140 |
/**
|
143 |
* @since 3.0
|
144 |
* @access private
|
145 |
*/
|
146 |
+
private function _mkdir() {
|
147 |
+
mkdir( LITESPEED_STATIC_DIR . '/avatar', 0755, true );
|
|
|
148 |
}
|
149 |
|
150 |
/**
|
153 |
* @since 3.0
|
154 |
* @access public
|
155 |
*/
|
156 |
+
public function queue_count() {
|
|
|
157 |
global $wpdb;
|
158 |
|
159 |
// If var not exists, mean table not exists // todo: not true
|
172 |
*
|
173 |
* @since 3.0
|
174 |
*/
|
175 |
+
private function _rewrite( $url ) {
|
|
|
176 |
return LITESPEED_STATIC_URL . '/avatar/' . md5( $url ) . '.jpg';
|
177 |
}
|
178 |
|
182 |
* @since 3.0
|
183 |
* @access private
|
184 |
*/
|
185 |
+
private function _realpath( $url ) {
|
|
|
186 |
return LITESPEED_STATIC_DIR . '/avatar/' . md5( $url ) . '.jpg';
|
187 |
}
|
188 |
|
192 |
* @since 3.0
|
193 |
* @access public
|
194 |
*/
|
195 |
+
public function rm_cache_folder() {
|
|
|
196 |
if ( file_exists( LITESPEED_STATIC_DIR . '/avatar' ) ) {
|
197 |
+
File::rrmdir( LITESPEED_STATIC_DIR . '/avatar' );
|
198 |
}
|
199 |
|
200 |
// Clear avatar summary
|
201 |
+
self::save_summary( array() );
|
202 |
|
203 |
+
Debug2::debug2( '[Avatar] Cleared avatar queue' );
|
204 |
}
|
205 |
|
206 |
/**
|
209 |
* @since 3.0
|
210 |
* @access public
|
211 |
*/
|
212 |
+
public static function cron( $force = false ) {
|
213 |
+
global $wpdb;
|
|
|
214 |
|
215 |
$_instance = self::get_instance();
|
216 |
if ( ! $_instance->queue_count() ) {
|
217 |
+
Debug2::debug( '[Avatar] no queue' );
|
218 |
+
return;
|
219 |
}
|
220 |
|
221 |
// For cron, need to check request interval too
|
222 |
if ( ! $force ) {
|
223 |
if ( ! empty( $_instance->_summary[ 'curr_request' ] ) && time() - $_instance->_summary[ 'curr_request' ] < 300 ) {
|
224 |
+
Debug2::debug( '[Avatar] curr_request too close' );
|
225 |
+
return;
|
226 |
}
|
227 |
}
|
228 |
|
229 |
+
$q = "SELECT url FROM `$_instance->_tb` WHERE dateline < %d ORDER BY id DESC LIMIT %d";
|
230 |
+
$q = $wpdb->prepare( $q, array( time() - $_instance->_conf_cache_ttl, apply_filters( 'litespeed_avatar_limit', 30 ) ) );
|
231 |
|
232 |
+
$list = $wpdb->get_results( $q );
|
233 |
+
Debug2::debug( '[Avatar] cron job [count] ' . count( $list ) );
|
234 |
|
235 |
foreach ( $list as $v ) {
|
236 |
+
Debug2::debug( '[Avatar] cron job [url] ' . $v->url );
|
237 |
|
238 |
$_instance->_generate( $v->url );
|
239 |
}
|
245 |
* @since 3.0
|
246 |
* @access private
|
247 |
*/
|
248 |
+
private function _generate( $url ) {
|
249 |
+
global $wpdb;
|
|
|
250 |
|
251 |
// Record the data
|
252 |
|
253 |
+
$file = $this->_realpath( $url );
|
254 |
|
255 |
// Update request status
|
256 |
+
$this->_summary[ 'curr_request' ] = time();
|
257 |
+
self::save_summary();
|
258 |
|
259 |
// Generate
|
260 |
if ( ! self::has_cache() ) {
|
261 |
+
$this->_mkdir();
|
262 |
}
|
263 |
+
$response = wp_remote_get( $url, array( 'timeout' => 180, 'stream' => true, 'filename' => $file ) );
|
264 |
|
265 |
+
Debug2::debug( '[Avatar] _generate [url] ' . $url );
|
266 |
|
267 |
// Parse response data
|
268 |
if ( is_wp_error( $response ) ) {
|
269 |
+
$error_message = $response->get_error_message();
|
270 |
+
file_exists( $file ) && unlink( $file );
|
271 |
+
Debug2::debug( '[Avatar] failed to get: ' . $error_message );
|
272 |
+
return $url;
|
273 |
}
|
274 |
|
275 |
// Save summary data
|
276 |
+
$this->_summary[ 'last_spent' ] = time() - $this->_summary[ 'curr_request' ];
|
277 |
+
$this->_summary[ 'last_request' ] = $this->_summary[ 'curr_request' ];
|
278 |
+
$this->_summary[ 'curr_request' ] = 0;
|
279 |
+
self::save_summary();
|
280 |
|
281 |
// Update DB
|
282 |
+
$md5 = md5( $url );
|
283 |
+
$q = "UPDATE `$this->_tb` SET dateline=%d WHERE md5=%s";
|
284 |
+
$existed = $wpdb->query( $wpdb->prepare( $q, array( time(), $md5 ) ) );
|
285 |
if ( ! $existed ) {
|
286 |
+
$q = "INSERT INTO `$this->_tb` SET url=%s, md5=%s, dateline=%d";
|
287 |
+
$wpdb->query( $wpdb->prepare( $q, array( $url, $md5, time() ) ) );
|
288 |
}
|
289 |
|
290 |
+
Debug2::debug( '[Avatar] saved avatar ' . $file );
|
291 |
|
292 |
+
return $this->_rewrite( $url );
|
293 |
}
|
294 |
|
295 |
/**
|
298 |
* @since 3.0
|
299 |
* @access public
|
300 |
*/
|
301 |
+
public static function handler() {
|
302 |
+
$instance = self::get_instance();
|
|
|
303 |
|
304 |
+
$type = Router::verify_type();
|
305 |
|
306 |
switch ( $type ) {
|
307 |
case self::TYPE_GENERATE :
|
308 |
+
self::cron( true );
|
309 |
+
break;
|
310 |
|
311 |
default:
|
312 |
+
break;
|
313 |
}
|
314 |
|
315 |
+
Admin::redirect();
|
316 |
}
|
317 |
|
318 |
}
|
src/cdn.cls.php
CHANGED
@@ -408,8 +408,7 @@ class CDN extends Instance {
|
|
408 |
* @since 1.7
|
409 |
* @access public
|
410 |
*/
|
411 |
-
public function url_css( $url )
|
412 |
-
{
|
413 |
if ( $url && $url2 = $this->rewrite( $url, Base::CDN_MAPPING_INC_CSS ) ) {
|
414 |
$url = $url2;
|
415 |
}
|
408 |
* @since 1.7
|
409 |
* @access public
|
410 |
*/
|
411 |
+
public function url_css( $url ) {
|
|
|
412 |
if ( $url && $url2 = $this->rewrite( $url, Base::CDN_MAPPING_INC_CSS ) ) {
|
413 |
$url = $url2;
|
414 |
}
|
src/css.cls.php
CHANGED
@@ -240,7 +240,8 @@ class CSS extends Base {
|
|
240 |
|
241 |
// Load CSS content
|
242 |
$real_file = Utility::is_internal_file( $attrs[ 'href' ] );
|
243 |
-
|
|
|
244 |
Debug2::debug2( '[CCSS] Load Remote CSS ' . $attrs[ 'href' ] );
|
245 |
$con = wp_remote_retrieve_body( wp_remote_get( $attrs[ 'href' ] ) );
|
246 |
if ( ! $con ) {
|
240 |
|
241 |
// Load CSS content
|
242 |
$real_file = Utility::is_internal_file( $attrs[ 'href' ] );
|
243 |
+
$postfix = pathinfo( parse_url( $attrs[ 'href' ], PHP_URL_PATH ), PATHINFO_EXTENSION );
|
244 |
+
if ( ! $real_file || $postfix != 'css' ) {
|
245 |
Debug2::debug2( '[CCSS] Load Remote CSS ' . $attrs[ 'href' ] );
|
246 |
$con = wp_remote_retrieve_body( wp_remote_get( $attrs[ 'href' ] ) );
|
247 |
if ( ! $con ) {
|
src/esi.cls.php
CHANGED
@@ -331,7 +331,7 @@ class ESI extends Instance {
|
|
331 |
return ;
|
332 |
}
|
333 |
|
334 |
-
add_filter('widget_display_callback', array($this, 'sub_widget_block'), 0, 3)
|
335 |
|
336 |
// Add admin_bar esi
|
337 |
if ( Router::is_logged_in() ) {
|
@@ -360,11 +360,9 @@ class ESI extends Instance {
|
|
360 |
* @param bool $silence If generate wrapper comment or not
|
361 |
* @param bool $preserved If this ESI block is used in any filter, need to temporarily convert it to a string to avoid the HTML tag being removed/filtered.
|
362 |
* @param bool $svar If store the value in memory or not, in memory wil be faster
|
363 |
-
* @param
|
364 |
-
* @return bool|string False on error, the output otherwise.
|
365 |
*/
|
366 |
-
public static function sub_esi_block( $block_id, $wrapper, $params = array(), $control = 'private,no-vary', $silence = false, $preserved = false, $svar = false, $
|
367 |
-
{
|
368 |
if ( empty($block_id) || ! is_array($params) || preg_match('/[^\w-]/', $block_id) ) {
|
369 |
return false ;
|
370 |
}
|
@@ -411,7 +409,20 @@ class ESI extends Instance {
|
|
411 |
// Generate ESI URL
|
412 |
$url = add_query_arg( $appended_params, trailingslashit( wp_make_link_relative( home_url() ) ) ) ;
|
413 |
|
414 |
-
$output =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
415 |
if ( ! empty( $control ) ) {
|
416 |
$output .= " cache-control='$control'" ;
|
417 |
}
|
@@ -555,7 +566,6 @@ class ESI extends Instance {
|
|
555 |
do_action('litespeed_esi_load-' . LSCACHE_IS_ESI, $params) ;
|
556 |
}
|
557 |
|
558 |
-
// BEGIN helper functions
|
559 |
// The *_sub_* functions are helpers for the sub_* functions.
|
560 |
// The *_load_* functions are helpers for the load_* functions.
|
561 |
|
@@ -584,8 +594,6 @@ class ESI extends Instance {
|
|
584 |
return $options ;
|
585 |
}
|
586 |
|
587 |
-
// END helper functions.
|
588 |
-
|
589 |
/**
|
590 |
* Hooked to the widget_display_callback filter.
|
591 |
* If the admin configured the widget to display via esi, this function
|
@@ -598,8 +606,7 @@ class ESI extends Instance {
|
|
598 |
* @param array $args Parameter used to build the widget.
|
599 |
* @return mixed Return false if display through esi, instance otherwise.
|
600 |
*/
|
601 |
-
public function sub_widget_block( $instance, $widget, $args )
|
602 |
-
{
|
603 |
// #210407
|
604 |
if ( ! is_array( $instance ) ) {
|
605 |
return $instance ;
|
@@ -625,8 +632,9 @@ class ESI extends Instance {
|
|
625 |
self::PARAM_ARGS => $args
|
626 |
) ;
|
627 |
|
628 |
-
echo self::sub_esi_block( 'widget', 'widget ' . $name, $params, $esi_private . 'no-vary' )
|
629 |
-
|
|
|
630 |
}
|
631 |
|
632 |
/**
|
331 |
return ;
|
332 |
}
|
333 |
|
334 |
+
add_filter('widget_display_callback', array( $this, 'sub_widget_block' ), 0, 3);
|
335 |
|
336 |
// Add admin_bar esi
|
337 |
if ( Router::is_logged_in() ) {
|
360 |
* @param bool $silence If generate wrapper comment or not
|
361 |
* @param bool $preserved If this ESI block is used in any filter, need to temporarily convert it to a string to avoid the HTML tag being removed/filtered.
|
362 |
* @param bool $svar If store the value in memory or not, in memory wil be faster
|
363 |
+
* @param array $inline_val If show the current value for current request( this can avoid multiple esi requests in first time cache generating process )
|
|
|
364 |
*/
|
365 |
+
public static function sub_esi_block( $block_id, $wrapper, $params = array(), $control = 'private,no-vary', $silence = false, $preserved = false, $svar = false, $inline_param = array() ) {
|
|
|
366 |
if ( empty($block_id) || ! is_array($params) || preg_match('/[^\w-]/', $block_id) ) {
|
367 |
return false ;
|
368 |
}
|
409 |
// Generate ESI URL
|
410 |
$url = add_query_arg( $appended_params, trailingslashit( wp_make_link_relative( home_url() ) ) ) ;
|
411 |
|
412 |
+
$output = '';
|
413 |
+
|
414 |
+
if ( ! empty( $inline_param[ 'val' ] ) ) {
|
415 |
+
$output .= "<esi:inline name='$url'";
|
416 |
+
if ( ! empty( $inline_param[ 'control' ] ) ) {
|
417 |
+
$output .= " cache-control='" . $inline_param[ 'control' ] . "'";
|
418 |
+
}
|
419 |
+
if ( ! empty( $inline_param[ 'tag' ] ) ) {
|
420 |
+
$output .= " cache-tag='" . $inline_param[ 'tag' ] . "'";
|
421 |
+
}
|
422 |
+
$output .= '>' . $inline_param[ 'val' ] . '</esi:inline>';
|
423 |
+
}
|
424 |
+
|
425 |
+
$output .= "<esi:include src='$url'" ;
|
426 |
if ( ! empty( $control ) ) {
|
427 |
$output .= " cache-control='$control'" ;
|
428 |
}
|
566 |
do_action('litespeed_esi_load-' . LSCACHE_IS_ESI, $params) ;
|
567 |
}
|
568 |
|
|
|
569 |
// The *_sub_* functions are helpers for the sub_* functions.
|
570 |
// The *_load_* functions are helpers for the load_* functions.
|
571 |
|
594 |
return $options ;
|
595 |
}
|
596 |
|
|
|
|
|
597 |
/**
|
598 |
* Hooked to the widget_display_callback filter.
|
599 |
* If the admin configured the widget to display via esi, this function
|
606 |
* @param array $args Parameter used to build the widget.
|
607 |
* @return mixed Return false if display through esi, instance otherwise.
|
608 |
*/
|
609 |
+
public function sub_widget_block( $instance, $widget, $args ) {
|
|
|
610 |
// #210407
|
611 |
if ( ! is_array( $instance ) ) {
|
612 |
return $instance ;
|
632 |
self::PARAM_ARGS => $args
|
633 |
) ;
|
634 |
|
635 |
+
echo self::sub_esi_block( 'widget', 'widget ' . $name, $params, $esi_private . 'no-vary' );
|
636 |
+
|
637 |
+
return false;
|
638 |
}
|
639 |
|
640 |
/**
|
src/htaccess.cls.php
CHANGED
@@ -8,52 +8,51 @@
|
|
8 |
* @subpackage LiteSpeed/inc
|
9 |
* @author LiteSpeed Technologies <info@litespeedtech.com>
|
10 |
*/
|
11 |
-
namespace LiteSpeed
|
12 |
-
|
13 |
-
defined( 'WPINC' ) || exit
|
14 |
-
|
15 |
-
class Htaccess extends Instance
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
private $
|
22 |
-
private $
|
23 |
-
private $
|
24 |
-
private $
|
25 |
-
private $
|
26 |
-
private $
|
27 |
-
private $
|
28 |
-
private $
|
29 |
-
private $
|
30 |
-
private $
|
31 |
-
private $
|
32 |
-
|
33 |
-
|
34 |
-
const
|
35 |
-
const
|
36 |
-
const
|
37 |
-
const
|
38 |
-
const
|
39 |
-
const
|
40 |
-
const
|
41 |
-
const
|
42 |
-
const
|
43 |
-
const
|
44 |
-
const
|
45 |
-
const
|
46 |
-
const
|
47 |
-
const
|
48 |
-
const
|
49 |
-
const
|
50 |
-
const
|
51 |
-
const
|
52 |
-
const
|
53 |
-
const
|
54 |
-
|
55 |
-
|
56 |
-
const RW_PATTERN_RES = '/.*/[^/]*(responsive|css|js|dynamic|loader|fonts)\.php' ;
|
57 |
|
58 |
/**
|
59 |
* Initialize the class and set its properties.
|
@@ -61,11 +60,10 @@ class Htaccess extends Instance
|
|
61 |
* @since 1.0.7
|
62 |
* @access protected
|
63 |
*/
|
64 |
-
protected function __construct()
|
65 |
-
|
66 |
-
$this->
|
67 |
-
$this->
|
68 |
-
$this->_default_backend_htaccess = $this->backend_htaccess ;
|
69 |
|
70 |
$frontend_htaccess = Conf::val( Base::O_MISC_HTACCESS_FRONT );
|
71 |
if ( $frontend_htaccess && substr( $frontend_htaccess, -10 ) === '/.htaccess' ) {
|
@@ -77,38 +75,38 @@ class Htaccess extends Instance
|
|
77 |
}
|
78 |
|
79 |
// Filter for frontend&backend htaccess path
|
80 |
-
$this->frontend_htaccess = apply_filters( 'litespeed_frontend_htaccess', $this->frontend_htaccess )
|
81 |
-
$this->backend_htaccess = apply_filters( 'litespeed_backend_htaccess', $this->backend_htaccess )
|
82 |
|
83 |
-
clearstatcache()
|
84 |
|
85 |
// frontend .htaccess privilege
|
86 |
-
$test_permissions = file_exists( $this->frontend_htaccess ) ? $this->frontend_htaccess : dirname( $this->frontend_htaccess )
|
87 |
if ( is_readable( $test_permissions ) ) {
|
88 |
-
$this->frontend_htaccess_readable = true
|
89 |
}
|
90 |
if ( is_writable( $test_permissions ) ) {
|
91 |
-
$this->frontend_htaccess_writable = true
|
92 |
}
|
93 |
|
94 |
$this->__rewrite_on = array(
|
95 |
self::REWRITE_ON,
|
96 |
"CacheLookup on",
|
97 |
"RewriteRule .* - [E=Cache-Control:no-autoflush]",
|
98 |
-
)
|
99 |
|
100 |
// backend .htaccess privilege
|
101 |
if ( $this->frontend_htaccess === $this->backend_htaccess ) {
|
102 |
-
$this->backend_htaccess_readable = $this->frontend_htaccess_readable
|
103 |
-
$this->backend_htaccess_writable = $this->frontend_htaccess_writable
|
104 |
}
|
105 |
else {
|
106 |
-
$test_permissions = file_exists( $this->backend_htaccess ) ? $this->backend_htaccess : dirname( $this->backend_htaccess )
|
107 |
if ( is_readable( $test_permissions ) ) {
|
108 |
-
$this->backend_htaccess_readable = true
|
109 |
}
|
110 |
if ( is_writable( $test_permissions ) ) {
|
111 |
-
$this->backend_htaccess_writable = true
|
112 |
}
|
113 |
}
|
114 |
}
|
@@ -119,13 +117,12 @@ class Htaccess extends Instance
|
|
119 |
* @since 1.1.0
|
120 |
* @return string
|
121 |
*/
|
122 |
-
private function _readable( $kind = 'frontend' )
|
123 |
-
{
|
124 |
if( $kind === 'frontend' ) {
|
125 |
-
return $this->frontend_htaccess_readable
|
126 |
}
|
127 |
if( $kind === 'backend' ) {
|
128 |
-
return $this->backend_htaccess_readable
|
129 |
}
|
130 |
}
|
131 |
|
@@ -135,13 +132,12 @@ class Htaccess extends Instance
|
|
135 |
* @since 1.1.0
|
136 |
* @return string
|
137 |
*/
|
138 |
-
public function writable( $kind = 'frontend' )
|
139 |
-
{
|
140 |
if( $kind === 'frontend' ) {
|
141 |
-
return $this->frontend_htaccess_writable
|
142 |
}
|
143 |
if( $kind === 'backend' ) {
|
144 |
-
return $this->backend_htaccess_writable
|
145 |
}
|
146 |
}
|
147 |
|
@@ -151,12 +147,11 @@ class Htaccess extends Instance
|
|
151 |
* @since 1.1.0
|
152 |
* @return string
|
153 |
*/
|
154 |
-
public static function get_frontend_htaccess( $show_default = false )
|
155 |
-
{
|
156 |
if ( $show_default ) {
|
157 |
-
return self::get_instance()->_default_frontend_htaccess
|
158 |
}
|
159 |
-
return self::get_instance()->frontend_htaccess
|
160 |
}
|
161 |
|
162 |
/**
|
@@ -165,12 +160,11 @@ class Htaccess extends Instance
|
|
165 |
* @since 1.1.0
|
166 |
* @return string
|
167 |
*/
|
168 |
-
public static function get_backend_htaccess( $show_default = false )
|
169 |
-
{
|
170 |
if ( $show_default ) {
|
171 |
-
return self::get_instance()->_default_backend_htaccess
|
172 |
}
|
173 |
-
return self::get_instance()->backend_htaccess
|
174 |
}
|
175 |
|
176 |
/**
|
@@ -207,34 +201,33 @@ class Htaccess extends Instance
|
|
207 |
* @since 1.0.11
|
208 |
* @access private
|
209 |
*/
|
210 |
-
private function _path_set()
|
211 |
-
|
212 |
-
$
|
213 |
-
$
|
214 |
-
$this->frontend_htaccess = ( $frontend_htaccess_search ?: $frontend ) . '/.htaccess' ;
|
215 |
|
216 |
-
$backend = realpath( ABSPATH )
|
217 |
if ( $frontend == $backend ) {
|
218 |
-
$this->backend_htaccess = $this->frontend_htaccess
|
219 |
-
return
|
220 |
}
|
221 |
|
222 |
// Backend is a different path
|
223 |
-
$backend_htaccess_search = $this->_htaccess_search( $backend )
|
224 |
// Found affected .htaccess
|
225 |
if ( $backend_htaccess_search ) {
|
226 |
-
$this->backend_htaccess = $backend_htaccess_search . '/.htaccess'
|
227 |
-
return
|
228 |
}
|
229 |
|
230 |
// Frontend path is the parent of backend path
|
231 |
if ( stripos( $backend, $frontend . '/' ) === 0 ) {
|
232 |
// backend use frontend htaccess
|
233 |
-
$this->backend_htaccess = $this->frontend_htaccess
|
234 |
-
return
|
235 |
}
|
236 |
|
237 |
-
$this->backend_htaccess = $backend . '/.htaccess'
|
238 |
}
|
239 |
|
240 |
/**
|
@@ -244,19 +237,18 @@ class Htaccess extends Instance
|
|
244 |
* @param string $kind Frontend or backend
|
245 |
* @return string Path
|
246 |
*/
|
247 |
-
public function htaccess_path( $kind = 'frontend' )
|
248 |
-
{
|
249 |
switch ( $kind ) {
|
250 |
case 'backend' :
|
251 |
-
$path = $this->backend_htaccess
|
252 |
-
break
|
253 |
|
254 |
case 'frontend' :
|
255 |
default :
|
256 |
-
$path = $this->frontend_htaccess
|
257 |
-
break
|
258 |
}
|
259 |
-
return $path
|
260 |
}
|
261 |
|
262 |
/**
|
@@ -268,26 +260,25 @@ class Htaccess extends Instance
|
|
268 |
* @since 2.9 Used exception for failed reading
|
269 |
* @access public
|
270 |
*/
|
271 |
-
public function htaccess_read( $kind = 'frontend' )
|
272 |
-
|
273 |
-
$path = $this->htaccess_path( $kind ) ;
|
274 |
|
275 |
if( ! $path || ! file_exists( $path ) ) {
|
276 |
-
return "\n"
|
277 |
}
|
278 |
|
279 |
if ( ! $this->_readable( $kind ) ) {
|
280 |
-
Error::t( 'HTA_R' )
|
281 |
}
|
282 |
|
283 |
-
$content = File::read( $path )
|
284 |
if ( $content === false ) {
|
285 |
-
Error::t( 'HTA_GET' )
|
286 |
}
|
287 |
|
288 |
// Remove ^M characters.
|
289 |
-
$content = str_ireplace( "\x0D", "", $content )
|
290 |
-
return $content
|
291 |
}
|
292 |
|
293 |
/**
|
@@ -298,20 +289,19 @@ class Htaccess extends Instance
|
|
298 |
* @since 1.0.4
|
299 |
* @access public
|
300 |
*/
|
301 |
-
public function htaccess_save( $content, $kind = 'frontend' )
|
302 |
-
|
303 |
-
$path = $this->htaccess_path( $kind ) ;
|
304 |
|
305 |
if ( ! $this->writable( $kind ) ) {
|
306 |
-
Error::t( 'HTA_W' )
|
307 |
}
|
308 |
|
309 |
-
$this->_htaccess_backup( $kind )
|
310 |
|
311 |
// File put contents will truncate by default. Will create file if doesn't exist.
|
312 |
-
$res = File::save( $path, $content, false, false, false )
|
313 |
if ( $res !== true ) {
|
314 |
-
throw new \Exception( $res )
|
315 |
}
|
316 |
}
|
317 |
|
@@ -323,23 +313,22 @@ class Htaccess extends Instance
|
|
323 |
* @since 1.0.10
|
324 |
* @access private
|
325 |
*/
|
326 |
-
private function _htaccess_backup( $kind = 'frontend' )
|
327 |
-
|
328 |
-
$path = $this->htaccess_path( $kind ) ;
|
329 |
|
330 |
if ( ! file_exists( $path ) ) {
|
331 |
-
return
|
332 |
}
|
333 |
|
334 |
if ( file_exists( $path . '.bk' ) ) {
|
335 |
-
return
|
336 |
}
|
337 |
|
338 |
-
$res = copy( $path, $path . '.bk' )
|
339 |
|
340 |
// Failed to backup, abort
|
341 |
if ( ! $res ) {
|
342 |
-
Error::t( 'HTA_BK' )
|
343 |
}
|
344 |
}
|
345 |
|
@@ -350,22 +339,21 @@ class Htaccess extends Instance
|
|
350 |
*
|
351 |
* @since 1.1.0
|
352 |
*/
|
353 |
-
public function current_mobile_agents()
|
354 |
-
|
355 |
-
$rules = $this->_get_rule_by( self::MARKER_MOBILE ) ;
|
356 |
if( ! isset( $rules[ 0 ] ) ) {
|
357 |
-
Error::t( 'HTA_DNF', self::MARKER_MOBILE )
|
358 |
}
|
359 |
|
360 |
-
$rule = trim( $rules[ 0 ] )
|
361 |
-
// 'RewriteCond %{HTTP_USER_AGENT} ' . Utility::arr2regex( $cfg[ $id ], true ) . ' [NC]'
|
362 |
-
$match = substr( $rule, strlen( 'RewriteCond %{HTTP_USER_AGENT} ' ), -strlen( ' [NC]' ) )
|
363 |
|
364 |
if ( ! $match ) {
|
365 |
-
Error::t( 'HTA_DNF', __( 'Mobile Agent Rules', 'litespeed-cache' ) )
|
366 |
}
|
367 |
|
368 |
-
return $match
|
369 |
}
|
370 |
|
371 |
/**
|
@@ -376,28 +364,27 @@ class Htaccess extends Instance
|
|
376 |
* @since 1.1.0
|
377 |
* @access public
|
378 |
*/
|
379 |
-
public function current_login_cookie( $kind = 'frontend' )
|
380 |
-
|
381 |
-
$rule = $this->_get_rule_by( self::MARKER_LOGIN_COOKIE, $kind ) ;
|
382 |
|
383 |
if( ! $rule ) {
|
384 |
-
Error::t( 'HTA_DNF', self::MARKER_LOGIN_COOKIE )
|
385 |
}
|
386 |
|
387 |
if( strpos( $rule, 'RewriteRule .? - [E=' ) !== 0 ) {
|
388 |
-
Error::t( 'HTA_LOGIN_COOKIE_INVALID' )
|
389 |
}
|
390 |
|
391 |
-
$rule_cookie = substr( $rule, strlen( 'RewriteRule .? - [E=' ), -1 )
|
392 |
|
393 |
if ( LITESPEED_SERVER_TYPE === 'LITESPEED_SERVER_OLS' ) {
|
394 |
-
$rule_cookie = trim( $rule_cookie, '"' )
|
395 |
}
|
396 |
|
397 |
// Drop `Cache-Vary:`
|
398 |
-
$rule_cookie = substr( $rule_cookie, strlen( 'Cache-Vary:' ) )
|
399 |
|
400 |
-
return $rule_cookie
|
401 |
}
|
402 |
|
403 |
/**
|
@@ -406,35 +393,34 @@ class Htaccess extends Instance
|
|
406 |
* @since 2.0
|
407 |
* @access private
|
408 |
*/
|
409 |
-
private function _get_rule_by( $cond, $kind = 'frontend' )
|
410 |
-
|
411 |
-
|
412 |
-
$path = $this->htaccess_path( $kind ) ;
|
413 |
if ( ! $this->_readable( $kind ) ) {
|
414 |
-
return false
|
415 |
}
|
416 |
|
417 |
-
$rules = File::extract_from_markers( $path, self::MARKER )
|
418 |
if( ! in_array( $cond . self::MARKER_START, $rules ) || ! in_array( $cond . self::MARKER_END, $rules ) ) {
|
419 |
-
return false
|
420 |
}
|
421 |
|
422 |
-
$key_start = array_search( $cond . self::MARKER_START, $rules )
|
423 |
-
$key_end = array_search( $cond . self::MARKER_END, $rules )
|
424 |
if( $key_start === false || $key_end === false ) {
|
425 |
-
return false
|
426 |
}
|
427 |
|
428 |
-
$results = array_slice( $rules, $key_start + 1, $key_end - $key_start - 1 )
|
429 |
if( ! $results ) {
|
430 |
-
return false
|
431 |
}
|
432 |
|
433 |
if( count( $results ) == 1 ) {
|
434 |
-
return trim( $results[ 0 ] )
|
435 |
}
|
436 |
|
437 |
-
return array_filter( $results )
|
438 |
}
|
439 |
|
440 |
/**
|
@@ -444,14 +430,13 @@ class Htaccess extends Instance
|
|
444 |
* @access private
|
445 |
* @return array Rules set
|
446 |
*/
|
447 |
-
private function _browser_cache_rules( $cfg )
|
448 |
-
{
|
449 |
/**
|
450 |
* Add ttl setting
|
451 |
* @since 1.6.3
|
452 |
*/
|
453 |
-
$id = Base::O_CACHE_TTL_BROWSER
|
454 |
-
$ttl = $cfg[ $id ]
|
455 |
$rules = array(
|
456 |
self::EXPIRES_MODULE_START,
|
457 |
// '<FilesMatch "\.(pdf|ico|svg|xml|jpg|jpeg|png|gif|webp|ogg|mp4|webm|js|css|woff|woff2|ttf|eot)(\.gz)?$">',
|
@@ -488,8 +473,8 @@ class Htaccess extends Instance
|
|
488 |
'',
|
489 |
// '</FilesMatch>',
|
490 |
self::LS_MODULE_END,
|
491 |
-
)
|
492 |
-
return $rules
|
493 |
}
|
494 |
|
495 |
/**
|
@@ -499,15 +484,14 @@ class Htaccess extends Instance
|
|
499 |
* @access private
|
500 |
* @return array Rules set
|
501 |
*/
|
502 |
-
private function _cors_rules()
|
503 |
-
{
|
504 |
return array(
|
505 |
'<FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font\.css)$">',
|
506 |
'<IfModule mod_headers.c>',
|
507 |
'Header set Access-Control-Allow-Origin "*"',
|
508 |
'</IfModule>',
|
509 |
'</FilesMatch>',
|
510 |
-
)
|
511 |
}
|
512 |
|
513 |
/**
|
@@ -518,147 +502,146 @@ class Htaccess extends Instance
|
|
518 |
* @param array $cfg The settings to be used for rewrite rule
|
519 |
* @return array Rules array
|
520 |
*/
|
521 |
-
private function _generate_rules( $cfg )
|
522 |
-
|
523 |
-
$
|
524 |
-
$
|
525 |
-
$
|
526 |
-
$new_rules_backend_nonls = array() ;
|
527 |
|
528 |
// mobile agents
|
529 |
-
$id = Base::O_CACHE_MOBILE_RULES
|
530 |
if ( ! empty( $cfg[ Base::O_CACHE_MOBILE ] ) && ! empty( $cfg[ $id ] ) ) {
|
531 |
-
$new_rules[] = self::MARKER_MOBILE . self::MARKER_START
|
532 |
-
$new_rules[] = 'RewriteCond %{HTTP_USER_AGENT} ' . Utility::arr2regex( $cfg[ $id ], true ) . ' [NC]'
|
533 |
-
$new_rules[] = 'RewriteRule .* - [E=Cache-Control:vary=ismobile]'
|
534 |
-
$new_rules[] = self::MARKER_MOBILE . self::MARKER_END
|
535 |
-
$new_rules[] = ''
|
536 |
}
|
537 |
|
538 |
// nocache cookie
|
539 |
-
$id = Base::O_CACHE_EXC_COOKIES
|
540 |
if ( ! empty( $cfg[ $id ] ) ) {
|
541 |
-
$new_rules[] = self::MARKER_NOCACHE_COOKIES . self::MARKER_START
|
542 |
-
$new_rules[] = 'RewriteCond %{HTTP_COOKIE} ' . Utility::arr2regex( $cfg[ $id ], true )
|
543 |
-
$new_rules[] = 'RewriteRule .* - [E=Cache-Control:no-cache]'
|
544 |
-
$new_rules[] = self::MARKER_NOCACHE_COOKIES . self::MARKER_END
|
545 |
-
$new_rules[] = ''
|
546 |
}
|
547 |
|
548 |
// nocache user agents
|
549 |
-
$id = Base::O_CACHE_EXC_USERAGENTS
|
550 |
if ( ! empty( $cfg[ $id ] ) ) {
|
551 |
-
$new_rules[] = self::MARKER_NOCACHE_USER_AGENTS . self::MARKER_START
|
552 |
-
$new_rules[] = 'RewriteCond %{HTTP_USER_AGENT} ' . Utility::arr2regex( $cfg[ $id ], true )
|
553 |
-
$new_rules[] = 'RewriteRule .* - [E=Cache-Control:no-cache]'
|
554 |
-
$new_rules[] = self::MARKER_NOCACHE_USER_AGENTS . self::MARKER_END
|
555 |
-
$new_rules[] = ''
|
556 |
}
|
557 |
|
558 |
// caching php resource
|
559 |
-
$id = Base::O_CACHE_RES
|
560 |
if ( ! empty( $cfg[ $id ] ) ) {
|
561 |
-
$new_rules[] = $new_rules_backend[] = self::MARKER_CACHE_RESOURCE . self::MARKER_START
|
562 |
-
$new_rules[] = $new_rules_backend[] = 'RewriteRule ' . LSCWP_CONTENT_FOLDER . self::RW_PATTERN_RES . ' - [E=cache-control:max-age=3600]'
|
563 |
-
$new_rules[] = $new_rules_backend[] = self::MARKER_CACHE_RESOURCE . self::MARKER_END
|
564 |
-
$new_rules[] = $new_rules_backend[] = ''
|
565 |
}
|
566 |
|
567 |
// check login cookie
|
568 |
-
$id = Base::O_CACHE_LOGIN_COOKIE
|
569 |
|
570 |
// Need to keep this due to different behavior of OLS when handling response vary header @Sep/22/2018
|
571 |
if ( LITESPEED_SERVER_TYPE === 'LITESPEED_SERVER_OLS' ) {
|
572 |
if ( ! empty( $cfg[ $id ] ) ) {
|
573 |
-
$cfg[ $id ] .= ',wp-postpass_' . COOKIEHASH
|
574 |
}
|
575 |
else {
|
576 |
-
$cfg[ $id ] = 'wp-postpass_' . COOKIEHASH
|
577 |
}
|
578 |
}
|
579 |
|
580 |
-
$tp_cookies = apply_filters( 'litespeed_api_vary', array() )
|
581 |
if ( ! empty( $tp_cookies ) && is_array( $tp_cookies ) ) {
|
582 |
if ( ! empty( $cfg[ $id ] ) ) {
|
583 |
-
$cfg[ $id ] .= ',' . implode( ',', $tp_cookies )
|
584 |
}
|
585 |
else {
|
586 |
-
$cfg[ $id ] = implode( ',', $tp_cookies )
|
587 |
}
|
588 |
}
|
589 |
// frontend and backend
|
590 |
if ( ! empty( $cfg[ $id ] ) ) {
|
591 |
-
$env = 'Cache-Vary:' . $cfg[ $id ]
|
592 |
if ( LITESPEED_SERVER_TYPE === 'LITESPEED_SERVER_OLS' ) {
|
593 |
-
$env = '"' . $env . '"'
|
594 |
}
|
595 |
-
$new_rules[] = $new_rules_backend[] = self::MARKER_LOGIN_COOKIE . self::MARKER_START
|
596 |
-
$new_rules[] = $new_rules_backend[] = 'RewriteRule .? - [E=' . $env . ']'
|
597 |
-
$new_rules[] = $new_rules_backend[] = self::MARKER_LOGIN_COOKIE . self::MARKER_END
|
598 |
-
$new_rules[] = ''
|
599 |
}
|
600 |
|
601 |
// favicon
|
602 |
// frontend and backend
|
603 |
-
$id = Base::O_CACHE_FAVICON
|
604 |
if ( ! empty( $cfg[ $id ] ) ) {
|
605 |
-
$new_rules[] = $new_rules_backend[] = self::MARKER_FAVICON . self::MARKER_START
|
606 |
-
$new_rules[] = $new_rules_backend[] = 'RewriteRule favicon\.ico$ - [E=cache-control:max-age=86400]'
|
607 |
-
$new_rules[] = $new_rules_backend[] = self::MARKER_FAVICON . self::MARKER_END
|
608 |
-
$new_rules[] = ''
|
609 |
}
|
610 |
|
611 |
// CORS font rules
|
612 |
-
$id = Base::O_CDN
|
613 |
if ( ! empty( $cfg[ $id ] ) ) {
|
614 |
-
$new_rules[] = self::MARKER_CORS . self::MARKER_START
|
615 |
-
$new_rules = array_merge( $new_rules, $this->_cors_rules() )
|
616 |
-
$new_rules[] = self::MARKER_CORS . self::MARKER_END
|
617 |
-
$new_rules[] = ''
|
618 |
}
|
619 |
|
620 |
// webp support
|
621 |
-
$id = Base::O_IMG_OPTM_WEBP_REPLACE
|
622 |
if ( ! empty( $cfg[ $id ] ) ) {
|
623 |
-
$new_rules[] = self::MARKER_WEBP . self::MARKER_START
|
624 |
-
$new_rules[] = 'RewriteCond %{HTTP_ACCEPT} "image/webp" [or]'
|
625 |
-
$new_rules[] = 'RewriteCond %{HTTP_USER_AGENT} "Page Speed"'
|
626 |
-
$new_rules[] = 'RewriteRule .* - [E=Cache-Control:vary=%{ENV:LSCACHE_VARY_VALUE}+webp]'
|
627 |
-
$new_rules[] = self::MARKER_WEBP . self::MARKER_END
|
628 |
-
$new_rules[] = ''
|
629 |
}
|
630 |
|
631 |
// drop qs support
|
632 |
-
$id = Base::O_CACHE_DROP_QS
|
633 |
if ( ! empty( $cfg[ $id ] ) ) {
|
634 |
-
$new_rules[] = self::MARKER_DROPQS . self::MARKER_START
|
635 |
foreach ( $cfg[ $id ] as $v ) {
|
636 |
-
$new_rules[] = 'CacheKeyModify -qs:' . $v
|
637 |
}
|
638 |
-
$new_rules[] = self::MARKER_DROPQS . self::MARKER_END
|
639 |
-
$new_rules[] = ''
|
640 |
}
|
641 |
|
642 |
// Browser cache
|
643 |
-
$id = Base::O_CACHE_BROWSER
|
644 |
if ( ! empty( $cfg[ $id ] ) ) {
|
645 |
-
$new_rules_nonls[] = $new_rules_backend_nonls[] = self::MARKER_BROWSER_CACHE . self::MARKER_START
|
646 |
-
$new_rules_nonls = array_merge( $new_rules_nonls, $this->_browser_cache_rules( $cfg ) )
|
647 |
-
$new_rules_backend_nonls = array_merge( $new_rules_backend_nonls, $this->_browser_cache_rules( $cfg ) )
|
648 |
-
$new_rules_nonls[] = $new_rules_backend_nonls[] = self::MARKER_BROWSER_CACHE . self::MARKER_END
|
649 |
-
$new_rules_nonls[] = ''
|
650 |
}
|
651 |
|
652 |
// Add module wrapper for LiteSpeed rules
|
653 |
if ( $new_rules ) {
|
654 |
-
$new_rules = $this->_wrap_ls_module( $new_rules )
|
655 |
}
|
656 |
|
657 |
if ( $new_rules_backend ) {
|
658 |
-
$new_rules_backend = $this->_wrap_ls_module( $new_rules_backend )
|
659 |
}
|
660 |
|
661 |
-
return array( $new_rules, $new_rules_backend, $new_rules_nonls, $new_rules_backend_nonls )
|
662 |
}
|
663 |
|
664 |
/**
|
@@ -667,15 +650,14 @@ class Htaccess extends Instance
|
|
667 |
* @since 2.1.1
|
668 |
* @access private
|
669 |
*/
|
670 |
-
private function _wrap_ls_module( $rules = array() )
|
671 |
-
{
|
672 |
return array_merge(
|
673 |
array( self::LS_MODULE_START ),
|
674 |
$this->__rewrite_on,
|
675 |
array( '' ),
|
676 |
$rules,
|
677 |
array( self::LS_MODULE_END )
|
678 |
-
)
|
679 |
}
|
680 |
|
681 |
/**
|
@@ -684,10 +666,9 @@ class Htaccess extends Instance
|
|
684 |
* @since 2.1.1
|
685 |
* @access public
|
686 |
*/
|
687 |
-
public function insert_ls_wrapper()
|
688 |
-
|
689 |
-
$
|
690 |
-
$this->_insert_wrapper( $rules ) ;
|
691 |
}
|
692 |
|
693 |
/**
|
@@ -697,20 +678,19 @@ class Htaccess extends Instance
|
|
697 |
* @param array $rules
|
698 |
* @return array wrapped rules with module info
|
699 |
*/
|
700 |
-
private function _wrap_do_no_edit( $rules )
|
701 |
-
{
|
702 |
// When to clear rules, don't need DONOTEDIT msg
|
703 |
if ( $rules === false || ! is_array( $rules ) ) {
|
704 |
-
return $rules
|
705 |
}
|
706 |
|
707 |
$rules = array_merge(
|
708 |
array( self::LS_MODULE_DONOTEDIT ),
|
709 |
$rules,
|
710 |
array( self::LS_MODULE_DONOTEDIT )
|
711 |
-
)
|
712 |
|
713 |
-
return $rules
|
714 |
}
|
715 |
|
716 |
/**
|
@@ -721,20 +701,19 @@ class Htaccess extends Instance
|
|
721 |
* @since 1.1.0
|
722 |
* @access private
|
723 |
*/
|
724 |
-
private function _insert_wrapper( $rules = array(), $kind = false, $marker = false )
|
725 |
-
{
|
726 |
if ( $kind != 'backend' ) {
|
727 |
-
$kind = 'frontend'
|
728 |
}
|
729 |
|
730 |
// Default marker is LiteSpeed marker `LSCACHE`
|
731 |
if ( $marker === false ) {
|
732 |
-
$marker = self::MARKER
|
733 |
}
|
734 |
|
735 |
-
$this->_htaccess_backup( $kind )
|
736 |
|
737 |
-
File::insert_with_markers( $this->htaccess_path( $kind ), $this->_wrap_do_no_edit( $rules ), $marker, true )
|
738 |
}
|
739 |
|
740 |
/**
|
@@ -745,70 +724,69 @@ class Htaccess extends Instance
|
|
745 |
* @since 1.3
|
746 |
* @access public
|
747 |
*/
|
748 |
-
public function update( $cfg )
|
749 |
-
|
750 |
-
list( $frontend_rules, $backend_rules, $frontend_rules_nonls, $backend_rules_nonls ) = $this->_generate_rules( $cfg ) ;
|
751 |
|
752 |
// Check frontend content
|
753 |
-
list( $rules, $rules_nonls ) = $this->_extract_rules()
|
754 |
|
755 |
// Check Non-LiteSpeed rules
|
756 |
if ( $this->_wrap_do_no_edit( $frontend_rules_nonls ) != $rules_nonls ) {
|
757 |
-
Debug2::debug( '[Rules] Update non-ls frontend rules' )
|
758 |
// Need to update frontend htaccess
|
759 |
try {
|
760 |
-
$this->_insert_wrapper( $frontend_rules_nonls, false, self::MARKER_NONLS )
|
761 |
} catch ( \Exception $e ) {
|
762 |
-
$manual_guide_codes = $this->_rewrite_codes_msg( $this->frontend_htaccess, $frontend_rules_nonls, self::MARKER_NONLS )
|
763 |
-
Debug2::debug( '[Rules] Update Failed' )
|
764 |
-
throw new \Exception( $manual_guide_codes )
|
765 |
}
|
766 |
}
|
767 |
|
768 |
// Check LiteSpeed rules
|
769 |
if ( $this->_wrap_do_no_edit( $frontend_rules ) != $rules ) {
|
770 |
-
Debug2::debug( '[Rules] Update frontend rules' )
|
771 |
// Need to update frontend htaccess
|
772 |
try {
|
773 |
-
$this->_insert_wrapper( $frontend_rules )
|
774 |
} catch ( \Exception $e ) {
|
775 |
-
Debug2::debug( '[Rules] Update Failed' )
|
776 |
-
$manual_guide_codes = $this->_rewrite_codes_msg( $this->frontend_htaccess, $frontend_rules )
|
777 |
-
throw new \Exception( $manual_guide_codes )
|
778 |
}
|
779 |
}
|
780 |
|
781 |
if ( $this->frontend_htaccess !== $this->backend_htaccess ) {
|
782 |
-
list( $rules, $rules_nonls ) = $this->_extract_rules( 'backend' )
|
783 |
|
784 |
// Check Non-LiteSpeed rules for backend
|
785 |
if ( $this->_wrap_do_no_edit( $backend_rules_nonls ) != $rules_nonls ) {
|
786 |
-
Debug2::debug( '[Rules] Update non-ls backend rules' )
|
787 |
// Need to update frontend htaccess
|
788 |
try {
|
789 |
-
$this->_insert_wrapper( $backend_rules_nonls, 'backend', self::MARKER_NONLS )
|
790 |
} catch ( \Exception $e ) {
|
791 |
-
Debug2::debug( '[Rules] Update Failed' )
|
792 |
-
$manual_guide_codes = $this->_rewrite_codes_msg( $this->backend_htaccess, $backend_rules_nonls, self::MARKER_NONLS )
|
793 |
-
throw new \Exception( $manual_guide_codes )
|
794 |
}
|
795 |
}
|
796 |
|
797 |
// Check backend content
|
798 |
if ( $this->_wrap_do_no_edit( $backend_rules ) != $rules ) {
|
799 |
-
Debug2::debug( '[Rules] Update backend rules' )
|
800 |
// Need to update backend htaccess
|
801 |
try {
|
802 |
-
$this->_insert_wrapper( $backend_rules, 'backend' )
|
803 |
} catch ( \Exception $e ) {
|
804 |
-
Debug2::debug( '[Rules] Update Failed' )
|
805 |
-
$manual_guide_codes = $this->_rewrite_codes_msg( $this->backend_htaccess, $backend_rules )
|
806 |
-
throw new \Exception( $manual_guide_codes )
|
807 |
}
|
808 |
}
|
809 |
}
|
810 |
|
811 |
-
return true
|
812 |
}
|
813 |
|
814 |
/**
|
@@ -820,18 +798,17 @@ class Htaccess extends Instance
|
|
820 |
* @access private
|
821 |
* @param string $kind Frontend or backend .htaccess file
|
822 |
*/
|
823 |
-
private function _extract_rules( $kind = 'frontend' )
|
824 |
-
|
825 |
-
|
826 |
-
$path = $this->htaccess_path( $kind ) ;
|
827 |
if ( ! $this->_readable( $kind ) ) {
|
828 |
-
Error::t( 'E_HTA_R' )
|
829 |
}
|
830 |
|
831 |
-
$rules = File::extract_from_markers( $path, self::MARKER )
|
832 |
-
$rules_nonls = File::extract_from_markers( $path, self::MARKER_NONLS )
|
833 |
|
834 |
-
return array( $rules, $rules_nonls )
|
835 |
}
|
836 |
|
837 |
/**
|
@@ -842,12 +819,11 @@ class Htaccess extends Instance
|
|
842 |
* @param array $rules
|
843 |
* @return string final msg to output
|
844 |
*/
|
845 |
-
private function _rewrite_codes_msg( $file, $rules, $marker = false )
|
846 |
-
{
|
847 |
return sprintf( __( '<p>Please add/replace the following codes into the beginning of %1$s:</p> %2$s' , 'litespeed-cache' ),
|
848 |
$file,
|
849 |
'<textarea style="width:100%;" rows="10" readonly>' . htmlspecialchars( $this->_wrap_rules_with_marker( $rules, $marker ) ) . '</textarea>'
|
850 |
-
)
|
851 |
}
|
852 |
|
853 |
/**
|
@@ -855,22 +831,21 @@ class Htaccess extends Instance
|
|
855 |
*
|
856 |
* @since 1.1.5
|
857 |
*/
|
858 |
-
private function _wrap_rules_with_marker( $rules, $marker = false )
|
859 |
-
{
|
860 |
// Default marker is LiteSpeed marker `LSCACHE`
|
861 |
if ( $marker === false ) {
|
862 |
-
$marker = self::MARKER
|
863 |
}
|
864 |
|
865 |
-
$start_marker = "# BEGIN {$marker}"
|
866 |
-
$end_marker = "# END {$marker}"
|
867 |
$new_file_data = implode( "\n", array_merge(
|
868 |
array( $start_marker ),
|
869 |
$this->_wrap_do_no_edit($rules),
|
870 |
array( $end_marker )
|
871 |
-
) )
|
872 |
|
873 |
-
return $new_file_data
|
874 |
}
|
875 |
|
876 |
/**
|
@@ -879,15 +854,14 @@ class Htaccess extends Instance
|
|
879 |
* @since 1.0.4
|
880 |
* @access public
|
881 |
*/
|
882 |
-
public function clear_rules()
|
883 |
-
|
884 |
-
$this->_insert_wrapper( false ) ;// Use false to avoid do-not-edit msg
|
885 |
// Clear non ls rules
|
886 |
-
$this->_insert_wrapper( false, false, self::MARKER_NONLS )
|
887 |
|
888 |
if ( $this->frontend_htaccess !== $this->backend_htaccess ) {
|
889 |
-
$this->_insert_wrapper( false, 'backend' )
|
890 |
-
$this->_insert_wrapper( false, 'backend', self::MARKER_NONLS )
|
891 |
}
|
892 |
}
|
893 |
|
@@ -899,22 +873,21 @@ class Htaccess extends Instance
|
|
899 |
* @since 2.9 Used exception when saving
|
900 |
* @access public
|
901 |
*/
|
902 |
-
public function htaccess_editor_save()
|
903 |
-
{
|
904 |
if ( ! isset( $_POST[ self::EDITOR_TEXTAREA_NAME ] ) ) {
|
905 |
-
return
|
906 |
}
|
907 |
|
908 |
-
$content = Admin::cleanup_text($_POST[self::EDITOR_TEXTAREA_NAME])
|
909 |
|
910 |
try {
|
911 |
-
$this->htaccess_save($content)
|
912 |
} catch( \Exception $e ) {
|
913 |
-
Admin_Display::error( $e->getMessage() )
|
914 |
-
return
|
915 |
}
|
916 |
|
917 |
-
Admin_Display::succeed( __( 'File Saved.', 'litespeed-cache' ) )
|
918 |
|
919 |
}
|
920 |
}
|
8 |
* @subpackage LiteSpeed/inc
|
9 |
* @author LiteSpeed Technologies <info@litespeedtech.com>
|
10 |
*/
|
11 |
+
namespace LiteSpeed;
|
12 |
+
|
13 |
+
defined( 'WPINC' ) || exit;
|
14 |
+
|
15 |
+
class Htaccess extends Instance {
|
16 |
+
protected static $_instance;
|
17 |
+
|
18 |
+
const EDITOR_TEXTAREA_NAME = 'lscwp_ht_editor';
|
19 |
+
|
20 |
+
private $frontend_htaccess = null;
|
21 |
+
private $_default_frontend_htaccess = null;
|
22 |
+
private $backend_htaccess = null;
|
23 |
+
private $_default_backend_htaccess = null;
|
24 |
+
private $theme_htaccess = null;// Not used yet
|
25 |
+
private $frontend_htaccess_readable = false;
|
26 |
+
private $frontend_htaccess_writable = false;
|
27 |
+
private $backend_htaccess_readable = false;
|
28 |
+
private $backend_htaccess_writable = false;
|
29 |
+
private $theme_htaccess_readable = false;
|
30 |
+
private $theme_htaccess_writable = false;
|
31 |
+
private $__rewrite_on;
|
32 |
+
|
33 |
+
const LS_MODULE_START = '<IfModule LiteSpeed>';
|
34 |
+
const EXPIRES_MODULE_START = '<IfModule mod_expires.c>';
|
35 |
+
const LS_MODULE_END = '</IfModule>';
|
36 |
+
const LS_MODULE_REWRITE_START = '<IfModule mod_rewrite.c>';
|
37 |
+
const REWRITE_ON = 'RewriteEngine on';
|
38 |
+
const LS_MODULE_DONOTEDIT = "## LITESPEED WP CACHE PLUGIN - Do not edit the contents of this block! ##";
|
39 |
+
const MARKER = 'LSCACHE';
|
40 |
+
const MARKER_NONLS = 'NON_LSCACHE';
|
41 |
+
const MARKER_LOGIN_COOKIE = '### marker LOGIN COOKIE';
|
42 |
+
const MARKER_MOBILE = '### marker MOBILE';
|
43 |
+
const MARKER_NOCACHE_COOKIES = '### marker NOCACHE COOKIES';
|
44 |
+
const MARKER_NOCACHE_USER_AGENTS = '### marker NOCACHE USER AGENTS';
|
45 |
+
const MARKER_CACHE_RESOURCE = '### marker CACHE RESOURCE';
|
46 |
+
const MARKER_FAVICON = '### marker FAVICON';
|
47 |
+
const MARKER_BROWSER_CACHE = '### marker BROWSER CACHE';
|
48 |
+
const MARKER_MINIFY = '### marker MINIFY';
|
49 |
+
const MARKER_CORS = '### marker CORS';
|
50 |
+
const MARKER_WEBP = '### marker WEBP';
|
51 |
+
const MARKER_DROPQS = '### marker DROPQS';
|
52 |
+
const MARKER_START = ' start ###';
|
53 |
+
const MARKER_END = ' end ###';
|
54 |
+
|
55 |
+
const RW_PATTERN_RES = '/.*/[^/]*(responsive|css|js|dynamic|loader|fonts)\.php';
|
|
|
56 |
|
57 |
/**
|
58 |
* Initialize the class and set its properties.
|
60 |
* @since 1.0.7
|
61 |
* @access protected
|
62 |
*/
|
63 |
+
protected function __construct() {
|
64 |
+
$this->_path_set();
|
65 |
+
$this->_default_frontend_htaccess = $this->frontend_htaccess;
|
66 |
+
$this->_default_backend_htaccess = $this->backend_htaccess;
|
|
|
67 |
|
68 |
$frontend_htaccess = Conf::val( Base::O_MISC_HTACCESS_FRONT );
|
69 |
if ( $frontend_htaccess && substr( $frontend_htaccess, -10 ) === '/.htaccess' ) {
|
75 |
}
|
76 |
|
77 |
// Filter for frontend&backend htaccess path
|
78 |
+
$this->frontend_htaccess = apply_filters( 'litespeed_frontend_htaccess', $this->frontend_htaccess );
|
79 |
+
$this->backend_htaccess = apply_filters( 'litespeed_backend_htaccess', $this->backend_htaccess );
|
80 |
|
81 |
+
clearstatcache();
|
82 |
|
83 |
// frontend .htaccess privilege
|
84 |
+
$test_permissions = file_exists( $this->frontend_htaccess ) ? $this->frontend_htaccess : dirname( $this->frontend_htaccess );
|
85 |
if ( is_readable( $test_permissions ) ) {
|
86 |
+
$this->frontend_htaccess_readable = true;
|
87 |
}
|
88 |
if ( is_writable( $test_permissions ) ) {
|
89 |
+
$this->frontend_htaccess_writable = true;
|
90 |
}
|
91 |
|
92 |
$this->__rewrite_on = array(
|
93 |
self::REWRITE_ON,
|
94 |
"CacheLookup on",
|
95 |
"RewriteRule .* - [E=Cache-Control:no-autoflush]",
|
96 |
+
);
|
97 |
|
98 |
// backend .htaccess privilege
|
99 |
if ( $this->frontend_htaccess === $this->backend_htaccess ) {
|
100 |
+
$this->backend_htaccess_readable = $this->frontend_htaccess_readable;
|
101 |
+
$this->backend_htaccess_writable = $this->frontend_htaccess_writable;
|
102 |
}
|
103 |
else {
|
104 |
+
$test_permissions = file_exists( $this->backend_htaccess ) ? $this->backend_htaccess : dirname( $this->backend_htaccess );
|
105 |
if ( is_readable( $test_permissions ) ) {
|
106 |
+
$this->backend_htaccess_readable = true;
|
107 |
}
|
108 |
if ( is_writable( $test_permissions ) ) {
|
109 |
+
$this->backend_htaccess_writable = true;
|
110 |
}
|
111 |
}
|
112 |
}
|
117 |
* @since 1.1.0
|
118 |
* @return string
|
119 |
*/
|
120 |
+
private function _readable( $kind = 'frontend' ) {
|
|
|
121 |
if( $kind === 'frontend' ) {
|
122 |
+
return $this->frontend_htaccess_readable;
|
123 |
}
|
124 |
if( $kind === 'backend' ) {
|
125 |
+
return $this->backend_htaccess_readable;
|
126 |
}
|
127 |
}
|
128 |
|
132 |
* @since 1.1.0
|
133 |
* @return string
|
134 |
*/
|
135 |
+
public function writable( $kind = 'frontend' ) {
|
|
|
136 |
if( $kind === 'frontend' ) {
|
137 |
+
return $this->frontend_htaccess_writable;
|
138 |
}
|
139 |
if( $kind === 'backend' ) {
|
140 |
+
return $this->backend_htaccess_writable;
|
141 |
}
|
142 |
}
|
143 |
|
147 |
* @since 1.1.0
|
148 |
* @return string
|
149 |
*/
|
150 |
+
public static function get_frontend_htaccess( $show_default = false ) {
|
|
|
151 |
if ( $show_default ) {
|
152 |
+
return self::get_instance()->_default_frontend_htaccess;
|
153 |
}
|
154 |
+
return self::get_instance()->frontend_htaccess;
|
155 |
}
|
156 |
|
157 |
/**
|
160 |
* @since 1.1.0
|
161 |
* @return string
|
162 |
*/
|
163 |
+
public static function get_backend_htaccess( $show_default = false ) {
|
|
|
164 |
if ( $show_default ) {
|
165 |
+
return self::get_instance()->_default_backend_htaccess;
|
166 |
}
|
167 |
+
return self::get_instance()->backend_htaccess;
|
168 |
}
|
169 |
|
170 |
/**
|
201 |
* @since 1.0.11
|
202 |
* @access private
|
203 |
*/
|
204 |
+
private function _path_set() {
|
205 |
+
$frontend = Router::frontend_path();
|
206 |
+
$frontend_htaccess_search = $this->_htaccess_search( $frontend );// The existing .htaccess path to be used for frontend .htaccess
|
207 |
+
$this->frontend_htaccess = ( $frontend_htaccess_search ?: $frontend ) . '/.htaccess';
|
|
|
208 |
|
209 |
+
$backend = realpath( ABSPATH ); // /home/user/public_html/backend/
|
210 |
if ( $frontend == $backend ) {
|
211 |
+
$this->backend_htaccess = $this->frontend_htaccess;
|
212 |
+
return;
|
213 |
}
|
214 |
|
215 |
// Backend is a different path
|
216 |
+
$backend_htaccess_search = $this->_htaccess_search( $backend );
|
217 |
// Found affected .htaccess
|
218 |
if ( $backend_htaccess_search ) {
|
219 |
+
$this->backend_htaccess = $backend_htaccess_search . '/.htaccess';
|
220 |
+
return;
|
221 |
}
|
222 |
|
223 |
// Frontend path is the parent of backend path
|
224 |
if ( stripos( $backend, $frontend . '/' ) === 0 ) {
|
225 |
// backend use frontend htaccess
|
226 |
+
$this->backend_htaccess = $this->frontend_htaccess;
|
227 |
+
return;
|
228 |
}
|
229 |
|
230 |
+
$this->backend_htaccess = $backend . '/.htaccess';
|
231 |
}
|
232 |
|
233 |
/**
|
237 |
* @param string $kind Frontend or backend
|
238 |
* @return string Path
|
239 |
*/
|
240 |
+
public function htaccess_path( $kind = 'frontend' ) {
|
|
|
241 |
switch ( $kind ) {
|
242 |
case 'backend' :
|
243 |
+
$path = $this->backend_htaccess;
|
244 |
+
break;
|
245 |
|
246 |
case 'frontend' :
|
247 |
default :
|
248 |
+
$path = $this->frontend_htaccess;
|
249 |
+
break;
|
250 |
}
|
251 |
+
return $path;
|
252 |
}
|
253 |
|
254 |
/**
|
260 |
* @since 2.9 Used exception for failed reading
|
261 |
* @access public
|
262 |
*/
|
263 |
+
public function htaccess_read( $kind = 'frontend' ) {
|
264 |
+
$path = $this->htaccess_path( $kind );
|
|
|
265 |
|
266 |
if( ! $path || ! file_exists( $path ) ) {
|
267 |
+
return "\n";
|
268 |
}
|
269 |
|
270 |
if ( ! $this->_readable( $kind ) ) {
|
271 |
+
Error::t( 'HTA_R' );
|
272 |
}
|
273 |
|
274 |
+
$content = File::read( $path );
|
275 |
if ( $content === false ) {
|
276 |
+
Error::t( 'HTA_GET' );
|
277 |
}
|
278 |
|
279 |
// Remove ^M characters.
|
280 |
+
$content = str_ireplace( "\x0D", "", $content );
|
281 |
+
return $content;
|
282 |
}
|
283 |
|
284 |
/**
|
289 |
* @since 1.0.4
|
290 |
* @access public
|
291 |
*/
|
292 |
+
public function htaccess_save( $content, $kind = 'frontend' ) {
|
293 |
+
$path = $this->htaccess_path( $kind );
|
|
|
294 |
|
295 |
if ( ! $this->writable( $kind ) ) {
|
296 |
+
Error::t( 'HTA_W' );
|
297 |
}
|
298 |
|
299 |
+
$this->_htaccess_backup( $kind );
|
300 |
|
301 |
// File put contents will truncate by default. Will create file if doesn't exist.
|
302 |
+
$res = File::save( $path, $content, false, false, false );
|
303 |
if ( $res !== true ) {
|
304 |
+
throw new \Exception( $res );
|
305 |
}
|
306 |
}
|
307 |
|
313 |
* @since 1.0.10
|
314 |
* @access private
|
315 |
*/
|
316 |
+
private function _htaccess_backup( $kind = 'frontend' ) {
|
317 |
+
$path = $this->htaccess_path( $kind );
|
|
|
318 |
|
319 |
if ( ! file_exists( $path ) ) {
|
320 |
+
return;
|
321 |
}
|
322 |
|
323 |
if ( file_exists( $path . '.bk' ) ) {
|
324 |
+
return;
|
325 |
}
|
326 |
|
327 |
+
$res = copy( $path, $path . '.bk' );
|
328 |
|
329 |
// Failed to backup, abort
|
330 |
if ( ! $res ) {
|
331 |
+
Error::t( 'HTA_BK' );
|
332 |
}
|
333 |
}
|
334 |
|
339 |
*
|
340 |
* @since 1.1.0
|
341 |
*/
|
342 |
+
public function current_mobile_agents() {
|
343 |
+
$rules = $this->_get_rule_by( self::MARKER_MOBILE );
|
|
|
344 |
if( ! isset( $rules[ 0 ] ) ) {
|
345 |
+
Error::t( 'HTA_DNF', self::MARKER_MOBILE );
|
346 |
}
|
347 |
|
348 |
+
$rule = trim( $rules[ 0 ] );
|
349 |
+
// 'RewriteCond %{HTTP_USER_AGENT} ' . Utility::arr2regex( $cfg[ $id ], true ) . ' [NC]';
|
350 |
+
$match = substr( $rule, strlen( 'RewriteCond %{HTTP_USER_AGENT} ' ), -strlen( ' [NC]' ) );
|
351 |
|
352 |
if ( ! $match ) {
|
353 |
+
Error::t( 'HTA_DNF', __( 'Mobile Agent Rules', 'litespeed-cache' ) );
|
354 |
}
|
355 |
|
356 |
+
return $match;
|
357 |
}
|
358 |
|
359 |
/**
|
364 |
* @since 1.1.0
|
365 |
* @access public
|
366 |
*/
|
367 |
+
public function current_login_cookie( $kind = 'frontend' ) {
|
368 |
+
$rule = $this->_get_rule_by( self::MARKER_LOGIN_COOKIE, $kind );
|
|
|
369 |
|
370 |
if( ! $rule ) {
|
371 |
+
Error::t( 'HTA_DNF', self::MARKER_LOGIN_COOKIE );
|
372 |
}
|
373 |
|
374 |
if( strpos( $rule, 'RewriteRule .? - [E=' ) !== 0 ) {
|
375 |
+
Error::t( 'HTA_LOGIN_COOKIE_INVALID' );
|
376 |
}
|
377 |
|
378 |
+
$rule_cookie = substr( $rule, strlen( 'RewriteRule .? - [E=' ), -1 );
|
379 |
|
380 |
if ( LITESPEED_SERVER_TYPE === 'LITESPEED_SERVER_OLS' ) {
|
381 |
+
$rule_cookie = trim( $rule_cookie, '"' );
|
382 |
}
|
383 |
|
384 |
// Drop `Cache-Vary:`
|
385 |
+
$rule_cookie = substr( $rule_cookie, strlen( 'Cache-Vary:' ) );
|
386 |
|
387 |
+
return $rule_cookie;
|
388 |
}
|
389 |
|
390 |
/**
|
393 |
* @since 2.0
|
394 |
* @access private
|
395 |
*/
|
396 |
+
private function _get_rule_by( $cond, $kind = 'frontend' ) {
|
397 |
+
clearstatcache();
|
398 |
+
$path = $this->htaccess_path( $kind );
|
|
|
399 |
if ( ! $this->_readable( $kind ) ) {
|
400 |
+
return false;
|
401 |
}
|
402 |
|
403 |
+
$rules = File::extract_from_markers( $path, self::MARKER );
|
404 |
if( ! in_array( $cond . self::MARKER_START, $rules ) || ! in_array( $cond . self::MARKER_END, $rules ) ) {
|
405 |
+
return false;
|
406 |
}
|
407 |
|
408 |
+
$key_start = array_search( $cond . self::MARKER_START, $rules );
|
409 |
+
$key_end = array_search( $cond . self::MARKER_END, $rules );
|
410 |
if( $key_start === false || $key_end === false ) {
|
411 |
+
return false;
|
412 |
}
|
413 |
|
414 |
+
$results = array_slice( $rules, $key_start + 1, $key_end - $key_start - 1 );
|
415 |
if( ! $results ) {
|
416 |
+
return false;
|
417 |
}
|
418 |
|
419 |
if( count( $results ) == 1 ) {
|
420 |
+
return trim( $results[ 0 ] );
|
421 |
}
|
422 |
|
423 |
+
return array_filter( $results );
|
424 |
}
|
425 |
|
426 |
/**
|
430 |
* @access private
|
431 |
* @return array Rules set
|
432 |
*/
|
433 |
+
private function _browser_cache_rules( $cfg ) {
|
|
|
434 |
/**
|
435 |
* Add ttl setting
|
436 |
* @since 1.6.3
|
437 |
*/
|
438 |
+
$id = Base::O_CACHE_TTL_BROWSER;
|
439 |
+
$ttl = $cfg[ $id ];
|
440 |
$rules = array(
|
441 |
self::EXPIRES_MODULE_START,
|
442 |
// '<FilesMatch "\.(pdf|ico|svg|xml|jpg|jpeg|png|gif|webp|ogg|mp4|webm|js|css|woff|woff2|ttf|eot)(\.gz)?$">',
|
473 |
'',
|
474 |
// '</FilesMatch>',
|
475 |
self::LS_MODULE_END,
|
476 |
+
);
|
477 |
+
return $rules;
|
478 |
}
|
479 |
|
480 |
/**
|
484 |
* @access private
|
485 |
* @return array Rules set
|
486 |
*/
|
487 |
+
private function _cors_rules() {
|
|
|
488 |
return array(
|
489 |
'<FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font\.css)$">',
|
490 |
'<IfModule mod_headers.c>',
|
491 |
'Header set Access-Control-Allow-Origin "*"',
|
492 |
'</IfModule>',
|
493 |
'</FilesMatch>',
|
494 |
+
);
|
495 |
}
|
496 |
|
497 |
/**
|
502 |
* @param array $cfg The settings to be used for rewrite rule
|
503 |
* @return array Rules array
|
504 |
*/
|
505 |
+
private function _generate_rules( $cfg ) {
|
506 |
+
$new_rules = array();
|
507 |
+
$new_rules_nonls = array();
|
508 |
+
$new_rules_backend = array();
|
509 |
+
$new_rules_backend_nonls = array();
|
|
|
510 |
|
511 |
// mobile agents
|
512 |
+
$id = Base::O_CACHE_MOBILE_RULES;
|
513 |
if ( ! empty( $cfg[ Base::O_CACHE_MOBILE ] ) && ! empty( $cfg[ $id ] ) ) {
|
514 |
+
$new_rules[] = self::MARKER_MOBILE . self::MARKER_START;
|
515 |
+
$new_rules[] = 'RewriteCond %{HTTP_USER_AGENT} ' . Utility::arr2regex( $cfg[ $id ], true ) . ' [NC]';
|
516 |
+
$new_rules[] = 'RewriteRule .* - [E=Cache-Control:vary=ismobile]';
|
517 |
+
$new_rules[] = self::MARKER_MOBILE . self::MARKER_END;
|
518 |
+
$new_rules[] = '';
|
519 |
}
|
520 |
|
521 |
// nocache cookie
|
522 |
+
$id = Base::O_CACHE_EXC_COOKIES;
|
523 |
if ( ! empty( $cfg[ $id ] ) ) {
|
524 |
+
$new_rules[] = self::MARKER_NOCACHE_COOKIES . self::MARKER_START;
|
525 |
+
$new_rules[] = 'RewriteCond %{HTTP_COOKIE} ' . Utility::arr2regex( $cfg[ $id ], true );
|
526 |
+
$new_rules[] = 'RewriteRule .* - [E=Cache-Control:no-cache]';
|
527 |
+
$new_rules[] = self::MARKER_NOCACHE_COOKIES . self::MARKER_END;
|
528 |
+
$new_rules[] = '';
|
529 |
}
|
530 |
|
531 |
// nocache user agents
|
532 |
+
$id = Base::O_CACHE_EXC_USERAGENTS;
|
533 |
if ( ! empty( $cfg[ $id ] ) ) {
|
534 |
+
$new_rules[] = self::MARKER_NOCACHE_USER_AGENTS . self::MARKER_START;
|
535 |
+
$new_rules[] = 'RewriteCond %{HTTP_USER_AGENT} ' . Utility::arr2regex( $cfg[ $id ], true );
|
536 |
+
$new_rules[] = 'RewriteRule .* - [E=Cache-Control:no-cache]';
|
537 |
+
$new_rules[] = self::MARKER_NOCACHE_USER_AGENTS . self::MARKER_END;
|
538 |
+
$new_rules[] = '';
|
539 |
}
|
540 |
|
541 |
// caching php resource
|
542 |
+
$id = Base::O_CACHE_RES;
|
543 |
if ( ! empty( $cfg[ $id ] ) ) {
|
544 |
+
$new_rules[] = $new_rules_backend[] = self::MARKER_CACHE_RESOURCE . self::MARKER_START;
|
545 |
+
$new_rules[] = $new_rules_backend[] = 'RewriteRule ' . LSCWP_CONTENT_FOLDER . self::RW_PATTERN_RES . ' - [E=cache-control:max-age=3600]';
|
546 |
+
$new_rules[] = $new_rules_backend[] = self::MARKER_CACHE_RESOURCE . self::MARKER_END;
|
547 |
+
$new_rules[] = $new_rules_backend[] = '';
|
548 |
}
|
549 |
|
550 |
// check login cookie
|
551 |
+
$id = Base::O_CACHE_LOGIN_COOKIE;
|
552 |
|
553 |
// Need to keep this due to different behavior of OLS when handling response vary header @Sep/22/2018
|
554 |
if ( LITESPEED_SERVER_TYPE === 'LITESPEED_SERVER_OLS' ) {
|
555 |
if ( ! empty( $cfg[ $id ] ) ) {
|
556 |
+
$cfg[ $id ] .= ',wp-postpass_' . COOKIEHASH;
|
557 |
}
|
558 |
else {
|
559 |
+
$cfg[ $id ] = 'wp-postpass_' . COOKIEHASH;
|
560 |
}
|
561 |
}
|
562 |
|
563 |
+
$tp_cookies = apply_filters( 'litespeed_api_vary', array() );
|
564 |
if ( ! empty( $tp_cookies ) && is_array( $tp_cookies ) ) {
|
565 |
if ( ! empty( $cfg[ $id ] ) ) {
|
566 |
+
$cfg[ $id ] .= ',' . implode( ',', $tp_cookies );
|
567 |
}
|
568 |
else {
|
569 |
+
$cfg[ $id ] = implode( ',', $tp_cookies );
|
570 |
}
|
571 |
}
|
572 |
// frontend and backend
|
573 |
if ( ! empty( $cfg[ $id ] ) ) {
|
574 |
+
$env = 'Cache-Vary:' . $cfg[ $id ];
|
575 |
if ( LITESPEED_SERVER_TYPE === 'LITESPEED_SERVER_OLS' ) {
|
576 |
+
$env = '"' . $env . '"';
|
577 |
}
|
578 |
+
$new_rules[] = $new_rules_backend[] = self::MARKER_LOGIN_COOKIE . self::MARKER_START;
|
579 |
+
$new_rules[] = $new_rules_backend[] = 'RewriteRule .? - [E=' . $env . ']';
|
580 |
+
$new_rules[] = $new_rules_backend[] = self::MARKER_LOGIN_COOKIE . self::MARKER_END;
|
581 |
+
$new_rules[] = '';
|
582 |
}
|
583 |
|
584 |
// favicon
|
585 |
// frontend and backend
|
586 |
+
$id = Base::O_CACHE_FAVICON;
|
587 |
if ( ! empty( $cfg[ $id ] ) ) {
|
588 |
+
$new_rules[] = $new_rules_backend[] = self::MARKER_FAVICON . self::MARKER_START;
|
589 |
+
$new_rules[] = $new_rules_backend[] = 'RewriteRule favicon\.ico$ - [E=cache-control:max-age=86400]';
|
590 |
+
$new_rules[] = $new_rules_backend[] = self::MARKER_FAVICON . self::MARKER_END;
|
591 |
+
$new_rules[] = '';
|
592 |
}
|
593 |
|
594 |
// CORS font rules
|
595 |
+
$id = Base::O_CDN;
|
596 |
if ( ! empty( $cfg[ $id ] ) ) {
|
597 |
+
$new_rules[] = self::MARKER_CORS . self::MARKER_START;
|
598 |
+
$new_rules = array_merge( $new_rules, $this->_cors_rules() ); //todo: network
|
599 |
+
$new_rules[] = self::MARKER_CORS . self::MARKER_END;
|
600 |
+
$new_rules[] = '';
|
601 |
}
|
602 |
|
603 |
// webp support
|
604 |
+
$id = Base::O_IMG_OPTM_WEBP_REPLACE;
|
605 |
if ( ! empty( $cfg[ $id ] ) ) {
|
606 |
+
$new_rules[] = self::MARKER_WEBP . self::MARKER_START;
|
607 |
+
$new_rules[] = 'RewriteCond %{HTTP_ACCEPT} "image/webp" [or]';
|
608 |
+
$new_rules[] = 'RewriteCond %{HTTP_USER_AGENT} "Page Speed"';
|
609 |
+
$new_rules[] = 'RewriteRule .* - [E=Cache-Control:vary=%{ENV:LSCACHE_VARY_VALUE}+webp]';
|
610 |
+
$new_rules[] = self::MARKER_WEBP . self::MARKER_END;
|
611 |
+
$new_rules[] = '';
|
612 |
}
|
613 |
|
614 |
// drop qs support
|
615 |
+
$id = Base::O_CACHE_DROP_QS;
|
616 |
if ( ! empty( $cfg[ $id ] ) ) {
|
617 |
+
$new_rules[] = self::MARKER_DROPQS . self::MARKER_START;
|
618 |
foreach ( $cfg[ $id ] as $v ) {
|
619 |
+
$new_rules[] = 'CacheKeyModify -qs:' . $v;
|
620 |
}
|
621 |
+
$new_rules[] = self::MARKER_DROPQS . self::MARKER_END;
|
622 |
+
$new_rules[] = '';
|
623 |
}
|
624 |
|
625 |
// Browser cache
|
626 |
+
$id = Base::O_CACHE_BROWSER;
|
627 |
if ( ! empty( $cfg[ $id ] ) ) {
|
628 |
+
$new_rules_nonls[] = $new_rules_backend_nonls[] = self::MARKER_BROWSER_CACHE . self::MARKER_START;
|
629 |
+
$new_rules_nonls = array_merge( $new_rules_nonls, $this->_browser_cache_rules( $cfg ) );
|
630 |
+
$new_rules_backend_nonls = array_merge( $new_rules_backend_nonls, $this->_browser_cache_rules( $cfg ) );
|
631 |
+
$new_rules_nonls[] = $new_rules_backend_nonls[] = self::MARKER_BROWSER_CACHE . self::MARKER_END;
|
632 |
+
$new_rules_nonls[] = '';
|
633 |
}
|
634 |
|
635 |
// Add module wrapper for LiteSpeed rules
|
636 |
if ( $new_rules ) {
|
637 |
+
$new_rules = $this->_wrap_ls_module( $new_rules );
|
638 |
}
|
639 |
|
640 |
if ( $new_rules_backend ) {
|
641 |
+
$new_rules_backend = $this->_wrap_ls_module( $new_rules_backend );
|
642 |
}
|
643 |
|
644 |
+
return array( $new_rules, $new_rules_backend, $new_rules_nonls, $new_rules_backend_nonls );
|
645 |
}
|
646 |
|
647 |
/**
|
650 |
* @since 2.1.1
|
651 |
* @access private
|
652 |
*/
|
653 |
+
private function _wrap_ls_module( $rules = array() ) {
|
|
|
654 |
return array_merge(
|
655 |
array( self::LS_MODULE_START ),
|
656 |
$this->__rewrite_on,
|
657 |
array( '' ),
|
658 |
$rules,
|
659 |
array( self::LS_MODULE_END )
|
660 |
+
);
|
661 |
}
|
662 |
|
663 |
/**
|
666 |
* @since 2.1.1
|
667 |
* @access public
|
668 |
*/
|
669 |
+
public function insert_ls_wrapper() {
|
670 |
+
$rules = $this->_wrap_ls_module();
|
671 |
+
$this->_insert_wrapper( $rules );
|
|
|
672 |
}
|
673 |
|
674 |
/**
|
678 |
* @param array $rules
|
679 |
* @return array wrapped rules with module info
|
680 |
*/
|
681 |
+
private function _wrap_do_no_edit( $rules ) {
|
|
|
682 |
// When to clear rules, don't need DONOTEDIT msg
|
683 |
if ( $rules === false || ! is_array( $rules ) ) {
|
684 |
+
return $rules;
|
685 |
}
|
686 |
|
687 |
$rules = array_merge(
|
688 |
array( self::LS_MODULE_DONOTEDIT ),
|
689 |
$rules,
|
690 |
array( self::LS_MODULE_DONOTEDIT )
|
691 |
+
);
|
692 |
|
693 |
+
return $rules;
|
694 |
}
|
695 |
|
696 |
/**
|
701 |
* @since 1.1.0
|
702 |
* @access private
|
703 |
*/
|
704 |
+
private function _insert_wrapper( $rules = array(), $kind = false, $marker = false ) {
|
|
|
705 |
if ( $kind != 'backend' ) {
|
706 |
+
$kind = 'frontend';
|
707 |
}
|
708 |
|
709 |
// Default marker is LiteSpeed marker `LSCACHE`
|
710 |
if ( $marker === false ) {
|
711 |
+
$marker = self::MARKER;
|
712 |
}
|
713 |
|
714 |
+
$this->_htaccess_backup( $kind );
|
715 |
|
716 |
+
File::insert_with_markers( $this->htaccess_path( $kind ), $this->_wrap_do_no_edit( $rules ), $marker, true );
|
717 |
}
|
718 |
|
719 |
/**
|
724 |
* @since 1.3
|
725 |
* @access public
|
726 |
*/
|
727 |
+
public function update( $cfg ) {
|
728 |
+
list( $frontend_rules, $backend_rules, $frontend_rules_nonls, $backend_rules_nonls ) = $this->_generate_rules( $cfg );
|
|
|
729 |
|
730 |
// Check frontend content
|
731 |
+
list( $rules, $rules_nonls ) = $this->_extract_rules();
|
732 |
|
733 |
// Check Non-LiteSpeed rules
|
734 |
if ( $this->_wrap_do_no_edit( $frontend_rules_nonls ) != $rules_nonls ) {
|
735 |
+
Debug2::debug( '[Rules] Update non-ls frontend rules' );
|
736 |
// Need to update frontend htaccess
|
737 |
try {
|
738 |
+
$this->_insert_wrapper( $frontend_rules_nonls, false, self::MARKER_NONLS );
|
739 |
} catch ( \Exception $e ) {
|
740 |
+
$manual_guide_codes = $this->_rewrite_codes_msg( $this->frontend_htaccess, $frontend_rules_nonls, self::MARKER_NONLS );
|
741 |
+
Debug2::debug( '[Rules] Update Failed' );
|
742 |
+
throw new \Exception( $manual_guide_codes );
|
743 |
}
|
744 |
}
|
745 |
|
746 |
// Check LiteSpeed rules
|
747 |
if ( $this->_wrap_do_no_edit( $frontend_rules ) != $rules ) {
|
748 |
+
Debug2::debug( '[Rules] Update frontend rules' );
|
749 |
// Need to update frontend htaccess
|
750 |
try {
|
751 |
+
$this->_insert_wrapper( $frontend_rules );
|
752 |
} catch ( \Exception $e ) {
|
753 |
+
Debug2::debug( '[Rules] Update Failed' );
|
754 |
+
$manual_guide_codes = $this->_rewrite_codes_msg( $this->frontend_htaccess, $frontend_rules );
|
755 |
+
throw new \Exception( $manual_guide_codes );
|
756 |
}
|
757 |
}
|
758 |
|
759 |
if ( $this->frontend_htaccess !== $this->backend_htaccess ) {
|
760 |
+
list( $rules, $rules_nonls ) = $this->_extract_rules( 'backend' );
|
761 |
|
762 |
// Check Non-LiteSpeed rules for backend
|
763 |
if ( $this->_wrap_do_no_edit( $backend_rules_nonls ) != $rules_nonls ) {
|
764 |
+
Debug2::debug( '[Rules] Update non-ls backend rules' );
|
765 |
// Need to update frontend htaccess
|
766 |
try {
|
767 |
+
$this->_insert_wrapper( $backend_rules_nonls, 'backend', self::MARKER_NONLS );
|
768 |
} catch ( \Exception $e ) {
|
769 |
+
Debug2::debug( '[Rules] Update Failed' );
|
770 |
+
$manual_guide_codes = $this->_rewrite_codes_msg( $this->backend_htaccess, $backend_rules_nonls, self::MARKER_NONLS );
|
771 |
+
throw new \Exception( $manual_guide_codes );
|
772 |
}
|
773 |
}
|
774 |
|
775 |
// Check backend content
|
776 |
if ( $this->_wrap_do_no_edit( $backend_rules ) != $rules ) {
|
777 |
+
Debug2::debug( '[Rules] Update backend rules' );
|
778 |
// Need to update backend htaccess
|
779 |
try {
|
780 |
+
$this->_insert_wrapper( $backend_rules, 'backend' );
|
781 |
} catch ( \Exception $e ) {
|
782 |
+
Debug2::debug( '[Rules] Update Failed' );
|
783 |
+
$manual_guide_codes = $this->_rewrite_codes_msg( $this->backend_htaccess, $backend_rules );
|
784 |
+
throw new \Exception( $manual_guide_codes );
|
785 |
}
|
786 |
}
|
787 |
}
|
788 |
|
789 |
+
return true;
|
790 |
}
|
791 |
|
792 |
/**
|
798 |
* @access private
|
799 |
* @param string $kind Frontend or backend .htaccess file
|
800 |
*/
|
801 |
+
private function _extract_rules( $kind = 'frontend' ) {
|
802 |
+
clearstatcache();
|
803 |
+
$path = $this->htaccess_path( $kind );
|
|
|
804 |
if ( ! $this->_readable( $kind ) ) {
|
805 |
+
Error::t( 'E_HTA_R' );
|
806 |
}
|
807 |
|
808 |
+
$rules = File::extract_from_markers( $path, self::MARKER );
|
809 |
+
$rules_nonls = File::extract_from_markers( $path, self::MARKER_NONLS );
|
810 |
|
811 |
+
return array( $rules, $rules_nonls );
|
812 |
}
|
813 |
|
814 |
/**
|
819 |
* @param array $rules
|
820 |
* @return string final msg to output
|
821 |
*/
|
822 |
+
private function _rewrite_codes_msg( $file, $rules, $marker = false ) {
|
|
|
823 |
return sprintf( __( '<p>Please add/replace the following codes into the beginning of %1$s:</p> %2$s' , 'litespeed-cache' ),
|
824 |
$file,
|
825 |
'<textarea style="width:100%;" rows="10" readonly>' . htmlspecialchars( $this->_wrap_rules_with_marker( $rules, $marker ) ) . '</textarea>'
|
826 |
+
);
|
827 |
}
|
828 |
|
829 |
/**
|
831 |
*
|
832 |
* @since 1.1.5
|
833 |
*/
|
834 |
+
private function _wrap_rules_with_marker( $rules, $marker = false ) {
|
|
|
835 |
// Default marker is LiteSpeed marker `LSCACHE`
|
836 |
if ( $marker === false ) {
|
837 |
+
$marker = self::MARKER;
|
838 |
}
|
839 |
|
840 |
+
$start_marker = "# BEGIN {$marker}";
|
841 |
+
$end_marker = "# END {$marker}";
|
842 |
$new_file_data = implode( "\n", array_merge(
|
843 |
array( $start_marker ),
|
844 |
$this->_wrap_do_no_edit($rules),
|
845 |
array( $end_marker )
|
846 |
+
) );
|
847 |
|
848 |
+
return $new_file_data;
|
849 |
}
|
850 |
|
851 |
/**
|
854 |
* @since 1.0.4
|
855 |
* @access public
|
856 |
*/
|
857 |
+
public function clear_rules() {
|
858 |
+
$this->_insert_wrapper( false );// Use false to avoid do-not-edit msg
|
|
|
859 |
// Clear non ls rules
|
860 |
+
$this->_insert_wrapper( false, false, self::MARKER_NONLS );
|
861 |
|
862 |
if ( $this->frontend_htaccess !== $this->backend_htaccess ) {
|
863 |
+
$this->_insert_wrapper( false, 'backend' );
|
864 |
+
$this->_insert_wrapper( false, 'backend', self::MARKER_NONLS );
|
865 |
}
|
866 |
}
|
867 |
|
873 |
* @since 2.9 Used exception when saving
|
874 |
* @access public
|
875 |
*/
|
876 |
+
public function htaccess_editor_save() {
|
|
|
877 |
if ( ! isset( $_POST[ self::EDITOR_TEXTAREA_NAME ] ) ) {
|
878 |
+
return;
|
879 |
}
|
880 |
|
881 |
+
$content = Admin::cleanup_text($_POST[self::EDITOR_TEXTAREA_NAME]);
|
882 |
|
883 |
try {
|
884 |
+
$this->htaccess_save($content);
|
885 |
} catch( \Exception $e ) {
|
886 |
+
Admin_Display::error( $e->getMessage() );
|
887 |
+
return;
|
888 |
}
|
889 |
|
890 |
+
Admin_Display::succeed( __( 'File Saved.', 'litespeed-cache' ) );
|
891 |
|
892 |
}
|
893 |
}
|
src/media.cls.php
CHANGED
@@ -8,18 +8,17 @@
|
|
8 |
* @subpackage Core/inc
|
9 |
* @author LiteSpeed Technologies <info@litespeedtech.com>
|
10 |
*/
|
11 |
-
namespace LiteSpeed
|
12 |
|
13 |
-
defined( 'WPINC' ) || exit
|
14 |
|
15 |
-
class Media extends Instance
|
16 |
-
|
17 |
-
protected static $_instance ;
|
18 |
|
19 |
-
const LIB_FILE_IMG_LAZYLOAD = 'assets/js/lazyload.min.js'
|
20 |
|
21 |
-
private $content
|
22 |
-
private $_wp_upload_dir
|
23 |
|
24 |
/**
|
25 |
* Init
|
@@ -27,8 +26,7 @@ class Media extends Instance
|
|
27 |
* @since 1.4
|
28 |
* @access protected
|
29 |
*/
|
30 |
-
protected function __construct()
|
31 |
-
{
|
32 |
Debug2::debug2( '[Media] init' );
|
33 |
|
34 |
$this->_wp_upload_dir = wp_upload_dir();
|
@@ -43,8 +41,7 @@ class Media extends Instance
|
|
43 |
* @since 3.0
|
44 |
* @access public
|
45 |
*/
|
46 |
-
public function init()
|
47 |
-
{
|
48 |
if ( $this->can_media() ) {
|
49 |
// Due to ajax call doesn't send correct accept header, have to limit webp to HTML only
|
50 |
if ( Conf::val( Base::O_IMG_OPTM_WEBP_REPLACE ) ) {
|
@@ -53,17 +50,17 @@ class Media extends Instance
|
|
53 |
* @since 1.6.2
|
54 |
*/
|
55 |
// Moved to htaccess
|
56 |
-
// add_filter( 'litespeed_vary', array( $this, 'vary_add' ) )
|
57 |
|
58 |
//
|
59 |
if ( $this->webp_support() ) {
|
60 |
// Hook to srcset
|
61 |
if ( function_exists( 'wp_calculate_image_srcset' ) ) {
|
62 |
-
add_filter( 'wp_calculate_image_srcset', array( $this, 'webp_srcset' ), 988 )
|
63 |
}
|
64 |
// Hook to mime icon
|
65 |
-
// add_filter( 'wp_get_attachment_image_src', array( $this, 'webp_attach_img_src' ), 988 )
|
66 |
-
// add_filter( 'wp_get_attachment_url', array( $this, 'webp_url' ), 988 )
|
67 |
}
|
68 |
}
|
69 |
|
@@ -71,14 +68,14 @@ class Media extends Instance
|
|
71 |
* Replace gravatar
|
72 |
* @since 3.0
|
73 |
*/
|
74 |
-
Avatar::get_instance()
|
75 |
}
|
76 |
|
77 |
/**
|
78 |
* JPG quality control
|
79 |
* @since 3.0
|
80 |
*/
|
81 |
-
add_filter( 'jpeg_quality', array( $this, 'adjust_jpg_quality' ) )
|
82 |
|
83 |
}
|
84 |
|
@@ -88,15 +85,14 @@ class Media extends Instance
|
|
88 |
* @since 3.0
|
89 |
* @access public
|
90 |
*/
|
91 |
-
public function adjust_jpg_quality( $quality )
|
92 |
-
|
93 |
-
$v = Conf::val( Base::O_IMG_OPTM_JPG_QUALITY ) ;
|
94 |
|
95 |
if ( $v ) {
|
96 |
-
return $v
|
97 |
}
|
98 |
|
99 |
-
return $quality
|
100 |
}
|
101 |
|
102 |
/**
|
@@ -105,13 +101,12 @@ class Media extends Instance
|
|
105 |
* @since 1.6.2
|
106 |
* @access private
|
107 |
*/
|
108 |
-
private function can_media()
|
109 |
-
{
|
110 |
if ( is_admin() ) {
|
111 |
-
return false
|
112 |
}
|
113 |
|
114 |
-
return true
|
115 |
}
|
116 |
|
117 |
/**
|
@@ -120,15 +115,14 @@ class Media extends Instance
|
|
120 |
* @since 1.6.3
|
121 |
* @access public
|
122 |
*/
|
123 |
-
public function after_admin_init()
|
124 |
-
|
125 |
-
add_filter( '
|
126 |
-
add_filter( 'manage_media_custom_column', array( $this, 'media_row_actions' ), 10, 2 ) ;
|
127 |
|
128 |
-
add_action( 'litespeed_media_row', array( $this, 'media_row_con' ) )
|
129 |
|
130 |
// Hook to attachment delete action
|
131 |
-
add_action( 'delete_attachment', array( $this, 'delete_attachment' ) )
|
132 |
}
|
133 |
|
134 |
/**
|
@@ -137,10 +131,9 @@ class Media extends Instance
|
|
137 |
* @since 2.4.3
|
138 |
* @access public
|
139 |
*/
|
140 |
-
public function delete_attachment( $post_id )
|
141 |
-
|
142 |
-
|
143 |
-
Img_Optm::get_instance()->reset_row( $post_id ) ;
|
144 |
}
|
145 |
|
146 |
/**
|
@@ -151,16 +144,15 @@ class Media extends Instance
|
|
151 |
* @since 2.9.8
|
152 |
* @access public
|
153 |
*/
|
154 |
-
public function info( $short_file_path, $post_id )
|
155 |
-
|
156 |
-
$real_file = $this->_wp_upload_dir[ 'basedir' ] . '/' . $short_file_path ;
|
157 |
|
158 |
if ( file_exists( $real_file ) ) {
|
159 |
return array(
|
160 |
'url' => $this->_wp_upload_dir[ 'baseurl' ] . '/' . $short_file_path,
|
161 |
'md5' => md5_file( $real_file ),
|
162 |
'size' => filesize( $real_file ),
|
163 |
-
)
|
164 |
}
|
165 |
|
166 |
/**
|
@@ -168,12 +160,12 @@ class Media extends Instance
|
|
168 |
* @since 2.9.8
|
169 |
* @return array( 'url', 'md5', 'size' )
|
170 |
*/
|
171 |
-
$info = apply_filters( 'litespeed_media_info', array(), $short_file_path, $post_id )
|
172 |
if ( ! empty( $info[ 'url' ] ) && ! empty( $info[ 'md5' ] ) && ! empty( $info[ 'size' ] ) ) {
|
173 |
-
return $info
|
174 |
}
|
175 |
|
176 |
-
return false
|
177 |
}
|
178 |
|
179 |
/**
|
@@ -182,16 +174,15 @@ class Media extends Instance
|
|
182 |
* @since 2.9.8
|
183 |
* @access public
|
184 |
*/
|
185 |
-
public function del( $short_file_path, $post_id )
|
186 |
-
|
187 |
-
$real_file = $this->_wp_upload_dir[ 'basedir' ] . '/' . $short_file_path ;
|
188 |
|
189 |
if ( file_exists( $real_file ) ) {
|
190 |
-
unlink( $real_file )
|
191 |
-
Debug2::debug( '[Media] deleted ' . $real_file )
|
192 |
}
|
193 |
|
194 |
-
do_action( 'litespeed_media_del', $short_file_path, $post_id )
|
195 |
}
|
196 |
|
197 |
/**
|
@@ -200,17 +191,16 @@ class Media extends Instance
|
|
200 |
* @since 2.9.8
|
201 |
* @access public
|
202 |
*/
|
203 |
-
public function rename( $short_file_path, $short_file_path_new, $post_id )
|
204 |
-
|
205 |
-
$
|
206 |
-
$real_file_new = $this->_wp_upload_dir[ 'basedir' ] . '/' . $short_file_path_new ;
|
207 |
|
208 |
if ( file_exists( $real_file ) ) {
|
209 |
-
rename( $real_file, $real_file_new )
|
210 |
-
Debug2::debug( '[Media] renamed ' . $real_file . ' to ' . $real_file_new )
|
211 |
}
|
212 |
|
213 |
-
do_action( 'litespeed_media_rename', $short_file_path, $short_file_path_new, $post_id )
|
214 |
}
|
215 |
|
216 |
/**
|
@@ -219,11 +209,10 @@ class Media extends Instance
|
|
219 |
* @since 1.6.3
|
220 |
* @access public
|
221 |
*/
|
222 |
-
public function media_row_title( $posts_columns )
|
223 |
-
|
224 |
-
$posts_columns[ 'imgoptm' ] = __( 'LiteSpeed Optimization', 'litespeed-cache' ) ;
|
225 |
|
226 |
-
return $posts_columns
|
227 |
}
|
228 |
|
229 |
/**
|
@@ -232,8 +221,7 @@ class Media extends Instance
|
|
232 |
* @since 1.6.2
|
233 |
* @access public
|
234 |
*/
|
235 |
-
public function media_row_actions( $column_name, $post_id )
|
236 |
-
{
|
237 |
if ( $column_name !== 'imgoptm' ) {
|
238 |
return;
|
239 |
}
|
@@ -247,39 +235,38 @@ class Media extends Instance
|
|
247 |
*
|
248 |
* @since 3.0
|
249 |
*/
|
250 |
-
public function media_row_con( $post_id )
|
251 |
-
|
252 |
-
$att_info = wp_get_attachment_metadata( $post_id ) ;
|
253 |
if ( empty( $att_info[ 'file' ] ) ) {
|
254 |
return;
|
255 |
}
|
256 |
|
257 |
-
$short_path = $att_info[ 'file' ]
|
258 |
|
259 |
-
$size_meta = get_post_meta( $post_id, Img_Optm::DB_SIZE, true )
|
260 |
|
261 |
echo '<p>';
|
262 |
// Original image info
|
263 |
if ( $size_meta && ! empty ( $size_meta[ 'ori_saved' ] ) ) {
|
264 |
-
$percent = ceil( $size_meta[ 'ori_saved' ] * 100 / $size_meta[ 'ori_total' ] )
|
265 |
|
266 |
-
$extension = pathinfo( $short_path, PATHINFO_EXTENSION )
|
267 |
-
$bk_file = substr( $short_path, 0, -strlen( $extension ) ) . 'bk.' . $extension
|
268 |
-
$bk_optm_file = substr( $short_path, 0, -strlen( $extension ) ) . 'bk.optm.' . $extension
|
269 |
|
270 |
-
$link = Utility::build_url( Router::ACTION_IMG_OPTM, 'orig' . $post_id )
|
271 |
-
$desc = false
|
272 |
|
273 |
-
$cls = ''
|
274 |
|
275 |
if ( $this->info( $bk_file, $post_id ) ) {
|
276 |
-
$curr_status = __( '(optm)', 'litespeed-cache' )
|
277 |
-
$desc = __( 'Currently using optimized version of file.', 'litespeed-cache' ) . ' ' . __( 'Click to switch to original (unoptimized) version.', 'litespeed-cache' )
|
278 |
}
|
279 |
elseif ( $this->info( $bk_optm_file, $post_id ) ) {
|
280 |
-
$cls .= ' litespeed-warning'
|
281 |
-
$curr_status = __( '(non-optm)', 'litespeed-cache' )
|
282 |
-
$desc = __( 'Currently using original (unoptimized) version of file.', 'litespeed-cache' ) . ' ' . __( 'Click to switch to optimized version.', 'litespeed-cache' )
|
283 |
}
|
284 |
|
285 |
echo GUI::pie_tiny( $percent, 24,
|
@@ -287,19 +274,19 @@ class Media extends Instance
|
|
287 |
$percent . '%',
|
288 |
Utility::real_size( $size_meta[ 'ori_saved' ] )
|
289 |
) , 'left'
|
290 |
-
)
|
291 |
|
292 |
-
echo sprintf( __( 'Orig saved %s', 'litespeed-cache' ), $percent . '%' )
|
293 |
|
294 |
if ( $desc ) {
|
295 |
-
echo sprintf( ' <a href="%1$s" class="litespeed-media-href %2$s" data-balloon-pos="left" data-balloon-break aria-label="%3$s">%4$s</a>', $link, $cls, $desc, $curr_status )
|
296 |
}
|
297 |
else {
|
298 |
echo sprintf(
|
299 |
' <span class="litespeed-desc" data-balloon-pos="left" data-balloon-break aria-label="%1$s">%2$s</span>',
|
300 |
__( 'Using optimized version of file. ', 'litespeed-cache' ) . ' ' . __( 'No backup of original file exists.', 'litespeed-cache' ),
|
301 |
__( '(optm)', 'litespeed-cache' )
|
302 |
-
)
|
303 |
}
|
304 |
|
305 |
|
@@ -308,8 +295,8 @@ class Media extends Instance
|
|
308 |
echo GUI::pie_tiny( 0, 24,
|
309 |
__( 'Congratulation! Your file was already optmized', 'litespeed-cache' ),
|
310 |
'left'
|
311 |
-
)
|
312 |
-
echo sprintf( __( 'Orig %s', 'litespeed-cache' ), '<span class="litespeed-desc">' . __( '(no savings)', 'litespeed-cache' ) . '</span>' )
|
313 |
}
|
314 |
else {
|
315 |
echo __( 'Orig', 'litespeed-cache' ) . '<span class="litespeed-left10">—</span>';
|
@@ -319,21 +306,21 @@ class Media extends Instance
|
|
319 |
echo '<p>';
|
320 |
// WebP info
|
321 |
if ( $size_meta && ! empty ( $size_meta[ 'webp_saved' ] ) ) {
|
322 |
-
$percent = ceil( $size_meta[ 'webp_saved' ] * 100 / $size_meta[ 'webp_total' ] )
|
323 |
|
324 |
-
$link = Utility::build_url( Router::ACTION_IMG_OPTM, 'webp' . $post_id )
|
325 |
-
$desc = false
|
326 |
|
327 |
-
$cls = ''
|
328 |
|
329 |
if ( $this->info( $short_path . '.webp', $post_id ) ) {
|
330 |
-
$curr_status = __( '(optm)', 'litespeed-cache' )
|
331 |
-
$desc = __( 'Currently using optimized version of WebP file.', 'litespeed-cache' ) . ' ' . __( 'Click to switch to original (unoptimized) version.', 'litespeed-cache' )
|
332 |
}
|
333 |
elseif ( $this->info( $short_path . '.optm.webp', $post_id ) ) {
|
334 |
-
$cls .= ' litespeed-warning'
|
335 |
-
$curr_status = __( '(non-optm)', 'litespeed-cache' )
|
336 |
-
$desc = __( 'Currently using original (unoptimized) version of WebP file.', 'litespeed-cache' ) . ' ' . __( 'Click to switch to optimized version.', 'litespeed-cache' )
|
337 |
}
|
338 |
|
339 |
echo GUI::pie_tiny( $percent, 24,
|
@@ -341,18 +328,18 @@ class Media extends Instance
|
|
341 |
$percent . '%',
|
342 |
Utility::real_size( $size_meta[ 'webp_saved' ] )
|
343 |
) , 'left'
|
344 |
-
)
|
345 |
-
echo sprintf( __( 'WebP saved %s', 'litespeed-cache' ), $percent . '%' )
|
346 |
|
347 |
if ( $desc ) {
|
348 |
-
echo sprintf( ' <a href="%1$s" class="litespeed-media-href %2$s" data-balloon-pos="left" data-balloon-break aria-label="%3$s">%4$s</a>', $link, $cls, $desc, $curr_status )
|
349 |
}
|
350 |
else {
|
351 |
echo sprintf(
|
352 |
' <span class="litespeed-desc" data-balloon-pos="left" data-balloon-break aria-label="%1$s">%2$s</span>',
|
353 |
__( 'Using optimized version of file. ', 'litespeed-cache' ) . ' ' . __( 'No backup of unoptimized WebP file exists.', 'litespeed-cache' ),
|
354 |
__( '(optm)', 'litespeed-cache' )
|
355 |
-
)
|
356 |
}
|
357 |
|
358 |
} else {
|
@@ -367,8 +354,8 @@ class Media extends Instance
|
|
367 |
echo sprintf( '<div class="row-actions"><span class="delete"><a href="%1$s" class="">%2$s</a></span></div>',
|
368 |
Utility::build_url( Router::ACTION_IMG_OPTM, Img_Optm::TYPE_RESET_ROW, false, null, array( 'id' => $post_id ) ),
|
369 |
__( 'Restore from backup', 'litespeed-cache' )
|
370 |
-
)
|
371 |
-
echo '</div>'
|
372 |
}
|
373 |
}
|
374 |
|
@@ -381,24 +368,24 @@ class Media extends Instance
|
|
381 |
* @return array $sizes Data for all currently-registered image sizes.
|
382 |
*/
|
383 |
public function get_image_sizes() {
|
384 |
-
global $_wp_additional_image_sizes
|
385 |
$sizes = array();
|
386 |
|
387 |
foreach ( get_intermediate_image_sizes() as $_size ) {
|
388 |
if ( in_array( $_size, array( 'thumbnail', 'medium', 'medium_large', 'large' ) ) ) {
|
389 |
-
$sizes[ $_size ][ 'width' ] = get_option( $_size . '_size_w' )
|
390 |
-
$sizes[ $_size ][ 'height' ] = get_option( $_size . '_size_h' )
|
391 |
-
$sizes[ $_size ][ 'crop' ] = (bool) get_option( $_size . '_crop' )
|
392 |
} elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
|
393 |
$sizes[ $_size ] = array(
|
394 |
'width' => $_wp_additional_image_sizes[ $_size ][ 'width' ],
|
395 |
'height' => $_wp_additional_image_sizes[ $_size ][ 'height' ],
|
396 |
'crop' => $_wp_additional_image_sizes[ $_size ][ 'crop' ]
|
397 |
-
)
|
398 |
}
|
399 |
}
|
400 |
|
401 |
-
return $sizes
|
402 |
}
|
403 |
|
404 |
|
@@ -408,17 +395,16 @@ class Media extends Instance
|
|
408 |
* @since 1.6.2
|
409 |
* @access public
|
410 |
*/
|
411 |
-
private function webp_support()
|
412 |
-
{
|
413 |
if ( ! empty( $_SERVER[ 'HTTP_ACCEPT' ] ) && strpos( $_SERVER[ 'HTTP_ACCEPT' ], 'image/webp' ) !== false ) {
|
414 |
-
return true
|
415 |
}
|
416 |
|
417 |
if ( ! empty( $_SERVER[ 'HTTP_USER_AGENT' ] ) && strpos( $_SERVER[ 'HTTP_USER_AGENT' ], 'Page Speed' ) !== false ) {
|
418 |
-
return true
|
419 |
}
|
420 |
|
421 |
-
return false
|
422 |
}
|
423 |
|
424 |
/**
|
@@ -431,25 +417,24 @@ class Media extends Instance
|
|
431 |
* @access public
|
432 |
* @return string The buffer
|
433 |
*/
|
434 |
-
public static function finalize( $content )
|
435 |
-
{
|
436 |
if ( defined( 'LITESPEED_NO_LAZY' ) ) {
|
437 |
-
Debug2::debug2( '[Media] bypass: NO_LAZY const' )
|
438 |
-
return $content
|
439 |
}
|
440 |
|
441 |
if ( ! defined( 'LITESPEED_IS_HTML' ) ) {
|
442 |
-
Debug2::debug2( '[Media] bypass: Not frontend HTML type' )
|
443 |
-
return $content
|
444 |
}
|
445 |
|
446 |
-
Debug2::debug( '[Media] finalize' )
|
447 |
|
448 |
-
$instance = self::get_instance()
|
449 |
-
$instance->content = $content
|
450 |
|
451 |
-
$instance->_finalize()
|
452 |
-
return $instance->content
|
453 |
}
|
454 |
|
455 |
/**
|
@@ -458,81 +443,80 @@ class Media extends Instance
|
|
458 |
* @since 1.4
|
459 |
* @access private
|
460 |
*/
|
461 |
-
private function _finalize()
|
462 |
-
{
|
463 |
/**
|
464 |
* Use webp for optimized images
|
465 |
* @since 1.6.2
|
466 |
*/
|
467 |
if ( Conf::val( Base::O_IMG_OPTM_WEBP_REPLACE ) && $this->webp_support() ) {
|
468 |
-
$this->_replace_buffer_img_webp()
|
469 |
}
|
470 |
|
471 |
/**
|
472 |
* Check if URI is excluded
|
473 |
* @since 3.0
|
474 |
*/
|
475 |
-
$excludes = Conf::val( Base::O_MEDIA_LAZY_URI_EXC )
|
476 |
if ( $excludes ) {
|
477 |
-
$result = Utility::str_hit_array( $_SERVER[ 'REQUEST_URI' ], $excludes )
|
478 |
if ( $result ) {
|
479 |
-
Debug2::debug( '[Media] bypass lazyload: hit URI Excludes setting: ' . $result )
|
480 |
-
return
|
481 |
}
|
482 |
}
|
483 |
|
484 |
-
$cfg_lazy = Conf::val( Base::O_MEDIA_LAZY )
|
485 |
-
$cfg_iframe_lazy = Conf::val( Base::O_MEDIA_IFRAME_LAZY )
|
486 |
|
487 |
if ( $cfg_lazy ) {
|
488 |
-
list( $src_list, $html_list, $placeholder_list ) = $this->_parse_img()
|
489 |
-
$html_list_ori = $html_list
|
490 |
}
|
491 |
|
492 |
// image lazy load
|
493 |
if ( $cfg_lazy ) {
|
494 |
|
495 |
-
$__placeholder = Placeholder::get_instance()
|
496 |
|
497 |
foreach ( $html_list as $k => $v ) {
|
498 |
-
$size = $placeholder_list[ $k ]
|
499 |
-
$src = $src_list[ $k ]
|
500 |
|
501 |
-
$html_list[ $k ] = $__placeholder->replace( $v, $src, $size )
|
502 |
}
|
503 |
}
|
504 |
|
505 |
if ( $cfg_lazy ) {
|
506 |
-
$this->content = str_replace( $html_list_ori, $html_list, $this->content )
|
507 |
}
|
508 |
|
509 |
// iframe lazy load
|
510 |
if ( $cfg_iframe_lazy ) {
|
511 |
-
$html_list = $this->_parse_iframe()
|
512 |
-
$html_list_ori = $html_list
|
513 |
|
514 |
foreach ( $html_list as $k => $v ) {
|
515 |
-
$snippet = Conf::val( Base::O_OPTM_NOSCRIPT_RM ) ? '' : '<noscript>' . $v . '</noscript>'
|
516 |
-
$v = str_replace( ' src=', ' data-src=', $v )
|
517 |
-
$v = str_replace( '<iframe ', '<iframe data-lazyloaded="1" src="about:blank" ', $v )
|
518 |
-
$snippet = $v . $snippet
|
519 |
|
520 |
-
$html_list[ $k ] = $snippet
|
521 |
}
|
522 |
|
523 |
-
$this->content = str_replace( $html_list_ori, $html_list, $this->content )
|
524 |
}
|
525 |
|
526 |
// Include lazyload lib js and init lazyload
|
527 |
if ( $cfg_lazy || $cfg_iframe_lazy ) {
|
528 |
if ( Conf::val( Base::O_MEDIA_LAZYJS_INLINE ) ) {
|
529 |
-
$lazy_lib = '<script>' . File::read( LSCWP_DIR . self::LIB_FILE_IMG_LAZYLOAD ) . '</script>'
|
530 |
} else {
|
531 |
-
$lazy_lib_url = LSWCP_PLUGIN_URL . self::LIB_FILE_IMG_LAZYLOAD
|
532 |
-
$lazy_lib = '<script src="' . $lazy_lib_url . '"></script>'
|
533 |
}
|
534 |
|
535 |
-
$this->content = str_replace( '</body>', $lazy_lib . '</body>', $this->content )
|
536 |
}
|
537 |
}
|
538 |
|
@@ -544,41 +528,40 @@ class Media extends Instance
|
|
544 |
* @access private
|
545 |
* @return array All the src & related raw html list
|
546 |
*/
|
547 |
-
private function _parse_img()
|
548 |
-
{
|
549 |
/**
|
550 |
* Exclude list
|
551 |
* @since 1.5
|
552 |
* @since 2.7.1 Changed to array
|
553 |
*/
|
554 |
-
$excludes = apply_filters( 'litespeed_media_lazy_img_excludes', Conf::val( Base::O_MEDIA_LAZY_EXC ) )
|
555 |
|
556 |
-
$cls_excludes = apply_filters( 'litespeed_media_lazy_img_cls_excludes', Conf::val( Base::O_MEDIA_LAZY_CLS_EXC ) )
|
557 |
$cls_excludes[] = 'skip-lazy'; // https://core.trac.wordpress.org/ticket/44427
|
558 |
|
559 |
-
$src_list = array()
|
560 |
-
$html_list = array()
|
561 |
-
$placeholder_list = array()
|
562 |
|
563 |
-
$content = preg_replace( '#<!--.*-->#sU', '', $this->content )
|
564 |
/**
|
565 |
* Exclude parent classes
|
566 |
* @since 3.0
|
567 |
*/
|
568 |
-
$parent_cls_exc = apply_filters( 'litespeed_media_lazy_img_parent_cls_excludes', Conf::val( Base::O_MEDIA_LAZY_PARENT_CLS_EXC ) )
|
569 |
if ( $parent_cls_exc ) {
|
570 |
-
Debug2::debug2( '[Media] Lazyload Class excludes', $parent_cls_exc )
|
571 |
foreach ( $parent_cls_exc as $v ) {
|
572 |
-
$content = preg_replace( '#<(\w+) [^>]*class=(\'|")[^\'"]*' . preg_quote( $v, '#' ) . '[^\'"]*\2[^>]*>.*</\1>#sU', '', $content )
|
573 |
}
|
574 |
}
|
575 |
|
576 |
-
preg_match_all( '#<img \s*([^>]+)/?>#isU', $content, $matches, PREG_SET_ORDER )
|
577 |
foreach ( $matches as $match ) {
|
578 |
-
$attrs = Utility::parse_attr( $match[ 1 ] )
|
579 |
|
580 |
if ( empty( $attrs[ 'src' ] ) ) {
|
581 |
-
continue
|
582 |
}
|
583 |
|
584 |
/**
|
@@ -586,20 +569,20 @@ class Media extends Instance
|
|
586 |
* @since 1.6
|
587 |
*/
|
588 |
if ( strpos( $attrs[ 'src' ], 'base64' ) !== false || substr( $attrs[ 'src' ], 0, 5 ) === 'data:' ) {
|
589 |
-
Debug2::debug2( '[Media] lazyload bypassed base64 img' )
|
590 |
-
continue
|
591 |
}
|
592 |
|
593 |
-
Debug2::debug2( '[Media] lazyload found: ' . $attrs[ 'src' ] )
|
594 |
|
595 |
if ( ! empty( $attrs[ 'data-no-lazy' ] ) || ! empty( $attrs[ 'data-skip-lazy' ] ) || ! empty( $attrs[ 'data-lazyloaded' ] ) || ! empty( $attrs[ 'data-src' ] ) || ! empty( $attrs[ 'data-srcset' ] ) ) {
|
596 |
-
Debug2::debug2( '[Media] bypassed' )
|
597 |
-
continue
|
598 |
}
|
599 |
|
600 |
if ( ! empty( $attrs[ 'class' ] ) && $hit = Utility::str_hit_array( $attrs[ 'class' ], $cls_excludes ) ) {
|
601 |
-
Debug2::debug2( '[Media] lazyload image cls excludes [hit] ' . $hit )
|
602 |
-
continue
|
603 |
}
|
604 |
|
605 |
/**
|
@@ -607,8 +590,8 @@ class Media extends Instance
|
|
607 |
* @since 1.5
|
608 |
*/
|
609 |
if ( $excludes && Utility::str_hit_array( $attrs[ 'src' ], $excludes ) ) {
|
610 |
-
Debug2::debug2( '[Media] lazyload image exclude ' . $attrs[ 'src' ] )
|
611 |
-
continue
|
612 |
}
|
613 |
|
614 |
/**
|
@@ -617,26 +600,26 @@ class Media extends Instance
|
|
617 |
* @since 3.0
|
618 |
*/
|
619 |
if ( strpos( $attrs[ 'src' ], '{' ) !== false ) {
|
620 |
-
Debug2::debug2( '[Media] image src has {} ' . $attrs[ 'src' ] )
|
621 |
-
continue
|
622 |
}
|
623 |
|
624 |
// to avoid multiple replacement
|
625 |
if ( in_array( $match[ 0 ], $html_list ) ) {
|
626 |
-
continue
|
627 |
}
|
628 |
|
629 |
-
$placeholder = false
|
630 |
if ( ! empty( $attrs[ 'width' ] ) && ! empty( $attrs[ 'height' ] ) ) {
|
631 |
-
$placeholder = $attrs[ 'width' ] . 'x' . $attrs[ 'height' ]
|
632 |
}
|
633 |
|
634 |
-
$src_list[] = $attrs[ 'src' ]
|
635 |
-
$html_list[] = $match[ 0 ]
|
636 |
-
$placeholder_list[] = $placeholder
|
637 |
}
|
638 |
|
639 |
-
return array( $src_list, $html_list, $placeholder_list )
|
640 |
}
|
641 |
|
642 |
/**
|
@@ -646,61 +629,60 @@ class Media extends Instance
|
|
646 |
* @access private
|
647 |
* @return array All the src & related raw html list
|
648 |
*/
|
649 |
-
private function _parse_iframe()
|
650 |
-
{
|
651 |
$cls_excludes = apply_filters( 'litespeed_media_iframe_lazy_cls_excludes', Conf::val( Base::O_MEDIA_IFRAME_LAZY_CLS_EXC ) );
|
652 |
$cls_excludes[] = 'skip-lazy'; // https://core.trac.wordpress.org/ticket/44427
|
653 |
|
654 |
-
$html_list = array()
|
655 |
|
656 |
-
$content = preg_replace( '#<!--.*-->#sU', '', $this->content )
|
657 |
|
658 |
/**
|
659 |
* Exclude parent classes
|
660 |
* @since 3.0
|
661 |
*/
|
662 |
-
$parent_cls_exc = apply_filters( 'litespeed_media_iframe_lazy_parent_cls_excludes', Conf::val( Base::O_MEDIA_IFRAME_LAZY_PARENT_CLS_EXC ) )
|
663 |
if ( $parent_cls_exc ) {
|
664 |
-
Debug2::debug2( '[Media] Iframe Lazyload Class excludes', $parent_cls_exc )
|
665 |
foreach ( $parent_cls_exc as $v ) {
|
666 |
-
$content = preg_replace( '#<(\w+) [^>]*class=(\'|")[^\'"]*' . preg_quote( $v, '#' ) . '[^\'"]*\2[^>]*>.*</\1>#sU', '', $content )
|
667 |
}
|
668 |
}
|
669 |
|
670 |
-
preg_match_all( '#<iframe \s*([^>]+)></iframe>#isU', $content, $matches, PREG_SET_ORDER )
|
671 |
foreach ( $matches as $match ) {
|
672 |
-
$attrs = Utility::parse_attr( $match[ 1 ] )
|
673 |
|
674 |
if ( empty( $attrs[ 'src' ] ) ) {
|
675 |
-
continue
|
676 |
}
|
677 |
|
678 |
-
Debug2::debug2( '[Media] found iframe: ' . $attrs[ 'src' ] )
|
679 |
|
680 |
if ( ! empty( $attrs[ 'data-no-lazy' ] ) || ! empty( $attrs[ 'data-skip-lazy' ] ) || ! empty( $attrs[ 'data-lazyloaded' ] ) || ! empty( $attrs[ 'data-src' ] ) ) {
|
681 |
-
Debug2::debug2( '[Media] bypassed' )
|
682 |
-
continue
|
683 |
}
|
684 |
|
685 |
if ( ! empty( $attrs[ 'class' ] ) && $hit = Utility::str_hit_array( $attrs[ 'class' ], $cls_excludes ) ) {
|
686 |
-
Debug2::debug2( '[Media] iframe lazyload cls excludes [hit] ' . $hit )
|
687 |
-
continue
|
688 |
}
|
689 |
|
690 |
if ( apply_filters( 'litespeed_iframe_lazyload_exc', false, $attrs[ 'src' ] ) ) {
|
691 |
-
Debug2::debug2( '[Media] bypassed by filter' )
|
692 |
-
continue
|
693 |
}
|
694 |
|
695 |
// to avoid multiple replacement
|
696 |
if ( in_array( $match[ 0 ], $html_list ) ) {
|
697 |
-
continue
|
698 |
}
|
699 |
|
700 |
-
$html_list[] = $match[ 0 ]
|
701 |
}
|
702 |
|
703 |
-
return $html_list
|
704 |
}
|
705 |
|
706 |
/**
|
@@ -709,42 +691,41 @@ class Media extends Instance
|
|
709 |
* @since 1.6.2
|
710 |
* @access private
|
711 |
*/
|
712 |
-
private function _replace_buffer_img_webp()
|
713 |
-
|
714 |
-
// preg_match_all( '#<img([^>]+?)src=([\'"\\\]*)([^\'"\s\\\>]+)([\'"\\\]*)([^>]*)>#i', $this->content, $matches ) ;
|
715 |
/**
|
716 |
* Added custom element & attribute support
|
717 |
* @since 2.2.2
|
718 |
*/
|
719 |
-
$webp_ele_to_check = Conf::val( Base::O_IMG_OPTM_WEBP_ATTR )
|
720 |
|
721 |
foreach ( $webp_ele_to_check as $v ) {
|
722 |
if ( ! $v || strpos( $v, '.' ) === false ) {
|
723 |
-
Debug2::debug2( '[Media] buffer_webp no . attribute ' . $v )
|
724 |
-
continue
|
725 |
}
|
726 |
|
727 |
-
Debug2::debug2( '[Media] buffer_webp attribute ' . $v )
|
728 |
|
729 |
-
$v = explode( '.', $v )
|
730 |
-
$attr = preg_quote( $v[ 1 ], '#' )
|
731 |
if ( $v[ 0 ] ) {
|
732 |
-
$pattern = '#<' . preg_quote( $v[ 0 ], '#' ) . '([^>]+)' . $attr . '=([\'"])(.+)\g{2}#iU'
|
733 |
}
|
734 |
else {
|
735 |
-
$pattern = '# ' . $attr . '=([\'"])(.+)\g{1}#iU'
|
736 |
}
|
737 |
|
738 |
-
preg_match_all( $pattern, $this->content, $matches )
|
739 |
|
740 |
foreach ( $matches[ $v[ 0 ] ? 3 : 2 ] as $k2 => $url ) {
|
741 |
// Check if is a DATA-URI
|
742 |
if ( strpos( $url, 'data:image' ) !== false ) {
|
743 |
-
continue
|
744 |
}
|
745 |
|
746 |
if ( ! $url2 = $this->replace_webp( $url ) ) {
|
747 |
-
continue
|
748 |
}
|
749 |
|
750 |
if ( $v[ 0 ] ) {
|
@@ -752,16 +733,16 @@ class Media extends Instance
|
|
752 |
'<' . $v[ 0 ] . '%1$s' . $v[ 1 ] . '=%2$s',
|
753 |
$matches[ 1 ][ $k2 ],
|
754 |
$matches[ 2 ][ $k2 ] . $url2 . $matches[ 2 ][ $k2 ]
|
755 |
-
)
|
756 |
}
|
757 |
else {
|
758 |
$html_snippet = sprintf(
|
759 |
' ' . $v[ 1 ] . '=%1$s',
|
760 |
$matches[ 1 ][ $k2 ] . $url2 . $matches[ 1 ][ $k2 ]
|
761 |
-
)
|
762 |
}
|
763 |
|
764 |
-
$this->content = str_replace( $matches[ 0 ][ $k2 ], $html_snippet, $this->content )
|
765 |
|
766 |
}
|
767 |
}
|
@@ -769,30 +750,30 @@ class Media extends Instance
|
|
769 |
// parse srcset
|
770 |
// todo: should apply this to cdn too
|
771 |
if ( Conf::val( Base::O_IMG_OPTM_WEBP_REPLACE_SRCSET ) ) {
|
772 |
-
$this->content = Utility::srcset_replace( $this->content, array( $this, 'replace_webp' ) )
|
773 |
}
|
774 |
|
775 |
// Replace background-image
|
776 |
-
preg_match_all( '#background\-image:(\s*)url\((.*)\)#iU', $this->content, $matches )
|
777 |
foreach ( $matches[ 2 ] as $k => $url ) {
|
778 |
// Check if is a DATA-URI
|
779 |
if ( strpos( $url, 'data:image' ) !== false ) {
|
780 |
-
continue
|
781 |
}
|
782 |
|
783 |
/**
|
784 |
* Support quotes in src `background-image: url('src')`
|
785 |
* @since 2.9.3
|
786 |
*/
|
787 |
-
$url = trim( $url, '\'"' )
|
788 |
|
789 |
if ( ! $url2 = $this->replace_webp( $url ) ) {
|
790 |
-
continue
|
791 |
}
|
792 |
|
793 |
-
// $html_snippet = sprintf( 'background-image:%1$surl(%2$s)', $matches[ 1 ][ $k ], $url2 )
|
794 |
-
$html_snippet = str_replace( $url, $url2, $matches[ 0 ][ $k ] )
|
795 |
-
$this->content = str_replace( $matches[ 0 ][ $k ], $html_snippet, $this->content )
|
796 |
}
|
797 |
}
|
798 |
|
@@ -804,13 +785,12 @@ class Media extends Instance
|
|
804 |
* @param array $img The URL of the attachment image src, the width, the height
|
805 |
* @return array
|
806 |
*/
|
807 |
-
public function webp_attach_img_src( $img )
|
808 |
-
|
809 |
-
Debug2::debug2( '[Media] changing attach src: ' . $img[0] ) ;
|
810 |
if ( $img && $url = $this->replace_webp( $img[ 0 ] ) ) {
|
811 |
-
$img[ 0 ] = $url
|
812 |
}
|
813 |
-
return $img
|
814 |
}
|
815 |
|
816 |
/**
|
@@ -821,12 +801,11 @@ class Media extends Instance
|
|
821 |
* @param string $url
|
822 |
* @return string
|
823 |
*/
|
824 |
-
public function webp_url( $url )
|
825 |
-
{
|
826 |
if ( $url && $url2 = $this->replace_webp( $url ) ) {
|
827 |
-
$url = $url2
|
828 |
}
|
829 |
-
return $url
|
830 |
}
|
831 |
|
832 |
/**
|
@@ -837,17 +816,16 @@ class Media extends Instance
|
|
837 |
* @param array $srcs
|
838 |
* @return array
|
839 |
*/
|
840 |
-
public function webp_srcset( $srcs )
|
841 |
-
{
|
842 |
if ( $srcs ) {
|
843 |
foreach ( $srcs as $w => $data ) {
|
844 |
if( ! $url = $this->replace_webp( $data[ 'url' ] ) ) {
|
845 |
-
continue
|
846 |
}
|
847 |
-
$srcs[ $w ][ 'url' ] = $url
|
848 |
}
|
849 |
}
|
850 |
-
return $srcs
|
851 |
}
|
852 |
|
853 |
/**
|
@@ -856,13 +834,12 @@ class Media extends Instance
|
|
856 |
* @since 1.6.2
|
857 |
* @access public
|
858 |
*/
|
859 |
-
public function replace_webp( $url )
|
860 |
-
|
861 |
-
Debug2::debug2( '[Media] webp replacing: ' . $url, 4 ) ;
|
862 |
|
863 |
if ( substr( $url, -5 ) == '.webp' ) {
|
864 |
-
Debug2::debug2( '[Media] already webp' )
|
865 |
-
return false
|
866 |
}
|
867 |
|
868 |
/**
|
@@ -874,21 +851,21 @@ class Media extends Instance
|
|
874 |
if ( apply_filters( 'litespeed_media_check_ori', Utility::is_internal_file( $url ), $url ) ) {
|
875 |
// check if has webp file
|
876 |
if ( apply_filters( 'litespeed_media_check_webp', Utility::is_internal_file( $url, 'webp' ), $url ) ) {
|
877 |
-
$url .= '.webp'
|
878 |
}
|
879 |
else {
|
880 |
-
Debug2::debug2( '[Media] -no WebP file, bypassed' )
|
881 |
-
return false
|
882 |
}
|
883 |
}
|
884 |
else {
|
885 |
-
Debug2::debug2( '[Media] -no file, bypassed' )
|
886 |
-
return false
|
887 |
}
|
888 |
|
889 |
-
Debug2::debug2( '[Media] - replaced to: ' . $url )
|
890 |
|
891 |
-
return $url
|
892 |
}
|
893 |
|
894 |
}
|
8 |
* @subpackage Core/inc
|
9 |
* @author LiteSpeed Technologies <info@litespeedtech.com>
|
10 |
*/
|
11 |
+
namespace LiteSpeed;
|
12 |
|
13 |
+
defined( 'WPINC' ) || exit;
|
14 |
|
15 |
+
class Media extends Instance {
|
16 |
+
protected static $_instance;
|
|
|
17 |
|
18 |
+
const LIB_FILE_IMG_LAZYLOAD = 'assets/js/lazyload.min.js';
|
19 |
|
20 |
+
private $content;
|
21 |
+
private $_wp_upload_dir;
|
22 |
|
23 |
/**
|
24 |
* Init
|
26 |
* @since 1.4
|
27 |
* @access protected
|
28 |
*/
|
29 |
+
protected function __construct() {
|
|
|
30 |
Debug2::debug2( '[Media] init' );
|
31 |
|
32 |
$this->_wp_upload_dir = wp_upload_dir();
|
41 |
* @since 3.0
|
42 |
* @access public
|
43 |
*/
|
44 |
+
public function init() {
|
|
|
45 |
if ( $this->can_media() ) {
|
46 |
// Due to ajax call doesn't send correct accept header, have to limit webp to HTML only
|
47 |
if ( Conf::val( Base::O_IMG_OPTM_WEBP_REPLACE ) ) {
|
50 |
* @since 1.6.2
|
51 |
*/
|
52 |
// Moved to htaccess
|
53 |
+
// add_filter( 'litespeed_vary', array( $this, 'vary_add' ) );
|
54 |
|
55 |
//
|
56 |
if ( $this->webp_support() ) {
|
57 |
// Hook to srcset
|
58 |
if ( function_exists( 'wp_calculate_image_srcset' ) ) {
|
59 |
+
add_filter( 'wp_calculate_image_srcset', array( $this, 'webp_srcset' ), 988 );
|
60 |
}
|
61 |
// Hook to mime icon
|
62 |
+
// add_filter( 'wp_get_attachment_image_src', array( $this, 'webp_attach_img_src' ), 988 );// todo: need to check why not
|
63 |
+
// add_filter( 'wp_get_attachment_url', array( $this, 'webp_url' ), 988 ); // disabled to avoid wp-admin display
|
64 |
}
|
65 |
}
|
66 |
|
68 |
* Replace gravatar
|
69 |
* @since 3.0
|
70 |
*/
|
71 |
+
Avatar::get_instance();
|
72 |
}
|
73 |
|
74 |
/**
|
75 |
* JPG quality control
|
76 |
* @since 3.0
|
77 |
*/
|
78 |
+
add_filter( 'jpeg_quality', array( $this, 'adjust_jpg_quality' ) );
|
79 |
|
80 |
}
|
81 |
|
85 |
* @since 3.0
|
86 |
* @access public
|
87 |
*/
|
88 |
+
public function adjust_jpg_quality( $quality ) {
|
89 |
+
$v = Conf::val( Base::O_IMG_OPTM_JPG_QUALITY );
|
|
|
90 |
|
91 |
if ( $v ) {
|
92 |
+
return $v;
|
93 |
}
|
94 |
|
95 |
+
return $quality;
|
96 |
}
|
97 |
|
98 |
/**
|
101 |
* @since 1.6.2
|
102 |
* @access private
|
103 |
*/
|
104 |
+
private function can_media() {
|
|
|
105 |
if ( is_admin() ) {
|
106 |
+
return false;
|
107 |
}
|
108 |
|
109 |
+
return true;
|
110 |
}
|
111 |
|
112 |
/**
|
115 |
* @since 1.6.3
|
116 |
* @access public
|
117 |
*/
|
118 |
+
public function after_admin_init() {
|
119 |
+
add_filter( 'manage_media_columns', array( $this, 'media_row_title' ) );
|
120 |
+
add_filter( 'manage_media_custom_column', array( $this, 'media_row_actions' ), 10, 2 );
|
|
|
121 |
|
122 |
+
add_action( 'litespeed_media_row', array( $this, 'media_row_con' ) );
|
123 |
|
124 |
// Hook to attachment delete action
|
125 |
+
add_action( 'delete_attachment', array( $this, 'delete_attachment' ) );
|
126 |
}
|
127 |
|
128 |
/**
|
131 |
* @since 2.4.3
|
132 |
* @access public
|
133 |
*/
|
134 |
+
public function delete_attachment( $post_id ) {
|
135 |
+
Debug2::debug( '[Media] delete_attachment [pid] ' . $post_id );
|
136 |
+
Img_Optm::get_instance()->reset_row( $post_id );
|
|
|
137 |
}
|
138 |
|
139 |
/**
|
144 |
* @since 2.9.8
|
145 |
* @access public
|
146 |
*/
|
147 |
+
public function info( $short_file_path, $post_id ) {
|
148 |
+
$real_file = $this->_wp_upload_dir[ 'basedir' ] . '/' . $short_file_path;
|
|
|
149 |
|
150 |
if ( file_exists( $real_file ) ) {
|
151 |
return array(
|
152 |
'url' => $this->_wp_upload_dir[ 'baseurl' ] . '/' . $short_file_path,
|
153 |
'md5' => md5_file( $real_file ),
|
154 |
'size' => filesize( $real_file ),
|
155 |
+
);
|
156 |
}
|
157 |
|
158 |
/**
|
160 |
* @since 2.9.8
|
161 |
* @return array( 'url', 'md5', 'size' )
|
162 |
*/
|
163 |
+
$info = apply_filters( 'litespeed_media_info', array(), $short_file_path, $post_id );
|
164 |
if ( ! empty( $info[ 'url' ] ) && ! empty( $info[ 'md5' ] ) && ! empty( $info[ 'size' ] ) ) {
|
165 |
+
return $info;
|
166 |
}
|
167 |
|
168 |
+
return false;
|
169 |
}
|
170 |
|
171 |
/**
|
174 |
* @since 2.9.8
|
175 |
* @access public
|
176 |
*/
|
177 |
+
public function del( $short_file_path, $post_id ) {
|
178 |
+
$real_file = $this->_wp_upload_dir[ 'basedir' ] . '/' . $short_file_path;
|
|
|
179 |
|
180 |
if ( file_exists( $real_file ) ) {
|
181 |
+
unlink( $real_file );
|
182 |
+
Debug2::debug( '[Media] deleted ' . $real_file );
|
183 |
}
|
184 |
|
185 |
+
do_action( 'litespeed_media_del', $short_file_path, $post_id );
|
186 |
}
|
187 |
|
188 |
/**
|
191 |
* @since 2.9.8
|
192 |
* @access public
|
193 |
*/
|
194 |
+
public function rename( $short_file_path, $short_file_path_new, $post_id ) {
|
195 |
+
$real_file = $this->_wp_upload_dir[ 'basedir' ] . '/' . $short_file_path;
|
196 |
+
$real_file_new = $this->_wp_upload_dir[ 'basedir' ] . '/' . $short_file_path_new;
|
|
|
197 |
|
198 |
if ( file_exists( $real_file ) ) {
|
199 |
+
rename( $real_file, $real_file_new );
|
200 |
+
Debug2::debug( '[Media] renamed ' . $real_file . ' to ' . $real_file_new );
|
201 |
}
|
202 |
|
203 |
+
do_action( 'litespeed_media_rename', $short_file_path, $short_file_path_new, $post_id );
|
204 |
}
|
205 |
|
206 |
/**
|
209 |
* @since 1.6.3
|
210 |
* @access public
|
211 |
*/
|
212 |
+
public function media_row_title( $posts_columns ) {
|
213 |
+
$posts_columns[ 'imgoptm' ] = __( 'LiteSpeed Optimization', 'litespeed-cache' );
|
|
|
214 |
|
215 |
+
return $posts_columns;
|
216 |
}
|
217 |
|
218 |
/**
|
221 |
* @since 1.6.2
|
222 |
* @access public
|
223 |
*/
|
224 |
+
public function media_row_actions( $column_name, $post_id ) {
|
|
|
225 |
if ( $column_name !== 'imgoptm' ) {
|
226 |
return;
|
227 |
}
|
235 |
*
|
236 |
* @since 3.0
|
237 |
*/
|
238 |
+
public function media_row_con( $post_id ) {
|
239 |
+
$att_info = wp_get_attachment_metadata( $post_id );
|
|
|
240 |
if ( empty( $att_info[ 'file' ] ) ) {
|
241 |
return;
|
242 |
}
|
243 |
|
244 |
+
$short_path = $att_info[ 'file' ];
|
245 |
|
246 |
+
$size_meta = get_post_meta( $post_id, Img_Optm::DB_SIZE, true );
|
247 |
|
248 |
echo '<p>';
|
249 |
// Original image info
|
250 |
if ( $size_meta && ! empty ( $size_meta[ 'ori_saved' ] ) ) {
|
251 |
+
$percent = ceil( $size_meta[ 'ori_saved' ] * 100 / $size_meta[ 'ori_total' ] );
|
252 |
|
253 |
+
$extension = pathinfo( $short_path, PATHINFO_EXTENSION );
|
254 |
+
$bk_file = substr( $short_path, 0, -strlen( $extension ) ) . 'bk.' . $extension;
|
255 |
+
$bk_optm_file = substr( $short_path, 0, -strlen( $extension ) ) . 'bk.optm.' . $extension;
|
256 |
|
257 |
+
$link = Utility::build_url( Router::ACTION_IMG_OPTM, 'orig' . $post_id );
|
258 |
+
$desc = false;
|
259 |
|
260 |
+
$cls = '';
|
261 |
|
262 |
if ( $this->info( $bk_file, $post_id ) ) {
|
263 |
+
$curr_status = __( '(optm)', 'litespeed-cache' );
|
264 |
+
$desc = __( 'Currently using optimized version of file.', 'litespeed-cache' ) . ' ' . __( 'Click to switch to original (unoptimized) version.', 'litespeed-cache' );
|
265 |
}
|
266 |
elseif ( $this->info( $bk_optm_file, $post_id ) ) {
|
267 |
+
$cls .= ' litespeed-warning';
|
268 |
+
$curr_status = __( '(non-optm)', 'litespeed-cache' );
|
269 |
+
$desc = __( 'Currently using original (unoptimized) version of file.', 'litespeed-cache' ) . ' ' . __( 'Click to switch to optimized version.', 'litespeed-cache' );
|
270 |
}
|
271 |
|
272 |
echo GUI::pie_tiny( $percent, 24,
|
274 |
$percent . '%',
|
275 |
Utility::real_size( $size_meta[ 'ori_saved' ] )
|
276 |
) , 'left'
|
277 |
+
);
|
278 |
|
279 |
+
echo sprintf( __( 'Orig saved %s', 'litespeed-cache' ), $percent . '%' );
|
280 |
|
281 |
if ( $desc ) {
|
282 |
+
echo sprintf( ' <a href="%1$s" class="litespeed-media-href %2$s" data-balloon-pos="left" data-balloon-break aria-label="%3$s">%4$s</a>', $link, $cls, $desc, $curr_status );
|
283 |
}
|
284 |
else {
|
285 |
echo sprintf(
|
286 |
' <span class="litespeed-desc" data-balloon-pos="left" data-balloon-break aria-label="%1$s">%2$s</span>',
|
287 |
__( 'Using optimized version of file. ', 'litespeed-cache' ) . ' ' . __( 'No backup of original file exists.', 'litespeed-cache' ),
|
288 |
__( '(optm)', 'litespeed-cache' )
|
289 |
+
);
|
290 |
}
|
291 |
|
292 |
|
295 |
echo GUI::pie_tiny( 0, 24,
|
296 |
__( 'Congratulation! Your file was already optmized', 'litespeed-cache' ),
|
297 |
'left'
|
298 |
+
);
|
299 |
+
echo sprintf( __( 'Orig %s', 'litespeed-cache' ), '<span class="litespeed-desc">' . __( '(no savings)', 'litespeed-cache' ) . '</span>' );
|
300 |
}
|
301 |
else {
|
302 |
echo __( 'Orig', 'litespeed-cache' ) . '<span class="litespeed-left10">—</span>';
|
306 |
echo '<p>';
|
307 |
// WebP info
|
308 |
if ( $size_meta && ! empty ( $size_meta[ 'webp_saved' ] ) ) {
|
309 |
+
$percent = ceil( $size_meta[ 'webp_saved' ] * 100 / $size_meta[ 'webp_total' ] );
|
310 |
|
311 |
+
$link = Utility::build_url( Router::ACTION_IMG_OPTM, 'webp' . $post_id );
|
312 |
+
$desc = false;
|
313 |
|
314 |
+
$cls = '';
|
315 |
|
316 |
if ( $this->info( $short_path . '.webp', $post_id ) ) {
|
317 |
+
$curr_status = __( '(optm)', 'litespeed-cache' );
|
318 |
+
$desc = __( 'Currently using optimized version of WebP file.', 'litespeed-cache' ) . ' ' . __( 'Click to switch to original (unoptimized) version.', 'litespeed-cache' );
|
319 |
}
|
320 |
elseif ( $this->info( $short_path . '.optm.webp', $post_id ) ) {
|
321 |
+
$cls .= ' litespeed-warning';
|
322 |
+
$curr_status = __( '(non-optm)', 'litespeed-cache' );
|
323 |
+
$desc = __( 'Currently using original (unoptimized) version of WebP file.', 'litespeed-cache' ) . ' ' . __( 'Click to switch to optimized version.', 'litespeed-cache' );
|
324 |
}
|
325 |
|
326 |
echo GUI::pie_tiny( $percent, 24,
|
328 |
$percent . '%',
|
329 |
Utility::real_size( $size_meta[ 'webp_saved' ] )
|
330 |
) , 'left'
|
331 |
+
);
|
332 |
+
echo sprintf( __( 'WebP saved %s', 'litespeed-cache' ), $percent . '%' );
|
333 |
|
334 |
if ( $desc ) {
|
335 |
+
echo sprintf( ' <a href="%1$s" class="litespeed-media-href %2$s" data-balloon-pos="left" data-balloon-break aria-label="%3$s">%4$s</a>', $link, $cls, $desc, $curr_status );
|
336 |
}
|
337 |
else {
|
338 |
echo sprintf(
|
339 |
' <span class="litespeed-desc" data-balloon-pos="left" data-balloon-break aria-label="%1$s">%2$s</span>',
|
340 |
__( 'Using optimized version of file. ', 'litespeed-cache' ) . ' ' . __( 'No backup of unoptimized WebP file exists.', 'litespeed-cache' ),
|
341 |
__( '(optm)', 'litespeed-cache' )
|
342 |
+
);
|
343 |
}
|
344 |
|
345 |
} else {
|
354 |
echo sprintf( '<div class="row-actions"><span class="delete"><a href="%1$s" class="">%2$s</a></span></div>',
|
355 |
Utility::build_url( Router::ACTION_IMG_OPTM, Img_Optm::TYPE_RESET_ROW, false, null, array( 'id' => $post_id ) ),
|
356 |
__( 'Restore from backup', 'litespeed-cache' )
|
357 |
+
);
|
358 |
+
echo '</div>';
|
359 |
}
|
360 |
}
|
361 |
|
368 |
* @return array $sizes Data for all currently-registered image sizes.
|
369 |
*/
|
370 |
public function get_image_sizes() {
|
371 |
+
global $_wp_additional_image_sizes;
|
372 |
$sizes = array();
|
373 |
|
374 |
foreach ( get_intermediate_image_sizes() as $_size ) {
|
375 |
if ( in_array( $_size, array( 'thumbnail', 'medium', 'medium_large', 'large' ) ) ) {
|
376 |
+
$sizes[ $_size ][ 'width' ] = get_option( $_size . '_size_w' );
|
377 |
+
$sizes[ $_size ][ 'height' ] = get_option( $_size . '_size_h' );
|
378 |
+
$sizes[ $_size ][ 'crop' ] = (bool) get_option( $_size . '_crop' );
|
379 |
} elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
|
380 |
$sizes[ $_size ] = array(
|
381 |
'width' => $_wp_additional_image_sizes[ $_size ][ 'width' ],
|
382 |
'height' => $_wp_additional_image_sizes[ $_size ][ 'height' ],
|
383 |
'crop' => $_wp_additional_image_sizes[ $_size ][ 'crop' ]
|
384 |
+
);
|
385 |
}
|
386 |
}
|
387 |
|
388 |
+
return $sizes;
|
389 |
}
|
390 |
|
391 |
|
395 |
* @since 1.6.2
|
396 |
* @access public
|
397 |
*/
|
398 |
+
private function webp_support() {
|
|
|
399 |
if ( ! empty( $_SERVER[ 'HTTP_ACCEPT' ] ) && strpos( $_SERVER[ 'HTTP_ACCEPT' ], 'image/webp' ) !== false ) {
|
400 |
+
return true;
|
401 |
}
|
402 |
|
403 |
if ( ! empty( $_SERVER[ 'HTTP_USER_AGENT' ] ) && strpos( $_SERVER[ 'HTTP_USER_AGENT' ], 'Page Speed' ) !== false ) {
|
404 |
+
return true;
|
405 |
}
|
406 |
|
407 |
+
return false;
|
408 |
}
|
409 |
|
410 |
/**
|
417 |
* @access public
|
418 |
* @return string The buffer
|
419 |
*/
|
420 |
+
public static function finalize( $content ) {
|
|
|
421 |
if ( defined( 'LITESPEED_NO_LAZY' ) ) {
|
422 |
+
Debug2::debug2( '[Media] bypass: NO_LAZY const' );
|
423 |
+
return $content;
|
424 |
}
|
425 |
|
426 |
if ( ! defined( 'LITESPEED_IS_HTML' ) ) {
|
427 |
+
Debug2::debug2( '[Media] bypass: Not frontend HTML type' );
|
428 |
+
return $content;
|
429 |
}
|
430 |
|
431 |
+
Debug2::debug( '[Media] finalize' );
|
432 |
|
433 |
+
$instance = self::get_instance();
|
434 |
+
$instance->content = $content;
|
435 |
|
436 |
+
$instance->_finalize();
|
437 |
+
return $instance->content;
|
438 |
}
|
439 |
|
440 |
/**
|
443 |
* @since 1.4
|
444 |
* @access private
|
445 |
*/
|
446 |
+
private function _finalize() {
|
|
|
447 |
/**
|
448 |
* Use webp for optimized images
|
449 |
* @since 1.6.2
|
450 |
*/
|
451 |
if ( Conf::val( Base::O_IMG_OPTM_WEBP_REPLACE ) && $this->webp_support() ) {
|
452 |
+
$this->_replace_buffer_img_webp();
|
453 |
}
|
454 |
|
455 |
/**
|
456 |
* Check if URI is excluded
|
457 |
* @since 3.0
|
458 |
*/
|
459 |
+
$excludes = Conf::val( Base::O_MEDIA_LAZY_URI_EXC );
|
460 |
if ( $excludes ) {
|
461 |
+
$result = Utility::str_hit_array( $_SERVER[ 'REQUEST_URI' ], $excludes );
|
462 |
if ( $result ) {
|
463 |
+
Debug2::debug( '[Media] bypass lazyload: hit URI Excludes setting: ' . $result );
|
464 |
+
return;
|
465 |
}
|
466 |
}
|
467 |
|
468 |
+
$cfg_lazy = Conf::val( Base::O_MEDIA_LAZY );
|
469 |
+
$cfg_iframe_lazy = Conf::val( Base::O_MEDIA_IFRAME_LAZY );
|
470 |
|
471 |
if ( $cfg_lazy ) {
|
472 |
+
list( $src_list, $html_list, $placeholder_list ) = $this->_parse_img();
|
473 |
+
$html_list_ori = $html_list;
|
474 |
}
|
475 |
|
476 |
// image lazy load
|
477 |
if ( $cfg_lazy ) {
|
478 |
|
479 |
+
$__placeholder = Placeholder::get_instance();
|
480 |
|
481 |
foreach ( $html_list as $k => $v ) {
|
482 |
+
$size = $placeholder_list[ $k ];
|
483 |
+
$src = $src_list[ $k ];
|
484 |
|
485 |
+
$html_list[ $k ] = $__placeholder->replace( $v, $src, $size );
|
486 |
}
|
487 |
}
|
488 |
|
489 |
if ( $cfg_lazy ) {
|
490 |
+
$this->content = str_replace( $html_list_ori, $html_list, $this->content );
|
491 |
}
|
492 |
|
493 |
// iframe lazy load
|
494 |
if ( $cfg_iframe_lazy ) {
|
495 |
+
$html_list = $this->_parse_iframe();
|
496 |
+
$html_list_ori = $html_list;
|
497 |
|
498 |
foreach ( $html_list as $k => $v ) {
|
499 |
+
$snippet = Conf::val( Base::O_OPTM_NOSCRIPT_RM ) ? '' : '<noscript>' . $v . '</noscript>';
|
500 |
+
$v = str_replace( ' src=', ' data-src=', $v );
|
501 |
+
$v = str_replace( '<iframe ', '<iframe data-lazyloaded="1" src="about:blank" ', $v );
|
502 |
+
$snippet = $v . $snippet;
|
503 |
|
504 |
+
$html_list[ $k ] = $snippet;
|
505 |
}
|
506 |
|
507 |
+
$this->content = str_replace( $html_list_ori, $html_list, $this->content );
|
508 |
}
|
509 |
|
510 |
// Include lazyload lib js and init lazyload
|
511 |
if ( $cfg_lazy || $cfg_iframe_lazy ) {
|
512 |
if ( Conf::val( Base::O_MEDIA_LAZYJS_INLINE ) ) {
|
513 |
+
$lazy_lib = '<script>' . File::read( LSCWP_DIR . self::LIB_FILE_IMG_LAZYLOAD ) . '</script>';
|
514 |
} else {
|
515 |
+
$lazy_lib_url = LSWCP_PLUGIN_URL . self::LIB_FILE_IMG_LAZYLOAD;
|
516 |
+
$lazy_lib = '<script src="' . $lazy_lib_url . '"></script>';
|
517 |
}
|
518 |
|
519 |
+
$this->content = str_replace( '</body>', $lazy_lib . '</body>', $this->content );
|
520 |
}
|
521 |
}
|
522 |
|
528 |
* @access private
|
529 |
* @return array All the src & related raw html list
|
530 |
*/
|
531 |
+
private function _parse_img() {
|
|
|
532 |
/**
|
533 |
* Exclude list
|
534 |
* @since 1.5
|
535 |
* @since 2.7.1 Changed to array
|
536 |
*/
|
537 |
+
$excludes = apply_filters( 'litespeed_media_lazy_img_excludes', Conf::val( Base::O_MEDIA_LAZY_EXC ) );
|
538 |
|
539 |
+
$cls_excludes = apply_filters( 'litespeed_media_lazy_img_cls_excludes', Conf::val( Base::O_MEDIA_LAZY_CLS_EXC ) );
|
540 |
$cls_excludes[] = 'skip-lazy'; // https://core.trac.wordpress.org/ticket/44427
|
541 |
|
542 |
+
$src_list = array();
|
543 |
+
$html_list = array();
|
544 |
+
$placeholder_list = array();
|
545 |
|
546 |
+
$content = preg_replace( '#<!--.*-->#sU', '', $this->content );
|
547 |
/**
|
548 |
* Exclude parent classes
|
549 |
* @since 3.0
|
550 |
*/
|
551 |
+
$parent_cls_exc = apply_filters( 'litespeed_media_lazy_img_parent_cls_excludes', Conf::val( Base::O_MEDIA_LAZY_PARENT_CLS_EXC ) );
|
552 |
if ( $parent_cls_exc ) {
|
553 |
+
Debug2::debug2( '[Media] Lazyload Class excludes', $parent_cls_exc );
|
554 |
foreach ( $parent_cls_exc as $v ) {
|
555 |
+
$content = preg_replace( '#<(\w+) [^>]*class=(\'|")[^\'"]*' . preg_quote( $v, '#' ) . '[^\'"]*\2[^>]*>.*</\1>#sU', '', $content );
|
556 |
}
|
557 |
}
|
558 |
|
559 |
+
preg_match_all( '#<img \s*([^>]+)/?>#isU', $content, $matches, PREG_SET_ORDER );
|
560 |
foreach ( $matches as $match ) {
|
561 |
+
$attrs = Utility::parse_attr( $match[ 1 ] );
|
562 |
|
563 |
if ( empty( $attrs[ 'src' ] ) ) {
|
564 |
+
continue;
|
565 |
}
|
566 |
|
567 |
/**
|
569 |
* @since 1.6
|
570 |
*/
|
571 |
if ( strpos( $attrs[ 'src' ], 'base64' ) !== false || substr( $attrs[ 'src' ], 0, 5 ) === 'data:' ) {
|
572 |
+
Debug2::debug2( '[Media] lazyload bypassed base64 img' );
|
573 |
+
continue;
|
574 |
}
|
575 |
|
576 |
+
Debug2::debug2( '[Media] lazyload found: ' . $attrs[ 'src' ] );
|
577 |
|
578 |
if ( ! empty( $attrs[ 'data-no-lazy' ] ) || ! empty( $attrs[ 'data-skip-lazy' ] ) || ! empty( $attrs[ 'data-lazyloaded' ] ) || ! empty( $attrs[ 'data-src' ] ) || ! empty( $attrs[ 'data-srcset' ] ) ) {
|
579 |
+
Debug2::debug2( '[Media] bypassed' );
|
580 |
+
continue;
|
581 |
}
|
582 |
|
583 |
if ( ! empty( $attrs[ 'class' ] ) && $hit = Utility::str_hit_array( $attrs[ 'class' ], $cls_excludes ) ) {
|
584 |
+
Debug2::debug2( '[Media] lazyload image cls excludes [hit] ' . $hit );
|
585 |
+
continue;
|
586 |
}
|
587 |
|
588 |
/**
|
590 |
* @since 1.5
|
591 |
*/
|
592 |
if ( $excludes && Utility::str_hit_array( $attrs[ 'src' ], $excludes ) ) {
|
593 |
+
Debug2::debug2( '[Media] lazyload image exclude ' . $attrs[ 'src' ] );
|
594 |
+
continue;
|
595 |
}
|
596 |
|
597 |
/**
|
600 |
* @since 3.0
|
601 |
*/
|
602 |
if ( strpos( $attrs[ 'src' ], '{' ) !== false ) {
|
603 |
+
Debug2::debug2( '[Media] image src has {} ' . $attrs[ 'src' ] );
|
604 |
+
continue;
|
605 |
}
|
606 |
|
607 |
// to avoid multiple replacement
|
608 |
if ( in_array( $match[ 0 ], $html_list ) ) {
|
609 |
+
continue;
|
610 |
}
|
611 |
|
612 |
+
$placeholder = false;
|
613 |
if ( ! empty( $attrs[ 'width' ] ) && ! empty( $attrs[ 'height' ] ) ) {
|
614 |
+
$placeholder = $attrs[ 'width' ] . 'x' . $attrs[ 'height' ];
|
615 |
}
|
616 |
|
617 |
+
$src_list[] = $attrs[ 'src' ];
|
618 |
+
$html_list[] = $match[ 0 ];
|
619 |
+
$placeholder_list[] = $placeholder;
|
620 |
}
|
621 |
|
622 |
+
return array( $src_list, $html_list, $placeholder_list );
|
623 |
}
|
624 |
|
625 |
/**
|
629 |
* @access private
|
630 |
* @return array All the src & related raw html list
|
631 |
*/
|
632 |
+
private function _parse_iframe() {
|
|
|
633 |
$cls_excludes = apply_filters( 'litespeed_media_iframe_lazy_cls_excludes', Conf::val( Base::O_MEDIA_IFRAME_LAZY_CLS_EXC ) );
|
634 |
$cls_excludes[] = 'skip-lazy'; // https://core.trac.wordpress.org/ticket/44427
|
635 |
|
636 |
+
$html_list = array();
|
637 |
|
638 |
+
$content = preg_replace( '#<!--.*-->#sU', '', $this->content );
|
639 |
|
640 |
/**
|
641 |
* Exclude parent classes
|
642 |
* @since 3.0
|
643 |
*/
|
644 |
+
$parent_cls_exc = apply_filters( 'litespeed_media_iframe_lazy_parent_cls_excludes', Conf::val( Base::O_MEDIA_IFRAME_LAZY_PARENT_CLS_EXC ) );
|
645 |
if ( $parent_cls_exc ) {
|
646 |
+
Debug2::debug2( '[Media] Iframe Lazyload Class excludes', $parent_cls_exc );
|
647 |
foreach ( $parent_cls_exc as $v ) {
|
648 |
+
$content = preg_replace( '#<(\w+) [^>]*class=(\'|")[^\'"]*' . preg_quote( $v, '#' ) . '[^\'"]*\2[^>]*>.*</\1>#sU', '', $content );
|
649 |
}
|
650 |
}
|
651 |
|
652 |
+
preg_match_all( '#<iframe \s*([^>]+)></iframe>#isU', $content, $matches, PREG_SET_ORDER );
|
653 |
foreach ( $matches as $match ) {
|
654 |
+
$attrs = Utility::parse_attr( $match[ 1 ] );
|
655 |
|
656 |
if ( empty( $attrs[ 'src' ] ) ) {
|
657 |
+
continue;
|
658 |
}
|
659 |
|
660 |
+
Debug2::debug2( '[Media] found iframe: ' . $attrs[ 'src' ] );
|
661 |
|
662 |
if ( ! empty( $attrs[ 'data-no-lazy' ] ) || ! empty( $attrs[ 'data-skip-lazy' ] ) || ! empty( $attrs[ 'data-lazyloaded' ] ) || ! empty( $attrs[ 'data-src' ] ) ) {
|
663 |
+
Debug2::debug2( '[Media] bypassed' );
|
664 |
+
continue;
|
665 |
}
|
666 |
|
667 |
if ( ! empty( $attrs[ 'class' ] ) && $hit = Utility::str_hit_array( $attrs[ 'class' ], $cls_excludes ) ) {
|
668 |
+
Debug2::debug2( '[Media] iframe lazyload cls excludes [hit] ' . $hit );
|
669 |
+
continue;
|
670 |
}
|
671 |
|
672 |
if ( apply_filters( 'litespeed_iframe_lazyload_exc', false, $attrs[ 'src' ] ) ) {
|
673 |
+
Debug2::debug2( '[Media] bypassed by filter' );
|
674 |
+
continue;
|
675 |
}
|
676 |
|
677 |
// to avoid multiple replacement
|
678 |
if ( in_array( $match[ 0 ], $html_list ) ) {
|
679 |
+
continue;
|
680 |
}
|
681 |
|
682 |
+
$html_list[] = $match[ 0 ];
|
683 |
}
|
684 |
|
685 |
+
return $html_list;
|
686 |
}
|
687 |
|
688 |
/**
|
691 |
* @since 1.6.2
|
692 |
* @access private
|
693 |
*/
|
694 |
+
private function _replace_buffer_img_webp() {
|
695 |
+
// preg_match_all( '#<img([^>]+?)src=([\'"\\\]*)([^\'"\s\\\>]+)([\'"\\\]*)([^>]*)>#i', $this->content, $matches );
|
|
|
696 |
/**
|
697 |
* Added custom element & attribute support
|
698 |
* @since 2.2.2
|
699 |
*/
|
700 |
+
$webp_ele_to_check = Conf::val( Base::O_IMG_OPTM_WEBP_ATTR );
|
701 |
|
702 |
foreach ( $webp_ele_to_check as $v ) {
|
703 |
if ( ! $v || strpos( $v, '.' ) === false ) {
|
704 |
+
Debug2::debug2( '[Media] buffer_webp no . attribute ' . $v );
|
705 |
+
continue;
|
706 |
}
|
707 |
|
708 |
+
Debug2::debug2( '[Media] buffer_webp attribute ' . $v );
|
709 |
|
710 |
+
$v = explode( '.', $v );
|
711 |
+
$attr = preg_quote( $v[ 1 ], '#' );
|
712 |
if ( $v[ 0 ] ) {
|
713 |
+
$pattern = '#<' . preg_quote( $v[ 0 ], '#' ) . '([^>]+)' . $attr . '=([\'"])(.+)\g{2}#iU';
|
714 |
}
|
715 |
else {
|
716 |
+
$pattern = '# ' . $attr . '=([\'"])(.+)\g{1}#iU';
|
717 |
}
|
718 |
|
719 |
+
preg_match_all( $pattern, $this->content, $matches );
|
720 |
|
721 |
foreach ( $matches[ $v[ 0 ] ? 3 : 2 ] as $k2 => $url ) {
|
722 |
// Check if is a DATA-URI
|
723 |
if ( strpos( $url, 'data:image' ) !== false ) {
|
724 |
+
continue;
|
725 |
}
|
726 |
|
727 |
if ( ! $url2 = $this->replace_webp( $url ) ) {
|
728 |
+
continue;
|
729 |
}
|
730 |
|
731 |
if ( $v[ 0 ] ) {
|
733 |
'<' . $v[ 0 ] . '%1$s' . $v[ 1 ] . '=%2$s',
|
734 |
$matches[ 1 ][ $k2 ],
|
735 |
$matches[ 2 ][ $k2 ] . $url2 . $matches[ 2 ][ $k2 ]
|
736 |
+
);
|
737 |
}
|
738 |
else {
|
739 |
$html_snippet = sprintf(
|
740 |
' ' . $v[ 1 ] . '=%1$s',
|
741 |
$matches[ 1 ][ $k2 ] . $url2 . $matches[ 1 ][ $k2 ]
|
742 |
+
);
|
743 |
}
|
744 |
|
745 |
+
$this->content = str_replace( $matches[ 0 ][ $k2 ], $html_snippet, $this->content );
|
746 |
|
747 |
}
|
748 |
}
|
750 |
// parse srcset
|
751 |
// todo: should apply this to cdn too
|
752 |
if ( Conf::val( Base::O_IMG_OPTM_WEBP_REPLACE_SRCSET ) ) {
|
753 |
+
$this->content = Utility::srcset_replace( $this->content, array( $this, 'replace_webp' ) );
|
754 |
}
|
755 |
|
756 |
// Replace background-image
|
757 |
+
preg_match_all( '#background\-image:(\s*)url\((.*)\)#iU', $this->content, $matches );
|
758 |
foreach ( $matches[ 2 ] as $k => $url ) {
|
759 |
// Check if is a DATA-URI
|
760 |
if ( strpos( $url, 'data:image' ) !== false ) {
|
761 |
+
continue;
|
762 |
}
|
763 |
|
764 |
/**
|
765 |
* Support quotes in src `background-image: url('src')`
|
766 |
* @since 2.9.3
|
767 |
*/
|
768 |
+
$url = trim( $url, '\'"' );
|
769 |
|
770 |
if ( ! $url2 = $this->replace_webp( $url ) ) {
|
771 |
+
continue;
|
772 |
}
|
773 |
|
774 |
+
// $html_snippet = sprintf( 'background-image:%1$surl(%2$s)', $matches[ 1 ][ $k ], $url2 );
|
775 |
+
$html_snippet = str_replace( $url, $url2, $matches[ 0 ][ $k ] );
|
776 |
+
$this->content = str_replace( $matches[ 0 ][ $k ], $html_snippet, $this->content );
|
777 |
}
|
778 |
}
|
779 |
|
785 |
* @param array $img The URL of the attachment image src, the width, the height
|
786 |
* @return array
|
787 |
*/
|
788 |
+
public function webp_attach_img_src( $img ) {
|
789 |
+
Debug2::debug2( '[Media] changing attach src: ' . $img[0] );
|
|
|
790 |
if ( $img && $url = $this->replace_webp( $img[ 0 ] ) ) {
|
791 |
+
$img[ 0 ] = $url;
|
792 |
}
|
793 |
+
return $img;
|
794 |
}
|
795 |
|
796 |
/**
|
801 |
* @param string $url
|
802 |
* @return string
|
803 |
*/
|
804 |
+
public function webp_url( $url ) {
|
|
|
805 |
if ( $url && $url2 = $this->replace_webp( $url ) ) {
|
806 |
+
$url = $url2;
|
807 |
}
|
808 |
+
return $url;
|
809 |
}
|
810 |
|
811 |
/**
|
816 |
* @param array $srcs
|
817 |
* @return array
|
818 |
*/
|
819 |
+
public function webp_srcset( $srcs ) {
|
|
|
820 |
if ( $srcs ) {
|
821 |
foreach ( $srcs as $w => $data ) {
|
822 |
if( ! $url = $this->replace_webp( $data[ 'url' ] ) ) {
|
823 |
+
continue;
|
824 |
}
|
825 |
+
$srcs[ $w ][ 'url' ] = $url;
|
826 |
}
|
827 |
}
|
828 |
+
return $srcs;
|
829 |
}
|
830 |
|
831 |
/**
|
834 |
* @since 1.6.2
|
835 |
* @access public
|
836 |
*/
|
837 |
+
public function replace_webp( $url ) {
|
838 |
+
Debug2::debug2( '[Media] webp replacing: ' . $url, 4 );
|
|
|
839 |
|
840 |
if ( substr( $url, -5 ) == '.webp' ) {
|
841 |
+
Debug2::debug2( '[Media] already webp' );
|
842 |
+
return false;
|
843 |
}
|
844 |
|
845 |
/**
|
851 |
if ( apply_filters( 'litespeed_media_check_ori', Utility::is_internal_file( $url ), $url ) ) {
|
852 |
// check if has webp file
|
853 |
if ( apply_filters( 'litespeed_media_check_webp', Utility::is_internal_file( $url, 'webp' ), $url ) ) {
|
854 |
+
$url .= '.webp';
|
855 |
}
|
856 |
else {
|
857 |
+
Debug2::debug2( '[Media] -no WebP file, bypassed' );
|
858 |
+
return false;
|
859 |
}
|
860 |
}
|
861 |
else {
|
862 |
+
Debug2::debug2( '[Media] -no file, bypassed' );
|
863 |
+
return false;
|
864 |
}
|
865 |
|
866 |
+
Debug2::debug2( '[Media] - replaced to: ' . $url );
|
867 |
|
868 |
+
return $url;
|
869 |
}
|
870 |
|
871 |
}
|
src/object.lib.php
CHANGED
@@ -4,27 +4,25 @@
|
|
4 |
*
|
5 |
* @since 1.8
|
6 |
*/
|
7 |
-
defined( 'WPINC' ) || exit
|
8 |
|
9 |
/**
|
10 |
* Handle exception
|
11 |
*/
|
12 |
if ( ! function_exists( 'litespeed_exception_handler' ) ) {
|
13 |
-
function litespeed_exception_handler( $errno, $errstr, $errfile, $errline )
|
14 |
-
|
15 |
-
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline) ;
|
16 |
}
|
17 |
}
|
18 |
|
19 |
-
require_once __DIR__ . '/object-cache.cls.php'
|
20 |
|
21 |
/**
|
22 |
* Sets up Object Cache Global and assigns it.
|
23 |
*
|
24 |
* @since 1.8
|
25 |
*/
|
26 |
-
function wp_cache_init()
|
27 |
-
{
|
28 |
$GLOBALS['wp_object_cache'] = WP_Object_Cache::get_instance();
|
29 |
}
|
30 |
|
@@ -33,11 +31,10 @@ function wp_cache_init()
|
|
33 |
*
|
34 |
* @since 1.8
|
35 |
*/
|
36 |
-
function wp_cache_get( $key, $group = '', $force = false, &$found = null )
|
37 |
-
|
38 |
-
global $wp_object_cache ;
|
39 |
|
40 |
-
return $wp_object_cache->get( $key, $group, $force, $found )
|
41 |
}
|
42 |
|
43 |
/**
|
@@ -45,11 +42,10 @@ function wp_cache_get( $key, $group = '', $force = false, &$found = null )
|
|
45 |
*
|
46 |
* @since 1.8
|
47 |
*/
|
48 |
-
function wp_cache_set( $key, $data, $group = '', $expire = 0 )
|
49 |
-
|
50 |
-
global $wp_object_cache ;
|
51 |
|
52 |
-
return $wp_object_cache->set( $key, $data, $group, $expire )
|
53 |
}
|
54 |
|
55 |
/**
|
@@ -57,11 +53,10 @@ function wp_cache_set( $key, $data, $group = '', $expire = 0 )
|
|
57 |
*
|
58 |
* @since 1.8
|
59 |
*/
|
60 |
-
function wp_cache_add( $key, $data, $group = '', $expire = 0 )
|
61 |
-
|
62 |
-
global $wp_object_cache ;
|
63 |
|
64 |
-
return $wp_object_cache->add( $key, $data, $group, $expire )
|
65 |
}
|
66 |
|
67 |
/**
|
@@ -69,11 +64,10 @@ function wp_cache_add( $key, $data, $group = '', $expire = 0 )
|
|
69 |
*
|
70 |
* @since 1.8
|
71 |
*/
|
72 |
-
function wp_cache_replace( $key, $data, $group = '', $expire = 0 )
|
73 |
-
|
74 |
-
global $wp_object_cache ;
|
75 |
|
76 |
-
return $wp_object_cache->replace( $key, $data, $group, $expire )
|
77 |
}
|
78 |
|
79 |
/**
|
@@ -81,11 +75,10 @@ function wp_cache_replace( $key, $data, $group = '', $expire = 0 )
|
|
81 |
*
|
82 |
* @since 1.8
|
83 |
*/
|
84 |
-
function wp_cache_incr( $key, $offset = 1, $group = '' )
|
85 |
-
|
86 |
-
global $wp_object_cache ;
|
87 |
|
88 |
-
return $wp_object_cache->incr_desr( $key, $offset, $group )
|
89 |
}
|
90 |
|
91 |
/**
|
@@ -93,11 +86,10 @@ function wp_cache_incr( $key, $offset = 1, $group = '' )
|
|
93 |
*
|
94 |
* @since 1.8
|
95 |
*/
|
96 |
-
function wp_cache_decr( $key, $offset = 1, $group = '' )
|
97 |
-
|
98 |
-
global $wp_object_cache ;
|
99 |
|
100 |
-
return $wp_object_cache->incr_desr( $key, $offset, $group, false )
|
101 |
}
|
102 |
|
103 |
/**
|
@@ -105,11 +97,10 @@ function wp_cache_decr( $key, $offset = 1, $group = '' )
|
|
105 |
*
|
106 |
* @since 1.8
|
107 |
*/
|
108 |
-
function wp_cache_delete( $key, $group = '' )
|
109 |
-
|
110 |
-
global $wp_object_cache ;
|
111 |
|
112 |
-
return $wp_object_cache->delete( $key, $group )
|
113 |
}
|
114 |
|
115 |
/**
|
@@ -117,11 +108,10 @@ function wp_cache_delete( $key, $group = '' )
|
|
117 |
*
|
118 |
* @since 1.8
|
119 |
*/
|
120 |
-
function wp_cache_flush()
|
121 |
-
|
122 |
-
global $wp_object_cache ;
|
123 |
|
124 |
-
return $wp_object_cache->flush()
|
125 |
}
|
126 |
|
127 |
/**
|
@@ -129,11 +119,10 @@ function wp_cache_flush()
|
|
129 |
*
|
130 |
* @since 1.8
|
131 |
*/
|
132 |
-
function wp_cache_add_global_groups( $groups )
|
133 |
-
|
134 |
-
global $wp_object_cache ;
|
135 |
|
136 |
-
$wp_object_cache->add_global_groups( $groups )
|
137 |
}
|
138 |
|
139 |
/**
|
@@ -141,11 +130,10 @@ function wp_cache_add_global_groups( $groups )
|
|
141 |
*
|
142 |
* @since 1.8
|
143 |
*/
|
144 |
-
function wp_cache_add_non_persistent_groups( $groups )
|
145 |
-
|
146 |
-
global $wp_object_cache ;
|
147 |
|
148 |
-
$wp_object_cache->add_non_persistent_groups( $groups )
|
149 |
}
|
150 |
|
151 |
/**
|
@@ -161,9 +149,9 @@ function wp_cache_add_non_persistent_groups( $groups )
|
|
161 |
* @param int $blog_id Site ID.
|
162 |
*/
|
163 |
function wp_cache_switch_to_blog( $blog_id ) {
|
164 |
-
global $wp_object_cache
|
165 |
|
166 |
-
$wp_object_cache->switch_to_blog( $blog_id )
|
167 |
}
|
168 |
|
169 |
/**
|
@@ -171,30 +159,28 @@ function wp_cache_switch_to_blog( $blog_id ) {
|
|
171 |
*
|
172 |
* @since 1.8
|
173 |
*/
|
174 |
-
function wp_cache_close()
|
175 |
-
|
176 |
-
return true ;
|
177 |
}
|
178 |
|
179 |
|
180 |
|
181 |
-
class WP_Object_Cache
|
182 |
-
|
183 |
-
protected static $_instance ;
|
184 |
|
185 |
-
private $_object_cache
|
186 |
|
187 |
-
private $_cache = array()
|
188 |
-
private $_cache_404 = array()
|
189 |
|
190 |
-
private $cache_total = 0
|
191 |
-
private $count_hit_incall = 0
|
192 |
-
private $count_hit = 0
|
193 |
-
private $count_miss_incall = 0
|
194 |
-
private $count_miss = 0
|
195 |
-
private $count_set = 0
|
196 |
|
197 |
-
private $blog_prefix
|
198 |
|
199 |
/**
|
200 |
* Init
|
@@ -202,18 +188,17 @@ class WP_Object_Cache
|
|
202 |
* @since 1.8
|
203 |
* @access protected
|
204 |
*/
|
205 |
-
protected function __construct()
|
206 |
-
|
207 |
-
$this->_object_cache = \LiteSpeed\Object_Cache::get_instance() ;
|
208 |
|
209 |
-
$this->multisite = is_multisite()
|
210 |
-
$this->blog_prefix = $this->multisite ? get_current_blog_id() . ':' : ''
|
211 |
|
212 |
/**
|
213 |
* Fix multiple instance using same oc issue
|
214 |
* @since 1.8.2
|
215 |
*/
|
216 |
-
! defined( 'LSOC_PREFIX' ) && define( 'LSOC_PREFIX', substr( md5( __FILE__ ), -5 ) )
|
217 |
}
|
218 |
|
219 |
/**
|
@@ -222,16 +207,15 @@ class WP_Object_Cache
|
|
222 |
* @since 1.8
|
223 |
* @access public
|
224 |
*/
|
225 |
-
public function debug()
|
226 |
-
{
|
227 |
$log = ' [total] ' . $this->cache_total
|
228 |
. ' [hit_incall] ' . $this->count_hit_incall
|
229 |
. ' [hit] ' . $this->count_hit
|
230 |
. ' [miss_incall] ' . $this->count_miss_incall
|
231 |
. ' [miss] ' . $this->count_miss
|
232 |
-
. ' [set] ' . $this->count_set
|
233 |
|
234 |
-
return $log
|
235 |
}
|
236 |
|
237 |
/**
|
@@ -240,62 +224,61 @@ class WP_Object_Cache
|
|
240 |
* @since 1.8
|
241 |
* @access public
|
242 |
*/
|
243 |
-
public function get( $key, $group = 'default', $force = false, &$found = null )
|
244 |
-
|
245 |
-
$final_key = $this->_key( $key, $group ) ;
|
246 |
// error_log('');
|
247 |
// error_log("oc: get \t\t\t[key] " . $final_key . ( $force ? "\t\t\t [forced] " : '' ) );
|
248 |
-
$found = false
|
249 |
-
$found_in_oc = false
|
250 |
-
$cache_val = false
|
251 |
if ( array_key_exists( $final_key, $this->_cache ) && ! $force ) {
|
252 |
-
$found = true
|
253 |
-
$cache_val = $this->_cache[ $final_key ]
|
254 |
-
$this->count_hit_incall
|
255 |
}
|
256 |
elseif ( ! array_key_exists( $final_key, $this->_cache_404 ) && ! $this->_object_cache->is_non_persistent( $group ) ) {
|
257 |
-
$v = $this->_object_cache->get( $final_key )
|
258 |
|
259 |
if ( $v !== null ) {
|
260 |
-
$v = @maybe_unserialize( $v )
|
261 |
}
|
262 |
|
263 |
// To be compatible with false val
|
264 |
if ( is_array( $v ) && array_key_exists( 'data', $v ) ) {
|
265 |
-
$this->count_hit
|
266 |
-
$found = true
|
267 |
-
$found_in_oc = true
|
268 |
-
$cache_val = $v[ 'data' ]
|
269 |
}
|
270 |
else { // Can't find key, cache it to 404
|
271 |
-
// error_log("oc: add404\t\t\t[key] " . $final_key )
|
272 |
-
$this->_cache_404[ $final_key ] = 1
|
273 |
-
$this->count_miss
|
274 |
}
|
275 |
}
|
276 |
else {
|
277 |
-
$this->count_miss_incall
|
278 |
}
|
279 |
|
280 |
if ( is_object( $cache_val ) ) {
|
281 |
-
$cache_val = clone $cache_val
|
282 |
}
|
283 |
|
284 |
// If not found but has `Store Transients` cfg on, still need to follow WP's get_transient() logic
|
285 |
if ( ! $found && $this->_object_cache->store_transients( $group ) ) {
|
286 |
-
$cache_val = $this->_transient_get( $key, $group )
|
287 |
if ( $cache_val ) {
|
288 |
-
$found = true
|
289 |
}
|
290 |
}
|
291 |
|
292 |
if ( $found_in_oc ) {
|
293 |
-
$this->_cache[ $final_key ] = $cache_val
|
294 |
}
|
295 |
|
296 |
-
$this->cache_total
|
297 |
|
298 |
-
return $cache_val
|
299 |
}
|
300 |
|
301 |
/**
|
@@ -304,31 +287,30 @@ class WP_Object_Cache
|
|
304 |
* @since 1.8
|
305 |
* @access public
|
306 |
*/
|
307 |
-
public function set( $key, $data, $group = 'default', $expire = 0 )
|
308 |
-
|
309 |
-
$final_key = $this->_key( $key, $group ) ;
|
310 |
|
311 |
if ( is_object( $data ) ) {
|
312 |
-
$data = clone $data
|
313 |
}
|
314 |
-
// error_log("oc: set \t\t\t[key] " . $final_key )
|
315 |
-
$this->_cache[ $final_key ] = $data
|
316 |
|
317 |
if( array_key_exists( $final_key, $this->_cache_404 ) ) {
|
318 |
-
// error_log("oc: unset404\t\t\t[key] " . $final_key )
|
319 |
-
unset( $this->_cache_404[ $final_key ] )
|
320 |
}
|
321 |
|
322 |
if ( ! $this->_object_cache->is_non_persistent( $group ) ) {
|
323 |
-
$this->_object_cache->set( $final_key, serialize( array( 'data' => $data ) ), $expire )
|
324 |
-
$this->count_set
|
325 |
}
|
326 |
|
327 |
if ( $this->_object_cache->store_transients( $group ) ) {
|
328 |
-
$this->_transient_set( $key, $data, $group, $expire )
|
329 |
}
|
330 |
|
331 |
-
return true
|
332 |
}
|
333 |
|
334 |
/**
|
@@ -337,19 +319,18 @@ class WP_Object_Cache
|
|
337 |
* @since 1.8
|
338 |
* @access public
|
339 |
*/
|
340 |
-
public function add( $key, $data, $group = 'default', $expire = 0 )
|
341 |
-
{
|
342 |
if ( wp_suspend_cache_addition() ) {
|
343 |
-
return false
|
344 |
}
|
345 |
|
346 |
-
$final_key = $this->_key( $key, $group )
|
347 |
|
348 |
if ( array_key_exists( $final_key, $this->_cache ) ) {
|
349 |
-
return false
|
350 |
}
|
351 |
|
352 |
-
return $this->set( $key, $data, $group, $expire )
|
353 |
}
|
354 |
|
355 |
/**
|
@@ -358,15 +339,14 @@ class WP_Object_Cache
|
|
358 |
* @since 1.8
|
359 |
* @access public
|
360 |
*/
|
361 |
-
public function replace( $key, $data, $group = 'default', $expire = 0 )
|
362 |
-
|
363 |
-
$final_key = $this->_key( $key, $group ) ;
|
364 |
|
365 |
if ( ! array_key_exists( $final_key, $this->_cache ) ) {
|
366 |
-
return false
|
367 |
}
|
368 |
|
369 |
-
return $this->set( $key, $data, $group, $expire )
|
370 |
}
|
371 |
|
372 |
/**
|
@@ -375,34 +355,33 @@ class WP_Object_Cache
|
|
375 |
* @since 1.8
|
376 |
* @access public
|
377 |
*/
|
378 |
-
public function incr_desr( $key, $offset = 1, $group = 'default', $incr = true )
|
379 |
-
|
380 |
-
$cache_val = $this->get( $key, $group ) ;
|
381 |
|
382 |
if ( $cache_val === false ) {
|
383 |
-
return false
|
384 |
}
|
385 |
|
386 |
if ( ! is_numeric( $cache_val ) ) {
|
387 |
-
$cache_val = 0
|
388 |
}
|
389 |
|
390 |
-
$offset = (int) $offset
|
391 |
|
392 |
if ( $incr ) {
|
393 |
-
$cache_val += $offset
|
394 |
}
|
395 |
else {
|
396 |
-
$cache_val -= $offset
|
397 |
}
|
398 |
|
399 |
if ( $cache_val < 0 ) {
|
400 |
-
$cache_val = 0
|
401 |
}
|
402 |
|
403 |
-
$this->set( $key, $cache_val, $group )
|
404 |
|
405 |
-
return $cache_val
|
406 |
}
|
407 |
|
408 |
/**
|
@@ -411,25 +390,24 @@ class WP_Object_Cache
|
|
411 |
* @since 1.8
|
412 |
* @access public
|
413 |
*/
|
414 |
-
public function delete( $key, $group = 'default' )
|
415 |
-
{
|
416 |
|
417 |
-
$final_key = $this->_key( $key, $group )
|
418 |
|
419 |
if ( $this->_object_cache->store_transients( $group ) ) {
|
420 |
-
$this->_transient_del( $key, $group )
|
421 |
}
|
422 |
|
423 |
if ( array_key_exists( $final_key, $this->_cache ) ) {
|
424 |
-
unset( $this->_cache[ $final_key ] )
|
425 |
}
|
426 |
-
// error_log("oc: delete \t\t\t[key] " . $final_key )
|
427 |
|
428 |
if ( $this->_object_cache->is_non_persistent( $group ) ) {
|
429 |
-
return false
|
430 |
}
|
431 |
|
432 |
-
return $this->_object_cache->delete( $final_key )
|
433 |
}
|
434 |
|
435 |
/**
|
@@ -438,15 +416,14 @@ class WP_Object_Cache
|
|
438 |
* @since 1.8
|
439 |
* @access public
|
440 |
*/
|
441 |
-
public function flush()
|
442 |
-
|
443 |
-
$this->
|
444 |
-
|
445 |
-
// error_log("oc: flush " ) ;
|
446 |
|
447 |
-
$this->_object_cache->flush()
|
448 |
|
449 |
-
return true
|
450 |
}
|
451 |
|
452 |
/**
|
@@ -455,9 +432,8 @@ class WP_Object_Cache
|
|
455 |
* @since 1.8
|
456 |
* @access public
|
457 |
*/
|
458 |
-
public function add_global_groups( $groups )
|
459 |
-
|
460 |
-
$this->_object_cache->add_global_groups( $groups ) ;
|
461 |
}
|
462 |
|
463 |
/**
|
@@ -466,9 +442,8 @@ class WP_Object_Cache
|
|
466 |
* @since 1.8
|
467 |
* @access public
|
468 |
*/
|
469 |
-
public function add_non_persistent_groups( $groups )
|
470 |
-
|
471 |
-
$this->_object_cache->add_non_persistent_groups( $groups ) ;
|
472 |
}
|
473 |
|
474 |
/**
|
@@ -477,11 +452,10 @@ class WP_Object_Cache
|
|
477 |
* @since 1.8
|
478 |
* @access private
|
479 |
*/
|
480 |
-
private function _key( $key, $group = 'default' )
|
481 |
-
|
482 |
-
$prefix = $this->_object_cache->is_global( $group ) ? '' : $this->blog_prefix ;
|
483 |
|
484 |
-
return LSOC_PREFIX . $prefix . $group . '.' . $key
|
485 |
}
|
486 |
|
487 |
/**
|
@@ -494,8 +468,8 @@ class WP_Object_Cache
|
|
494 |
* @param int $blog_id Blog ID.
|
495 |
*/
|
496 |
public function switch_to_blog( $blog_id ) {
|
497 |
-
$blog_id = (int) $blog_id
|
498 |
-
$this->blog_prefix = $this->multisite ? $blog_id . ':' : ''
|
499 |
}
|
500 |
|
501 |
/**
|
@@ -505,8 +479,7 @@ class WP_Object_Cache
|
|
505 |
* @access private
|
506 |
* @see `wp-includes/option.php` function `get_transient`/`set_site_transient`
|
507 |
*/
|
508 |
-
private function _transient_get( $transient, $group )
|
509 |
-
{
|
510 |
if ( $group == 'transient' ) {
|
511 |
/**** Ori WP func start ****/
|
512 |
$transient_option = '_transient_' . $transient;
|
@@ -547,10 +520,10 @@ class WP_Object_Cache
|
|
547 |
/**** Ori WP func end ****/
|
548 |
}
|
549 |
else {
|
550 |
-
$value = false
|
551 |
}
|
552 |
|
553 |
-
return $value
|
554 |
}
|
555 |
|
556 |
/**
|
@@ -560,8 +533,7 @@ class WP_Object_Cache
|
|
560 |
* @access private
|
561 |
* @see `wp-includes/option.php` function `set_transient`/`set_site_transient`
|
562 |
*/
|
563 |
-
private function _transient_set( $transient, $value, $group, $expiration )
|
564 |
-
{
|
565 |
if ( $group == 'transient' ) {
|
566 |
/**** Ori WP func start ****/
|
567 |
$transient_timeout = '_transient_timeout_' . $transient;
|
@@ -609,10 +581,10 @@ class WP_Object_Cache
|
|
609 |
/**** Ori WP func end ****/
|
610 |
}
|
611 |
else {
|
612 |
-
$result = null
|
613 |
}
|
614 |
|
615 |
-
return $result
|
616 |
}
|
617 |
|
618 |
/**
|
@@ -622,8 +594,7 @@ class WP_Object_Cache
|
|
622 |
* @access private
|
623 |
* @see `wp-includes/option.php` function `delete_transient`/`delete_site_transient`
|
624 |
*/
|
625 |
-
private function _transient_del( $transient, $group )
|
626 |
-
{
|
627 |
if ( $group == 'transient' ) {
|
628 |
/**** Ori WP func start ****/
|
629 |
$option_timeout = '_transient_timeout_' . $transient;
|
@@ -650,12 +621,11 @@ class WP_Object_Cache
|
|
650 |
* @since 1.8
|
651 |
* @access public
|
652 |
*/
|
653 |
-
public static function get_instance()
|
654 |
-
{
|
655 |
if ( ! isset( self::$_instance ) ) {
|
656 |
-
self::$_instance = new self()
|
657 |
}
|
658 |
|
659 |
-
return self::$_instance
|
660 |
}
|
661 |
}
|
4 |
*
|
5 |
* @since 1.8
|
6 |
*/
|
7 |
+
defined( 'WPINC' ) || exit;
|
8 |
|
9 |
/**
|
10 |
* Handle exception
|
11 |
*/
|
12 |
if ( ! function_exists( 'litespeed_exception_handler' ) ) {
|
13 |
+
function litespeed_exception_handler( $errno, $errstr, $errfile, $errline ) {
|
14 |
+
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
|
|
|
15 |
}
|
16 |
}
|
17 |
|
18 |
+
require_once __DIR__ . '/object-cache.cls.php';
|
19 |
|
20 |
/**
|
21 |
* Sets up Object Cache Global and assigns it.
|
22 |
*
|
23 |
* @since 1.8
|
24 |
*/
|
25 |
+
function wp_cache_init() {
|
|
|
26 |
$GLOBALS['wp_object_cache'] = WP_Object_Cache::get_instance();
|
27 |
}
|
28 |
|
31 |
*
|
32 |
* @since 1.8
|
33 |
*/
|
34 |
+
function wp_cache_get( $key, $group = '', $force = false, &$found = null ) {
|
35 |
+
global $wp_object_cache;
|
|
|
36 |
|
37 |
+
return $wp_object_cache->get( $key, $group, $force, $found );
|
38 |
}
|
39 |
|
40 |
/**
|
42 |
*
|
43 |
* @since 1.8
|
44 |
*/
|
45 |
+
function wp_cache_set( $key, $data, $group = '', $expire = 0 ) {
|
46 |
+
global $wp_object_cache;
|
|
|
47 |
|
48 |
+
return $wp_object_cache->set( $key, $data, $group, $expire );
|
49 |
}
|
50 |
|
51 |
/**
|
53 |
*
|
54 |
* @since 1.8
|
55 |
*/
|
56 |
+
function wp_cache_add( $key, $data, $group = '', $expire = 0 ) {
|
57 |
+
global $wp_object_cache;
|
|
|
58 |
|
59 |
+
return $wp_object_cache->add( $key, $data, $group, $expire );
|
60 |
}
|
61 |
|
62 |
/**
|
64 |
*
|
65 |
* @since 1.8
|
66 |
*/
|
67 |
+
function wp_cache_replace( $key, $data, $group = '', $expire = 0 ) {
|
68 |
+
global $wp_object_cache;
|
|
|
69 |
|
70 |
+
return $wp_object_cache->replace( $key, $data, $group, $expire );
|
71 |
}
|
72 |
|
73 |
/**
|
75 |
*
|
76 |
* @since 1.8
|
77 |
*/
|
78 |
+
function wp_cache_incr( $key, $offset = 1, $group = '' ) {
|
79 |
+
global $wp_object_cache;
|
|
|
80 |
|
81 |
+
return $wp_object_cache->incr_desr( $key, $offset, $group );
|
82 |
}
|
83 |
|
84 |
/**
|
86 |
*
|
87 |
* @since 1.8
|
88 |
*/
|
89 |
+
function wp_cache_decr( $key, $offset = 1, $group = '' ) {
|
90 |
+
global $wp_object_cache;
|
|
|
91 |
|
92 |
+
return $wp_object_cache->incr_desr( $key, $offset, $group, false );
|
93 |
}
|
94 |
|
95 |
/**
|
97 |
*
|
98 |
* @since 1.8
|
99 |
*/
|
100 |
+
function wp_cache_delete( $key, $group = '' ) {
|
101 |
+
global $wp_object_cache;
|
|
|
102 |
|
103 |
+
return $wp_object_cache->delete( $key, $group );
|
104 |
}
|
105 |
|
106 |
/**
|
108 |
*
|
109 |
* @since 1.8
|
110 |
*/
|
111 |
+
function wp_cache_flush() {
|
112 |
+
global $wp_object_cache;
|
|
|
113 |
|
114 |
+
return $wp_object_cache->flush();
|
115 |
}
|
116 |
|
117 |
/**
|
119 |
*
|
120 |
* @since 1.8
|
121 |
*/
|
122 |
+
function wp_cache_add_global_groups( $groups ) {
|
123 |
+
global $wp_object_cache;
|
|
|
124 |
|
125 |
+
$wp_object_cache->add_global_groups( $groups );
|
126 |
}
|
127 |
|
128 |
/**
|
130 |
*
|
131 |
* @since 1.8
|
132 |
*/
|
133 |
+
function wp_cache_add_non_persistent_groups( $groups ) {
|
134 |
+
global $wp_object_cache;
|
|
|
135 |
|
136 |
+
$wp_object_cache->add_non_persistent_groups( $groups );
|
137 |
}
|
138 |
|
139 |
/**
|
149 |
* @param int $blog_id Site ID.
|
150 |
*/
|
151 |
function wp_cache_switch_to_blog( $blog_id ) {
|
152 |
+
global $wp_object_cache;
|
153 |
|
154 |
+
$wp_object_cache->switch_to_blog( $blog_id );
|
155 |
}
|
156 |
|
157 |
/**
|
159 |
*
|
160 |
* @since 1.8
|
161 |
*/
|
162 |
+
function wp_cache_close() {
|
163 |
+
return true;
|
|
|
164 |
}
|
165 |
|
166 |
|
167 |
|
168 |
+
class WP_Object_Cache {
|
169 |
+
protected static $_instance;
|
|
|
170 |
|
171 |
+
private $_object_cache;
|
172 |
|
173 |
+
private $_cache = array();
|
174 |
+
private $_cache_404 = array();
|
175 |
|
176 |
+
private $cache_total = 0;
|
177 |
+
private $count_hit_incall = 0;
|
178 |
+
private $count_hit = 0;
|
179 |
+
private $count_miss_incall = 0;
|
180 |
+
private $count_miss = 0;
|
181 |
+
private $count_set = 0;
|
182 |
|
183 |
+
private $blog_prefix;
|
184 |
|
185 |
/**
|
186 |
* Init
|
188 |
* @since 1.8
|
189 |
* @access protected
|
190 |
*/
|
191 |
+
protected function __construct() {
|
192 |
+
$this->_object_cache = \LiteSpeed\Object_Cache::get_instance();
|
|
|
193 |
|
194 |
+
$this->multisite = is_multisite();
|
195 |
+
$this->blog_prefix = $this->multisite ? get_current_blog_id() . ':' : '';
|
196 |
|
197 |
/**
|
198 |
* Fix multiple instance using same oc issue
|
199 |
* @since 1.8.2
|
200 |
*/
|
201 |
+
! defined( 'LSOC_PREFIX' ) && define( 'LSOC_PREFIX', substr( md5( __FILE__ ), -5 ) );
|
202 |
}
|
203 |
|
204 |
/**
|
207 |
* @since 1.8
|
208 |
* @access public
|
209 |
*/
|
210 |
+
public function debug() {
|
|
|
211 |
$log = ' [total] ' . $this->cache_total
|
212 |
. ' [hit_incall] ' . $this->count_hit_incall
|
213 |
. ' [hit] ' . $this->count_hit
|
214 |
. ' [miss_incall] ' . $this->count_miss_incall
|
215 |
. ' [miss] ' . $this->count_miss
|
216 |
+
. ' [set] ' . $this->count_set;
|
217 |
|
218 |
+
return $log;
|
219 |
}
|
220 |
|
221 |
/**
|
224 |
* @since 1.8
|
225 |
* @access public
|
226 |
*/
|
227 |
+
public function get( $key, $group = 'default', $force = false, &$found = null ) {
|
228 |
+
$final_key = $this->_key( $key, $group );
|
|
|
229 |
// error_log('');
|
230 |
// error_log("oc: get \t\t\t[key] " . $final_key . ( $force ? "\t\t\t [forced] " : '' ) );
|
231 |
+
$found = false;
|
232 |
+
$found_in_oc = false;
|
233 |
+
$cache_val = false;
|
234 |
if ( array_key_exists( $final_key, $this->_cache ) && ! $force ) {
|
235 |
+
$found = true;
|
236 |
+
$cache_val = $this->_cache[ $final_key ];
|
237 |
+
$this->count_hit_incall ++;
|
238 |
}
|
239 |
elseif ( ! array_key_exists( $final_key, $this->_cache_404 ) && ! $this->_object_cache->is_non_persistent( $group ) ) {
|
240 |
+
$v = $this->_object_cache->get( $final_key );
|
241 |
|
242 |
if ( $v !== null ) {
|
243 |
+
$v = @maybe_unserialize( $v );
|
244 |
}
|
245 |
|
246 |
// To be compatible with false val
|
247 |
if ( is_array( $v ) && array_key_exists( 'data', $v ) ) {
|
248 |
+
$this->count_hit ++;
|
249 |
+
$found = true;
|
250 |
+
$found_in_oc = true;
|
251 |
+
$cache_val = $v[ 'data' ];
|
252 |
}
|
253 |
else { // Can't find key, cache it to 404
|
254 |
+
// error_log("oc: add404\t\t\t[key] " . $final_key );
|
255 |
+
$this->_cache_404[ $final_key ] = 1;
|
256 |
+
$this->count_miss ++;
|
257 |
}
|
258 |
}
|
259 |
else {
|
260 |
+
$this->count_miss_incall ++;
|
261 |
}
|
262 |
|
263 |
if ( is_object( $cache_val ) ) {
|
264 |
+
$cache_val = clone $cache_val;
|
265 |
}
|
266 |
|
267 |
// If not found but has `Store Transients` cfg on, still need to follow WP's get_transient() logic
|
268 |
if ( ! $found && $this->_object_cache->store_transients( $group ) ) {
|
269 |
+
$cache_val = $this->_transient_get( $key, $group );
|
270 |
if ( $cache_val ) {
|
271 |
+
$found = true; // $found not used for now (v1.8.3)
|
272 |
}
|
273 |
}
|
274 |
|
275 |
if ( $found_in_oc ) {
|
276 |
+
$this->_cache[ $final_key ] = $cache_val;
|
277 |
}
|
278 |
|
279 |
+
$this->cache_total ++;
|
280 |
|
281 |
+
return $cache_val;
|
282 |
}
|
283 |
|
284 |
/**
|
287 |
* @since 1.8
|
288 |
* @access public
|
289 |
*/
|
290 |
+
public function set( $key, $data, $group = 'default', $expire = 0 ) {
|
291 |
+
$final_key = $this->_key( $key, $group );
|
|
|
292 |
|
293 |
if ( is_object( $data ) ) {
|
294 |
+
$data = clone $data;
|
295 |
}
|
296 |
+
// error_log("oc: set \t\t\t[key] " . $final_key );
|
297 |
+
$this->_cache[ $final_key ] = $data;
|
298 |
|
299 |
if( array_key_exists( $final_key, $this->_cache_404 ) ) {
|
300 |
+
// error_log("oc: unset404\t\t\t[key] " . $final_key );
|
301 |
+
unset( $this->_cache_404[ $final_key ] );
|
302 |
}
|
303 |
|
304 |
if ( ! $this->_object_cache->is_non_persistent( $group ) ) {
|
305 |
+
$this->_object_cache->set( $final_key, serialize( array( 'data' => $data ) ), $expire );
|
306 |
+
$this->count_set ++;
|
307 |
}
|
308 |
|
309 |
if ( $this->_object_cache->store_transients( $group ) ) {
|
310 |
+
$this->_transient_set( $key, $data, $group, $expire );
|
311 |
}
|
312 |
|
313 |
+
return true;
|
314 |
}
|
315 |
|
316 |
/**
|
319 |
* @since 1.8
|
320 |
* @access public
|
321 |
*/
|
322 |
+
public function add( $key, $data, $group = 'default', $expire = 0 ) {
|
|
|
323 |
if ( wp_suspend_cache_addition() ) {
|
324 |
+
return false;
|
325 |
}
|
326 |
|
327 |
+
$final_key = $this->_key( $key, $group );
|
328 |
|
329 |
if ( array_key_exists( $final_key, $this->_cache ) ) {
|
330 |
+
return false;
|
331 |
}
|
332 |
|
333 |
+
return $this->set( $key, $data, $group, $expire );
|
334 |
}
|
335 |
|
336 |
/**
|
339 |
* @since 1.8
|
340 |
* @access public
|
341 |
*/
|
342 |
+
public function replace( $key, $data, $group = 'default', $expire = 0 ) {
|
343 |
+
$final_key = $this->_key( $key, $group );
|
|
|
344 |
|
345 |
if ( ! array_key_exists( $final_key, $this->_cache ) ) {
|
346 |
+
return false;
|
347 |
}
|
348 |
|
349 |
+
return $this->set( $key, $data, $group, $expire );
|
350 |
}
|
351 |
|
352 |
/**
|
355 |
* @since 1.8
|
356 |
* @access public
|
357 |
*/
|
358 |
+
public function incr_desr( $key, $offset = 1, $group = 'default', $incr = true ) {
|
359 |
+
$cache_val = $this->get( $key, $group );
|
|
|
360 |
|
361 |
if ( $cache_val === false ) {
|
362 |
+
return false;
|
363 |
}
|
364 |
|
365 |
if ( ! is_numeric( $cache_val ) ) {
|
366 |
+
$cache_val = 0;
|
367 |
}
|
368 |
|
369 |
+
$offset = (int) $offset;
|
370 |
|
371 |
if ( $incr ) {
|
372 |
+
$cache_val += $offset;
|
373 |
}
|
374 |
else {
|
375 |
+
$cache_val -= $offset;
|
376 |
}
|
377 |
|
378 |
if ( $cache_val < 0 ) {
|
379 |
+
$cache_val = 0;
|
380 |
}
|
381 |
|
382 |
+
$this->set( $key, $cache_val, $group );
|
383 |
|
384 |
+
return $cache_val;
|
385 |
}
|
386 |
|
387 |
/**
|
390 |
* @since 1.8
|
391 |
* @access public
|
392 |
*/
|
393 |
+
public function delete( $key, $group = 'default' ) {
|
|
|
394 |
|
395 |
+
$final_key = $this->_key( $key, $group );
|
396 |
|
397 |
if ( $this->_object_cache->store_transients( $group ) ) {
|
398 |
+
$this->_transient_del( $key, $group );
|
399 |
}
|
400 |
|
401 |
if ( array_key_exists( $final_key, $this->_cache ) ) {
|
402 |
+
unset( $this->_cache[ $final_key ] );
|
403 |
}
|
404 |
+
// error_log("oc: delete \t\t\t[key] " . $final_key );
|
405 |
|
406 |
if ( $this->_object_cache->is_non_persistent( $group ) ) {
|
407 |
+
return false;
|
408 |
}
|
409 |
|
410 |
+
return $this->_object_cache->delete( $final_key );
|
411 |
}
|
412 |
|
413 |
/**
|
416 |
* @since 1.8
|
417 |
* @access public
|
418 |
*/
|
419 |
+
public function flush() {
|
420 |
+
$this->_cache = array();
|
421 |
+
$this->_cache_404 = array();
|
422 |
+
// error_log("oc: flush " );
|
|
|
423 |
|
424 |
+
$this->_object_cache->flush();
|
425 |
|
426 |
+
return true;
|
427 |
}
|
428 |
|
429 |
/**
|
432 |
* @since 1.8
|
433 |
* @access public
|
434 |
*/
|
435 |
+
public function add_global_groups( $groups ) {
|
436 |
+
$this->_object_cache->add_global_groups( $groups );
|
|
|
437 |
}
|
438 |
|
439 |
/**
|
442 |
* @since 1.8
|
443 |
* @access public
|
444 |
*/
|
445 |
+
public function add_non_persistent_groups( $groups ) {
|
446 |
+
$this->_object_cache->add_non_persistent_groups( $groups );
|
|
|
447 |
}
|
448 |
|
449 |
/**
|
452 |
* @since 1.8
|
453 |
* @access private
|
454 |
*/
|
455 |
+
private function _key( $key, $group = 'default' ) {
|
456 |
+
$prefix = $this->_object_cache->is_global( $group ) ? '' : $this->blog_prefix;
|
|
|
457 |
|
458 |
+
return LSOC_PREFIX . $prefix . $group . '.' . $key;
|
459 |
}
|
460 |
|
461 |
/**
|
468 |
* @param int $blog_id Blog ID.
|
469 |
*/
|
470 |
public function switch_to_blog( $blog_id ) {
|
471 |
+
$blog_id = (int) $blog_id;
|
472 |
+
$this->blog_prefix = $this->multisite ? $blog_id . ':' : '';
|
473 |
}
|
474 |
|
475 |
/**
|
479 |
* @access private
|
480 |
* @see `wp-includes/option.php` function `get_transient`/`set_site_transient`
|
481 |
*/
|
482 |
+
private function _transient_get( $transient, $group ) {
|
|
|
483 |
if ( $group == 'transient' ) {
|
484 |
/**** Ori WP func start ****/
|
485 |
$transient_option = '_transient_' . $transient;
|
520 |
/**** Ori WP func end ****/
|
521 |
}
|
522 |
else {
|
523 |
+
$value = false;
|
524 |
}
|
525 |
|
526 |
+
return $value;
|
527 |
}
|
528 |
|
529 |
/**
|
533 |
* @access private
|
534 |
* @see `wp-includes/option.php` function `set_transient`/`set_site_transient`
|
535 |
*/
|
536 |
+
private function _transient_set( $transient, $value, $group, $expiration ) {
|
|
|
537 |
if ( $group == 'transient' ) {
|
538 |
/**** Ori WP func start ****/
|
539 |
$transient_timeout = '_transient_timeout_' . $transient;
|
581 |
/**** Ori WP func end ****/
|
582 |
}
|
583 |
else {
|
584 |
+
$result = null;
|
585 |
}
|
586 |
|
587 |
+
return $result;
|
588 |
}
|
589 |
|
590 |
/**
|
594 |
* @access private
|
595 |
* @see `wp-includes/option.php` function `delete_transient`/`delete_site_transient`
|
596 |
*/
|
597 |
+
private function _transient_del( $transient, $group ) {
|
|
|
598 |
if ( $group == 'transient' ) {
|
599 |
/**** Ori WP func start ****/
|
600 |
$option_timeout = '_transient_timeout_' . $transient;
|
621 |
* @since 1.8
|
622 |
* @access public
|
623 |
*/
|
624 |
+
public static function get_instance() {
|
|
|
625 |
if ( ! isset( self::$_instance ) ) {
|
626 |
+
self::$_instance = new self();
|
627 |
}
|
628 |
|
629 |
+
return self::$_instance;
|
630 |
}
|
631 |
}
|
src/optimize.cls.php
CHANGED
@@ -1160,8 +1160,17 @@ class Optimize extends Base {
|
|
1160 |
if ( in_array( $match[ 0 ], $html_list ) ) {
|
1161 |
continue;
|
1162 |
}
|
1163 |
-
|
1164 |
if ( $excludes && $exclude = Utility::str_hit_array( $attrs[ 'src' ], $excludes ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1165 |
Debug2::debug2( '[Optm] _parse_js bypassed exclude ' . $exclude );
|
1166 |
continue;
|
1167 |
}
|
1160 |
if ( in_array( $match[ 0 ], $html_list ) ) {
|
1161 |
continue;
|
1162 |
}
|
1163 |
+
|
1164 |
if ( $excludes && $exclude = Utility::str_hit_array( $attrs[ 'src' ], $excludes ) ) {
|
1165 |
+
// Maybe defer
|
1166 |
+
if ( $this->cfg_js_defer ) {
|
1167 |
+
$deferred = $this->_js_defer( array( $match[ 0 ] ) );
|
1168 |
+
$deferred = $deferred[ 0 ];
|
1169 |
+
if ( $deferred != $match[ 0 ] ) {
|
1170 |
+
$this->content = str_replace( $match[ 0 ], $deferred, $this->content );
|
1171 |
+
}
|
1172 |
+
}
|
1173 |
+
|
1174 |
Debug2::debug2( '[Optm] _parse_js bypassed exclude ' . $exclude );
|
1175 |
continue;
|
1176 |
}
|
src/optimizer.cls.php
CHANGED
@@ -103,7 +103,16 @@ class Optimizer extends Instance {
|
|
103 |
// Parse real file path
|
104 |
$real_files = array();
|
105 |
foreach ( $src_list as $src_info ) {
|
106 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
|
108 |
if ( ! $real_file ) {
|
109 |
continue;
|
@@ -111,12 +120,12 @@ class Optimizer extends Instance {
|
|
111 |
|
112 |
if ( ! empty( $src_info[ 'media' ] ) ) {
|
113 |
$real_files[] = array(
|
114 |
-
'src' => $real_file
|
115 |
'media' => $src_info[ 'media' ],
|
116 |
);
|
117 |
}
|
118 |
else {
|
119 |
-
$real_files[] = $real_file
|
120 |
}
|
121 |
}
|
122 |
|
@@ -182,7 +191,16 @@ class Optimizer extends Instance {
|
|
182 |
$real_path = $path_info;
|
183 |
}
|
184 |
Debug2::debug2( '[Optmer] [real_path] ' . $real_path );
|
185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
|
187 |
// Font optimize
|
188 |
if ( $this->_conf_css_font_display ) {
|
@@ -195,7 +213,7 @@ class Optimizer extends Instance {
|
|
195 |
$data = self::minify_css( $data );
|
196 |
}
|
197 |
|
198 |
-
$data = Lib\CSS_MIN\UriRewriter::rewrite( $data, dirname
|
199 |
|
200 |
if ( $media ) {
|
201 |
$data = '@media ' . $media . '{' . $data . "\n}";
|
@@ -216,7 +234,13 @@ class Optimizer extends Instance {
|
|
216 |
private function _serve_js( $files, $concat_only ) {
|
217 |
$con = array();
|
218 |
foreach ( $files as $real_path ) {
|
219 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
|
221 |
if ( ! $concat_only && ! $this->_is_min( $real_path ) ) {
|
222 |
$data = self::minify_js( $data );
|
103 |
// Parse real file path
|
104 |
$real_files = array();
|
105 |
foreach ( $src_list as $src_info ) {
|
106 |
+
$src = ! empty( $src_info[ 'src' ] ) ? $src_info[ 'src' ] : $src_info;
|
107 |
+
$postfix = pathinfo( parse_url( $src, PHP_URL_PATH ), PATHINFO_EXTENSION );
|
108 |
+
if ( $postfix != $file_type ) {
|
109 |
+
Debug2::debug2( '[Optmer] Not static file, will read as remote [src] ' . $src );
|
110 |
+
$real_file = $src;
|
111 |
+
}
|
112 |
+
else {
|
113 |
+
$real_file = Utility::is_internal_file( $src );
|
114 |
+
$real_file = ! empty( $real_file[ 0 ] ) ? $real_file[ 0 ] : false;
|
115 |
+
}
|
116 |
|
117 |
if ( ! $real_file ) {
|
118 |
continue;
|
120 |
|
121 |
if ( ! empty( $src_info[ 'media' ] ) ) {
|
122 |
$real_files[] = array(
|
123 |
+
'src' => $real_file,
|
124 |
'media' => $src_info[ 'media' ],
|
125 |
);
|
126 |
}
|
127 |
else {
|
128 |
+
$real_files[] = $real_file;
|
129 |
}
|
130 |
}
|
131 |
|
191 |
$real_path = $path_info;
|
192 |
}
|
193 |
Debug2::debug2( '[Optmer] [real_path] ' . $real_path );
|
194 |
+
|
195 |
+
// Check if its remote or local path
|
196 |
+
if ( strpos( $real_path, 'http' ) === 0 ) {
|
197 |
+
$data = wp_remote_retrieve_body( wp_remote_get( $real_path ) );
|
198 |
+
$dirname = dirname( parse_url( $real_path, PHP_URL_PATH ) );
|
199 |
+
}
|
200 |
+
else {
|
201 |
+
$data = File::read( $real_path );
|
202 |
+
$dirname = dirname( $real_path );
|
203 |
+
}
|
204 |
|
205 |
// Font optimize
|
206 |
if ( $this->_conf_css_font_display ) {
|
213 |
$data = self::minify_css( $data );
|
214 |
}
|
215 |
|
216 |
+
$data = Lib\CSS_MIN\UriRewriter::rewrite( $data, $dirname );
|
217 |
|
218 |
if ( $media ) {
|
219 |
$data = '@media ' . $media . '{' . $data . "\n}";
|
234 |
private function _serve_js( $files, $concat_only ) {
|
235 |
$con = array();
|
236 |
foreach ( $files as $real_path ) {
|
237 |
+
// Check if its remote or local path
|
238 |
+
if ( strpos( $real_path, 'http' ) === 0 ) {
|
239 |
+
$data = wp_remote_retrieve_body( wp_remote_get( $real_path ) );
|
240 |
+
}
|
241 |
+
else {
|
242 |
+
$data = File::read( $real_path );
|
243 |
+
}
|
244 |
|
245 |
if ( ! $concat_only && ! $this->_is_min( $real_path ) ) {
|
246 |
$data = self::minify_js( $data );
|
src/tag.cls.php
CHANGED
@@ -43,10 +43,9 @@ class Tag extends Instance {
|
|
43 |
*
|
44 |
* @since 2.2.3
|
45 |
*/
|
46 |
-
protected function __construct()
|
47 |
-
{
|
48 |
// register recent posts widget tag before theme renders it to make it work
|
49 |
-
add_filter( 'widget_posts_args', array( $this, 'add_widget_recent_posts' ) )
|
50 |
|
51 |
}
|
52 |
|
@@ -59,33 +58,32 @@ class Tag extends Instance {
|
|
59 |
* @since 1.0.0
|
60 |
* @access public
|
61 |
*/
|
62 |
-
public static function check_login_cacheable()
|
63 |
-
{
|
64 |
if ( ! Conf::val( Base::O_CACHE_PAGE_LOGIN ) ) {
|
65 |
-
return
|
66 |
}
|
67 |
if ( Control::isset_notcacheable() ) {
|
68 |
-
return
|
69 |
}
|
70 |
|
71 |
if ( ! empty( $_GET ) ) {
|
72 |
-
Control::set_nocache( 'has GET request' )
|
73 |
-
return
|
74 |
}
|
75 |
|
76 |
-
Control::set_cacheable()
|
77 |
|
78 |
-
self::add( self::TYPE_LOGIN )
|
79 |
|
80 |
// we need to send lsc-cookie manually to make it be sent to all other users when is cacheable
|
81 |
-
$list = headers_list()
|
82 |
if ( empty( $list ) ) {
|
83 |
-
return
|
84 |
}
|
85 |
foreach ( $list as $hdr ) {
|
86 |
if ( strncasecmp( $hdr, 'set-cookie:', 11 ) == 0 ) {
|
87 |
-
$cookie = substr( $hdr, 12 )
|
88 |
-
@header( 'lsc-cookie: ' . $cookie, false )
|
89 |
}
|
90 |
}
|
91 |
}
|
@@ -98,10 +96,9 @@ class Tag extends Instance {
|
|
98 |
* @access public
|
99 |
* @param array $params [wordpress params for widget_posts_args]
|
100 |
*/
|
101 |
-
public function add_widget_recent_posts( $params )
|
102 |
-
|
103 |
-
|
104 |
-
return $params ;
|
105 |
}
|
106 |
|
107 |
/**
|
@@ -111,13 +108,12 @@ class Tag extends Instance {
|
|
111 |
* @access public
|
112 |
* @param mixed $tags A string or array of cache tags to add to the current list.
|
113 |
*/
|
114 |
-
public static function add( $tags )
|
115 |
-
{
|
116 |
if ( ! is_array( $tags ) ) {
|
117 |
-
$tags = array( $tags )
|
118 |
}
|
119 |
|
120 |
-
self::$_tags = array_merge( self::$_tags, $tags )
|
121 |
}
|
122 |
|
123 |
/**
|
@@ -126,8 +122,7 @@ class Tag extends Instance {
|
|
126 |
* @since 3.0
|
127 |
* @access public
|
128 |
*/
|
129 |
-
public static function add_post( $pid )
|
130 |
-
{
|
131 |
self::add( self::TYPE_POST . $pid );
|
132 |
}
|
133 |
|
@@ -137,8 +132,7 @@ class Tag extends Instance {
|
|
137 |
* @since 3.0
|
138 |
* @access public
|
139 |
*/
|
140 |
-
public static function add_widget( $id )
|
141 |
-
{
|
142 |
self::add( self::TYPE_WIDGET . $id );
|
143 |
}
|
144 |
|
@@ -148,8 +142,7 @@ class Tag extends Instance {
|
|
148 |
* @since 3.0
|
149 |
* @access public
|
150 |
*/
|
151 |
-
public static function add_private_esi( $tag )
|
152 |
-
{
|
153 |
self::add_private( self::TYPE_ESI . $tag );
|
154 |
}
|
155 |
|
@@ -160,13 +153,12 @@ class Tag extends Instance {
|
|
160 |
* @access public
|
161 |
* @param mixed $tags A string or array of cache tags to add to the current list.
|
162 |
*/
|
163 |
-
public static function add_private( $tags )
|
164 |
-
{
|
165 |
if ( ! is_array( $tags ) ) {
|
166 |
-
$tags = array( $tags )
|
167 |
}
|
168 |
|
169 |
-
self::$_tags_priv = array_merge( self::$_tags_priv, $tags )
|
170 |
}
|
171 |
|
172 |
/**
|
@@ -175,9 +167,8 @@ class Tag extends Instance {
|
|
175 |
* @since 1.1.3
|
176 |
* @access public
|
177 |
*/
|
178 |
-
public static function output_tags()
|
179 |
-
|
180 |
-
return self::$_tags ;
|
181 |
}
|
182 |
|
183 |
/**
|
@@ -189,20 +180,19 @@ class Tag extends Instance {
|
|
189 |
* @param boolean $ori Return the original url or not
|
190 |
* @return bool|string False on input error, hash otherwise.
|
191 |
*/
|
192 |
-
public static function get_uri_tag( $uri, $ori = false )
|
193 |
-
|
194 |
-
$no_qs = strtok( $uri, '?' ) ;
|
195 |
if ( empty( $no_qs ) ) {
|
196 |
-
return false
|
197 |
}
|
198 |
-
$slashed = trailingslashit( $no_qs )
|
199 |
|
200 |
// If only needs uri tag
|
201 |
if ( $ori ) {
|
202 |
-
return $slashed
|
203 |
}
|
204 |
-
// return self::TYPE_URL . ( $slashed )
|
205 |
-
return self::TYPE_URL . md5( $slashed )
|
206 |
}
|
207 |
|
208 |
/**
|
@@ -212,9 +202,8 @@ class Tag extends Instance {
|
|
212 |
* @access public
|
213 |
* @param boolean $ori Return the original url or not
|
214 |
*/
|
215 |
-
public static function build_uri_tag( $ori = false )
|
216 |
-
|
217 |
-
return self::get_uri_tag( urldecode( $_SERVER['REQUEST_URI'] ), $ori ) ;
|
218 |
}
|
219 |
|
220 |
/**
|
@@ -227,88 +216,87 @@ class Tag extends Instance {
|
|
227 |
* @access private
|
228 |
* @return array The list of cache tags to set.
|
229 |
*/
|
230 |
-
private static function _build_type_tags()
|
231 |
-
|
232 |
-
$tags = array() ;
|
233 |
|
234 |
-
$tags[] = Utility::page_type()
|
235 |
|
236 |
-
$tags[] = self::build_uri_tag()
|
237 |
|
238 |
if ( is_front_page() ) {
|
239 |
-
$tags[] = self::TYPE_FRONTPAGE
|
240 |
}
|
241 |
elseif ( is_home() ) {
|
242 |
-
$tags[] = self::TYPE_HOME
|
243 |
}
|
244 |
|
245 |
-
$queried_obj_id = get_queried_object_id()
|
246 |
if ( is_archive() ) {
|
247 |
//An Archive is a Category, Tag, Author, Date, Custom Post Type or Custom Taxonomy based pages.
|
248 |
if ( is_category() || is_tag() || is_tax() ) {
|
249 |
-
$tags[] = self::TYPE_ARCHIVE_TERM . $queried_obj_id
|
250 |
}
|
251 |
elseif ( is_post_type_archive() ) {
|
252 |
-
global $wp_query
|
253 |
-
$post_type = $wp_query->get( 'post_type' )
|
254 |
-
$tags[] = self::TYPE_ARCHIVE_POSTTYPE . $post_type
|
255 |
}
|
256 |
elseif ( is_author() ) {
|
257 |
-
$tags[] = self::TYPE_AUTHOR . $queried_obj_id
|
258 |
}
|
259 |
elseif ( is_date() ) {
|
260 |
-
global $post
|
261 |
-
$date = $post->post_date
|
262 |
-
$date = strtotime( $date )
|
263 |
if ( is_day() ) {
|
264 |
-
$tags[] = self::TYPE_ARCHIVE_DATE . date( 'Ymd', $date )
|
265 |
}
|
266 |
elseif ( is_month() ) {
|
267 |
-
$tags[] = self::TYPE_ARCHIVE_DATE . date( 'Ym', $date )
|
268 |
}
|
269 |
elseif ( is_year() ) {
|
270 |
-
$tags[] = self::TYPE_ARCHIVE_DATE . date( 'Y', $date )
|
271 |
}
|
272 |
}
|
273 |
}
|
274 |
elseif ( is_singular() ) {
|
275 |
//$this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
|
276 |
-
$tags[] = self::TYPE_POST . $queried_obj_id
|
277 |
|
278 |
if ( is_page() ) {
|
279 |
-
$tags[] = self::TYPE_PAGES
|
280 |
}
|
281 |
}
|
282 |
elseif ( is_feed() ) {
|
283 |
-
$tags[] = self::TYPE_FEED
|
284 |
}
|
285 |
|
286 |
// Check REST API
|
287 |
if ( REST::get_instance()->is_rest() ) {
|
288 |
-
$tags[] = self::TYPE_REST
|
289 |
|
290 |
-
$path = ! empty( $_SERVER[ 'SCRIPT_URL' ] ) ? $_SERVER[ 'SCRIPT_URL' ] : false
|
291 |
if ( $path ) {
|
292 |
// posts collections tag
|
293 |
if ( substr( $path, -6 ) == '/posts' ) {
|
294 |
-
$tags[] = self::TYPE_LIST
|
295 |
}
|
296 |
|
297 |
// single post tag
|
298 |
global $post;
|
299 |
if ( ! empty( $post->ID ) && substr( $path, - strlen( $post->ID ) - 1 ) === '/' . $post->ID ) {
|
300 |
-
$tags[] = self::TYPE_POST . $post->ID
|
301 |
}
|
302 |
|
303 |
// pages collections & single page tag
|
304 |
if ( stripos( $path, '/pages' ) !== false ) {
|
305 |
-
$tags[] = self::TYPE_PAGES
|
306 |
}
|
307 |
}
|
308 |
|
309 |
}
|
310 |
|
311 |
-
return $tags
|
312 |
}
|
313 |
|
314 |
/**
|
@@ -317,19 +305,18 @@ class Tag extends Instance {
|
|
317 |
* @access private
|
318 |
* @since 1.1.3
|
319 |
*/
|
320 |
-
private static function _finalize()
|
321 |
-
{
|
322 |
// run 3rdparty hooks to tag
|
323 |
do_action( 'litespeed_tag_finalize' );
|
324 |
// generate wp tags
|
325 |
if ( ! defined( 'LSCACHE_IS_ESI' ) ) {
|
326 |
-
$type_tags = self::_build_type_tags()
|
327 |
-
self::$_tags = array_merge( self::$_tags, $type_tags )
|
328 |
}
|
329 |
// append blog main tag
|
330 |
-
self::$_tags[] = ''
|
331 |
// removed duplicates
|
332 |
-
self::$_tags = array_unique( self::$_tags )
|
333 |
}
|
334 |
|
335 |
/**
|
@@ -340,32 +327,31 @@ class Tag extends Instance {
|
|
340 |
* @access public
|
341 |
* @return string empty string if empty, otherwise the cache tags header.
|
342 |
*/
|
343 |
-
public static function output()
|
344 |
-
|
345 |
-
self::_finalize() ;
|
346 |
|
347 |
-
$prefix_tags = array()
|
348 |
/**
|
349 |
* Only append blog_id when is multisite
|
350 |
* @since 2.9.3
|
351 |
*/
|
352 |
-
$prefix = LSWCP_TAG_PREFIX . ( is_multisite() ? get_current_blog_id() : '' ) . '_'
|
353 |
|
354 |
// If is_private and has private tags, append them first, then specify prefix to `public` for public tags
|
355 |
if ( Control::is_private() ) {
|
356 |
foreach ( self::$_tags_priv as $priv_tag ) {
|
357 |
-
$prefix_tags[] = $prefix . $priv_tag
|
358 |
}
|
359 |
-
$prefix = 'public:' . $prefix
|
360 |
}
|
361 |
|
362 |
foreach ( self::$_tags as $tag ) {
|
363 |
-
$prefix_tags[] = $prefix . $tag
|
364 |
}
|
365 |
|
366 |
-
$hdr = self::X_HEADER . ': ' . implode( ',', $prefix_tags )
|
367 |
|
368 |
-
return $hdr
|
369 |
}
|
370 |
|
371 |
}
|
43 |
*
|
44 |
* @since 2.2.3
|
45 |
*/
|
46 |
+
protected function __construct() {
|
|
|
47 |
// register recent posts widget tag before theme renders it to make it work
|
48 |
+
add_filter( 'widget_posts_args', array( $this, 'add_widget_recent_posts' ) );
|
49 |
|
50 |
}
|
51 |
|
58 |
* @since 1.0.0
|
59 |
* @access public
|
60 |
*/
|
61 |
+
public static function check_login_cacheable() {
|
|
|
62 |
if ( ! Conf::val( Base::O_CACHE_PAGE_LOGIN ) ) {
|
63 |
+
return;
|
64 |
}
|
65 |
if ( Control::isset_notcacheable() ) {
|
66 |
+
return;
|
67 |
}
|
68 |
|
69 |
if ( ! empty( $_GET ) ) {
|
70 |
+
Control::set_nocache( 'has GET request' );
|
71 |
+
return;
|
72 |
}
|
73 |
|
74 |
+
Control::set_cacheable();
|
75 |
|
76 |
+
self::add( self::TYPE_LOGIN );
|
77 |
|
78 |
// we need to send lsc-cookie manually to make it be sent to all other users when is cacheable
|
79 |
+
$list = headers_list();
|
80 |
if ( empty( $list ) ) {
|
81 |
+
return;
|
82 |
}
|
83 |
foreach ( $list as $hdr ) {
|
84 |
if ( strncasecmp( $hdr, 'set-cookie:', 11 ) == 0 ) {
|
85 |
+
$cookie = substr( $hdr, 12 );
|
86 |
+
@header( 'lsc-cookie: ' . $cookie, false );
|
87 |
}
|
88 |
}
|
89 |
}
|
96 |
* @access public
|
97 |
* @param array $params [wordpress params for widget_posts_args]
|
98 |
*/
|
99 |
+
public function add_widget_recent_posts( $params ) {
|
100 |
+
self::add( self::TYPE_PAGES_WITH_RECENT_POSTS );
|
101 |
+
return $params;
|
|
|
102 |
}
|
103 |
|
104 |
/**
|
108 |
* @access public
|
109 |
* @param mixed $tags A string or array of cache tags to add to the current list.
|
110 |
*/
|
111 |
+
public static function add( $tags ) {
|
|
|
112 |
if ( ! is_array( $tags ) ) {
|
113 |
+
$tags = array( $tags );
|
114 |
}
|
115 |
|
116 |
+
self::$_tags = array_merge( self::$_tags, $tags );
|
117 |
}
|
118 |
|
119 |
/**
|
122 |
* @since 3.0
|
123 |
* @access public
|
124 |
*/
|
125 |
+
public static function add_post( $pid ) {
|
|
|
126 |
self::add( self::TYPE_POST . $pid );
|
127 |
}
|
128 |
|
132 |
* @since 3.0
|
133 |
* @access public
|
134 |
*/
|
135 |
+
public static function add_widget( $id ) {
|
|
|
136 |
self::add( self::TYPE_WIDGET . $id );
|
137 |
}
|
138 |
|
142 |
* @since 3.0
|
143 |
* @access public
|
144 |
*/
|
145 |
+
public static function add_private_esi( $tag ) {
|
|
|
146 |
self::add_private( self::TYPE_ESI . $tag );
|
147 |
}
|
148 |
|
153 |
* @access public
|
154 |
* @param mixed $tags A string or array of cache tags to add to the current list.
|
155 |
*/
|
156 |
+
public static function add_private( $tags ) {
|
|
|
157 |
if ( ! is_array( $tags ) ) {
|
158 |
+
$tags = array( $tags );
|
159 |
}
|
160 |
|
161 |
+
self::$_tags_priv = array_merge( self::$_tags_priv, $tags );
|
162 |
}
|
163 |
|
164 |
/**
|
167 |
* @since 1.1.3
|
168 |
* @access public
|
169 |
*/
|
170 |
+
public static function output_tags() {
|
171 |
+
return self::$_tags;
|
|
|
172 |
}
|
173 |
|
174 |
/**
|
180 |
* @param boolean $ori Return the original url or not
|
181 |
* @return bool|string False on input error, hash otherwise.
|
182 |
*/
|
183 |
+
public static function get_uri_tag( $uri, $ori = false ) {
|
184 |
+
$no_qs = strtok( $uri, '?' );
|
|
|
185 |
if ( empty( $no_qs ) ) {
|
186 |
+
return false;
|
187 |
}
|
188 |
+
$slashed = trailingslashit( $no_qs );
|
189 |
|
190 |
// If only needs uri tag
|
191 |
if ( $ori ) {
|
192 |
+
return $slashed;
|
193 |
}
|
194 |
+
// return self::TYPE_URL . ( $slashed );
|
195 |
+
return self::TYPE_URL . md5( $slashed );
|
196 |
}
|
197 |
|
198 |
/**
|
202 |
* @access public
|
203 |
* @param boolean $ori Return the original url or not
|
204 |
*/
|
205 |
+
public static function build_uri_tag( $ori = false ) {
|
206 |
+
return self::get_uri_tag( urldecode( $_SERVER['REQUEST_URI'] ), $ori );
|
|
|
207 |
}
|
208 |
|
209 |
/**
|
216 |
* @access private
|
217 |
* @return array The list of cache tags to set.
|
218 |
*/
|
219 |
+
private static function _build_type_tags() {
|
220 |
+
$tags = array();
|
|
|
221 |
|
222 |
+
$tags[] = Utility::page_type();
|
223 |
|
224 |
+
$tags[] = self::build_uri_tag();
|
225 |
|
226 |
if ( is_front_page() ) {
|
227 |
+
$tags[] = self::TYPE_FRONTPAGE;
|
228 |
}
|
229 |
elseif ( is_home() ) {
|
230 |
+
$tags[] = self::TYPE_HOME;
|
231 |
}
|
232 |
|
233 |
+
$queried_obj_id = get_queried_object_id();
|
234 |
if ( is_archive() ) {
|
235 |
//An Archive is a Category, Tag, Author, Date, Custom Post Type or Custom Taxonomy based pages.
|
236 |
if ( is_category() || is_tag() || is_tax() ) {
|
237 |
+
$tags[] = self::TYPE_ARCHIVE_TERM . $queried_obj_id;
|
238 |
}
|
239 |
elseif ( is_post_type_archive() ) {
|
240 |
+
global $wp_query;
|
241 |
+
$post_type = $wp_query->get( 'post_type' );
|
242 |
+
$tags[] = self::TYPE_ARCHIVE_POSTTYPE . $post_type;
|
243 |
}
|
244 |
elseif ( is_author() ) {
|
245 |
+
$tags[] = self::TYPE_AUTHOR . $queried_obj_id;
|
246 |
}
|
247 |
elseif ( is_date() ) {
|
248 |
+
global $post;
|
249 |
+
$date = $post->post_date;
|
250 |
+
$date = strtotime( $date );
|
251 |
if ( is_day() ) {
|
252 |
+
$tags[] = self::TYPE_ARCHIVE_DATE . date( 'Ymd', $date );
|
253 |
}
|
254 |
elseif ( is_month() ) {
|
255 |
+
$tags[] = self::TYPE_ARCHIVE_DATE . date( 'Ym', $date );
|
256 |
}
|
257 |
elseif ( is_year() ) {
|
258 |
+
$tags[] = self::TYPE_ARCHIVE_DATE . date( 'Y', $date );
|
259 |
}
|
260 |
}
|
261 |
}
|
262 |
elseif ( is_singular() ) {
|
263 |
//$this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
|
264 |
+
$tags[] = self::TYPE_POST . $queried_obj_id;
|
265 |
|
266 |
if ( is_page() ) {
|
267 |
+
$tags[] = self::TYPE_PAGES;
|
268 |
}
|
269 |
}
|
270 |
elseif ( is_feed() ) {
|
271 |
+
$tags[] = self::TYPE_FEED;
|
272 |
}
|
273 |
|
274 |
// Check REST API
|
275 |
if ( REST::get_instance()->is_rest() ) {
|
276 |
+
$tags[] = self::TYPE_REST;
|
277 |
|
278 |
+
$path = ! empty( $_SERVER[ 'SCRIPT_URL' ] ) ? $_SERVER[ 'SCRIPT_URL' ] : false;
|
279 |
if ( $path ) {
|
280 |
// posts collections tag
|
281 |
if ( substr( $path, -6 ) == '/posts' ) {
|
282 |
+
$tags[] = self::TYPE_LIST;// Not used for purge yet
|
283 |
}
|
284 |
|
285 |
// single post tag
|
286 |
global $post;
|
287 |
if ( ! empty( $post->ID ) && substr( $path, - strlen( $post->ID ) - 1 ) === '/' . $post->ID ) {
|
288 |
+
$tags[] = self::TYPE_POST . $post->ID;
|
289 |
}
|
290 |
|
291 |
// pages collections & single page tag
|
292 |
if ( stripos( $path, '/pages' ) !== false ) {
|
293 |
+
$tags[] = self::TYPE_PAGES;
|
294 |
}
|
295 |
}
|
296 |
|
297 |
}
|
298 |
|
299 |
+
return $tags;
|
300 |
}
|
301 |
|
302 |
/**
|
305 |
* @access private
|
306 |
* @since 1.1.3
|
307 |
*/
|
308 |
+
private static function _finalize() {
|
|
|
309 |
// run 3rdparty hooks to tag
|
310 |
do_action( 'litespeed_tag_finalize' );
|
311 |
// generate wp tags
|
312 |
if ( ! defined( 'LSCACHE_IS_ESI' ) ) {
|
313 |
+
$type_tags = self::_build_type_tags();
|
314 |
+
self::$_tags = array_merge( self::$_tags, $type_tags );
|
315 |
}
|
316 |
// append blog main tag
|
317 |
+
self::$_tags[] = '';
|
318 |
// removed duplicates
|
319 |
+
self::$_tags = array_unique( self::$_tags );
|
320 |
}
|
321 |
|
322 |
/**
|
327 |
* @access public
|
328 |
* @return string empty string if empty, otherwise the cache tags header.
|
329 |
*/
|
330 |
+
public static function output() {
|
331 |
+
self::_finalize();
|
|
|
332 |
|
333 |
+
$prefix_tags = array();
|
334 |
/**
|
335 |
* Only append blog_id when is multisite
|
336 |
* @since 2.9.3
|
337 |
*/
|
338 |
+
$prefix = LSWCP_TAG_PREFIX . ( is_multisite() ? get_current_blog_id() : '' ) . '_';
|
339 |
|
340 |
// If is_private and has private tags, append them first, then specify prefix to `public` for public tags
|
341 |
if ( Control::is_private() ) {
|
342 |
foreach ( self::$_tags_priv as $priv_tag ) {
|
343 |
+
$prefix_tags[] = $prefix . $priv_tag;
|
344 |
}
|
345 |
+
$prefix = 'public:' . $prefix;
|
346 |
}
|
347 |
|
348 |
foreach ( self::$_tags as $tag ) {
|
349 |
+
$prefix_tags[] = $prefix . $tag;
|
350 |
}
|
351 |
|
352 |
+
$hdr = self::X_HEADER . ': ' . implode( ',', $prefix_tags );
|
353 |
|
354 |
+
return $hdr;
|
355 |
}
|
356 |
|
357 |
}
|
src/tool.cls.php
CHANGED
@@ -7,20 +7,19 @@
|
|
7 |
* @subpackage LiteSpeed/inc
|
8 |
* @author LiteSpeed Technologies <info@litespeedtech.com>
|
9 |
*/
|
10 |
-
namespace LiteSpeed
|
11 |
|
12 |
-
defined( 'WPINC' ) || exit
|
13 |
|
14 |
-
class Tool extends Instance
|
15 |
-
|
16 |
-
protected static $_instance ;
|
17 |
|
18 |
-
private $_conf_heartbeat_front
|
19 |
-
private $_conf_heartbeat_front_ttl
|
20 |
-
private $_conf_heartbeat_back
|
21 |
-
private $_conf_heartbeat_back_ttl
|
22 |
-
private $_conf_heartbeat_editor
|
23 |
-
private $_conf_heartbeat_editor_ttl
|
24 |
|
25 |
/**
|
26 |
* Init
|
@@ -28,14 +27,13 @@ class Tool extends Instance
|
|
28 |
* @since 3.0
|
29 |
* @access protected
|
30 |
*/
|
31 |
-
protected function __construct()
|
32 |
-
|
33 |
-
$this->
|
34 |
-
$this->
|
35 |
-
$this->
|
36 |
-
$this->
|
37 |
-
$this->
|
38 |
-
$this->_conf_heartbeat_editor_ttl = Conf::val( Base::O_MISC_HEARTBEAT_EDITOR_TTL ) ;
|
39 |
}
|
40 |
|
41 |
/**
|
@@ -44,21 +42,20 @@ class Tool extends Instance
|
|
44 |
* @since 3.0
|
45 |
* @access public
|
46 |
*/
|
47 |
-
public function check_ip()
|
48 |
-
|
49 |
-
Debug2::debug( '[Tool] ✅ check_ip' ) ;
|
50 |
|
51 |
-
$response = wp_remote_get( 'https://www.doapi.us/ip' )
|
52 |
|
53 |
if ( is_wp_error( $response ) ) {
|
54 |
-
return new \WP_Error( 'remote_get_fail', 'Failed to fetch from https://www.doapi.us/ip', array( 'status' => 404 ) )
|
55 |
}
|
56 |
|
57 |
-
$data = $response[ 'body' ]
|
58 |
|
59 |
-
Debug2::debug( '[Tool] result [ip] ' . $data )
|
60 |
|
61 |
-
return $data
|
62 |
}
|
63 |
|
64 |
/**
|
@@ -69,13 +66,12 @@ class Tool extends Instance
|
|
69 |
* @since 3.0
|
70 |
* @access public
|
71 |
*/
|
72 |
-
public static function heartbeat()
|
73 |
-
|
74 |
-
$instance = self::get_instance() ;
|
75 |
|
76 |
-
add_action( 'wp_enqueue_scripts', array( $instance, 'heartbeat_frontend' ) )
|
77 |
-
add_action( 'admin_enqueue_scripts', array( $instance, 'heartbeat_backend' ) )
|
78 |
-
add_filter( 'heartbeat_settings', array( $instance, 'heartbeat_settings' ) )
|
79 |
}
|
80 |
|
81 |
/**
|
@@ -84,15 +80,14 @@ class Tool extends Instance
|
|
84 |
* @since 3.0
|
85 |
* @access public
|
86 |
*/
|
87 |
-
public function heartbeat_frontend()
|
88 |
-
{
|
89 |
if ( ! $this->_conf_heartbeat_front ) {
|
90 |
-
return
|
91 |
}
|
92 |
|
93 |
if ( ! $this->_conf_heartbeat_front_ttl ) {
|
94 |
-
wp_deregister_script( 'heartbeat' )
|
95 |
-
Debug2::debug( '[Tool] Deregistered frontend heartbeat' )
|
96 |
}
|
97 |
}
|
98 |
|
@@ -102,26 +97,25 @@ class Tool extends Instance
|
|
102 |
* @since 3.0
|
103 |
* @access public
|
104 |
*/
|
105 |
-
public function heartbeat_backend()
|
106 |
-
{
|
107 |
if ( $this->_is_editor() ) {
|
108 |
if ( ! $this->_conf_heartbeat_editor ) {
|
109 |
-
return
|
110 |
}
|
111 |
|
112 |
if ( ! $this->_conf_heartbeat_editor_ttl ) {
|
113 |
-
wp_deregister_script( 'heartbeat' )
|
114 |
-
Debug2::debug( '[Tool] Deregistered editor heartbeat' )
|
115 |
}
|
116 |
}
|
117 |
else {
|
118 |
if ( ! $this->_conf_heartbeat_back ) {
|
119 |
-
return
|
120 |
}
|
121 |
|
122 |
if ( ! $this->_conf_heartbeat_back_ttl ) {
|
123 |
-
wp_deregister_script( 'heartbeat' )
|
124 |
-
Debug2::debug( '[Tool] Deregistered backend heartbeat' )
|
125 |
}
|
126 |
}
|
127 |
|
@@ -133,28 +127,27 @@ class Tool extends Instance
|
|
133 |
* @since 3.0
|
134 |
* @access public
|
135 |
*/
|
136 |
-
public function heartbeat_settings( $settings )
|
137 |
-
{
|
138 |
// Check editor first to make frontend editor valid too
|
139 |
if ( $this->_is_editor() ) {
|
140 |
if ( $this->_conf_heartbeat_editor ) {
|
141 |
-
$settings[ 'interval' ] = $this->_conf_heartbeat_editor_ttl
|
142 |
-
Debug2::debug( '[Tool] Heartbeat interval set to ' . $this->_conf_heartbeat_editor_ttl )
|
143 |
}
|
144 |
}
|
145 |
elseif ( ! is_admin() ) {
|
146 |
if ( $this->_conf_heartbeat_front ) {
|
147 |
-
$settings[ 'interval' ] = $this->_conf_heartbeat_front_ttl
|
148 |
-
Debug2::debug( '[Tool] Heartbeat interval set to ' . $this->_conf_heartbeat_front_ttl )
|
149 |
}
|
150 |
}
|
151 |
else {
|
152 |
if ( $this->_conf_heartbeat_back ) {
|
153 |
-
$settings[ 'interval' ] = $this->_conf_heartbeat_back_ttl
|
154 |
-
Debug2::debug( '[Tool] Heartbeat interval set to ' . $this->_conf_heartbeat_back_ttl )
|
155 |
}
|
156 |
}
|
157 |
-
return $settings
|
158 |
}
|
159 |
|
160 |
/**
|
@@ -163,11 +156,10 @@ class Tool extends Instance
|
|
163 |
* @since 3.0
|
164 |
* @access public
|
165 |
*/
|
166 |
-
private function _is_editor()
|
167 |
-
|
168 |
-
$res = is_admin() && Utility::str_hit_array( $_SERVER[ 'REQUEST_URI' ], array( 'post.php', 'post-new.php' ) ) ;
|
169 |
|
170 |
-
return apply_filters( 'litespeed_is_editor', $res )
|
171 |
}
|
172 |
|
173 |
}
|
7 |
* @subpackage LiteSpeed/inc
|
8 |
* @author LiteSpeed Technologies <info@litespeedtech.com>
|
9 |
*/
|
10 |
+
namespace LiteSpeed;
|
11 |
|
12 |
+
defined( 'WPINC' ) || exit;
|
13 |
|
14 |
+
class Tool extends Instance {
|
15 |
+
protected static $_instance;
|
|
|
16 |
|
17 |
+
private $_conf_heartbeat_front;
|
18 |
+
private $_conf_heartbeat_front_ttl;
|
19 |
+
private $_conf_heartbeat_back;
|
20 |
+
private $_conf_heartbeat_back_ttl;
|
21 |
+
private $_conf_heartbeat_editor;
|
22 |
+
private $_conf_heartbeat_editor_ttl;
|
23 |
|
24 |
/**
|
25 |
* Init
|
27 |
* @since 3.0
|
28 |
* @access protected
|
29 |
*/
|
30 |
+
protected function __construct() {
|
31 |
+
$this->_conf_heartbeat_front = Conf::val( Base::O_MISC_HEARTBEAT_FRONT );
|
32 |
+
$this->_conf_heartbeat_front_ttl = Conf::val( Base::O_MISC_HEARTBEAT_FRONT_TTL );
|
33 |
+
$this->_conf_heartbeat_back = Conf::val( Base::O_MISC_HEARTBEAT_BACK );
|
34 |
+
$this->_conf_heartbeat_back_ttl = Conf::val( Base::O_MISC_HEARTBEAT_BACK_TTL );
|
35 |
+
$this->_conf_heartbeat_editor = Conf::val( Base::O_MISC_HEARTBEAT_EDITOR );
|
36 |
+
$this->_conf_heartbeat_editor_ttl = Conf::val( Base::O_MISC_HEARTBEAT_EDITOR_TTL );
|
|
|
37 |
}
|
38 |
|
39 |
/**
|
42 |
* @since 3.0
|
43 |
* @access public
|
44 |
*/
|
45 |
+
public function check_ip() {
|
46 |
+
Debug2::debug( '[Tool] ✅ check_ip' );
|
|
|
47 |
|
48 |
+
$response = wp_remote_get( 'https://www.doapi.us/ip' );
|
49 |
|
50 |
if ( is_wp_error( $response ) ) {
|
51 |
+
return new \WP_Error( 'remote_get_fail', 'Failed to fetch from https://www.doapi.us/ip', array( 'status' => 404 ) );
|
52 |
}
|
53 |
|
54 |
+
$data = $response[ 'body' ];
|
55 |
|
56 |
+
Debug2::debug( '[Tool] result [ip] ' . $data );
|
57 |
|
58 |
+
return $data;
|
59 |
}
|
60 |
|
61 |
/**
|
66 |
* @since 3.0
|
67 |
* @access public
|
68 |
*/
|
69 |
+
public static function heartbeat() {
|
70 |
+
$instance = self::get_instance();
|
|
|
71 |
|
72 |
+
add_action( 'wp_enqueue_scripts', array( $instance, 'heartbeat_frontend' ) );
|
73 |
+
add_action( 'admin_enqueue_scripts', array( $instance, 'heartbeat_backend' ) );
|
74 |
+
add_filter( 'heartbeat_settings', array( $instance, 'heartbeat_settings' ) );
|
75 |
}
|
76 |
|
77 |
/**
|
80 |
* @since 3.0
|
81 |
* @access public
|
82 |
*/
|
83 |
+
public function heartbeat_frontend() {
|
|
|
84 |
if ( ! $this->_conf_heartbeat_front ) {
|
85 |
+
return;
|
86 |
}
|
87 |
|
88 |
if ( ! $this->_conf_heartbeat_front_ttl ) {
|
89 |
+
wp_deregister_script( 'heartbeat' );
|
90 |
+
Debug2::debug( '[Tool] Deregistered frontend heartbeat' );
|
91 |
}
|
92 |
}
|
93 |
|
97 |
* @since 3.0
|
98 |
* @access public
|
99 |
*/
|
100 |
+
public function heartbeat_backend() {
|
|
|
101 |
if ( $this->_is_editor() ) {
|
102 |
if ( ! $this->_conf_heartbeat_editor ) {
|
103 |
+
return;
|
104 |
}
|
105 |
|
106 |
if ( ! $this->_conf_heartbeat_editor_ttl ) {
|
107 |
+
wp_deregister_script( 'heartbeat' );
|
108 |
+
Debug2::debug( '[Tool] Deregistered editor heartbeat' );
|
109 |
}
|
110 |
}
|
111 |
else {
|
112 |
if ( ! $this->_conf_heartbeat_back ) {
|
113 |
+
return;
|
114 |
}
|
115 |
|
116 |
if ( ! $this->_conf_heartbeat_back_ttl ) {
|
117 |
+
wp_deregister_script( 'heartbeat' );
|
118 |
+
Debug2::debug( '[Tool] Deregistered backend heartbeat' );
|
119 |
}
|
120 |
}
|
121 |
|
127 |
* @since 3.0
|
128 |
* @access public
|
129 |
*/
|
130 |
+
public function heartbeat_settings( $settings ) {
|
|
|
131 |
// Check editor first to make frontend editor valid too
|
132 |
if ( $this->_is_editor() ) {
|
133 |
if ( $this->_conf_heartbeat_editor ) {
|
134 |
+
$settings[ 'interval' ] = $this->_conf_heartbeat_editor_ttl;
|
135 |
+
Debug2::debug( '[Tool] Heartbeat interval set to ' . $this->_conf_heartbeat_editor_ttl );
|
136 |
}
|
137 |
}
|
138 |
elseif ( ! is_admin() ) {
|
139 |
if ( $this->_conf_heartbeat_front ) {
|
140 |
+
$settings[ 'interval' ] = $this->_conf_heartbeat_front_ttl;
|
141 |
+
Debug2::debug( '[Tool] Heartbeat interval set to ' . $this->_conf_heartbeat_front_ttl );
|
142 |
}
|
143 |
}
|
144 |
else {
|
145 |
if ( $this->_conf_heartbeat_back ) {
|
146 |
+
$settings[ 'interval' ] = $this->_conf_heartbeat_back_ttl;
|
147 |
+
Debug2::debug( '[Tool] Heartbeat interval set to ' . $this->_conf_heartbeat_back_ttl );
|
148 |
}
|
149 |
}
|
150 |
+
return $settings;
|
151 |
}
|
152 |
|
153 |
/**
|
156 |
* @since 3.0
|
157 |
* @access public
|
158 |
*/
|
159 |
+
private function _is_editor() {
|
160 |
+
$res = is_admin() && Utility::str_hit_array( $_SERVER[ 'REQUEST_URI' ], array( 'post.php', 'post-new.php' ) );
|
|
|
161 |
|
162 |
+
return apply_filters( 'litespeed_is_editor', $res );
|
163 |
}
|
164 |
|
165 |
}
|
src/vary.cls.php
CHANGED
@@ -128,48 +128,47 @@ class Vary extends Instance {
|
|
128 |
* @param array $comments The current comments to output
|
129 |
* @return array The comments to output.
|
130 |
*/
|
131 |
-
public function check_commenter( $comments )
|
132 |
-
{
|
133 |
/**
|
134 |
* Hook to bypass pending comment check for comment related plugins compatibility
|
135 |
* @since 2.9.5
|
136 |
*/
|
137 |
if ( apply_filters( 'litespeed_vary_check_commenter_pending', true ) ) {
|
138 |
-
$pending = false
|
139 |
foreach ( $comments as $comment ) {
|
140 |
if ( ! $comment->comment_approved ) {// current user has pending comment
|
141 |
-
$pending = true
|
142 |
-
break
|
143 |
}
|
144 |
}
|
145 |
|
146 |
// No pending comments, don't need to add private cache
|
147 |
if ( ! $pending ) {
|
148 |
-
$this->remove_commenter()
|
149 |
|
150 |
// Remove commenter prefilled info if exists, for public cache
|
151 |
foreach( $_COOKIE as $cookie_name => $cookie_value ) {
|
152 |
if ( strlen( $cookie_name ) >= 15 && strpos( $cookie_name, 'comment_author_' ) === 0 ) {
|
153 |
-
unset( $_COOKIE[ $cookie_name ] )
|
154 |
}
|
155 |
}
|
156 |
|
157 |
-
return $comments
|
158 |
}
|
159 |
}
|
160 |
|
161 |
// Current user/visitor has pending comments
|
162 |
// set vary=2 for next time vary lookup
|
163 |
-
$this->add_commenter()
|
164 |
|
165 |
if ( Conf::val( Base::O_CACHE_COMMENTER ) ) {
|
166 |
-
Control::set_private( 'existing commenter' )
|
167 |
}
|
168 |
else {
|
169 |
-
Control::set_nocache( 'existing commenter' )
|
170 |
}
|
171 |
|
172 |
-
return $comments
|
173 |
}
|
174 |
|
175 |
/**
|
@@ -178,12 +177,11 @@ class Vary extends Instance {
|
|
178 |
* @since 1.1.3
|
179 |
* @access public
|
180 |
*/
|
181 |
-
public static function has_vary()
|
182 |
-
{
|
183 |
if ( empty( $_COOKIE[ self::$_vary_name ] ) ) {
|
184 |
-
return false
|
185 |
}
|
186 |
-
return $_COOKIE[ self::$_vary_name ]
|
187 |
}
|
188 |
|
189 |
/**
|
@@ -193,18 +191,17 @@ class Vary extends Instance {
|
|
193 |
* @since 1.6.2 Removed static referral
|
194 |
* @access public
|
195 |
*/
|
196 |
-
public function add_logged_in( $logged_in_cookie = false, $expire = false, $expiration = false, $uid = false )
|
197 |
-
|
198 |
-
Debug2::debug( '[Vary] add_logged_in' ) ;
|
199 |
|
200 |
/**
|
201 |
* NOTE: Run before `$this->_update_default_vary()` to make vary changeable
|
202 |
* @since 2.2.2
|
203 |
*/
|
204 |
-
self::can_ajax_vary()
|
205 |
|
206 |
// If the cookie is lost somehow, set it
|
207 |
-
$this->_update_default_vary( $uid, $expire )
|
208 |
}
|
209 |
|
210 |
/**
|
@@ -214,18 +211,17 @@ class Vary extends Instance {
|
|
214 |
* @since 1.6.2 Removed static referral
|
215 |
* @access public
|
216 |
*/
|
217 |
-
public function remove_logged_in()
|
218 |
-
|
219 |
-
Debug2::debug( '[Vary] remove_logged_in' ) ;
|
220 |
|
221 |
/**
|
222 |
* NOTE: Run before `$this->_update_default_vary()` to make vary changeable
|
223 |
* @since 2.2.2
|
224 |
*/
|
225 |
-
self::can_ajax_vary()
|
226 |
|
227 |
// Force update vary to remove login status
|
228 |
-
$this->_update_default_vary( -1 )
|
229 |
}
|
230 |
|
231 |
/**
|
@@ -235,9 +231,8 @@ class Vary extends Instance {
|
|
235 |
* @since 2.6 Changed to static
|
236 |
* @access public
|
237 |
*/
|
238 |
-
public static function can_ajax_vary()
|
239 |
-
|
240 |
-
Debug2::debug( '[Vary] _can_change_vary -> true' ) ;
|
241 |
self::$_can_change_vary = true;
|
242 |
}
|
243 |
|
@@ -247,13 +242,12 @@ class Vary extends Instance {
|
|
247 |
* @since 1.6.2
|
248 |
* @access private
|
249 |
*/
|
250 |
-
private function can_change_vary()
|
251 |
-
{
|
252 |
// Don't change for ajax due to ajax not sending webp header
|
253 |
if ( Router::is_ajax() ) {
|
254 |
if ( ! self::$_can_change_vary ) {
|
255 |
-
Debug2::debug( '[Vary] can_change_vary bypassed due to ajax call' )
|
256 |
-
return false
|
257 |
}
|
258 |
}
|
259 |
|
@@ -262,8 +256,8 @@ class Vary extends Instance {
|
|
262 |
* @since 1.6.5
|
263 |
*/
|
264 |
if ( $_SERVER["REQUEST_METHOD"] !== 'GET' && $_SERVER["REQUEST_METHOD"] !== 'POST' ) {
|
265 |
-
Debug2::debug( '[Vary] can_change_vary bypassed due to method not get/post' )
|
266 |
-
return false
|
267 |
}
|
268 |
|
269 |
/**
|
@@ -271,16 +265,16 @@ class Vary extends Instance {
|
|
271 |
* @since 2.9.8 To enable woocommerce cart not empty warm up (@Taba)
|
272 |
*/
|
273 |
if ( ! empty( $_SERVER[ 'HTTP_USER_AGENT' ] ) && strpos( $_SERVER[ 'HTTP_USER_AGENT' ], Crawler::FAST_USER_AGENT ) === 0 ) {
|
274 |
-
Debug2::debug( '[Vary] can_change_vary bypassed due to crawler' )
|
275 |
-
return false
|
276 |
}
|
277 |
|
278 |
if ( ! apply_filters( 'litespeed_can_change_vary', true ) ) {
|
279 |
-
Debug2::debug( '[Vary] can_change_vary bypassed due to litespeed_can_change_vary hook' )
|
280 |
-
return false
|
281 |
}
|
282 |
|
283 |
-
return true
|
284 |
}
|
285 |
|
286 |
/**
|
@@ -290,30 +284,29 @@ class Vary extends Instance {
|
|
290 |
* @since 1.6.6.1 Add ran check to make it only run once ( No run multiple times due to login process doesn't have valid uid )
|
291 |
* @access private
|
292 |
*/
|
293 |
-
private function _update_default_vary( $uid = false, $expire = false )
|
294 |
-
{
|
295 |
// Make sure header output only run once
|
296 |
if ( ! defined( 'LITESPEED_DID_' . __FUNCTION__ ) ) {
|
297 |
-
define( 'LITESPEED_DID_' . __FUNCTION__, true )
|
298 |
}
|
299 |
else {
|
300 |
-
Debug2::debug2( "[Vary] _update_default_vary bypassed due to run already" )
|
301 |
-
return
|
302 |
}
|
303 |
|
304 |
// If the cookie is lost somehow, set it
|
305 |
-
$vary = $this->finalize_default_vary( $uid )
|
306 |
-
$current_vary = self::has_vary()
|
307 |
if ( $current_vary !== $vary && $current_vary !== 'commenter' && $this->can_change_vary() ) {
|
308 |
-
// $_COOKIE[ self::$_vary_name ] = $vary
|
309 |
|
310 |
// save it
|
311 |
if ( ! $expire ) {
|
312 |
-
$expire = time() + 2 * DAY_IN_SECONDS
|
313 |
}
|
314 |
-
self::_cookie( $vary, $expire )
|
315 |
-
Debug2::debug( "[Vary] set_cookie ---> $vary" )
|
316 |
-
Control::set_nocache( 'changing default vary' . " $current_vary => $vary" )
|
317 |
}
|
318 |
}
|
319 |
|
@@ -323,9 +316,8 @@ class Vary extends Instance {
|
|
323 |
* @since 1.9.1
|
324 |
* @access public
|
325 |
*/
|
326 |
-
public function get_vary_name()
|
327 |
-
|
328 |
-
return self::$_vary_name ;
|
329 |
}
|
330 |
|
331 |
/**
|
@@ -337,22 +329,21 @@ class Vary extends Instance {
|
|
337 |
* @param string $role The user role
|
338 |
* @return int The set value if already set
|
339 |
*/
|
340 |
-
public function in_vary_group( $role )
|
341 |
-
|
342 |
-
$
|
343 |
-
$vary_groups = Conf::val( Base::O_CACHE_VARY_GROUP ) ;
|
344 |
if ( array_key_exists( $role, $vary_groups ) ) {
|
345 |
-
$group = $vary_groups[ $role ]
|
346 |
}
|
347 |
elseif ( $role === 'administrator' ) {
|
348 |
-
$group = 99
|
349 |
}
|
350 |
|
351 |
if ( $group ) {
|
352 |
-
Debug2::debug2( '[Vary] role in vary_group [group] ' . $group )
|
353 |
}
|
354 |
|
355 |
-
return $group
|
356 |
}
|
357 |
|
358 |
/**
|
@@ -376,31 +367,31 @@ class Vary extends Instance {
|
|
376 |
}
|
377 |
|
378 |
// get user's group id
|
379 |
-
$role = Router::get_role( $uid )
|
380 |
|
381 |
if ( $uid > 0 && $role ) {
|
382 |
-
$vary[ 'logged-in' ] = 1
|
383 |
|
384 |
// parse role group from settings
|
385 |
if ( $role_group = $this->in_vary_group( $role ) ) {
|
386 |
-
$vary[ 'role' ] = $role_group
|
387 |
}
|
388 |
|
389 |
// Get admin bar set
|
390 |
// see @_get_admin_bar_pref()
|
391 |
-
$pref = get_user_option( 'show_admin_bar_front', $uid )
|
392 |
-
Debug2::debug2( '[Vary] show_admin_bar_front: ' . $pref )
|
393 |
-
$admin_bar = $pref === false || $pref === 'true'
|
394 |
|
395 |
if ( $admin_bar ) {
|
396 |
-
$vary[ 'admin_bar' ] = 1
|
397 |
-
Debug2::debug2( '[Vary] admin bar : true' )
|
398 |
}
|
399 |
|
400 |
}
|
401 |
else {
|
402 |
// Guest user
|
403 |
-
Debug2::debug( '[Vary] role id: failed, guest' )
|
404 |
|
405 |
}
|
406 |
|
@@ -413,21 +404,21 @@ class Vary extends Instance {
|
|
413 |
$vary = apply_filters( 'litespeed_vary', $vary );
|
414 |
|
415 |
if ( ! $vary ) {
|
416 |
-
return false
|
417 |
}
|
418 |
|
419 |
-
ksort( $vary )
|
420 |
-
$res = array()
|
421 |
foreach ( $vary as $key => $val ) {
|
422 |
-
$res[] = $key . ':' . $val
|
423 |
}
|
424 |
|
425 |
-
$res = implode( ';', $res )
|
426 |
if ( defined( 'LSCWP_LOG' ) ) {
|
427 |
-
return $res
|
428 |
}
|
429 |
// Encrypt in production
|
430 |
-
return md5( Conf::val( Base::HASH ) . $res )
|
431 |
|
432 |
}
|
433 |
|
@@ -439,9 +430,8 @@ class Vary extends Instance {
|
|
439 |
* @since 1.1.6
|
440 |
* @access public
|
441 |
*/
|
442 |
-
public function append_commenter()
|
443 |
-
|
444 |
-
$this->add_commenter( true ) ;
|
445 |
}
|
446 |
|
447 |
/**
|
@@ -451,16 +441,15 @@ class Vary extends Instance {
|
|
451 |
* @access private
|
452 |
* @param boolean $from_redirect If the request is from redirect page or not
|
453 |
*/
|
454 |
-
private function add_commenter( $from_redirect = false )
|
455 |
-
{
|
456 |
// If the cookie is lost somehow, set it
|
457 |
if ( self::has_vary() !== 'commenter' ) {
|
458 |
-
// $_COOKIE[ self::$_vary_name ] = 'commenter'
|
459 |
|
460 |
// save it
|
461 |
// only set commenter status for current domain path
|
462 |
-
self::_cookie( 'commenter', time() + apply_filters( 'comment_cookie_lifetime', 30000000 ), self::_relative_path( $from_redirect ) )
|
463 |
-
Control::set_nocache( 'adding commenter status' )
|
464 |
}
|
465 |
}
|
466 |
|
@@ -470,15 +459,14 @@ class Vary extends Instance {
|
|
470 |
* @since 1.1.3
|
471 |
* @access private
|
472 |
*/
|
473 |
-
private function remove_commenter()
|
474 |
-
{
|
475 |
if ( self::has_vary() === 'commenter' ) {
|
476 |
// remove logged in status from global var
|
477 |
-
// unset( $_COOKIE[ self::$_vary_name ] )
|
478 |
|
479 |
// save it
|
480 |
-
self::_cookie( false, false, self::_relative_path() )
|
481 |
-
Control::set_nocache( 'removing commenter status' )
|
482 |
}
|
483 |
}
|
484 |
|
@@ -489,16 +477,15 @@ class Vary extends Instance {
|
|
489 |
* @access private
|
490 |
* @param boolean $from_redirect If the request is from redirect page or not
|
491 |
*/
|
492 |
-
private static function _relative_path( $from_redirect = false )
|
493 |
-
|
494 |
-
$
|
495 |
-
$tag = $from_redirect ? 'HTTP_REFERER' : 'SCRIPT_URL' ;
|
496 |
if ( ! empty( $_SERVER[ $tag ] ) ) {
|
497 |
-
$path = parse_url( $_SERVER[ $tag ] )
|
498 |
-
$path = ! empty( $path[ 'path' ] ) ? $path[ 'path' ] : false
|
499 |
-
Debug2::debug( '[Vary] Cookie Vary path: ' . $path )
|
500 |
}
|
501 |
-
return $path
|
502 |
}
|
503 |
|
504 |
/**
|
@@ -512,45 +499,43 @@ class Vary extends Instance {
|
|
512 |
* @return mixed false if the user has the postpass cookie. Empty string
|
513 |
* if the post is not password protected. Vary header otherwise.
|
514 |
*/
|
515 |
-
public static function finalize()
|
516 |
-
|
517 |
-
return self::get_instance()->_finalize() ;
|
518 |
|
519 |
}
|
520 |
|
521 |
-
private function _finalize()
|
522 |
-
{
|
523 |
// Finalize default vary
|
524 |
-
$this->_update_default_vary()
|
525 |
|
526 |
/**
|
527 |
* Non caccheable page can still set vary ( for logged in process )
|
528 |
* @since 1.6.6.1
|
529 |
*/
|
530 |
// if ( ! Control::is_cacheable() ) {
|
531 |
-
// Debug2::debug2( 'Vary: bypass finalize due to not cacheable' )
|
532 |
// return false;
|
533 |
// }
|
534 |
|
535 |
-
$tp_cookies = $this->_format_vary_cookies()
|
536 |
-
global $post
|
537 |
if ( ! empty($post->post_password) ) {
|
538 |
if ( isset($_COOKIE['wp-postpass_' . COOKIEHASH]) ) {
|
539 |
-
Debug2::debug( '[Vary] finalize bypassed due to password protected vary ' )
|
540 |
// If user has password cookie, do not cache
|
541 |
-
Control::set_nocache('password protected vary')
|
542 |
-
return
|
543 |
}
|
544 |
|
545 |
-
$tp_cookies[] = 'cookie=wp-postpass_' . COOKIEHASH
|
546 |
}
|
547 |
|
548 |
if ( empty($tp_cookies) ) {
|
549 |
-
Debug2::debug2( '[Vary] no custimzed vary ' )
|
550 |
-
return
|
551 |
}
|
552 |
|
553 |
-
return self::X_HEADER . ': ' . implode(',', $tp_cookies)
|
554 |
|
555 |
}
|
556 |
|
@@ -561,35 +546,34 @@ class Vary extends Instance {
|
|
561 |
* @access private
|
562 |
* @return array An array of all vary cookies currently added.
|
563 |
*/
|
564 |
-
private function _format_vary_cookies()
|
565 |
-
{
|
566 |
/**
|
567 |
* To add new varys, use hook `API::filter_vary_cookies()` before here
|
568 |
*/
|
569 |
-
do_action( 'litespeed_vary_add' )
|
570 |
|
571 |
/**
|
572 |
* Give a filter to manipulate vary
|
573 |
* @since 2.7.1
|
574 |
*/
|
575 |
-
$cookies = apply_filters( 'litespeed_vary_cookies', self::$_vary_cookies )
|
576 |
if ( $cookies !== self::$_vary_cookies ) {
|
577 |
-
Debug2::debug( '[Vary] vary changed by filter [Old] ' . var_export( self::$_vary_cookies, true ) . ' [New] ' . var_export( $cookies, true ) )
|
578 |
}
|
579 |
|
580 |
if ( ! empty( $cookies ) ) {
|
581 |
-
$cookies = array_filter( array_unique( $cookies ) )
|
582 |
}
|
583 |
|
584 |
if ( empty($cookies) ) {
|
585 |
-
return false
|
586 |
}
|
587 |
|
588 |
foreach ($cookies as $key => $val) {
|
589 |
-
$cookies[$key] = 'cookie=' . $val
|
590 |
}
|
591 |
|
592 |
-
return $cookies
|
593 |
}
|
594 |
|
595 |
/**
|
@@ -601,15 +585,14 @@ class Vary extends Instance {
|
|
601 |
* @access public
|
602 |
* @param mixed $vary A string or array of vary cookies to add to the current list.
|
603 |
*/
|
604 |
-
public static function add( $vary )
|
605 |
-
{
|
606 |
if ( ! is_array( $vary ) ) {
|
607 |
-
$vary = array( $vary )
|
608 |
}
|
609 |
|
610 |
-
error_log( 'Deprecated since LSCWP 2.7.1! [Vary] Add new vary ' . var_export( $vary, true ) )
|
611 |
|
612 |
-
self::$_vary_cookies = array_merge(self::$_vary_cookies, $vary)
|
613 |
}
|
614 |
|
615 |
/**
|
@@ -618,8 +601,7 @@ class Vary extends Instance {
|
|
618 |
* @since 2.6
|
619 |
* @access public
|
620 |
*/
|
621 |
-
public static function append( $name, $val )
|
622 |
-
{
|
623 |
self::$_default_vary_val[ $name ] = $val;
|
624 |
}
|
625 |
|
@@ -634,19 +616,18 @@ class Vary extends Instance {
|
|
634 |
* @param integer $expire Expire time.
|
635 |
* @param boolean $path False if use wp root path as cookie path
|
636 |
*/
|
637 |
-
private static function _cookie($val = false, $expire = false, $path = false)
|
638 |
-
{
|
639 |
if ( ! $val ) {
|
640 |
-
$expire = 1
|
641 |
}
|
642 |
|
643 |
/**
|
644 |
* Add HTTPS bypass in case clients use both HTTP and HTTPS version of site
|
645 |
* @since 1.7
|
646 |
*/
|
647 |
-
$is_ssl = Conf::val( Base::O_UTIL_NO_HTTPS_VARY ) ? false : is_ssl()
|
648 |
|
649 |
-
setcookie( self::$_vary_name, $val, $expire, $path?: COOKIEPATH, COOKIE_DOMAIN, $is_ssl, true )
|
650 |
}
|
651 |
|
652 |
}
|
128 |
* @param array $comments The current comments to output
|
129 |
* @return array The comments to output.
|
130 |
*/
|
131 |
+
public function check_commenter( $comments ) {
|
|
|
132 |
/**
|
133 |
* Hook to bypass pending comment check for comment related plugins compatibility
|
134 |
* @since 2.9.5
|
135 |
*/
|
136 |
if ( apply_filters( 'litespeed_vary_check_commenter_pending', true ) ) {
|
137 |
+
$pending = false;
|
138 |
foreach ( $comments as $comment ) {
|
139 |
if ( ! $comment->comment_approved ) {// current user has pending comment
|
140 |
+
$pending = true;
|
141 |
+
break;
|
142 |
}
|
143 |
}
|
144 |
|
145 |
// No pending comments, don't need to add private cache
|
146 |
if ( ! $pending ) {
|
147 |
+
$this->remove_commenter();
|
148 |
|
149 |
// Remove commenter prefilled info if exists, for public cache
|
150 |
foreach( $_COOKIE as $cookie_name => $cookie_value ) {
|
151 |
if ( strlen( $cookie_name ) >= 15 && strpos( $cookie_name, 'comment_author_' ) === 0 ) {
|
152 |
+
unset( $_COOKIE[ $cookie_name ] );
|
153 |
}
|
154 |
}
|
155 |
|
156 |
+
return $comments;
|
157 |
}
|
158 |
}
|
159 |
|
160 |
// Current user/visitor has pending comments
|
161 |
// set vary=2 for next time vary lookup
|
162 |
+
$this->add_commenter();
|
163 |
|
164 |
if ( Conf::val( Base::O_CACHE_COMMENTER ) ) {
|
165 |
+
Control::set_private( 'existing commenter' );
|
166 |
}
|
167 |
else {
|
168 |
+
Control::set_nocache( 'existing commenter' );
|
169 |
}
|
170 |
|
171 |
+
return $comments;
|
172 |
}
|
173 |
|
174 |
/**
|
177 |
* @since 1.1.3
|
178 |
* @access public
|
179 |
*/
|
180 |
+
public static function has_vary() {
|
|
|
181 |
if ( empty( $_COOKIE[ self::$_vary_name ] ) ) {
|
182 |
+
return false;
|
183 |
}
|
184 |
+
return $_COOKIE[ self::$_vary_name ];
|
185 |
}
|
186 |
|
187 |
/**
|
191 |
* @since 1.6.2 Removed static referral
|
192 |
* @access public
|
193 |
*/
|
194 |
+
public function add_logged_in( $logged_in_cookie = false, $expire = false, $expiration = false, $uid = false ) {
|
195 |
+
Debug2::debug( '[Vary] add_logged_in' );
|
|
|
196 |
|
197 |
/**
|
198 |
* NOTE: Run before `$this->_update_default_vary()` to make vary changeable
|
199 |
* @since 2.2.2
|
200 |
*/
|
201 |
+
self::can_ajax_vary();
|
202 |
|
203 |
// If the cookie is lost somehow, set it
|
204 |
+
$this->_update_default_vary( $uid, $expire );
|
205 |
}
|
206 |
|
207 |
/**
|
211 |
* @since 1.6.2 Removed static referral
|
212 |
* @access public
|
213 |
*/
|
214 |
+
public function remove_logged_in() {
|
215 |
+
Debug2::debug( '[Vary] remove_logged_in' );
|
|
|
216 |
|
217 |
/**
|
218 |
* NOTE: Run before `$this->_update_default_vary()` to make vary changeable
|
219 |
* @since 2.2.2
|
220 |
*/
|
221 |
+
self::can_ajax_vary();
|
222 |
|
223 |
// Force update vary to remove login status
|
224 |
+
$this->_update_default_vary( -1 );
|
225 |
}
|
226 |
|
227 |
/**
|
231 |
* @since 2.6 Changed to static
|
232 |
* @access public
|
233 |
*/
|
234 |
+
public static function can_ajax_vary() {
|
235 |
+
Debug2::debug( '[Vary] _can_change_vary -> true' );
|
|
|
236 |
self::$_can_change_vary = true;
|
237 |
}
|
238 |
|
242 |
* @since 1.6.2
|
243 |
* @access private
|
244 |
*/
|
245 |
+
private function can_change_vary() {
|
|
|
246 |
// Don't change for ajax due to ajax not sending webp header
|
247 |
if ( Router::is_ajax() ) {
|
248 |
if ( ! self::$_can_change_vary ) {
|
249 |
+
Debug2::debug( '[Vary] can_change_vary bypassed due to ajax call' );
|
250 |
+
return false;
|
251 |
}
|
252 |
}
|
253 |
|
256 |
* @since 1.6.5
|
257 |
*/
|
258 |
if ( $_SERVER["REQUEST_METHOD"] !== 'GET' && $_SERVER["REQUEST_METHOD"] !== 'POST' ) {
|
259 |
+
Debug2::debug( '[Vary] can_change_vary bypassed due to method not get/post' );
|
260 |
+
return false;
|
261 |
}
|
262 |
|
263 |
/**
|
265 |
* @since 2.9.8 To enable woocommerce cart not empty warm up (@Taba)
|
266 |
*/
|
267 |
if ( ! empty( $_SERVER[ 'HTTP_USER_AGENT' ] ) && strpos( $_SERVER[ 'HTTP_USER_AGENT' ], Crawler::FAST_USER_AGENT ) === 0 ) {
|
268 |
+
Debug2::debug( '[Vary] can_change_vary bypassed due to crawler' );
|
269 |
+
return false;
|
270 |
}
|
271 |
|
272 |
if ( ! apply_filters( 'litespeed_can_change_vary', true ) ) {
|
273 |
+
Debug2::debug( '[Vary] can_change_vary bypassed due to litespeed_can_change_vary hook' );
|
274 |
+
return false;
|
275 |
}
|
276 |
|
277 |
+
return true;
|
278 |
}
|
279 |
|
280 |
/**
|
284 |
* @since 1.6.6.1 Add ran check to make it only run once ( No run multiple times due to login process doesn't have valid uid )
|
285 |
* @access private
|
286 |
*/
|
287 |
+
private function _update_default_vary( $uid = false, $expire = false ) {
|
|
|
288 |
// Make sure header output only run once
|
289 |
if ( ! defined( 'LITESPEED_DID_' . __FUNCTION__ ) ) {
|
290 |
+
define( 'LITESPEED_DID_' . __FUNCTION__, true );
|
291 |
}
|
292 |
else {
|
293 |
+
Debug2::debug2( "[Vary] _update_default_vary bypassed due to run already" );
|
294 |
+
return;
|
295 |
}
|
296 |
|
297 |
// If the cookie is lost somehow, set it
|
298 |
+
$vary = $this->finalize_default_vary( $uid );
|
299 |
+
$current_vary = self::has_vary();
|
300 |
if ( $current_vary !== $vary && $current_vary !== 'commenter' && $this->can_change_vary() ) {
|
301 |
+
// $_COOKIE[ self::$_vary_name ] = $vary; // not needed
|
302 |
|
303 |
// save it
|
304 |
if ( ! $expire ) {
|
305 |
+
$expire = time() + 2 * DAY_IN_SECONDS;
|
306 |
}
|
307 |
+
self::_cookie( $vary, $expire );
|
308 |
+
Debug2::debug( "[Vary] set_cookie ---> $vary" );
|
309 |
+
Control::set_nocache( 'changing default vary' . " $current_vary => $vary" );
|
310 |
}
|
311 |
}
|
312 |
|
316 |
* @since 1.9.1
|
317 |
* @access public
|
318 |
*/
|
319 |
+
public function get_vary_name() {
|
320 |
+
return self::$_vary_name;
|
|
|
321 |
}
|
322 |
|
323 |
/**
|
329 |
* @param string $role The user role
|
330 |
* @return int The set value if already set
|
331 |
*/
|
332 |
+
public function in_vary_group( $role ) {
|
333 |
+
$group = 0;
|
334 |
+
$vary_groups = Conf::val( Base::O_CACHE_VARY_GROUP );
|
|
|
335 |
if ( array_key_exists( $role, $vary_groups ) ) {
|
336 |
+
$group = $vary_groups[ $role ];
|
337 |
}
|
338 |
elseif ( $role === 'administrator' ) {
|
339 |
+
$group = 99;
|
340 |
}
|
341 |
|
342 |
if ( $group ) {
|
343 |
+
Debug2::debug2( '[Vary] role in vary_group [group] ' . $group );
|
344 |
}
|
345 |
|
346 |
+
return $group;
|
347 |
}
|
348 |
|
349 |
/**
|
367 |
}
|
368 |
|
369 |
// get user's group id
|
370 |
+
$role = Router::get_role( $uid );
|
371 |
|
372 |
if ( $uid > 0 && $role ) {
|
373 |
+
$vary[ 'logged-in' ] = 1;
|
374 |
|
375 |
// parse role group from settings
|
376 |
if ( $role_group = $this->in_vary_group( $role ) ) {
|
377 |
+
$vary[ 'role' ] = $role_group;
|
378 |
}
|
379 |
|
380 |
// Get admin bar set
|
381 |
// see @_get_admin_bar_pref()
|
382 |
+
$pref = get_user_option( 'show_admin_bar_front', $uid );
|
383 |
+
Debug2::debug2( '[Vary] show_admin_bar_front: ' . $pref );
|
384 |
+
$admin_bar = $pref === false || $pref === 'true';
|
385 |
|
386 |
if ( $admin_bar ) {
|
387 |
+
$vary[ 'admin_bar' ] = 1;
|
388 |
+
Debug2::debug2( '[Vary] admin bar : true' );
|
389 |
}
|
390 |
|
391 |
}
|
392 |
else {
|
393 |
// Guest user
|
394 |
+
Debug2::debug( '[Vary] role id: failed, guest' );
|
395 |
|
396 |
}
|
397 |
|
404 |
$vary = apply_filters( 'litespeed_vary', $vary );
|
405 |
|
406 |
if ( ! $vary ) {
|
407 |
+
return false;
|
408 |
}
|
409 |
|
410 |
+
ksort( $vary );
|
411 |
+
$res = array();
|
412 |
foreach ( $vary as $key => $val ) {
|
413 |
+
$res[] = $key . ':' . $val;
|
414 |
}
|
415 |
|
416 |
+
$res = implode( ';', $res );
|
417 |
if ( defined( 'LSCWP_LOG' ) ) {
|
418 |
+
return $res;
|
419 |
}
|
420 |
// Encrypt in production
|
421 |
+
return md5( Conf::val( Base::HASH ) . $res );
|
422 |
|
423 |
}
|
424 |
|
430 |
* @since 1.1.6
|
431 |
* @access public
|
432 |
*/
|
433 |
+
public function append_commenter() {
|
434 |
+
$this->add_commenter( true );
|
|
|
435 |
}
|
436 |
|
437 |
/**
|
441 |
* @access private
|
442 |
* @param boolean $from_redirect If the request is from redirect page or not
|
443 |
*/
|
444 |
+
private function add_commenter( $from_redirect = false ) {
|
|
|
445 |
// If the cookie is lost somehow, set it
|
446 |
if ( self::has_vary() !== 'commenter' ) {
|
447 |
+
// $_COOKIE[ self::$_vary_name ] = 'commenter'; // not needed
|
448 |
|
449 |
// save it
|
450 |
// only set commenter status for current domain path
|
451 |
+
self::_cookie( 'commenter', time() + apply_filters( 'comment_cookie_lifetime', 30000000 ), self::_relative_path( $from_redirect ) );
|
452 |
+
Control::set_nocache( 'adding commenter status' );
|
453 |
}
|
454 |
}
|
455 |
|
459 |
* @since 1.1.3
|
460 |
* @access private
|
461 |
*/
|
462 |
+
private function remove_commenter() {
|
|
|
463 |
if ( self::has_vary() === 'commenter' ) {
|
464 |
// remove logged in status from global var
|
465 |
+
// unset( $_COOKIE[ self::$_vary_name ] ); // not needed
|
466 |
|
467 |
// save it
|
468 |
+
self::_cookie( false, false, self::_relative_path() );
|
469 |
+
Control::set_nocache( 'removing commenter status' );
|
470 |
}
|
471 |
}
|
472 |
|
477 |
* @access private
|
478 |
* @param boolean $from_redirect If the request is from redirect page or not
|
479 |
*/
|
480 |
+
private static function _relative_path( $from_redirect = false ) {
|
481 |
+
$path = false;
|
482 |
+
$tag = $from_redirect ? 'HTTP_REFERER' : 'SCRIPT_URL';
|
|
|
483 |
if ( ! empty( $_SERVER[ $tag ] ) ) {
|
484 |
+
$path = parse_url( $_SERVER[ $tag ] );
|
485 |
+
$path = ! empty( $path[ 'path' ] ) ? $path[ 'path' ] : false;
|
486 |
+
Debug2::debug( '[Vary] Cookie Vary path: ' . $path );
|
487 |
}
|
488 |
+
return $path;
|
489 |
}
|
490 |
|
491 |
/**
|
499 |
* @return mixed false if the user has the postpass cookie. Empty string
|
500 |
* if the post is not password protected. Vary header otherwise.
|
501 |
*/
|
502 |
+
public static function finalize() {
|
503 |
+
return self::get_instance()->_finalize();
|
|
|
504 |
|
505 |
}
|
506 |
|
507 |
+
private function _finalize() {
|
|
|
508 |
// Finalize default vary
|
509 |
+
$this->_update_default_vary();
|
510 |
|
511 |
/**
|
512 |
* Non caccheable page can still set vary ( for logged in process )
|
513 |
* @since 1.6.6.1
|
514 |
*/
|
515 |
// if ( ! Control::is_cacheable() ) {
|
516 |
+
// Debug2::debug2( 'Vary: bypass finalize due to not cacheable' );
|
517 |
// return false;
|
518 |
// }
|
519 |
|
520 |
+
$tp_cookies = $this->_format_vary_cookies();
|
521 |
+
global $post;
|
522 |
if ( ! empty($post->post_password) ) {
|
523 |
if ( isset($_COOKIE['wp-postpass_' . COOKIEHASH]) ) {
|
524 |
+
Debug2::debug( '[Vary] finalize bypassed due to password protected vary ' );
|
525 |
// If user has password cookie, do not cache
|
526 |
+
Control::set_nocache('password protected vary');
|
527 |
+
return;
|
528 |
}
|
529 |
|
530 |
+
$tp_cookies[] = 'cookie=wp-postpass_' . COOKIEHASH;
|
531 |
}
|
532 |
|
533 |
if ( empty($tp_cookies) ) {
|
534 |
+
Debug2::debug2( '[Vary] no custimzed vary ' );
|
535 |
+
return;
|
536 |
}
|
537 |
|
538 |
+
return self::X_HEADER . ': ' . implode(',', $tp_cookies);
|
539 |
|
540 |
}
|
541 |
|
546 |
* @access private
|
547 |
* @return array An array of all vary cookies currently added.
|
548 |
*/
|
549 |
+
private function _format_vary_cookies() {
|
|
|
550 |
/**
|
551 |
* To add new varys, use hook `API::filter_vary_cookies()` before here
|
552 |
*/
|
553 |
+
do_action( 'litespeed_vary_add' );
|
554 |
|
555 |
/**
|
556 |
* Give a filter to manipulate vary
|
557 |
* @since 2.7.1
|
558 |
*/
|
559 |
+
$cookies = apply_filters( 'litespeed_vary_cookies', self::$_vary_cookies );
|
560 |
if ( $cookies !== self::$_vary_cookies ) {
|
561 |
+
Debug2::debug( '[Vary] vary changed by filter [Old] ' . var_export( self::$_vary_cookies, true ) . ' [New] ' . var_export( $cookies, true ) );
|
562 |
}
|
563 |
|
564 |
if ( ! empty( $cookies ) ) {
|
565 |
+
$cookies = array_filter( array_unique( $cookies ) );
|
566 |
}
|
567 |
|
568 |
if ( empty($cookies) ) {
|
569 |
+
return false;
|
570 |
}
|
571 |
|
572 |
foreach ($cookies as $key => $val) {
|
573 |
+
$cookies[$key] = 'cookie=' . $val;
|
574 |
}
|
575 |
|
576 |
+
return $cookies;
|
577 |
}
|
578 |
|
579 |
/**
|
585 |
* @access public
|
586 |
* @param mixed $vary A string or array of vary cookies to add to the current list.
|
587 |
*/
|
588 |
+
public static function add( $vary ) {
|
|
|
589 |
if ( ! is_array( $vary ) ) {
|
590 |
+
$vary = array( $vary );
|
591 |
}
|
592 |
|
593 |
+
error_log( 'Deprecated since LSCWP 2.7.1! [Vary] Add new vary ' . var_export( $vary, true ) );
|
594 |
|
595 |
+
self::$_vary_cookies = array_merge(self::$_vary_cookies, $vary);
|
596 |
}
|
597 |
|
598 |
/**
|
601 |
* @since 2.6
|
602 |
* @access public
|
603 |
*/
|
604 |
+
public static function append( $name, $val ) {
|
|
|
605 |
self::$_default_vary_val[ $name ] = $val;
|
606 |
}
|
607 |
|
616 |
* @param integer $expire Expire time.
|
617 |
* @param boolean $path False if use wp root path as cookie path
|
618 |
*/
|
619 |
+
private static function _cookie($val = false, $expire = false, $path = false) {
|
|
|
620 |
if ( ! $val ) {
|
621 |
+
$expire = 1;
|
622 |
}
|
623 |
|
624 |
/**
|
625 |
* Add HTTPS bypass in case clients use both HTTP and HTTPS version of site
|
626 |
* @since 1.7
|
627 |
*/
|
628 |
+
$is_ssl = Conf::val( Base::O_UTIL_NO_HTTPS_VARY ) ? false : is_ssl();
|
629 |
|
630 |
+
setcookie( self::$_vary_name, $val, $expire, $path?: COOKIEPATH, COOKIE_DOMAIN, $is_ssl, true );
|
631 |
}
|
632 |
|
633 |
}
|
thirdparty/yith-wishlist.cls.php
CHANGED
@@ -3,19 +3,19 @@
|
|
3 |
* The Third Party integration with the YITH WooCommerce Wishlist plugin.
|
4 |
*
|
5 |
* @since 1.1.0
|
6 |
-
* @package LiteSpeed_Cache
|
7 |
-
* @subpackage LiteSpeed_Cache/thirdparty
|
8 |
-
* @author LiteSpeed Technologies <info@litespeedtech.com>
|
9 |
*/
|
10 |
-
namespace LiteSpeed\Thirdparty
|
11 |
|
12 |
-
defined( 'WPINC' ) || exit
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
-
class Yith_Wishlist
|
15 |
-
{
|
16 |
-
const ESI_PARAM_ATTS = 'yith_wcwl_atts' ;
|
17 |
-
const ESI_PARAM_POSTID = 'yith_wcwl_post_id' ;
|
18 |
-
private static $atts = null ; // Not currently used. Depends on how YITH adds attributes
|
19 |
|
20 |
/**
|
21 |
* Detects if YITH WooCommerce Wishlist and WooCommerce are installed.
|
@@ -23,18 +23,17 @@ class Yith_Wishlist
|
|
23 |
* @since 1.1.0
|
24 |
* @access public
|
25 |
*/
|
26 |
-
public static function detect()
|
27 |
-
{
|
28 |
if ( ! defined( 'WOOCOMMERCE_VERSION' ) || ! defined( 'YITH_WCWL' ) ) {
|
29 |
-
return
|
30 |
}
|
31 |
if ( apply_filters( 'litespeed_esi_status', false ) ) {
|
32 |
add_action( 'litespeed_tpl_normal', __CLASS__ . '::is_not_esi' );
|
33 |
add_action( 'litespeed_esi_load-yith_wcwl_add', __CLASS__ . '::load_add_to_wishlist' );
|
34 |
|
35 |
// hook to add/delete wishlist
|
36 |
-
add_action( 'yith_wcwl_added_to_wishlist', __CLASS__ . '::purge' )
|
37 |
-
add_action( 'yith_wcwl_removed_from_wishlist', __CLASS__ . '::purge' )
|
38 |
}
|
39 |
}
|
40 |
|
@@ -44,8 +43,7 @@ class Yith_Wishlist
|
|
44 |
* @since 1.2.0
|
45 |
* @access public
|
46 |
*/
|
47 |
-
public static function purge()
|
48 |
-
{
|
49 |
do_action( 'litespeed_purge_esi', 'yith_wcwl_add' );
|
50 |
}
|
51 |
|
@@ -58,32 +56,51 @@ class Yith_Wishlist
|
|
58 |
* @since 1.1.0
|
59 |
* @access public
|
60 |
*/
|
61 |
-
public static function is_not_esi()
|
62 |
-
|
63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
|
|
|
65 |
}
|
66 |
|
67 |
/**
|
68 |
* Hooked to the yith_wcwl_add_to_wishlisth_button_html filter.
|
69 |
*
|
70 |
-
* The add to wishlist button displays a different output when the item
|
71 |
-
*
|
72 |
-
* an ESI block. This function replaces the normal html with the ESI
|
73 |
-
* block.
|
74 |
*
|
75 |
* @since 1.1.0
|
76 |
* @access public
|
77 |
-
* @param $template unused
|
78 |
-
* @return string The html for future callbacks to filter.
|
79 |
*/
|
80 |
-
public static function sub_add_to_wishlist( $template )
|
81 |
-
{
|
82 |
-
global $post ;
|
83 |
$params = array(
|
84 |
-
self::ESI_PARAM_POSTID =>
|
85 |
-
)
|
86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
}
|
88 |
|
89 |
/**
|
@@ -93,15 +110,12 @@ class Yith_Wishlist
|
|
93 |
*
|
94 |
* @since 1.1.0
|
95 |
* @access public
|
96 |
-
* @global $post, $wp_query
|
97 |
-
* @param array $params The input ESI parameters.
|
98 |
*/
|
99 |
-
public static function load_add_to_wishlist( $params )
|
100 |
-
|
101 |
-
|
102 |
-
$
|
103 |
-
|
104 |
-
echo \YITH_WCWL_Shortcode::add_to_wishlist( /*$params[self::ESI_PARAM_ATTS]*/array() ) ;
|
105 |
do_action( 'litespeed_control_set_private', 'yith wishlist' );
|
106 |
do_action( 'litespeed_vary_no' );
|
107 |
}
|
3 |
* The Third Party integration with the YITH WooCommerce Wishlist plugin.
|
4 |
*
|
5 |
* @since 1.1.0
|
|
|
|
|
|
|
6 |
*/
|
7 |
+
namespace LiteSpeed\Thirdparty;
|
8 |
|
9 |
+
defined( 'WPINC' ) || exit;
|
10 |
+
|
11 |
+
use \LiteSpeed\Tag;
|
12 |
+
use \LiteSpeed\Conf;
|
13 |
+
use \LiteSpeed\Base;
|
14 |
+
|
15 |
+
class Yith_Wishlist {
|
16 |
+
const ESI_PARAM_POSTID = 'yith_pid';
|
17 |
+
private static $_post_id;
|
18 |
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
/**
|
21 |
* Detects if YITH WooCommerce Wishlist and WooCommerce are installed.
|
23 |
* @since 1.1.0
|
24 |
* @access public
|
25 |
*/
|
26 |
+
public static function detect() {
|
|
|
27 |
if ( ! defined( 'WOOCOMMERCE_VERSION' ) || ! defined( 'YITH_WCWL' ) ) {
|
28 |
+
return;
|
29 |
}
|
30 |
if ( apply_filters( 'litespeed_esi_status', false ) ) {
|
31 |
add_action( 'litespeed_tpl_normal', __CLASS__ . '::is_not_esi' );
|
32 |
add_action( 'litespeed_esi_load-yith_wcwl_add', __CLASS__ . '::load_add_to_wishlist' );
|
33 |
|
34 |
// hook to add/delete wishlist
|
35 |
+
add_action( 'yith_wcwl_added_to_wishlist', __CLASS__ . '::purge' );
|
36 |
+
add_action( 'yith_wcwl_removed_from_wishlist', __CLASS__ . '::purge' );
|
37 |
}
|
38 |
}
|
39 |
|
43 |
* @since 1.2.0
|
44 |
* @access public
|
45 |
*/
|
46 |
+
public static function purge() {
|
|
|
47 |
do_action( 'litespeed_purge_esi', 'yith_wcwl_add' );
|
48 |
}
|
49 |
|
56 |
* @since 1.1.0
|
57 |
* @access public
|
58 |
*/
|
59 |
+
public static function is_not_esi() {
|
60 |
+
add_filter( 'yith_wcwl_add_to_wishlist_params', __CLASS__ . '::add_to_wishlist_params', 999, 2 );
|
61 |
+
|
62 |
+
add_filter( 'yith_wcwl_add_to_wishlisth_button_html', __CLASS__ . '::sub_add_to_wishlist', 999 );
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Store the post id for later shortcode usage
|
67 |
+
*
|
68 |
+
* @since 3.4.1
|
69 |
+
*/
|
70 |
+
public static function add_to_wishlist_params( $defaults, $atts ) {
|
71 |
+
self::$_post_id = ! empty( $atts[ 'product_id' ] ) ? $atts[ 'product_id' ] : $defaults[ 'product_id' ];
|
72 |
|
73 |
+
return $defaults;
|
74 |
}
|
75 |
|
76 |
/**
|
77 |
* Hooked to the yith_wcwl_add_to_wishlisth_button_html filter.
|
78 |
*
|
79 |
+
* The add to wishlist button displays a different output when the item is already in the wishlist/cart.
|
80 |
+
* For this reason, the button must be an ESI block. This function replaces the normal html with the ESI block.
|
|
|
|
|
81 |
*
|
82 |
* @since 1.1.0
|
83 |
* @access public
|
|
|
|
|
84 |
*/
|
85 |
+
public static function sub_add_to_wishlist( $template ) {
|
|
|
|
|
86 |
$params = array(
|
87 |
+
self::ESI_PARAM_POSTID => self::$_post_id,
|
88 |
+
);
|
89 |
+
|
90 |
+
$inline_tags = array(
|
91 |
+
'',
|
92 |
+
rtrim( Tag::TYPE_ESI, '.' ),
|
93 |
+
Tag::TYPE_ESI . 'yith_wcwl_add',
|
94 |
+
);
|
95 |
+
$inline_tags = implode( ',', array_map( function($val){ return 'public:' . LSWCP_TAG_PREFIX . '_' . $val; }, $inline_tags ) );
|
96 |
+
$inline_tags .= ',' . LSWCP_TAG_PREFIX . '_tag_priv';
|
97 |
+
|
98 |
+
$inline_params = array(
|
99 |
+
'val' => $template,
|
100 |
+
'tag' => $inline_tags,
|
101 |
+
'control' => 'private,no-vary,max-age=' . Conf::val( Base::O_CACHE_TTL_PRIV ),
|
102 |
+
);
|
103 |
+
return apply_filters( 'litespeed_esi_url', 'yith_wcwl_add', 'YITH ADD TO WISHLIST', $params, 'private,no-vary', false, false, false, $inline_params );
|
104 |
}
|
105 |
|
106 |
/**
|
110 |
*
|
111 |
* @since 1.1.0
|
112 |
* @access public
|
|
|
|
|
113 |
*/
|
114 |
+
public static function load_add_to_wishlist( $params ) {
|
115 |
+
// global $post, $wp_query;
|
116 |
+
// $post = get_post( $params[ self::ESI_PARAM_POSTID ] );
|
117 |
+
// $wp_query->setup_postdata( $post );
|
118 |
+
echo \YITH_WCWL_Shortcode::add_to_wishlist( array( 'product_id' => $params[ self::ESI_PARAM_POSTID ] ) );
|
|
|
119 |
do_action( 'litespeed_control_set_private', 'yith wishlist' );
|
120 |
do_action( 'litespeed_vary_no' );
|
121 |
}
|