PluginProbe
EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant / 1.1.0
EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant v1.1.0
2.0.4 2.0.3 2.0.2 2.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2 1.3 2.0.0
easyfonts / easyfonts.php

easyfonts.php in EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant 1.1.0, at easyfonts.php

324 lines 14.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: EasyFonts
4 Plugin URI:
5 Description: Automatically Host existing google fonts locally on your server
6 Version: 1.1.0
7 Author: Uzair
8 Author URI: https://easywpstuff.com
9 License: GPL2
10 */
11
12 // If this file is called directly, abort.
13 if (!defined("WPINC")){
14 die;
15 }
16
17 require_once dirname(__FILE__) . '/lib/simple_html_dom.php';
18
19 include_once dirname(__FILE__) . '/inc/options.php';
20
21 include_once dirname(__FILE__) . '/inc/notices.php';
22
23 function get_base_url() {
24 if (is_ssl()) {
25 $base_url = set_url_scheme(wp_upload_dir()['baseurl'], 'https');
26 } else {
27 $base_url = wp_upload_dir()['baseurl'];
28 }
29 return $base_url;
30 }
31
32 function get_basecss_url() {
33 if (is_ssl()) {
34 $basecss_url = set_url_scheme(wp_upload_dir()['baseurl'], 'https');
35 } else {
36 $basecss_url = wp_upload_dir()['baseurl'];
37 }
38 return $basecss_url;
39 }
40
41 function wp_get_remote_css($decoded_url) {
42 $backtrace = debug_backtrace();
43 $function_name = isset($backtrace[1]['function']) ? $backtrace[1]['function'] : '';
44
45 $response = wp_remote_get($decoded_url, array('user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',));
46
47 if (is_wp_error($response)) {
48 add_settings_error($function_name, 'http_error', $response->get_error_message(), 'error');
49 return false;
50 }
51
52 $getcss = wp_remote_retrieve_body($response);
53 return $getcss;
54 }
55
56 function wp_get_remote_font($font_url) {
57 $backtrace = debug_backtrace();
58 $function_name = isset($backtrace[1]['function']) ? $backtrace[1]['function'] : '';
59 $font_response = wp_remote_get($font_url, array('user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',));
60 if (is_wp_error($font_response)) {
61 add_settings_error($function_name, 'http_error', $font_response->get_error_message(), 'error');
62 return false;
63 }
64 $getfont_data = wp_remote_retrieve_body($font_response);
65 return $getfont_data;
66 }
67
68 function easyfont_process_content_link_tag($content) {
69 $html = hgfl_str_get_html($content, false, true, 'UTF-8', false, PHP_EOL, ' ');
70 // Check if the 'easyfonts' directory exists and is writable
71 $easyfonts_dir = wp_upload_dir() ['basedir'] . '/easyfonts';
72 if (!wp_mkdir_p($easyfonts_dir)) {
73 return $content;
74 }
75 // Find all <link> tags with a rel attribute of 'stylesheet' and a href attribute that points to a Google Fonts stylesheet
76 foreach ($html->find('link[rel=stylesheet][href*=fonts.googleapis.com]') as $link) {
77 $url = $link->href;
78 if(strpos($url,'//') === 0){
79 $url = 'https:'.$url;
80 }
81 $decoded_url = rawurldecode(htmlspecialchars_decode($url));
82 // Generate a local filename for the stylesheet
83 $filename = hash('sha256', $decoded_url, false);
84 $filename = substr($filename, 0, 10) . '.css';
85 if (!file_exists($easyfonts_dir . '/' . $filename)) {
86 $css = wp_get_remote_css($decoded_url);
87 if (!preg_match_all('/@font-face\s*\{([^}]+)\}/', $css, $matches)) continue;
88
89 if (preg_match_all('/@font-face\s*\{([^}]+)\}/', $css, $matches)) {
90 foreach ($matches[1] as $match) {
91 if (preg_match_all('/src\s*:\s*([^;]+);/', $match, $srcs)) {
92 foreach ($srcs[1] as $src) {
93 if (preg_match('/url\(([^)]+)\)/', $src, $url_match)) {
94 $font_url = trim($url_match[1], "'\"");
95 $font_filename = hash('sha256', $font_url, false);
96 $font_filename = substr($font_filename, 0, 10) . '.' . pathinfo($font_url, PATHINFO_EXTENSION);
97 if (!file_exists($easyfonts_dir . '/' . $font_filename)) {
98 $font_data = wp_get_remote_font($font_url);
99 // Save the font file to the 'wp-content/uploads/easyfonts' directory
100 file_put_contents($easyfonts_dir . '/' . $font_filename, $font_data);
101 }
102 // Replace the src property with a local reference to the downloaded font file
103 $finalbase = get_base_url();
104 $css = str_replace($src, "url('" . $finalbase . "/easyfonts/" . $font_filename . "')", $css);
105 }
106 }
107 }
108 }
109 }
110 // Save the modified stylesheet to the 'wp-content/uploads/easyfonts' directory
111 file_put_contents($easyfonts_dir . '/' . $filename, $css);
112 }
113 $finalbasecss = get_basecss_url();
114 // Replace the href attribute with a local reference to the downloaded stylesheet
115 $link->href = $finalbasecss . '/easyfonts/' . $filename;
116 }
117 // Return the modified content
118 return $html->save();
119 }
120
121 function easyfont_process_content_import($content) {
122 // using simple html dom
123 $html = hgfl_str_get_html($content, false, true, 'UTF-8', false, PHP_EOL, ' ');
124 // Check if the 'easyfonts' directory exists and is writable
125 $easyfonts_dir = wp_upload_dir() ['basedir'] . '/easyfonts';
126 if (!wp_mkdir_p($easyfonts_dir)) {
127 return $content;
128 }
129 // Find all <style> tags with @import statements that import a Google Fonts stylesheet
130 foreach ($html->find('style') as $style) {
131 if (preg_match_all('/@import\s+(url\()?\s*([^\)]+)\s*(\))?/', $style->innertext, $matches)) {
132 foreach ($matches[2] as $match) {
133 if (strpos($match, 'fonts.googleapis.com') !== false) {
134 $url = trim($match, "'\"");
135 if (strpos($url, '//') === 0) {
136 $url = 'https:' . $url;
137 }
138 $decoded_url = rawurldecode(htmlspecialchars_decode($url));
139 $filename = hash('sha256', $decoded_url, false);
140 $filename = substr($filename, 0, 10) . '.css';
141 // Check if the stylesheet file already exists
142 if (!file_exists($easyfonts_dir . '/' . $filename)) {
143 $css = wp_get_remote_css($decoded_url);
144 if (preg_match_all('/@font-face\s*\{([^}]+)\}/', $css, $matches)) {
145 foreach ($matches[1] as $match) {
146 if (preg_match_all('/src\s*:\s*([^;]+);/', $match, $srcs)) {
147 foreach ($srcs[1] as $src) {
148 if (preg_match('/url\(([^)]+)\)/', $src, $url_match)) {
149 $font_url = trim($url_match[1], "'\"");
150 $font_filename = hash('sha256', $font_url, false);
151 $font_filename = substr($font_filename, 0, 10) . '.' . pathinfo($font_url, PATHINFO_EXTENSION);
152 // Check if the font file already exists
153 if (!file_exists($easyfonts_dir . '/' . $font_filename)) {
154
155 $font_data = wp_get_remote_font($font_url);
156 $file = fopen($easyfonts_dir . '/' . $font_filename, 'w');
157 fwrite($file, $font_data);
158 fclose($file);
159 }
160 $finalbase = get_base_url();
161 $css = str_replace($src, "url('" . $finalbase . "/easyfonts/" . $font_filename . "')", $css);
162 }
163 }
164 }
165 }
166 }
167 // Save the modified stylesheet to the 'wp-content/uploads/easyfonts' directory
168 file_put_contents($easyfonts_dir . '/' . $filename, $css);
169 }
170 $finalbasecss = get_basecss_url();
171 // Replace the @import statement with a local reference to the downloaded stylesheet
172 $style->innertext = str_replace($match, "" . $finalbasecss . '/easyfonts/' . $filename . "", $style->innertext);
173 }
174 }
175 }
176 }
177 // Return the modified content
178 return $html->save();
179 }
180 function easyfonts_remove_resource_hints($html) {
181 // Load the HTML into the Simple HTML DOM library
182 $dom = hgfl_str_get_html($html, false, true, 'UTF-8', false, PHP_EOL, ' ');
183
184 // Find all <link> elements with the preload, preconnect, or prefetch attributes
185 $links = $dom->find('link[rel=preload],link[rel=preconnect],link[rel=dns-prefetch]');
186
187 // Loop through the <link> elements
188 foreach($links as $link) {
189 // Check if the <link> element has a href attribute with the fonts.googleapis.com or fonts.gstatic.com domain
190 if (preg_match('/(https:\/\/|\/\/)(fonts\.googleapis\.com|fonts\.gstatic\.com)/', $link->href)) {
191 // Remove the <link> element
192 $link->outertext = '';
193 }
194 }
195
196 // Find all <style> elements
197 $styles = $dom->find('style');
198
199 // Loop through the <style> elements
200 foreach($styles as $style) {
201 // Remove comments that contain the fonts.googleapis.com or fonts.gstatic.com domain
202 if (strpos($style->innertext, 'fonts.googleapis.com') !== false || strpos($style->innertext, 'fonts.gstatic.com') !== false) {
203 $style->innertext = preg_replace('#/\*(?:[^*]*(?:\*(?!/))*)*\*/#','',$style->innertext);
204 }
205 }
206 // Return the modified HTML
207 return $dom->save();
208 }
209
210
211 function easyfont_remove_font_scripts($html) {
212 // Load the HTML string into a Simple HTML DOM object
213 $dom = hgfl_str_get_html($html, false, true, 'UTF-8', false, PHP_EOL, ' ');
214
215 // Find all `script` elements
216 $scripts = $dom->find('script');
217 foreach($scripts as $script) {
218 // Check if the `script` element contains the `WebFontConfig` or `webfont.js` strings
219 if(strpos($script->innertext, 'WebFontConfig') !== false || strpos($script->innertext, 'webfont.js') !== false) {
220 // Remove the `script` element
221 $script->outertext = '';
222 }
223 }
224
225 // Return the modified HTML as a string
226 return $dom->save();
227 }
228
229 function easyfont_download_gstatic_fonts($content) {
230 // Create the "easyfonts" directory if it doesn't exist
231 $easyfonts_dir = wp_upload_dir()['basedir'] . '/easyfonts';
232 if (!wp_mkdir_p($easyfonts_dir)) {
233 return $content;
234 }
235 $content = preg_replace('/(url\s?\(["\']?)\/\/(fonts\.gstatic\.com[^"\']+)/', '$1https://$2', $content);
236 $html = hgfl_str_get_html($content, false, true, 'UTF-8', false, PHP_EOL, ' ');
237 foreach ($html->find('style') as $style) {
238 if (preg_match_all('/url\(([^)]+)\)/', $style->innertext, $matches)) {
239 foreach ($matches[1] as $match) {
240 $url = trim($match, "'\"");
241 if(strpos($url,'//') === 0){
242 $url = 'https:'.$url;
243 }
244 if (strpos($url, 'fonts.gstatic.com') !== false) {
245 $path_parts = pathinfo($url);
246 $extension = isset($path_parts['extension'])?$path_parts['extension']:'';
247 if (empty($extension)) {
248 if(strpos($url,'/l/font') !== false){
249 $extension = 'svg';
250 }else{
251 $extension = 'woff2';
252 }
253 }
254 $filename = hash('sha256', $url, false);
255 $filename = substr($filename, 0, 10) . '.' . $extension;
256 // Check if the font file already exists
257 if (!file_exists($easyfonts_dir . '/' . $filename)) {
258 $font_data = wp_get_remote_font($url);
259 $file = fopen($easyfonts_dir . '/' . $filename, 'w');
260 fwrite($file, $font_data);
261 fclose($file);
262 }
263 $finalbase = get_base_url();
264 $local_url = $finalbase . '/easyfonts/' . $filename;
265 $content = str_replace($url, $local_url, $content);
266 }
267 }
268 }
269 }
270 return $content;
271 }
272
273
274 function easy_fonts_run_template_redirect() {
275
276 if (get_option('easyfonts_host_google_fonts_locally_link', false)) {
277 ob_start( 'easyfont_process_content_link_tag',0, PHP_OUTPUT_HANDLER_REMOVABLE );
278 }
279 if (get_option('easyfonts_host_google_fonts_locally_import', false)) {
280 ob_start( 'easyfont_process_content_import',0, PHP_OUTPUT_HANDLER_REMOVABLE );
281 }
282
283 if (get_option('easyfonts_remove_inline_css_fontface', false)) {
284 ob_start( 'easyfont_download_gstatic_fonts',0, PHP_OUTPUT_HANDLER_REMOVABLE );
285 }
286
287 if (get_option('easyfonts_remove_resource_hints', false)) {
288 ob_start( 'easyfonts_remove_resource_hints',0, PHP_OUTPUT_HANDLER_REMOVABLE );
289 }
290
291 if (get_option('easyfonts_remove_inline_script_font', false)) {
292 ob_start( 'easyfont_remove_font_scripts',0, PHP_OUTPUT_HANDLER_REMOVABLE );
293 }
294 //ob_start( 'download_gstatic_fonts',0, PHP_OUTPUT_HANDLER_REMOVABLE );
295
296
297 }
298 add_action( 'template_redirect', 'easy_fonts_run_template_redirect', 999 );
299
300
301 add_filter( 'wordpress_prepare_output', 'easyfont_run_after_smart_slider', 11 );
302
303 add_filter('groovy_menu_final_output', 'easyfont_run_after_smart_slider', 11);
304
305 function easyfont_run_after_smart_slider( $buffer ) {
306 if (get_option('easyfonts_host_google_fonts_locally_link', false)) {
307 $buffer = easyfont_process_content_link_tag( $buffer );
308 }
309 return $buffer;
310 }
311
312 function easyfonts_enqueue_options_styles() {
313 if ( 'settings_page_easyfonts' == get_current_screen()->id ) {
314 wp_enqueue_style( 'easyfonts-options-styles', plugin_dir_url( __FILE__ ) . 'assets/style.css', array(), '1.0.0' );
315 }
316 }
317 add_action( 'admin_enqueue_scripts', 'easyfonts_enqueue_options_styles' );
318
319 function easyfonts_settings_link($links) {
320 $settings_link = '<a href="options-general.php?page=easyfonts">Settings</a>';
321 array_push($links, $settings_link);
322 return $links;
323 }
324 add_filter("plugin_action_links_easyfonts/easyfonts.php", "easyfonts_settings_link");