PluginProbe
EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant / 1.1.1
EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant v1.1.1
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.1, at easyfonts.php

342 lines 14.3 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.1
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_html_with_dom($content, $callback) {
69 // using simple html dom
70 $html = hgfl_str_get_html($content, false, true, 'UTF-8', false, PHP_EOL, ' ');
71
72 if (empty($html)) {
73 return $content;
74 }
75
76 $callback($html);
77
78 $content = $html->save();
79 return $content;
80 }
81
82 function easyfont_process_content_link_tag($content) {
83 return easyfont_process_html_with_dom($content, function($html) {
84 // Check if the 'easyfonts' directory exists and is writable
85 $easyfonts_dir = wp_upload_dir() ['basedir'] . '/easyfonts';
86 if (!wp_mkdir_p($easyfonts_dir)) {
87 return $content;
88 }
89 // Find all <link> tags with a rel attribute of 'stylesheet' and a href attribute that points to a Google Fonts stylesheet
90 foreach ($html->find('link[rel=stylesheet][href*=fonts.googleapis.com]') as $link) {
91 $url = $link->href;
92 if(strpos($url,'//') === 0){
93 $url = 'https:'.$url;
94 }
95 $decoded_url = rawurldecode(htmlspecialchars_decode($url));
96 // Generate a local filename for the stylesheet
97 $filename = hash('sha256', $decoded_url, false);
98 $filename = substr($filename, 0, 10) . '.css';
99 if (!file_exists($easyfonts_dir . '/' . $filename)) {
100 $css = wp_get_remote_css($decoded_url);
101 if (!preg_match_all('/@font-face\s*\{([^}]+)\}/', $css, $matches)) continue;
102
103 if (preg_match_all('/@font-face\s*\{([^}]+)\}/', $css, $matches)) {
104 foreach ($matches[1] as $match) {
105 if (preg_match_all('/src\s*:\s*([^;]+);/', $match, $srcs)) {
106 foreach ($srcs[1] as $src) {
107 if (preg_match('/url\(([^)]+)\)/', $src, $url_match)) {
108 $font_url = trim($url_match[1], "'\"");
109 $font_filename = hash('sha256', $font_url, false);
110 $font_filename = substr($font_filename, 0, 10) . '.' . pathinfo($font_url, PATHINFO_EXTENSION);
111 if (!file_exists($easyfonts_dir . '/' . $font_filename)) {
112 $font_data = wp_get_remote_font($font_url);
113 // Save the font file to the 'wp-content/uploads/easyfonts' directory
114 file_put_contents($easyfonts_dir . '/' . $font_filename, $font_data);
115 }
116 // Replace the src property with a local reference to the downloaded font file
117 $finalbase = get_base_url();
118 $css = str_replace($src, "url('" . $finalbase . "/easyfonts/" . $font_filename . "')", $css);
119 }
120 }
121 }
122 }
123 }
124 // Save the modified stylesheet to the 'wp-content/uploads/easyfonts' directory
125 file_put_contents($easyfonts_dir . '/' . $filename, $css);
126 }
127 $finalbasecss = get_basecss_url();
128 // Replace the href attribute with a local reference to the downloaded stylesheet
129 $link->href = $finalbasecss . '/easyfonts/' . $filename;
130 }
131 // Return the modified content
132 });
133 }
134
135 function easyfont_process_content_import($content) {
136 // using simple html dom
137 return easyfont_process_html_with_dom($content, function($html) {
138 // Check if the 'easyfonts' directory exists and is writable
139 $easyfonts_dir = wp_upload_dir() ['basedir'] . '/easyfonts';
140 if (!wp_mkdir_p($easyfonts_dir)) {
141 return $content;
142 }
143 // Find all <style> tags with @import statements that import a Google Fonts stylesheet
144 foreach ($html->find('style') as $style) {
145 if (preg_match_all('/@import\s+(url\()?\s*([^\)]+)\s*(\))?/', $style->innertext, $matches)) {
146 foreach ($matches[2] as $match) {
147 if (strpos($match, 'fonts.googleapis.com') !== false) {
148 $url = trim($match, "'\"");
149 if (strpos($url, '//') === 0) {
150 $url = 'https:' . $url;
151 }
152 $decoded_url = rawurldecode(htmlspecialchars_decode($url));
153 $filename = hash('sha256', $decoded_url, false);
154 $filename = substr($filename, 0, 10) . '.css';
155 // Check if the stylesheet file already exists
156 if (!file_exists($easyfonts_dir . '/' . $filename)) {
157 $css = wp_get_remote_css($decoded_url);
158 if (preg_match_all('/@font-face\s*\{([^}]+)\}/', $css, $matches)) {
159 foreach ($matches[1] as $match) {
160 if (preg_match_all('/src\s*:\s*([^;]+);/', $match, $srcs)) {
161 foreach ($srcs[1] as $src) {
162 if (preg_match('/url\(([^)]+)\)/', $src, $url_match)) {
163 $font_url = trim($url_match[1], "'\"");
164 $font_filename = hash('sha256', $font_url, false);
165 $font_filename = substr($font_filename, 0, 10) . '.' . pathinfo($font_url, PATHINFO_EXTENSION);
166 // Check if the font file already exists
167 if (!file_exists($easyfonts_dir . '/' . $font_filename)) {
168
169 $font_data = wp_get_remote_font($font_url);
170 $file = fopen($easyfonts_dir . '/' . $font_filename, 'w');
171 fwrite($file, $font_data);
172 fclose($file);
173 }
174 $finalbase = get_base_url();
175 $css = str_replace($src, "url('" . $finalbase . "/easyfonts/" . $font_filename . "')", $css);
176 }
177 }
178 }
179 }
180 }
181 // Save the modified stylesheet to the 'wp-content/uploads/easyfonts' directory
182 file_put_contents($easyfonts_dir . '/' . $filename, $css);
183 }
184 $finalbasecss = get_basecss_url();
185 // Replace the @import statement with a local reference to the downloaded stylesheet
186 $style->innertext = str_replace($match, "" . $finalbasecss . '/easyfonts/' . $filename . "", $style->innertext);
187 }
188 }
189 }
190 }
191 // Return the modified content
192 });
193 }
194 function easyfonts_remove_resource_hints($content) {
195 // Load the HTML into the Simple HTML DOM library
196 return easyfont_process_html_with_dom($content, function($html) {
197
198 // Find all <link> elements with the preload, preconnect, or prefetch attributes
199 $links = $html->find('link[rel=preload],link[rel=preconnect],link[rel=dns-prefetch]');
200
201 // Loop through the <link> elements
202 foreach($links as $link) {
203 // Check if the <link> element has a href attribute with the fonts.googleapis.com or fonts.gstatic.com domain
204 if (preg_match('/(https:\/\/|\/\/)(fonts\.googleapis\.com|fonts\.gstatic\.com)/', $link->href)) {
205 // Remove the <link> element
206 $link->outertext = '';
207 }
208 }
209
210 // Find all <style> elements
211 $styles = $html->find('style');
212
213 // Loop through the <style> elements
214 foreach($styles as $style) {
215 // Remove comments that contain the fonts.googleapis.com or fonts.gstatic.com domain
216 if (strpos($style->innertext, 'fonts.googleapis.com') !== false || strpos($style->innertext, 'fonts.gstatic.com') !== false) {
217 $style->innertext = preg_replace('#/\*(?:[^*]*(?:\*(?!/))*)*\*/#','',$style->innertext);
218 }
219 }
220 // Return the modified HTML
221 });
222 }
223
224
225 function easyfont_remove_font_scripts($content) {
226 // Load the HTML string into a Simple HTML DOM object
227 return easyfont_process_html_with_dom($content, function($html) {
228
229 // Find all `script` elements
230 $scripts = $html->find('script');
231 foreach($scripts as $script) {
232 // Check if the `script` element contains the `WebFontConfig` or `webfont.js` strings
233 if(strpos($script->innertext, 'WebFontConfig') !== false || strpos($script->innertext, 'webfont.js') !== false) {
234 // Remove the `script` element
235 $script->outertext = '';
236 }
237 }
238
239 // Return the modified HTML as a string
240 });
241 }
242
243 function easyfont_download_gstatic_fonts($content) {
244 // Create the "easyfonts" directory if it doesn't exist
245 $easyfonts_dir = wp_upload_dir()['basedir'] . '/easyfonts';
246 if (!wp_mkdir_p($easyfonts_dir)) {
247 return $content;
248 }
249 $content = preg_replace('/(url\s?\(["\']?)\/\/(fonts\.gstatic\.com[^"\']+)/', '$1https://$2', $content);
250 $html = hgfl_str_get_html($content, false, true, 'UTF-8', false, PHP_EOL, ' ');
251 foreach ($html->find('style') as $style) {
252 if (preg_match_all('/url\(([^)]+)\)/', $style->innertext, $matches)) {
253 foreach ($matches[1] as $match) {
254 $url = trim($match, "'\"");
255 if(strpos($url,'//') === 0){
256 $url = 'https:'.$url;
257 }
258 if (strpos($url, 'fonts.gstatic.com') !== false) {
259 $path_parts = pathinfo($url);
260 $extension = isset($path_parts['extension'])?$path_parts['extension']:'';
261 if (empty($extension)) {
262 if(strpos($url,'/l/font') !== false){
263 $extension = 'svg';
264 }else{
265 $extension = 'woff2';
266 }
267 }
268 $filename = hash('sha256', $url, false);
269 $filename = substr($filename, 0, 10) . '.' . $extension;
270 // Check if the font file already exists
271 if (!file_exists($easyfonts_dir . '/' . $filename)) {
272 $font_data = wp_get_remote_font($url);
273 $file = fopen($easyfonts_dir . '/' . $filename, 'w');
274 fwrite($file, $font_data);
275 fclose($file);
276 }
277 $finalbase = get_base_url();
278 $local_url = $finalbase . '/easyfonts/' . $filename;
279 $content = str_replace($url, $local_url, $content);
280 }
281 }
282 }
283 }
284 return $content;
285 }
286
287
288 function easy_fonts_combined_callback($buffer) {
289 if (get_option('easyfonts_host_google_fonts_locally_link', false)) {
290 $buffer = easyfont_process_content_link_tag($buffer);
291 }
292
293 if (get_option('easyfonts_host_google_fonts_locally_import', false)) {
294 $buffer = easyfont_process_content_import($buffer);
295 }
296
297 if (get_option('easyfonts_remove_inline_css_fontface', false)) {
298 $buffer = easyfont_download_gstatic_fonts($buffer);
299 }
300
301 if (get_option('easyfonts_remove_resource_hints', false)) {
302 $buffer = easyfonts_remove_resource_hints($buffer);
303 }
304
305 if (get_option('easyfonts_remove_inline_script_font', false)) {
306 $buffer = easyfont_remove_font_scripts($buffer);
307 }
308
309 return $buffer;
310 }
311
312 function easy_fonts_run_template_redirect() {
313
314 ob_start('easy_fonts_combined_callback', 0, PHP_OUTPUT_HANDLER_REMOVABLE);
315 add_filter( 'wordpress_prepare_output', 'easyfont_run_after_smart_slider', 11 );
316 add_filter('groovy_menu_final_output', 'easyfont_run_after_smart_slider', 11);
317
318
319 }
320 add_action( 'template_redirect', 'easy_fonts_run_template_redirect', -999 );
321
322
323 function easyfont_run_after_smart_slider( $buffer ) {
324 if (get_option('easyfonts_host_google_fonts_locally_link', false)) {
325 $buffer = easyfont_process_content_link_tag( $buffer );
326 }
327 return $buffer;
328 }
329
330 function easyfonts_enqueue_options_styles() {
331 if ( 'settings_page_easyfonts' == get_current_screen()->id ) {
332 wp_enqueue_style( 'easyfonts-options-styles', plugin_dir_url( __FILE__ ) . 'assets/style.css', array(), '1.0.0' );
333 }
334 }
335 add_action( 'admin_enqueue_scripts', 'easyfonts_enqueue_options_styles' );
336
337 function easyfonts_settings_link($links) {
338 $settings_link = '<a href="options-general.php?page=easyfonts">Settings</a>';
339 array_push($links, $settings_link);
340 return $links;
341 }
342 add_filter("plugin_action_links_easyfonts/easyfonts.php", "easyfonts_settings_link");