Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 74 |
|
0.00% |
0 / 10 |
CRAP | |
0.00% |
0 / 1 |
Browser | |
0.00% |
0 / 74 |
|
0.00% |
0 / 10 |
420 | |
0.00% |
0 / 1 |
should_enable | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
on_rewrite | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
exclusionChange | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
maybeAddRules | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
removeRules | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
addRules | |
0.00% |
0 / 24 |
|
0.00% |
0 / 1 |
30 | |||
getFileTypeExpirations | |
0.00% |
0 / 40 |
|
0.00% |
0 / 1 |
30 | |||
on_activation | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
on_deactivation | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace NewfoldLabs\WP\Module\Performance\Cache\Types; |
4 | |
5 | use NewfoldLabs\WP\Module\Performance\OptionListener; |
6 | use NewfoldLabs\WP\ModuleLoader\Container; |
7 | use WP_Forge\WP_Htaccess_Manager\htaccess; |
8 | use NewfoldLabs\WP\Module\Performance\Cache\CacheExclusion; |
9 | use NewfoldLabs\WP\Module\Performance\Cache\CacheManager; |
10 | |
11 | use function NewfoldLabs\WP\Module\Performance\get_cache_level; |
12 | use function WP_Forge\WP_Htaccess_Manager\removeMarkers; |
13 | |
14 | /** |
15 | * Browser cache type. |
16 | */ |
17 | class Browser extends CacheBase { |
18 | /** |
19 | * The file marker name. |
20 | * |
21 | * @var string |
22 | */ |
23 | const MARKER = 'Newfold Browser Cache'; |
24 | |
25 | /** |
26 | * Whether or not the code for this cache type should be loaded. |
27 | * |
28 | * @param Container $container Dependency injection container. |
29 | * |
30 | * @return bool |
31 | */ |
32 | public static function should_enable( Container $container ) { |
33 | return (bool) $container->has( 'isApache' ) && $container->get( 'isApache' ); |
34 | } |
35 | |
36 | /** |
37 | * Constructor. |
38 | */ |
39 | public function __construct() { |
40 | |
41 | new OptionListener( CacheManager::OPTION_CACHE_LEVEL, array( __CLASS__, 'maybeAddRules' ) ); |
42 | |
43 | new OptionListener( CacheExclusion::OPTION_CACHE_EXCLUSION, array( __CLASS__, 'exclusionChange' ) ); |
44 | |
45 | add_filter( 'newfold_update_htaccess', array( $this, 'on_rewrite' ) ); |
46 | } |
47 | |
48 | /** |
49 | * When updating .htaccess, also update our rules as appropriate. |
50 | */ |
51 | public function on_rewrite() { |
52 | self::maybeAddRules( get_cache_level() ); |
53 | } |
54 | |
55 | /** |
56 | * Manage on exlcusion option change. |
57 | */ |
58 | public static function exclusionChange() { |
59 | self::maybeAddRules( get_cache_level() ); |
60 | } |
61 | |
62 | /** |
63 | * Determine whether to add or remove rules based on caching level. |
64 | * |
65 | * @param int|null $cacheLevel The caching level. |
66 | */ |
67 | public static function maybeAddRules( $cacheLevel ) { |
68 | absint( $cacheLevel ) > 0 ? self::addRules( $cacheLevel ) : self::removeRules(); |
69 | } |
70 | |
71 | /** |
72 | * Remove our rules from the .htaccess file. |
73 | */ |
74 | public static function removeRules() { |
75 | removeMarkers( self::MARKER ); |
76 | } |
77 | |
78 | /** |
79 | * Add our rules to the .htaccess file. |
80 | * |
81 | * @param int $cacheLevel The caching level. |
82 | * |
83 | * @return bool |
84 | */ |
85 | public static function addRules( $cacheLevel ) { |
86 | |
87 | $fileTypeExpirations = self::getFileTypeExpirations( $cacheLevel ); |
88 | |
89 | $tab = "\t"; |
90 | |
91 | $rules[] = '<IfModule mod_expires.c>'; |
92 | $rules[] = "{$tab}ExpiresActive On"; |
93 | |
94 | foreach ( $fileTypeExpirations as $file_type => $expiration ) { |
95 | if ( 'default' === $file_type ) { |
96 | $rules[] = "{$tab}ExpiresDefault \"access plus {$expiration}\""; |
97 | } else { |
98 | $rules[] = "{$tab}ExpiresByType {$file_type} \"access plus {$expiration}\""; |
99 | } |
100 | } |
101 | $rules[] = '</IfModule>'; |
102 | |
103 | $cache_exclusion = get_option( CacheExclusion::OPTION_CACHE_EXCLUSION, '' ); |
104 | if ( is_string( $cache_exclusion ) && '' !== $cache_exclusion ) { |
105 | $cache_exclusion_parameters = array_map( 'trim', explode( ',', sanitize_text_field( get_option( CacheExclusion::OPTION_CACHE_EXCLUSION, '' ) ) ) ); |
106 | $cache_exclusion_parameters = implode( '|', $cache_exclusion_parameters ); |
107 | |
108 | // Add the cache exclusion rules. |
109 | $rules[] = '<IfModule mod_rewrite.c>'; |
110 | $rules[] = 'RewriteEngine On'; |
111 | $rules[] = "RewriteCond %{REQUEST_URI} ^/({$cache_exclusion_parameters}) [NC]"; |
112 | $rules[] = '<IfModule mod_headers.c>'; |
113 | $rules[] = 'Header set Cache-Control "no-cache, no-store, must-revalidate"'; |
114 | $rules[] = 'Header set Pragma "no-cache"'; |
115 | $rules[] = 'Header set Expires 0'; |
116 | $rules[] = '</IfModule>'; |
117 | $rules[] = '</IfModule>'; |
118 | // Add the end of the rules about cache exclusion. |
119 | } |
120 | |
121 | $htaccess = new htaccess( self::MARKER ); |
122 | |
123 | return $htaccess->addContent( $rules ); |
124 | } |
125 | |
126 | /** |
127 | * Get the filetype expirations based on the current caching level. |
128 | * |
129 | * @param int $cacheLevel The caching level. |
130 | * |
131 | * @return string[] |
132 | */ |
133 | protected static function getFileTypeExpirations( int $cacheLevel ) { |
134 | |
135 | switch ( $cacheLevel ) { |
136 | case 3: |
137 | return array( |
138 | 'default' => '1 week', |
139 | 'text/html' => '8 hours', |
140 | 'image/jpg' => '1 week', |
141 | 'image/jpeg' => '1 week', |
142 | 'image/gif' => '1 week', |
143 | 'image/png' => '1 week', |
144 | 'text/css' => '1 week', |
145 | 'text/javascript' => '1 week', |
146 | 'application/pdf' => '1 month', |
147 | 'image/x-icon' => '1 year', |
148 | ); |
149 | |
150 | case 2: |
151 | return array( |
152 | 'default' => '24 hours', |
153 | 'text/html' => '2 hours', |
154 | 'image/jpg' => '24 hours', |
155 | 'image/jpeg' => '24 hours', |
156 | 'image/gif' => '24 hours', |
157 | 'image/png' => '24 hours', |
158 | 'text/css' => '24 hours', |
159 | 'text/javascript' => '24 hours', |
160 | 'application/pdf' => '1 week', |
161 | 'image/x-icon' => '1 year', |
162 | ); |
163 | |
164 | case 1: |
165 | return array( |
166 | 'default' => '5 minutes', |
167 | 'text/html' => '0 seconds', |
168 | 'image/jpg' => '1 hour', |
169 | 'image/jpeg' => '1 hour', |
170 | 'image/gif' => '1 hour', |
171 | 'image/png' => '1 hour', |
172 | 'text/css' => '1 hour', |
173 | 'text/javascript' => '1 hour', |
174 | 'application/pdf' => '6 hours', |
175 | 'image/x-icon' => '1 year', |
176 | ); |
177 | |
178 | default: |
179 | return array(); |
180 | } |
181 | } |
182 | |
183 | /** |
184 | * Handle activation logic. |
185 | */ |
186 | public static function on_activation() { |
187 | self::maybeAddRules( get_cache_level() ); |
188 | } |
189 | |
190 | /** |
191 | * Handle deactivation logic. |
192 | */ |
193 | public static function on_deactivation() { |
194 | self::removeRules(); |
195 | } |
196 | } |