PluginProbe
Leverage Browser Caching / trunk
Leverage Browser Caching vtrunk
3.1 3.0 trunk 2.3 2.4 2.5 2.6 2.7
leverage-browser-caching / inc / classes / class-lbrowserc-core.php

class-lbrowserc-core.php in Leverage Browser Caching trunk, at inc/classes/class-lbrowserc-core.php

202 lines 6.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Core class.
4 *
5 * @package Leverage Browser Caching
6 */
7
8 // Exit if accessed directly.
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 if ( ! class_exists( 'Lbrowserc_Core' ) ) {
14 /**
15 * Core class of plugin.
16 */
17 class Lbrowserc_Core {
18
19 /**
20 * Absolute path to the .htaccess file.
21 *
22 * @var string
23 */
24 private $htaccess_file;
25
26 /**
27 * Unique marker string used to identify the plugin's block in .htaccess.
28 *
29 * @var string
30 */
31 private $unique_string = 'LBROWSERCSTART';
32
33 /**
34 * Constructor — sets up the htaccess path and registers admin notice hooks.
35 */
36 public function __construct() {
37 $this->htaccess_file = wp_normalize_path( ABSPATH . '.htaccess' );
38
39 // Show admin notices when .htaccess cannot be found or accessed.
40 add_action( 'admin_notices', array( $this, 'admin_notices' ) );
41 }
42
43 /**
44 * Displays admin notices when .htaccess is missing or not accessible.
45 */
46 public function admin_notices() {
47 if ( ! current_user_can( 'manage_options' ) ) {
48 return;
49 }
50
51 $server_software = isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : '';
52 $is_apache = ( stripos( $server_software, 'apache' ) !== false );
53
54 if ( ! $is_apache ) {
55 return;
56 }
57
58 require_once ABSPATH . 'wp-admin/includes/file.php';
59 WP_Filesystem();
60 global $wp_filesystem;
61
62 if ( ! $wp_filesystem->exists( $this->htaccess_file ) ) {
63 $message = '<div class="notice notice-error"><p>';
64 $message .= __( 'Plugin Leverage Browser Caching: .htaccess file not found. This plugin works only for Apache server. If you are using Apache server, please create it.', 'leverage-browser-caching' );
65 $message .= '</p></div>';
66 echo wp_kses_post( $message );
67 } elseif ( ! $wp_filesystem->is_readable( $this->htaccess_file ) || ! $wp_filesystem->is_writable( $this->htaccess_file ) ) {
68 $message = '<div class="notice notice-error"><p>';
69 $message .= __( 'Plugin Leverage Browser Caching: .htaccess file is not readable or writable. Please change the file permissions.', 'leverage-browser-caching' );
70 $message .= '</p></div>';
71 echo wp_kses_post( $message );
72 }
73 }
74
75 /**
76 * Adds browser caching rules to .htaccess on plugin activation.
77 * Called via register_activation_hook().
78 */
79 public function add_code() {
80 // Only allow users with sufficient capability to modify server files.
81 if ( ! current_user_can( 'activate_plugins' ) ) {
82 return;
83 }
84
85 require_once ABSPATH . 'wp-admin/includes/file.php';
86 WP_Filesystem();
87 global $wp_filesystem;
88
89 // Bail if .htaccess does not exist.
90 if ( ! $wp_filesystem->exists( $this->htaccess_file ) ) {
91 return;
92 }
93
94 // Bail if .htaccess is not readable or writable.
95 if ( ! $wp_filesystem->is_readable( $this->htaccess_file ) || ! $wp_filesystem->is_writable( $this->htaccess_file ) ) {
96 return;
97 }
98
99 $htaccess_cntn = $wp_filesystem->get_contents( $this->htaccess_file );
100
101 // Do nothing if the plugin block is already present.
102 if ( strpos( $htaccess_cntn, $this->unique_string ) !== false ) {
103 return;
104 }
105
106 // Append the caching block and write back.
107 $htaccess_cntn .= $this->code_to_add();
108 $wp_filesystem->put_contents( $this->htaccess_file, $htaccess_cntn, FS_CHMOD_FILE );
109 }
110
111 /**
112 * Removes browser caching rules from .htaccess on plugin deactivation.
113 * Called via register_deactivation_hook().
114 */
115 public function remove_code() {
116 require_once ABSPATH . 'wp-admin/includes/file.php';
117 WP_Filesystem();
118 global $wp_filesystem;
119
120 // Bail if .htaccess does not exist.
121 if ( ! $wp_filesystem->exists( $this->htaccess_file ) ) {
122 return;
123 }
124
125 // Bail if .htaccess is not readable or writable.
126 if ( ! $wp_filesystem->is_readable( $this->htaccess_file ) || ! $wp_filesystem->is_writable( $this->htaccess_file ) ) {
127 return;
128 }
129
130 $htaccess_cntn = $wp_filesystem->get_contents( $this->htaccess_file );
131
132 // Do nothing if the plugin block is not present.
133 if ( strpos( $htaccess_cntn, $this->unique_string ) === false ) {
134 return;
135 }
136
137 // Remove the plugin's caching block.
138 $pattern = '/#\s?LBROWSERCSTART.*?LBROWSERCEND/s';
139 $htaccess_cntn = preg_replace( $pattern, '', $htaccess_cntn );
140
141 // Remove only the extra blank lines left by the removed block (max 2 → 1),
142 // without touching intentional formatting elsewhere in the file.
143 $htaccess_cntn = preg_replace( '/\n{3,}/', "\n\n", $htaccess_cntn );
144
145 $wp_filesystem->put_contents( $this->htaccess_file, $htaccess_cntn, FS_CHMOD_FILE );
146 }
147
148 /**
149 * Builds and returns the browser caching directives to insert into .htaccess.
150 *
151 * Uses a local variable to avoid overwriting the stored .htaccess content.
152 *
153 * @return string
154 */
155 private function code_to_add() {
156 $code = "\n";
157 $code .= '# LBROWSERCSTART Browser Caching' . "\n";
158 $code .= '<IfModule mod_expires.c>' . "\n";
159 $code .= 'ExpiresActive On' . "\n";
160
161 // Images.
162 $code .= 'ExpiresByType image/gif "access 1 year"' . "\n";
163 $code .= 'ExpiresByType image/jpeg "access 1 year"' . "\n";
164 $code .= 'ExpiresByType image/png "access 1 year"' . "\n";
165 $code .= 'ExpiresByType image/webp "access 1 year"' . "\n";
166 $code .= 'ExpiresByType image/avif "access 1 year"' . "\n";
167 $code .= 'ExpiresByType image/svg+xml "access 1 year"' . "\n";
168 $code .= 'ExpiresByType image/x-icon "access 1 year"' . "\n";
169 $code .= 'ExpiresByType image/vnd.microsoft.icon "access 1 year"' . "\n";
170
171 // Web fonts.
172 $code .= 'ExpiresByType font/woff "access 1 year"' . "\n";
173 $code .= 'ExpiresByType font/woff2 "access 1 year"' . "\n";
174 $code .= 'ExpiresByType font/ttf "access 1 year"' . "\n";
175 $code .= 'ExpiresByType application/font-woff "access 1 year"' . "\n";
176 $code .= 'ExpiresByType application/font-woff2 "access 1 year"' . "\n";
177
178 // Stylesheets and scripts.
179 $code .= 'ExpiresByType text/css "access 1 month"' . "\n";
180 $code .= 'ExpiresByType text/javascript "access 1 month"' . "\n";
181 $code .= 'ExpiresByType application/javascript "access 1 month"' . "\n";
182 $code .= 'ExpiresByType application/x-javascript "access 1 month"' . "\n";
183
184 // Documents.
185 $code .= 'ExpiresByType text/html "access 1 month"' . "\n";
186 $code .= 'ExpiresByType application/xhtml+xml "access 1 month"' . "\n";
187 $code .= 'ExpiresByType application/pdf "access 1 month"' . "\n";
188
189 // Data and other.
190 $code .= 'ExpiresByType application/json "access 1 month"' . "\n";
191 $code .= 'ExpiresByType application/x-shockwave-flash "access 1 month"' . "\n";
192
193 $code .= 'ExpiresDefault "access 1 month"' . "\n";
194 $code .= '</IfModule>' . "\n";
195 $code .= '# END Caching LBROWSERCEND' . "\n";
196
197 return $code;
198 }
199
200 }
201 }
202