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

298 lines 15.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.0.4
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
24 function easyfont_process_content_link_tag($content) {
25 $html = hgfl_str_get_html($content, false, true, 'UTF-8', false, PHP_EOL, ' ');
26 // Check if the 'easyfonts' directory exists and is writable
27 $easyfonts_dir = wp_upload_dir() ['basedir'] . '/easyfonts';
28 if (!wp_mkdir_p($easyfonts_dir)) {
29 return $content;
30 }
31 // Find all <link> tags with a rel attribute of 'stylesheet' and a href attribute that points to a Google Fonts stylesheet
32 foreach ($html->find('link[rel=stylesheet][href*=fonts.googleapis.com]') as $link) {
33 $url = $link->href;
34 if(strpos($url,'//') === 0){
35 $url = 'https:'.$url;
36 }
37 $decoded_url = urldecode(htmlspecialchars_decode($url));
38 // Generate a local filename for the stylesheet
39 $filename = hash('sha256', $decoded_url, false);
40 $filename = substr($filename, 0, 10) . '.css';
41 if (!file_exists($easyfonts_dir . '/' . $filename)) {
42 $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',));
43 if (is_wp_error($response)) {
44 add_settings_error('easyfont_process_content_link_tag', 'http_error', $response->get_error_message(), 'error');
45 return $content;
46 }
47 $css = wp_remote_retrieve_body($response);
48 if (!preg_match_all('/@font-face\s*\{([^}]+)\}/', $css, $matches)) continue;
49
50 if (preg_match_all('/@font-face\s*\{([^}]+)\}/', $css, $matches)) {
51 foreach ($matches[1] as $match) {
52 if (preg_match_all('/src\s*:\s*([^;]+);/', $match, $srcs)) {
53 foreach ($srcs[1] as $src) {
54 if (preg_match('/url\(([^)]+)\)/', $src, $url_match)) {
55 $font_url = trim($url_match[1], "'\"");
56 $font_filename = hash('sha256', $font_url, false);
57 $font_filename = substr($font_filename, 0, 10) . '.' . pathinfo($font_url, PATHINFO_EXTENSION);
58 if (!file_exists($easyfonts_dir . '/' . $font_filename)) {
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('easyfont_process_content_link_tag', 'http_error', $font_response->get_error_message(), 'error');
62 continue;
63 }
64 $font_data = wp_remote_retrieve_body($font_response);
65 // Save the font file to the 'wp-content/uploads/easyfonts' directory
66 file_put_contents($easyfonts_dir . '/' . $font_filename, $font_data);
67 }
68 // Replace the src property with a local reference to the downloaded font file
69 if (is_ssl()) {
70 $base_url = set_url_scheme(wp_upload_dir()['baseurl'], 'https');
71 } else {
72 $base_url = wp_upload_dir()['baseurl'];
73 }
74 $css = str_replace($src, "url('" . $base_url . "/easyfonts/" . $font_filename . "')", $css);
75 }
76 }
77 }
78 }
79 }
80 // Save the modified stylesheet to the 'wp-content/uploads/easyfonts' directory
81 file_put_contents($easyfonts_dir . '/' . $filename, $css);
82 }
83 // Replace the href attribute with a local reference to the downloaded stylesheet
84 $link->href = wp_upload_dir() ['baseurl'] . '/easyfonts/' . $filename;
85 }
86 // Return the modified content
87 return $html->save();
88 }
89
90 function easyfont_process_content_import($content) {
91
92 $html = hgfl_str_get_html($content, false, true, 'UTF-8', false, PHP_EOL, ' ');
93 // Check if the 'easyfonts' directory exists and is writable
94 $easyfonts_dir = wp_upload_dir() ['basedir'] . '/easyfonts';
95 if (!wp_mkdir_p($easyfonts_dir)) {
96 return $content;
97 }
98 // Find all <style> tags with @import statements that import a Google Fonts stylesheet
99 foreach ($html->find('style') as $style) {
100 if (preg_match_all('/@import\s+(url\()?\s*([^\);]+)\s*(\))?/', $style->innertext, $matches)) {
101 foreach ($matches[2] as $match) {
102 if (strpos($match, 'fonts.googleapis.com') !== false) {
103 $url = trim($match, "'\"");
104 if (strpos($url, '//') === 0) {
105 $url = 'https:' . $url;
106 }
107 $decoded_url = urldecode(htmlspecialchars_decode($url));
108 $filename = hash('sha256', $decoded_url, false);
109 $filename = substr($filename, 0, 10) . '.css';
110 // Check if the stylesheet file already exists
111 if (!file_exists($easyfonts_dir . '/' . $filename)) {
112 $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',));
113 if (is_wp_error($response)) {
114 add_settings_error('easyfont_process_content_import', 'http_error', $response->get_error_message(), 'error');
115 return $content;
116 }
117 $css = wp_remote_retrieve_body($response);
118 if (preg_match_all('/@font-face\s*\{([^}]+)\}/', $css, $matches)) {
119 foreach ($matches[1] as $match) {
120 if (preg_match_all('/src\s*:\s*([^;]+);/', $match, $srcs)) {
121 foreach ($srcs[1] as $src) {
122 if (preg_match('/url\(([^)]+)\)/', $src, $url_match)) {
123 $font_url = trim($url_match[1], "'\"");
124 $font_filename = hash('sha256', $font_url, false);
125 $font_filename = substr($font_filename, 0, 10) . '.' . pathinfo($font_url, PATHINFO_EXTENSION);
126 // Check if the font file already exists
127 if (!file_exists($easyfonts_dir . '/' . $font_filename)) {
128
129 $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',));
130 if (is_wp_error($font_response)) {
131 add_settings_error('easyfont_process_content_import', 'http_error', $font_response->get_error_message(), 'error');
132 continue;
133 }
134 $font_data = wp_remote_retrieve_body($font_response);
135 $file = fopen($easyfonts_dir . '/' . $font_filename, 'w');
136 fwrite($file, $font_data);
137 fclose($file);
138 }
139 if (is_ssl()) {
140 $base_url = set_url_scheme(wp_upload_dir()['baseurl'], 'https');
141 } else {
142 $base_url = wp_upload_dir()['baseurl'];
143 }
144 $css = str_replace($src, "url('" . $base_url . "/easyfonts/" . $font_filename . "')", $css);
145 }
146 }
147 }
148 }
149 }
150 // Save the modified stylesheet to the 'wp-content/uploads/easyfonts' directory
151 file_put_contents($easyfonts_dir . '/' . $filename, $css);
152 }
153 // Replace the @import statement with a local reference to the downloaded stylesheet
154 $style->innertext = str_replace($match, "" . wp_upload_dir() ['baseurl'] . '/easyfonts/' . $filename . "", $style->innertext);
155 }
156 }
157 }
158 }
159 // Return the modified content
160 return $html->save();
161 }
162 function easyfonts_remove_resource_hints($html) {
163 // Load the HTML into the Simple HTML DOM library
164 $dom = hgfl_str_get_html($html, false, true, 'UTF-8', false, PHP_EOL, ' ');
165
166 // Find all <link> elements with the preload, preconnect, or prefetch attributes
167 $links = $dom->find('link[rel=preload],link[rel=preconnect],link[rel=dns-prefetch]');
168
169 // Loop through the <link> elements
170 foreach($links as $link) {
171 // Check if the <link> element has a href attribute with the fonts.googleapis.com or fonts.gstatic.com domain
172 if (preg_match('/(https:\/\/|\/\/)(fonts\.googleapis\.com|fonts\.gstatic\.com)/', $link->href)) {
173 // Remove the <link> element
174 $link->outertext = '';
175 }
176 }
177
178 // Find all <style> elements
179 $styles = $dom->find('style');
180
181 // Loop through the <style> elements
182 foreach($styles as $style) {
183 // Remove comments that contain the fonts.googleapis.com or fonts.gstatic.com domain
184 if (strpos($style->innertext, 'fonts.googleapis.com') !== false || strpos($style->innertext, 'fonts.gstatic.com') !== false) {
185 $style->innertext = preg_replace('#/\*(?:[^*]*(?:\*(?!/))*)*\*/#','',$style->innertext);
186 }
187 }
188 // Return the modified HTML
189 return $dom->save();
190 }
191
192
193 function easyfont_remove_font_scripts($html) {
194 // Load the HTML string into a Simple HTML DOM object
195 $dom = hgfl_str_get_html($html, false, true, 'UTF-8', false, PHP_EOL, ' ');
196
197 // Find all `script` elements
198 $scripts = $dom->find('script');
199 foreach($scripts as $script) {
200 // Check if the `script` element contains the `WebFontConfig` or `webfont.js` strings
201 if(strpos($script->innertext, 'WebFontConfig') !== false || strpos($script->innertext, 'webfont.js') !== false) {
202 // Remove the `script` element
203 $script->outertext = '';
204 }
205 }
206
207 // Return the modified HTML as a string
208 return $dom->save();
209 }
210
211 function easyfont_download_gstatic_fonts($content) {
212 // Create the "easyfonts" directory if it doesn't exist
213 $easyfonts_dir = wp_upload_dir()['basedir'] . '/easyfonts';
214 if (!wp_mkdir_p($easyfonts_dir)) {
215 return $content;
216 }
217 $content = preg_replace('/(url\s?\(["\']?)\/\/(fonts\.gstatic\.com[^"\']+)/', '$1https://$2', $content);
218 $html = hgfl_str_get_html($content, false, true, 'UTF-8', false, PHP_EOL, ' ');
219 foreach ($html->find('style') as $style) {
220 if (preg_match_all('/url\(([^)]+)\)/', $style->innertext, $matches)) {
221 foreach ($matches[1] as $match) {
222 $url = trim($match, "'\"");
223 if(strpos($url,'//') === 0){
224 $url = 'https:'.$url;
225 }
226 if (strpos($url, 'fonts.gstatic.com') !== false) {
227 $path_parts = pathinfo($url);
228 $extension = isset($path_parts['extension'])?$path_parts['extension']:'';
229 if (empty($extension)) {
230 if(strpos($url,'/l/font') !== false){
231 $extension = 'svg';
232 }else{
233 $extension = 'woff2';
234 }
235 }
236 $filename = hash('sha256', $url, false);
237 $filename = substr($filename, 0, 10) . '.' . $extension;
238 // Check if the font file already exists
239 if (!file_exists($easyfonts_dir . '/' . $filename)) {
240 $response = wp_remote_get($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',));
241 if (is_wp_error($response)) {
242 add_settings_error('download_gstatic_fonts', 'http_error', $response->get_error_message(), 'error');
243 return $content;
244 }
245 $font_data = wp_remote_retrieve_body($response);
246 $file = fopen($easyfonts_dir . '/' . $filename, 'w');
247 fwrite($file, $font_data);
248 fclose($file);
249 }
250 $local_url = wp_upload_dir()['baseurl'] . '/easyfonts/' . $filename;
251 $content = str_replace($url, $local_url, $content);
252 }
253 }
254 }
255 }
256 return $content;
257 }
258
259
260 function easy_fonts_run_template_redirect() {
261
262 if (get_option('easyfonts_host_google_fonts_locally_link', false)) {
263 ob_start( 'easyfont_process_content_link_tag',0, PHP_OUTPUT_HANDLER_REMOVABLE );
264 }
265 if (get_option('easyfonts_host_google_fonts_locally_import', false)) {
266 ob_start( 'easyfont_process_content_import',0, PHP_OUTPUT_HANDLER_REMOVABLE );
267 }
268
269 if (get_option('easyfonts_remove_inline_css_fontface', false)) {
270 ob_start( 'easyfont_download_gstatic_fonts',0, PHP_OUTPUT_HANDLER_REMOVABLE );
271 }
272
273 if (get_option('easyfonts_remove_resource_hints', false)) {
274 ob_start( 'easyfonts_remove_resource_hints',0, PHP_OUTPUT_HANDLER_REMOVABLE );
275 }
276
277 if (get_option('easyfonts_remove_inline_script_font', false)) {
278 ob_start( 'easyfont_remove_font_scripts',0, PHP_OUTPUT_HANDLER_REMOVABLE );
279 }
280 //ob_start( 'download_gstatic_fonts',0, PHP_OUTPUT_HANDLER_REMOVABLE );
281
282
283 }
284 add_action( 'template_redirect', 'easy_fonts_run_template_redirect', 999 );
285
286 function easyfonts_enqueue_options_styles() {
287 if ( 'settings_page_easyfonts' == get_current_screen()->id ) {
288 wp_enqueue_style( 'easyfonts-options-styles', plugin_dir_url( __FILE__ ) . 'assets/style.css', array(), '1.0.0' );
289 }
290 }
291 add_action( 'admin_enqueue_scripts', 'easyfonts_enqueue_options_styles' );
292
293 function easyfonts_settings_link($links) {
294 $settings_link = '<a href="options-general.php?page=easyfonts">Settings</a>';
295 array_push($links, $settings_link);
296 return $links;
297 }
298 add_filter("plugin_action_links_easyfonts/easyfonts.php", "easyfonts_settings_link");