Local Google Fonts - Version 0.19

Version Description

Download this release

Release Info

Developer everpress
Plugin Icon 128x128 Local Google Fonts
Version 0.19
Comparing to
See all releases

Code changes from version 0.18 to 0.19

.wordpress-org/banner.png ADDED
Binary file
.wordpress-org/icon.png ADDED
Binary file
.wordpress-org/screenshot-1.png ADDED
Binary file
.wordpress-org/screenshot-2.png ADDED
Binary file
README.md CHANGED
@@ -3,8 +3,8 @@
3
  Contributors: everpress, xaverb
4
  Tags: googlefonts, google, fonts, gdpr, lgf, font, speed
5
  Requires at least: 4.6
6
- Tested up to: 6.0
7
- Stable tag: 0.18
8
  Requires PHP: 5.6+
9
  License: GPLv2 or later
10
  Donate link: https://evp.to/donate
@@ -23,7 +23,7 @@ more on [wptavern.com](https://wptavern.com/german-court-fines-website-owner-for
23
 
24
  ![Option Interface.](.wordpress-org/screenshot-1.png)
25
 
26
- ### 2. Access dev tools in your browser
27
 
28
  ![Dev tools](.wordpress-org/screenshot-2.png)
29
 
@@ -76,6 +76,10 @@ The plugin currently only checks fonts embedded via [`wp_enqueue_style`](https:/
76
 
77
  The Divi theme has a custom implementation of Google Fonts. To use LGF with Divi disable _Improve Google Fonts Loading_ on the Performance Settings page of Divi.
78
 
 
 
 
 
79
  ### How to host Fonts loaded with Slider Revolution?
80
 
81
  Slider Revolution uses it's own way to load Google Fonts and LGF cannot handle them. Slider Revolution has a built in feature for their sliders.
@@ -91,6 +95,17 @@ You may have loaded a subset which doesn't included required characters. Check a
91
 
92
  ## Changelog
93
 
 
 
 
 
 
 
 
 
 
 
 
94
  ### 0.18
95
 
96
  - do not use `remove_query_arg` to strip args as it can break some URLs
3
  Contributors: everpress, xaverb
4
  Tags: googlefonts, google, fonts, gdpr, lgf, font, speed
5
  Requires at least: 4.6
6
+ Tested up to: 6.1
7
+ Stable tag: 0.19
8
  Requires PHP: 5.6+
9
  License: GPLv2 or later
10
  Donate link: https://evp.to/donate
23
 
24
  ![Option Interface.](.wordpress-org/screenshot-1.png)
25
 
26
+ ### 2. Access development tools in your browser
27
 
28
  ![Dev tools](.wordpress-org/screenshot-2.png)
29
 
76
 
77
  The Divi theme has a custom implementation of Google Fonts. To use LGF with Divi disable _Improve Google Fonts Loading_ on the Performance Settings page of Divi.
78
 
79
+ ### Why only the woff2 font format is loaded?
80
+
81
+ Woff2 is the successor of the woff format and and offers a 30% average compression gain over the original format. It is also supported by over 96% of browsers ([source](https://caniuse.com/woff2)).
82
+
83
  ### How to host Fonts loaded with Slider Revolution?
84
 
85
  Slider Revolution uses it's own way to load Google Fonts and LGF cannot handle them. Slider Revolution has a built in feature for their sliders.
95
 
96
  ## Changelog
97
 
98
+ ### 0.19
99
+
100
+ - please reload fonts manually if you encounter problems after the update
101
+ - completely rewriting the way fonts are loaded which to drop the need for a third party API and support more (deprecated) fonts.
102
+ - better support for multi site (thanks @ravanh)
103
+ - the original style sheet is used for better compatibility
104
+ - added Settings link on the plugins list page
105
+ - added button to manually fetch homepage for used fonts
106
+ - only woff2 fonts are now loaded for better subset support
107
+ - removed unused seed variable
108
+
109
  ### 0.18
110
 
111
  - do not use `remove_query_arg` to strip args as it can break some URLs
assets/admin.js CHANGED
@@ -4,16 +4,20 @@ jQuery(document).ready(function ($) {
4
  $('.host-locally').on('click', function () {
5
  $(this).addClass('updating-message');
6
  });
 
 
 
 
 
 
 
7
 
8
  $('.get-support').on('click', function () {
9
- var url = new URL(
10
- 'https://app.codeable.io/affiliate-form/affiliate-form.html'
11
- );
12
  var args = new URLSearchParams();
13
 
14
  args.set('origin', location.origin);
15
  args.set('affiliateUrl', location.href);
16
- args.set('shortcode', 'adTZj');
17
  args.set('TB_iframe', 'true');
18
  args.set('height', 800);
19
  args.set('width', 900);
4
  $('.host-locally').on('click', function () {
5
  $(this).addClass('updating-message');
6
  });
7
+ $('.check').on('click', function () {
8
+ $(this).addClass('updating-message');
9
+ $.get(location.origin, function (response) {
10
+ location.reload();
11
+ });
12
+ return false;
13
+ });
14
 
15
  $('.get-support').on('click', function () {
 
 
 
16
  var args = new URLSearchParams();
17
 
18
  args.set('origin', location.origin);
19
  args.set('affiliateUrl', location.href);
20
+ args.set('shortcode', 'BmTD5');
21
  args.set('TB_iframe', 'true');
22
  args.set('height', 800);
23
  args.set('width', 900);
includes/class-local-google-fonts-admin.php CHANGED
@@ -40,7 +40,7 @@ class LGF_Admin {
40
 
41
  add_settings_section( 'default', '', '', 'local_google_fonts_settings_page' );
42
 
43
- add_settings_field( 'auto_load', __( 'Autoload', 'local-google-fonts' ), array( $this, 'auto_load_cb' ), 'local_google_fonts_settings_page', 'default' );
44
  }
45
 
46
  public function settings_page() {
@@ -102,13 +102,12 @@ class LGF_Admin {
102
 
103
  }
104
 
105
- public function auto_load_cb( $args ) {
106
 
107
  $options = get_option( 'local_google_fonts' );
108
- $checked = isset( $options['auto_load'] );
109
  ?>
110
  <p>
111
- <label><input type="checkbox" value="1" name="local_google_fonts[auto_load]" <?php checked( $checked ); ?>>
112
  <?php esc_html_e( 'Load Fonts automatically', 'local-google-fonts' ); ?>
113
  </label>
114
  </p>
@@ -130,206 +129,14 @@ class LGF_Admin {
130
  }
131
 
132
 
133
- public function get_font_info( $src, $handle = null ) {
134
 
135
- $folder = WP_CONTENT_DIR . '/uploads/fonts';
136
- $folder_url = WP_CONTENT_URL . '/uploads/fonts';
137
 
138
- // remove 'ver' query arg as it is added by WP
139
- $src = preg_replace('/&ver=([^&]+)/', '', $src);
140
 
141
- $id = md5( $src );
142
-
143
- // a bit sanitation as URLs are often registered with esc_url
144
- $src = str_replace( array( '#038;', '&amp;' ), '&', $src );
145
-
146
- $query = wp_parse_url( $src, PHP_URL_QUERY );
147
- wp_parse_str( $query, $args );
148
-
149
- // handling of multiple "family" arguments
150
- $parts = explode( '&', $query );
151
- $groups = array();
152
- foreach ( $parts as $part ) {
153
- if ( 0 === strpos( $part, 'family=' ) ) {
154
- $groups[] = str_replace( 'family=', '', $part );
155
- }
156
- }
157
-
158
- if ( ! empty( $groups ) ) {
159
- $args['family'] = rawurldecode( implode( '|', $groups ) );
160
- }
161
-
162
- $args = wp_parse_args(
163
- $args,
164
- array(
165
- 'subset' => null,
166
- 'display' => 'fallback',
167
- )
168
- );
169
-
170
- $groups = explode( '|', $args['family'] );
171
-
172
- $fontinfo = array();
173
- $families = array();
174
- foreach ( $groups as $i => $group ) {
175
- $parts = explode( ':', $group );
176
- $fam = sanitize_title( str_replace( '+', '-', $parts[0] ) );
177
- if ( ! isset( $families[ $fam ] ) ) {
178
- $families[ $fam ] = array( 'regular' );
179
- }
180
- if ( isset( $parts[1] ) ) {
181
- $variants = $this->normalize_variants( $parts[1] );
182
- $families[ $fam ] = array_unique( array_merge( $families[ $fam ], $variants ) );
183
- }
184
- }
185
-
186
- // do not load them as its most likely some helper font thing
187
- if ( count( $families ) > 30 ) {
188
- return new \WP_Error( 'to_many_families', esc_html__( 'This source contains more than 30 fonts and is most likely used as helper for your theme. Skipped.', 'local-google-fonts' ) );
189
- }
190
-
191
- $buffer = get_option( 'local_google_fonts_buffer', array() );
192
-
193
- foreach ( $families as $family => $variants ) {
194
- $url = 'https://local-google-fonts.herokuapp.com/api/fonts/';
195
- $alias = $this->font_family_alias( $family );
196
- $subsets = isset( $buffer[ $handle ]['subsets'][ $family ] ) ? implode( ',', array_filter( $buffer[ $handle ]['subsets'][ $family ] ) ) : $args['subset'];
197
- $the_url = add_query_arg(
198
- array(
199
- // doesn't seem to have an effect so we filter it later
200
- // 'variants' => implode( ',', $variants ),
201
- 'subsets' => $subsets,
202
- ),
203
- $url . $alias
204
- );
205
-
206
- $transient_key = 'lcg_s' . md5( $the_url );
207
- if ( false === ( $info = get_transient( $transient_key ) ) ) {
208
- $response = wp_remote_get( $the_url );
209
- // break early if there's an error here.
210
- if ( is_wp_error( $response ) ) {
211
- return $response;
212
- }
213
- $code = wp_remote_retrieve_response_code( $response );
214
- if ( 200 === $code ) {
215
- $body = wp_remote_retrieve_body( $response );
216
- $info = json_decode( $body );
217
- set_transient( $transient_key, $info, HOUR_IN_SECONDS );
218
- } elseif ( 503 === $code ) {
219
- return new \WP_Error( 'service_not_available', sprintf( esc_html__( '%s seems to be down right now. Please try again later.', 'local-google-fonts' ), $url ) );
220
- } else {
221
- continue;
222
- }
223
- }
224
-
225
- // if only regular is present we actually need all of them
226
- if ( count( $variants ) > 1 ) {
227
-
228
- foreach ( $info->variants as $i => $variant ) {
229
- // special case for italic 400
230
- if ( 'italic' == $variant->id && in_array( '400italic', $variants ) ) {
231
-
232
- } elseif ( ! in_array( $variant->id, $variants ) ) {
233
- unset( $info->variants[ $i ] );
234
- }
235
- }
236
- }
237
-
238
- // fonts with render bug /https://github.com/everpress-co/local-google-fonts/issues/1)
239
- if ( in_array( $family, array( 'montserrat', 'jost', 'inter', 'exo-2' ) ) ) {
240
-
241
- foreach ( $info->variants as $i => $variant ) {
242
-
243
- $san_family = str_replace( ' ', '', $info->family );
244
-
245
- $font_name = sprintf(
246
- '%s-%s%s',
247
- $san_family,
248
- $this->weightClass[ $variant->fontWeight ],
249
- ( $variant->fontStyle === 'italic' ? 'Italic' : '' )
250
- );
251
-
252
- // there's no RegularItalic
253
- $font_name = str_replace( $san_family . '-RegularItalic', $san_family . '-Italic', $font_name );
254
- $info->variants[ $i ]->woff2 = 'https://github.com/everpress-co/local-google-fonts-render-bug/raw/main/fonts/' . $family . '/' . $font_name . '.woff2';
255
- }
256
- }
257
-
258
- $filename = $id . '/' . $info->id . '-' . $info->version . '-' . $info->defSubset;
259
- $info->total = count( $info->variants ) * 5;
260
- $info->original = $family;
261
- $info->loaded = 0;
262
-
263
- foreach ( $info->variants as $i => $variant ) {
264
- $file = $filename . '-' . $variant->id;
265
-
266
- $info->variants[ $i ]->loaded = array();
267
- foreach ( array( 'woff', 'svg', 'woff2', 'ttf', 'eot' ) as $ext ) {
268
- if ( file_exists( $folder . '/' . $file . '.' . $ext ) ) {
269
- $info->loaded++;
270
- $info->variants[ $i ]->loaded[ $ext ] = $file . '.' . $ext;
271
- }
272
- }
273
- }
274
-
275
- $info->variants = array_values( $info->variants );
276
- $fontinfo[] = $info;
277
- }
278
-
279
- if ( empty( $fontinfo ) ) {
280
- return new \WP_Error( 'no_fontinfo', esc_html__( 'This font is not supported. Skipped.', 'local-google-fonts' ) );
281
- }
282
-
283
- return $fontinfo;
284
-
285
- }
286
-
287
- private function normalize_variants( $variants ) {
288
- // possibles
289
- // Merriweather:400,700,400italic,700italic
290
- // Open+Sans:wght@400;700
291
- // Open+Sans:ital,wght@0,800;1,800
292
- // Open+Sans:ital,wght@0,400;0,700;1,800
293
- // Google+Sans:300,300i,400,400i,500,500i,700,700i|Roboto:300,300i,400,400i,500,500i,700,700i
294
-
295
- if ( false !== strpos( $variants, '@' ) ) {
296
- $variant_parts = explode( '@', $variants );
297
- $styles = explode( ';', $variant_parts[1] );
298
- $variants = array();
299
- foreach ( $styles as $style ) {
300
- // regular version
301
- if ( 0 === strpos( $style, '0,' ) ) {
302
- $variants[] = substr( $style, 2 );
303
- // italic version
304
- } elseif ( 0 === strpos( $style, '1,' ) ) {
305
- $variants[] = substr( $style, 2 ) . 'italic';
306
- } else {
307
- $variants[] = $style;
308
- }
309
- }
310
- } else {
311
- // handle XXXi variants
312
- $variants = preg_replace( '/(\d{3}+)i/', '$1italic', $variants );
313
- // handle XXXitalic is converted into XXXitalictalic
314
- $variants = str_replace( 'italictalic', 'italic', $variants );
315
- $variants = explode( ',', $variants );
316
- }
317
-
318
- return $variants;
319
-
320
- }
321
-
322
- private function font_family_alias( $name ) {
323
-
324
- $alias = array(
325
- 'droid-sans' => 'noto-sans',
326
- );
327
-
328
- if ( isset( $alias[ $name ] ) ) {
329
- return $alias[ $name ];
330
- }
331
-
332
- return $name;
333
 
334
  }
335
 
40
 
41
  add_settings_section( 'default', '', '', 'local_google_fonts_settings_page' );
42
 
43
+ add_settings_field( 'settings', __( 'Options', 'local-google-fonts' ), array( $this, 'settings' ), 'local_google_fonts_settings_page', 'default' );
44
  }
45
 
46
  public function settings_page() {
102
 
103
  }
104
 
105
+ public function settings( $args ) {
106
 
107
  $options = get_option( 'local_google_fonts' );
 
108
  ?>
109
  <p>
110
+ <label><input type="checkbox" value="1" name="local_google_fonts[auto_load]" <?php checked( isset( $options['auto_load'] ) ); ?>>
111
  <?php esc_html_e( 'Load Fonts automatically', 'local-google-fonts' ); ?>
112
  </label>
113
  </p>
129
  }
130
 
131
 
132
+ public function get_parser( $src ) {
133
 
134
+ include_once dirname( LGF_PLUGIN_FILE ) . '/includes/class-local-google-fonts-parser.php';
 
135
 
136
+ $parser = new LGF_Parser( $src );
137
+ $parser->parse();
138
 
139
+ return $parser;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
  }
142
 
includes/class-local-google-fonts-parser.php ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ Thanks to https://github.com/WPTT/webfont-loader for parsing help
5
+ */
6
+
7
+ namespace EverPress;
8
+
9
+ class LGF_Parser {
10
+
11
+ private $src;
12
+ private $id;
13
+ private $styles;
14
+ private $remote_styles;
15
+ private $info;
16
+ private $format;
17
+
18
+
19
+ public function __construct( $src, $format = 'woff2' ) {
20
+
21
+ $this->set_src( $src );
22
+ $this->set_format( $format );
23
+
24
+ }
25
+
26
+ public function parse() {
27
+
28
+ $result = array();
29
+ $this->remote_styles = '';
30
+ $this->styles = '';
31
+ $upload_dir = wp_get_upload_dir();
32
+ $folder = $upload_dir['error'] ? WP_CONTENT_DIR . '/uploads/fonts' : $upload_dir['basedir'] . '/fonts';
33
+ $folder_url = $upload_dir['error'] ? WP_CONTENT_URL . '/uploads/fonts' : $upload_dir['baseurl'] . '/fonts';
34
+
35
+ foreach ( $this->format as $format ) {
36
+ $remote_styles = $this->get_remote_styleheet( $format );
37
+ if ( is_wp_error( $remote_styles ) ) {
38
+ continue;
39
+ }
40
+
41
+ $font_faces = explode( '@font-face', $remote_styles );
42
+
43
+ $styles = $remote_styles;
44
+
45
+ // Loop all our font-face declarations.
46
+ foreach ( $font_faces as $font_face ) {
47
+
48
+ // Make sure we only process styles inside this declaration.
49
+ $style = explode( '}', $font_face )[0];
50
+
51
+ // Sanity check.
52
+ if ( false === strpos( $style, 'font-family' ) ) {
53
+ continue;
54
+ }
55
+
56
+ // Get an array of our font-families.
57
+ preg_match_all( '/font-family.*?\;/', $style, $matched_font_families );
58
+
59
+ // Get an array of our font-files.
60
+ preg_match_all( '/url\(.*?\)/i', $style, $matched_font_files );
61
+
62
+ // Get an array of our font-families.
63
+ preg_match_all( '/font-style.*?\;/', $style, $matched_font_styles );
64
+
65
+ // Get an array of our font-families.
66
+ preg_match_all( '/font-weight.*?\;/', $style, $matched_font_weights );
67
+
68
+ // Get an array of our font-families.
69
+ preg_match_all( '/unicode-range.*?\;/', $style, $matched_unicode_ranges );
70
+
71
+ // Get the font-family name.
72
+ $font_family = 'unknown';
73
+ $sanitized = 'unknown';
74
+ if ( isset( $matched_font_families[0] ) && isset( $matched_font_families[0][0] ) ) {
75
+ $font_family = rtrim( ltrim( $matched_font_families[0][0], 'font-family:' ), ';' );
76
+ $font_family = trim( str_replace( array( "'", ';' ), '', $font_family ) );
77
+ $sanitized = sanitize_key( strtolower( str_replace( ' ', '-', $font_family ) ) );
78
+ }
79
+
80
+ // Make sure the font-family is set in our array.
81
+ if ( ! isset( $result[ $sanitized ] ) ) {
82
+ $result[ $sanitized ] = array(
83
+ 'name' => $font_family,
84
+ 'stylesheet' => $folder_url . '/' . $this->id . '/font.css',
85
+ 'variants' => array(),
86
+ 'total' => 0,
87
+ 'loaded' => 0,
88
+ 'filesize' => 0,
89
+ 'faces' => array(),
90
+ );
91
+ }
92
+
93
+ // Get files for this font-family and add them to the array.
94
+ foreach ( $matched_font_files as $i => $match ) {
95
+
96
+ // Sanity check.
97
+ if ( ! isset( $match[0] ) ) {
98
+ continue;
99
+ }
100
+
101
+ // Add the file URL.
102
+ $remote_url = rtrim( ltrim( $match[0], 'url(' ), ')' );
103
+
104
+ // Make sure to convert relative URLs to absolute.
105
+ $remote_url = $this->get_absolute_path( $remote_url );
106
+
107
+ $version = '';
108
+ if ( preg_match( '/v(\d+)/', $remote_url, $m ) ) {
109
+ $version = 'v' . $m[1];
110
+ }
111
+
112
+ $font_style = null;
113
+ if ( isset( $matched_font_styles[ $i ][0] ) ) {
114
+ $font_style = rtrim( ltrim( $matched_font_styles[ $i ][0], 'font-style:' ), ';' );
115
+ $font_style = trim( str_replace( array( "'", ';' ), '', $font_style ) );
116
+ }
117
+
118
+ $font_weight = null;
119
+ if ( isset( $matched_font_weights[ $i ][0] ) ) {
120
+ $font_weight = rtrim( ltrim( $matched_font_weights[ $i ][0], 'font-weight:' ), ';' );
121
+ $font_weight = trim( str_replace( array( "'", ';' ), '', $font_weight ) );
122
+ }
123
+
124
+ $unicode_range = null;
125
+ if ( isset( $matched_unicode_ranges[ $i ][0] ) ) {
126
+ $unicode_range = rtrim( ltrim( $matched_unicode_ranges[ $i ][0], 'unicode-range:' ), ';' );
127
+ $unicode_range = trim( str_replace( array( "'", ';' ), '', $unicode_range ) );
128
+ }
129
+
130
+ $subset = $this->get_subset_by_range( $unicode_range );
131
+ $filename = $folder . '/' . $this->id . '/' . sprintf( '%s-%s-%s-%s-%s.%s', $sanitized, $subset, $version, $font_style, $font_weight, $format );
132
+
133
+ $result[ $sanitized ]['variants'][] = sprintf( '%s %s', $font_style, $font_weight );
134
+
135
+ $loaded = file_exists( $filename );
136
+
137
+ $result[ $sanitized ]['total']++;
138
+ $filesize = null;
139
+ if ( $loaded ) {
140
+ $result[ $sanitized ]['loaded']++;
141
+ $loaded = filemtime( $filename );
142
+ $filesize = filesize( $filename );
143
+ $result[ $sanitized ]['filesize'] += $filesize;
144
+ }
145
+ $local_url = $folder_url . '/' . $this->id . '/' . basename( $filename );
146
+
147
+ $styles = str_replace( $remote_url, $local_url, $styles );
148
+
149
+ $result[ $sanitized ]['faces'][] = array(
150
+ 'remote_url' => $remote_url,
151
+ 'local_url' => $local_url,
152
+ 'file' => $filename,
153
+ 'filesize' => $filesize,
154
+ 'loaded' => $loaded,
155
+ 'version' => $version,
156
+ 'format' => $format,
157
+ 'style' => $font_style,
158
+ 'weight' => $font_weight,
159
+ 'range' => $unicode_range,
160
+ 'subset' => $subset,
161
+ );
162
+ }
163
+
164
+ // faster array_unique
165
+ $result[ $sanitized ]['variants'] = array_keys( array_flip( $result[ $sanitized ]['variants'] ) );
166
+
167
+ }
168
+
169
+ $this->remote_styles .= $remote_styles;
170
+ $this->styles .= $styles;
171
+ }
172
+
173
+ $this->info = $result;
174
+
175
+ }
176
+
177
+ public function get_remote_styles() {
178
+
179
+ return $this->remote_styles;
180
+
181
+ }
182
+
183
+ public function get_styles() {
184
+
185
+ return $this->styles;
186
+
187
+ }
188
+
189
+ public function get_info() {
190
+
191
+ return $this->info;
192
+
193
+ }
194
+
195
+ public function set_src( $src ) {
196
+ $this->id = md5( $src );
197
+ if ( 0 === stripos( $src, '//' ) ) {
198
+ $parsed_url = wp_parse_url( home_url() );
199
+ $src = $parsed_url['scheme'] . ':' . $src;
200
+ }
201
+ $this->src = $src;
202
+ }
203
+
204
+ public function get_src() {
205
+
206
+ return $this->src;
207
+
208
+ }
209
+
210
+ public function set_format( $format ) {
211
+
212
+ $this->format = (array) $format;
213
+
214
+ }
215
+
216
+ public function get_format() {
217
+
218
+ return $this->format;
219
+
220
+ }
221
+
222
+ private function get_absolute_path( $url ) {
223
+
224
+ if ( 0 === stripos( $url, '//' ) ) {
225
+ $parsed_url = wp_parse_url( $this->src );
226
+ return $parsed_url['scheme'] . ':' . $url;
227
+ } elseif ( 0 === stripos( $url, '/' ) ) {
228
+ $parsed_url = wp_parse_url( $this->src );
229
+ return $parsed_url['scheme'] . '://' . $parsed_url['hostname'] . $url;
230
+ }
231
+
232
+ return $url;
233
+ }
234
+
235
+ private function get_remote_styleheet( $format = 'woff2' ) {
236
+
237
+ $response = $this->get_remote( $this->src, array( 'user-agent' => $this->get_user_agent_by_format( $format ) ) );
238
+ if ( is_wp_error( $response ) ) {
239
+ return $response;
240
+ }
241
+
242
+ return wp_remote_retrieve_body( $response );
243
+
244
+ }
245
+
246
+ private function get_remote( $url, $args = array() ) {
247
+
248
+ $transient_key = 'lcg_req_' . md5( $url . serialize( $args ) );
249
+ if ( false === ( $response = get_transient( $transient_key ) ) ) {
250
+ $response = wp_remote_get( $url, $args );
251
+
252
+ if ( is_wp_error( $response ) ) {
253
+ return $response;
254
+ }
255
+ $code = wp_remote_retrieve_response_code( $response );
256
+ if ( 200 === $code ) {
257
+ set_transient( $transient_key, $response, DAY_IN_SECONDS );
258
+ } else {
259
+ return new \WP_Error( 'service_not_available', sprintf( esc_html__( '%s seems to be down right now. Please try again later.', 'local-google-fonts' ), $this->src ) );
260
+ }
261
+ }
262
+ return $response;
263
+
264
+ }
265
+
266
+ private function get_user_agent_by_format( $format ) {
267
+
268
+ $user_agents = array(
269
+ 'eot' => 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)',
270
+ 'ttf' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1',
271
+ 'svg' => 'Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10gin_lib.cc',
272
+ 'woff' => 'Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25',
273
+ 'woff2' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36',
274
+ );
275
+
276
+ if ( isset( $user_agents[ $format ] ) ) {
277
+ return $user_agents[ $format ];
278
+ }
279
+
280
+ return null;
281
+ }
282
+
283
+
284
+ private function get_subset_by_range( $unicode_range ) {
285
+
286
+ $ranges = array(
287
+ 'cyrillic-ext' => 'U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F',
288
+ 'cyrillic' => 'U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116',
289
+ 'greek-ext' => 'U+1F00-1FFF',
290
+ 'greek' => 'U+0370-03FF',
291
+ 'hebrew' => 'U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F',
292
+ 'vietnamese' => 'U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB',
293
+ 'latin-ext' => 'U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF',
294
+ 'latin' => 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD',
295
+ );
296
+
297
+ if ( $pos = array_search( $unicode_range, $ranges ) ) {
298
+ return $pos;
299
+ }
300
+
301
+ return null;
302
+ }
303
+
304
+ }
includes/class-local-google-fonts.php CHANGED
@@ -6,7 +6,6 @@ class LGF {
6
 
7
  private static $instance = null;
8
 
9
- private $seed = AUTH_SALT;
10
  private $upload_dir;
11
 
12
  private function __construct() {
@@ -23,6 +22,8 @@ class LGF {
23
 
24
  add_action( 'admin_notices', array( $this, 'maybe_welcome_message' ) );
25
 
 
 
26
  }
27
 
28
  public static function get_instance() {
@@ -55,7 +56,7 @@ class LGF {
55
  public function process_url( $src, $handle ) {
56
 
57
  // remove 'ver' query arg as it is added by WP
58
- $src = preg_replace('/&ver=([^&]+)/', '', $src);
59
 
60
  $id = md5( $src );
61
 
@@ -77,6 +78,7 @@ class LGF {
77
  $style .= ' * ' . sprintf( 'Font file created by %s %s', $plugin_data['Name'], $plugin_data['Version'] ) . "\n";
78
  $style .= ' * Created: ' . date( 'r' ) . "\n";
79
  $style .= ' * Handle: ' . esc_attr( $handle ) . "\n";
 
80
  $style .= "*/\n\n";
81
 
82
  $query = wp_parse_url( $src, PHP_URL_QUERY );
@@ -89,69 +91,43 @@ class LGF {
89
  )
90
  );
91
 
92
- $folder = WP_CONTENT_DIR . '/uploads/fonts';
93
- $folder_url = WP_CONTENT_URL . '/uploads/fonts';
 
94
 
95
  $new_src = $folder_url . '/' . $id . '/font.css';
96
  $new_dir = $folder . '/' . $id . '/font.css';
97
 
98
- $class = LGF_Admin::get_instance();
99
- $fontinfo = $class->get_font_info( $src, $handle );
 
 
 
100
 
101
- if ( is_wp_error( $fontinfo ) ) {
102
  return $src;
103
  }
104
 
105
- foreach ( $fontinfo as $font ) {
106
- $filename = $font->id . '-' . $font->version . '-' . $font->defSubset;
107
- foreach ( $font->variants as $v ) {
108
 
109
- $file = $filename . '-' . $v->id;
110
- if ( ! is_dir( $folder . '/' . $id ) ) {
111
- wp_mkdir_p( $folder . '/' . $id );
112
- }
113
- foreach ( array( 'woff', 'svg', 'woff2', 'ttf', 'eot' ) as $ext ) {
114
-
115
- if ( $v->{$ext} ) {
116
- $tmp_file = download_url( $v->{$ext} );
117
- if ( ! is_wp_error( $tmp_file ) ) {
118
- $filepath = $folder . '/' . $id . '/' . $file . '.' . $ext;
119
- $WP_Filesystem->copy( $tmp_file, $filepath );
120
- $WP_Filesystem->delete( $tmp_file );
121
- } else {
122
- $v->{$ext} = null;
123
- }
124
- }
125
- }
126
- $style .= "@font-face {\n";
127
- $style .= "\tfont-family: " . $v->fontFamily . ";\n";
128
- $style .= "\tfont-style: " . $v->fontStyle . ";\n";
129
- $style .= "\tfont-weight: " . $v->fontWeight . ";\n";
130
- if ( $args['display'] && $args['display'] !== 'auto' ) {
131
- $style .= "\tfont-display: " . $args['display'] . ";\n";
132
- }
133
 
134
- $style .= "\tsrc: url('" . $folder_url . '/' . $id . '/' . $file . ".eot?v=$time');\n";
135
- $style .= "\tsrc: local(''),\n";
136
- $style .= "\t\turl('" . $folder_url . '/' . $id . '/' . $file . ".eot?v=$time#iefix') format('embedded-opentype'),\n";
 
 
 
 
 
 
137
 
138
- if ( $v->woff2 ) {
139
- $style .= "\t\turl('" . $folder_url . '/' . $id . '/' . $file . ".woff2?v=$time') format('woff2'),\n";
140
- }
141
- if ( $v->woff ) {
142
- $style .= "\t\turl('" . $folder_url . '/' . $id . '/' . $file . ".woff?v=$time') format('woff'),\n";
143
- }
144
- if ( $v->ttf ) {
145
- $style .= "\t\turl('" . $folder_url . '/' . $id . '/' . $file . ".ttf?v=$time') format('truetype'),\n";
146
- }
147
- if ( $v->svg ) {
148
- $style .= "\t\turl('" . $folder_url . '/' . $id . '/' . $file . ".svg?v=$time" . strrchr( $v->svg, '#' ) . "') format('svg');\n";
149
  }
150
- $style .= "}\n\n";
151
-
152
  }
153
  }
154
 
 
 
155
  $WP_Filesystem->put_contents( $new_dir, $style );
156
 
157
  return $new_src;
@@ -184,12 +160,13 @@ class LGF {
184
  $org = $src;
185
 
186
  // remove 'ver' query arg as it is added by WP
187
- $src = preg_replace('/&ver=([^&]+)/', '', $src);
188
 
189
  $id = md5( $src );
190
 
191
- $folder = WP_CONTENT_DIR . '/uploads/fonts';
192
- $folder_url = WP_CONTENT_URL . '/uploads/fonts';
 
193
 
194
  $stylesheet = $folder . '/' . $id . '/font.css';
195
  $stylesheet_url = $folder_url . '/' . $id . '/font.css';
@@ -238,7 +215,8 @@ class LGF {
238
 
239
 
240
  public function clear() {
241
- $folder = WP_CONTENT_DIR . '/uploads/fonts';
 
242
  if ( is_dir( $folder ) ) {
243
  $WP_Filesystem = $this->wp_filesystem();
244
  $WP_Filesystem->delete( $folder, true );
@@ -252,7 +230,8 @@ class LGF {
252
  }
253
 
254
  public function remove_set( $id = null ) {
255
- $folder = WP_CONTENT_DIR . '/uploads/fonts';
 
256
  if ( ! is_null( $id ) ) {
257
  $folder .= '/' . basename( $id );
258
  }
@@ -268,6 +247,9 @@ class LGF {
268
  if ( get_option( 'local_google_fonts_buffer' ) || get_option( 'local_google_fonts' ) ) {
269
  return;
270
  }
 
 
 
271
  ?>
272
  <div class="notice notice-info">
273
  <p><?php printf( esc_html__( 'Thanks for using Local Google Fonts. Please check the %s.', 'local-google-fonts' ), '<a href="' . admin_url( 'options-general.php?page=lgf-settings' ) . '">' . esc_html__( 'settings page', 'local-google-fonts' ) . '</a>' ); ?></p>
@@ -275,6 +257,15 @@ class LGF {
275
  <?php
276
  }
277
 
 
 
 
 
 
 
 
 
 
278
  private function wp_filesystem() {
279
  global $wp_filesystem;
280
 
6
 
7
  private static $instance = null;
8
 
 
9
  private $upload_dir;
10
 
11
  private function __construct() {
22
 
23
  add_action( 'admin_notices', array( $this, 'maybe_welcome_message' ) );
24
 
25
+ add_filter( 'plugin_action_links', array( &$this, 'add_action_link' ), 10, 2 );
26
+
27
  }
28
 
29
  public static function get_instance() {
56
  public function process_url( $src, $handle ) {
57
 
58
  // remove 'ver' query arg as it is added by WP
59
+ $src = preg_replace( '/&ver=([^&]+)/', '', $src );
60
 
61
  $id = md5( $src );
62
 
78
  $style .= ' * ' . sprintf( 'Font file created by %s %s', $plugin_data['Name'], $plugin_data['Version'] ) . "\n";
79
  $style .= ' * Created: ' . date( 'r' ) . "\n";
80
  $style .= ' * Handle: ' . esc_attr( $handle ) . "\n";
81
+ $style .= ' * Original URL: ' . esc_attr( $src ) . "\n";
82
  $style .= "*/\n\n";
83
 
84
  $query = wp_parse_url( $src, PHP_URL_QUERY );
91
  )
92
  );
93
 
94
+ $upload_dir = wp_get_upload_dir();
95
+ $folder = $upload_dir['error'] ? WP_CONTENT_DIR . '/uploads/fonts' : $upload_dir['basedir'] . '/fonts';
96
+ $folder_url = $upload_dir['error'] ? WP_CONTENT_URL . '/uploads/fonts' : $upload_dir['baseurl'] . '/fonts';
97
 
98
  $new_src = $folder_url . '/' . $id . '/font.css';
99
  $new_dir = $folder . '/' . $id . '/font.css';
100
 
101
+ $class = LGF_Admin::get_instance();
102
+ $parser = $class->get_parser( $src );
103
+
104
+ $info = $parser->get_info();
105
+ $stylesheet = $parser->get_remote_styles();
106
 
107
+ if ( is_wp_error( $parser ) ) {
108
  return $src;
109
  }
110
 
111
+ foreach ( $info as $font ) {
 
 
112
 
113
+ foreach ( $font['faces'] as $face ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
+ $tmp_file = download_url( $face['remote_url'] );
116
+ if ( ! is_wp_error( $tmp_file ) ) {
117
+ if ( ! is_dir( dirname( $face['file'] ) ) ) {
118
+ wp_mkdir_p( dirname( $face['file'] ) );
119
+ }
120
+ $WP_Filesystem->copy( $tmp_file, $face['file'] );
121
+ $WP_Filesystem->delete( $tmp_file );
122
+ $local_file = add_query_arg( 'c', time(), $face['local_url'] );
123
+ $stylesheet = str_replace( $face['remote_url'], $local_file, $stylesheet );
124
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
 
 
126
  }
127
  }
128
 
129
+ $style .= $stylesheet;
130
+
131
  $WP_Filesystem->put_contents( $new_dir, $style );
132
 
133
  return $new_src;
160
  $org = $src;
161
 
162
  // remove 'ver' query arg as it is added by WP
163
+ $src = preg_replace( '/&ver=([^&]+)/', '', $src );
164
 
165
  $id = md5( $src );
166
 
167
+ $upload_dir = wp_get_upload_dir();
168
+ $folder = $upload_dir['error'] ? WP_CONTENT_DIR . '/uploads/fonts' : $upload_dir['basedir'] . '/fonts';
169
+ $folder_url = $upload_dir['error'] ? WP_CONTENT_URL . '/uploads/fonts' : $upload_dir['baseurl'] . '/fonts';
170
 
171
  $stylesheet = $folder . '/' . $id . '/font.css';
172
  $stylesheet_url = $folder_url . '/' . $id . '/font.css';
215
 
216
 
217
  public function clear() {
218
+ $upload_dir = wp_get_upload_dir();
219
+ $folder = $upload_dir['error'] ? WP_CONTENT_DIR . '/uploads/fonts' : $upload_dir['basedir'] . '/fonts';
220
  if ( is_dir( $folder ) ) {
221
  $WP_Filesystem = $this->wp_filesystem();
222
  $WP_Filesystem->delete( $folder, true );
230
  }
231
 
232
  public function remove_set( $id = null ) {
233
+ $upload_dir = wp_get_upload_dir();
234
+ $folder = $upload_dir['error'] ? WP_CONTENT_DIR . '/uploads/fonts' : $upload_dir['basedir'] . '/fonts';
235
  if ( ! is_null( $id ) ) {
236
  $folder .= '/' . basename( $id );
237
  }
247
  if ( get_option( 'local_google_fonts_buffer' ) || get_option( 'local_google_fonts' ) ) {
248
  return;
249
  }
250
+ if ( get_current_screen()->id == 'settings_page_lgf-settings' ) {
251
+ return;
252
+ }
253
  ?>
254
  <div class="notice notice-info">
255
  <p><?php printf( esc_html__( 'Thanks for using Local Google Fonts. Please check the %s.', 'local-google-fonts' ), '<a href="' . admin_url( 'options-general.php?page=lgf-settings' ) . '">' . esc_html__( 'settings page', 'local-google-fonts' ) . '</a>' ); ?></p>
257
  <?php
258
  }
259
 
260
+ public function add_action_link( $links, $file ) {
261
+
262
+ if ( $file == 'local-google-fonts/local-google-fonts.php' ) {
263
+ array_unshift( $links, '<a href="' . admin_url( 'options-general.php?page=lgf-settings' ) . '">' . esc_html__( 'Settings', 'local-google-fonts' ) . '</a>' );
264
+ }
265
+
266
+ return $links;
267
+ }
268
+
269
  private function wp_filesystem() {
270
  global $wp_filesystem;
271
 
local-google-fonts.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Local Google Fonts
4
  Description: Host your used Google fonts on your server and make your site GDPR compliant.
5
- Version: 0.18
6
  Author: EverPress
7
  Author URI: https://everpress.co
8
  License: GPLv2 or later
2
  /*
3
  Plugin Name: Local Google Fonts
4
  Description: Host your used Google fonts on your server and make your site GDPR compliant.
5
+ Version: 0.19
6
  Author: EverPress
7
  Author URI: https://everpress.co
8
  License: GPLv2 or later
views/settings.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
-
4
  $buffer = get_option( 'local_google_fonts_buffer', array() );
5
 
6
- $folder = WP_CONTENT_DIR . '/uploads/fonts';
7
- $folder_url = WP_CONTENT_URL . '/uploads/fonts';
 
8
  $count = count( $buffer );
9
 
10
  if ( ! $count ) :
@@ -22,20 +22,22 @@ if ( ! $count ) :
22
  settings_fields( 'local_google_fonts_settings_page' );
23
  do_settings_sections( 'local_google_fonts_settings_page' );
24
 
 
 
 
25
  ?>
26
- <?php submit_button(); ?>
27
-
28
  <hr>
29
  <h2><?php printf( esc_html__( _n( '%d Google font source found on your site.', '%d Google font sources found on your site.', $count, 'local-google-fonts' ) ), $count ); ?></h2>
30
 
31
  <p><?php esc_html_e( 'This page shows all discovered Google Fonts over time. If you miss a font start browsing your front end so they end up showing here.', 'local-google-fonts' ); ?></p>
32
-
33
  <?php foreach ( $buffer as $id => $data ) : ?>
34
 
35
  <h3><?php esc_html_e( 'Handle', 'local-google-fonts' ); ?>: <code><?php esc_html_e( $data['handle'] ); ?></code></h3>
36
  <p><?php esc_html_e( 'Original URL', 'local-google-fonts' ); ?>: <a href="<?php echo esc_url( $data['src'] ); ?>" class="dashicons dashicons-external" target="_blank" title="<?php esc_attr_e( 'show original URL', 'local-google-fonts' ); ?>"></a><code class="original-url"><?php echo rawurldecode( $data['src'] ); ?></code></p>
37
 
38
- <?php $fontinfo = $this->get_font_info( $data['src'], $data['handle'] ); ?>
39
 
40
  <?php if ( is_wp_error( $fontinfo ) ) : ?>
41
  <div class="notice inline error">
@@ -53,67 +55,57 @@ if ( ! $count ) :
53
  </thead>
54
  <tbody>
55
  <?php foreach ( $fontinfo as $i => $font ) : ?>
56
-
57
- <?php $filename = $font->id . '-' . $font->version . '-' . $font->defSubset; ?>
58
  <tr>
59
- <td><strong><?php echo esc_html( $font->family ); ?></strong><br>
60
- <?php if ( $font->id != $font->original ) : ?>
61
- <span class="font-alternative" title="<?php esc_attr_e( 'This is the best alternative for a font no longer supported.', 'local-google-fonts' ); ?>"><?php esc_html_e( 'alternative', 'local-google-fonts' ); ?></span>
62
- <?php endif; ?>
63
  </td>
64
  <td>
65
  <p class="code">
66
- <?php foreach ( $font->variants as $variant ) : ?>
67
- <span class="variant"><?php printf( '%s %s', $variant->fontStyle, $variant->fontWeight ); ?></span>
68
- <?php endforeach ?>
69
- </p>
70
- <?php $active_subsets = isset( $data['subsets'] ) ? $data['subsets'][ $font->id ] : array_keys( array_filter( (array) $font->subsetMap ) ); ?>
71
- <p><strong><?php esc_html_e( 'Subsets', 'local-google-fonts' ); ?></strong><br>
72
- <?php foreach ( $font->subsetMap as $subset => $is_active ) : ?>
73
- <label title="<?php printf( esc_attr__( 'Load %s subset with this font', 'local-google-fonts' ), $subset ); ?>" class="subset"><input type="checkbox" name="subsets[<?php echo esc_attr( $data['handle'] ); ?>][<?php echo esc_attr( $font->id ); ?>][]" value="<?php echo esc_attr( $subset ); ?>" <?php checked( in_array( $subset, $active_subsets ) ); ?>> <?php echo esc_html( $subset ); ?> </label>
74
  <?php endforeach ?>
75
  </p>
76
  <details>
77
- <summary><strong><?php printf( esc_html__( '%1$d of %2$d files loaded.', 'local-google-fonts' ), $font->loaded, $font->total ); ?></strong></summary>
78
  <div style="max-height: 280px; overflow: scroll;font-size: small;white-space: nowrap; overflow: hidden; overflow-y: auto;" class="code">
79
- <?php foreach ( $font->variants as $variant ) : ?>
80
  <div>
81
- <h4><?php printf( '%s %s', $variant->fontStyle, $variant->fontWeight ); ?></h4>
82
- <?php foreach ( array( 'woff', 'svg', 'woff2', 'ttf', 'eot' ) as $ext ) : ?>
83
  <ul>
84
  <li>
85
- <?php $file = $data['id'] . '/' . $filename . '-' . $variant->id . '.' . $ext; ?>
86
- <?php if ( file_exists( $folder . '/' . $file ) ) : ?>
87
- <code><?php esc_html_e( 'Local', 'local-google-fonts' ); ?>: <a href="<?php echo esc_url( $folder_url . '/' . $file ); ?>" download><?php echo esc_html( basename( $file ) ); ?></a></code>
88
  <strong title="<?php esc_attr_e( 'loaded, served from your server', 'local-google-fonts' ); ?>">✔</strong>
89
  <?php else : ?>
90
- <code><?php esc_html_e( 'Local', 'local-google-fonts' ); ?>: <?php echo esc_html( basename( $file ) ); ?></code>
91
  <strong class="wp-ui-text-notification" title="<?php esc_attr_e( 'not loaded, served from Google servers', 'local-google-fonts' ); ?>">✕</strong>
92
- <?php endif; ?>
93
- </li>
94
- <li><code><?php esc_html_e( 'Remote', 'local-google-fonts' ); ?>: <?php echo esc_url( $variant->{$ext} ); ?></code></li>
95
  </ul>
96
- <?php endforeach; ?>
97
  </div>
98
  <?php endforeach ?>
99
  </div>
100
  </details>
101
  </td>
102
  <td>
103
- <?php if ( is_dir( $folder . '/' . $data['id'] ) ) : ?>
104
- <?php printf( '%s %s', '<strong>✔</strong>', esc_html__( 'loaded, served from your server', 'local-google-fonts' ) ); ?>
 
 
105
  <?php else : ?>
106
- <?php printf( '%s %s', '<strong class="wp-ui-text-notification">✕</strong>', esc_html__( 'not loaded, served from Google servers', 'local-google-fonts' ) ); ?>
 
 
 
107
  <?php endif; ?>
108
-
109
  </td>
110
 
111
  </tr>
112
  <?php endforeach ?>
113
  </tbody>
114
- </table>
115
  <p>
116
- <?php if ( is_dir( $folder . '/' . $data['id'] ) ) : ?>
117
  <button class="host-locally button button-primary" name="hostlocal" value="<?php echo esc_attr( $data['handle'] ); ?>"><?php esc_html_e( 'Reload Fonts', 'local-google-fonts' ); ?></button>
118
  <button class="host-locally button button-link-delete" name="removelocal" value="<?php echo esc_attr( $data['handle'] ); ?>"><?php esc_html_e( 'Remove hosted files', 'local-google-fonts' ); ?></button>
119
  <?php else : ?>
@@ -122,21 +114,23 @@ if ( ! $count ) :
122
  </p>
123
  <?php endif; ?>
124
 
 
125
  <?php endforeach ?>
126
  <hr>
127
  <p class="textright">
 
128
  <button class="host-locally button button-link-delete" name="flush" value="1"><?php esc_html_e( 'Remove all stored data', 'local-google-fonts' ); ?></button>
129
- </p>
130
- <?php submit_button(); ?>
131
 
132
  </form>
133
  </section>
134
  <aside class="lgf-side">
135
 
136
- <h3><?php printf(esc_attr__( 'Optimize %s', 'local-google-fonts' ), wp_parse_url( get_option('home'), PHP_URL_HOST)); ?></h3>
137
- <p><?php printf(esc_attr__( 'We partner with %s to provide a trusted resource for hiring top quality premium support to help you optimize your site.', 'local-google-fonts' ),'<a href="https://codeable.io/?ref=k8TPX" ref="noopener noreferrer" target="_blank">Codeable</a>'); ?></p>
138
 
139
- <a href="https://codeable.io/?ref=k8TPX" class="codable-link" ref="noopener noreferrer" target="_blank" title="<?php esc_attr_e( 'visit Codeable', 'local-google-fonts' ); ?>">
140
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 498 127"><defs><path d="M0 126.968h499.874V0H0z"/></defs><g fill="none" fill-rule="evenodd"><path d="m193.5 52.009-8.951 4.146c-2.278-2.276-4.476-3.983-9.114-3.983-5.288 0-10.903 3.983-10.903 11.624 0 7.56 5.615 11.463 10.903 11.463 4.638 0 6.836-1.626 9.114-3.902l9.032 4.145c-4.07 6.829-10.416 9.999-18.308 9.999-9.439 0-22.05-6.828-22.05-21.705 0-14.714 12.611-21.949 22.05-21.949 7.73 0 14.239 3.333 18.226 10.162M205.273 63.878c0 7.478 5.613 11.462 10.903 11.462 5.207 0 10.903-3.984 10.903-11.462 0-7.723-5.696-11.707-10.903-11.707-5.29 0-10.903 3.984-10.903 11.707m33.035 0c0 14.795-12.531 21.786-22.132 21.786s-22.214-6.991-22.214-21.786c0-14.796 12.613-22.03 22.214-22.03 9.6 0 22.132 7.234 22.132 22.03M273.28 63.634c0-7.56-5.371-11.462-11.148-11.462-5.777 0-10.741 3.902-10.741 11.462 0 7.804 4.964 11.706 10.74 11.706 5.778 0 11.148-3.902 11.148-11.706Zm11.065-36.257v57.474H272.71v-6.666c0 3.008-5.451 7.479-12.611 7.479-8.87 0-20.017-6.991-20.017-22.03 0-14.552 11.148-21.787 20.017-21.787 7.16 0 12.611 4.715 12.611 6.666V27.377h11.636ZM299.95 59.57h20.18c-1.303-5.204-5.94-7.805-10.172-7.805-4.15 0-8.462 2.601-10.008 7.804m30.432 8.21h-30.514c1.384 5.284 5.696 8.049 11.31 8.049 5.29 0 7.324-1.22 10.335-2.845l6.427 6.259c-3.743 3.82-8.868 6.422-17.168 6.422-10.496 0-22.458-7.235-22.458-21.786 0-14.795 12.125-22.03 21.644-22.03 9.601 0 22.946 7.235 20.424 25.932M343.523 63.634c0 7.804 4.962 11.706 10.74 11.706 5.777 0 11.147-3.902 11.147-11.706 0-7.56-5.37-11.462-11.147-11.462-5.778 0-10.74 3.902-10.74 11.462m21.318-15.121v-5.934h11.635V84.85H364.84v-6.666c0 3.008-5.452 7.479-12.613 7.479-8.869 0-20.017-6.991-20.017-22.03 0-14.552 11.148-21.787 20.017-21.787 7.16 0 12.613 4.715 12.613 6.666M415.613 63.634c0-7.56-4.963-11.462-10.74-11.462-5.778 0-11.148 3.902-11.148 11.462 0 7.804 5.37 11.706 11.147 11.706 5.778 0 10.74-3.902 10.74-11.706m11.31 0c0 15.039-11.146 22.03-20.015 22.03-7.161 0-12.613-4.471-12.613-7.479v6.666h-11.635V27.377h11.635v21.136c0-1.95 5.452-6.666 12.613-6.666 8.869 0 20.016 7.235 20.016 21.787" fill="#151D23"/><path fill="#151D23" mask="url(#b)" d="M430.997 84.851h11.636V27.377h-11.636zM458.206 59.57h20.18c-1.302-5.204-5.94-7.805-10.171-7.805-4.15 0-8.462 2.601-10.009 7.804m30.432 8.21h-30.513c1.383 5.284 5.696 8.049 11.31 8.049 5.29 0 7.324-1.22 10.334-2.845l6.428 6.259c-3.742 3.82-8.87 6.422-17.168 6.422-10.497 0-22.458-7.235-22.458-21.786 0-14.795 12.124-22.03 21.644-22.03 9.601 0 22.946 7.235 20.423 25.932"/><path d="M42.362 84.645c0 23.375 18.966 42.323 42.362 42.323 23.397 0 42.362-18.948 42.362-42.323 0-23.374-18.965-42.322-42.362-42.322v42.322H42.362Z" fill="#FFB199" mask="url(#b)"/><path fill="#165260" mask="url(#b)" d="M84.724 42.323V0H0v84.645h42.362V42.323z"/></g></svg>
141
  </a>
142
 
1
  <?php
2
 
 
3
  $buffer = get_option( 'local_google_fonts_buffer', array() );
4
 
5
+ $upload_dir = wp_get_upload_dir();
6
+ $folder = $upload_dir['error'] ? WP_CONTENT_DIR . '/uploads/fonts' : $upload_dir['basedir'] . '/fonts';
7
+ $folder_url = $upload_dir['error'] ? WP_CONTENT_URL . '/uploads/fonts' : $upload_dir['baseurl'] . '/fonts';
8
  $count = count( $buffer );
9
 
10
  if ( ! $count ) :
22
  settings_fields( 'local_google_fonts_settings_page' );
23
  do_settings_sections( 'local_google_fonts_settings_page' );
24
 
25
+ if ( $count ) :
26
+ submit_button();
27
+ endif;
28
  ?>
29
+
 
30
  <hr>
31
  <h2><?php printf( esc_html__( _n( '%d Google font source found on your site.', '%d Google font sources found on your site.', $count, 'local-google-fonts' ) ), $count ); ?></h2>
32
 
33
  <p><?php esc_html_e( 'This page shows all discovered Google Fonts over time. If you miss a font start browsing your front end so they end up showing here.', 'local-google-fonts' ); ?></p>
34
+
35
  <?php foreach ( $buffer as $id => $data ) : ?>
36
 
37
  <h3><?php esc_html_e( 'Handle', 'local-google-fonts' ); ?>: <code><?php esc_html_e( $data['handle'] ); ?></code></h3>
38
  <p><?php esc_html_e( 'Original URL', 'local-google-fonts' ); ?>: <a href="<?php echo esc_url( $data['src'] ); ?>" class="dashicons dashicons-external" target="_blank" title="<?php esc_attr_e( 'show original URL', 'local-google-fonts' ); ?>"></a><code class="original-url"><?php echo rawurldecode( $data['src'] ); ?></code></p>
39
 
40
+ <?php $fontinfo = $this->get_parser( $data['src'] )->get_info(); ?>
41
 
42
  <?php if ( is_wp_error( $fontinfo ) ) : ?>
43
  <div class="notice inline error">
55
  </thead>
56
  <tbody>
57
  <?php foreach ( $fontinfo as $i => $font ) : ?>
 
 
58
  <tr>
59
+ <td><strong><?php echo esc_html( $font['name'] ); ?></strong>
 
 
 
60
  </td>
61
  <td>
62
  <p class="code">
63
+ <?php foreach ( $font['variants'] as $variant ) : ?>
64
+ <span class="variant"><?php echo esc_html( $variant ); ?></span>
 
 
 
 
 
 
65
  <?php endforeach ?>
66
  </p>
67
  <details>
68
+ <summary><strong><?php printf( esc_html__( '%1$d of %2$d files loaded.', 'local-google-fonts' ), $font['loaded'], $font['total'] ); ?></strong></summary>
69
  <div style="max-height: 280px; overflow: scroll;font-size: small;white-space: nowrap; overflow: hidden; overflow-y: auto;" class="code">
70
+ <?php foreach ( $font['faces'] as $face ) : ?>
71
  <div>
72
+ <strong><?php printf( '%s %s', $face['style'], $face['weight'] ); ?></strong>
 
73
  <ul>
74
  <li>
75
+ <?php if ( $face['loaded'] ) : ?>
76
+ <code><?php esc_html_e( 'Local', 'local-google-fonts' ); ?>: <a href="<?php echo esc_url( $face['local_url'] ); ?>" download><?php echo esc_html( basename( $face['file'] ) ); ?></a></code>
 
77
  <strong title="<?php esc_attr_e( 'loaded, served from your server', 'local-google-fonts' ); ?>">✔</strong>
78
  <?php else : ?>
79
+ <code><?php esc_html_e( 'Local', 'local-google-fonts' ); ?>: <?php echo esc_html( basename( $face['file'] ) ); ?></code>
80
  <strong class="wp-ui-text-notification" title="<?php esc_attr_e( 'not loaded, served from Google servers', 'local-google-fonts' ); ?>">✕</strong>
81
+ <?php endif; ?>
82
+ </li>
83
+ <li><code><?php esc_html_e( 'Remote', 'local-google-fonts' ); ?>: <?php echo esc_url( $face['remote_url'] ); ?></code></li>
84
  </ul>
 
85
  </div>
86
  <?php endforeach ?>
87
  </div>
88
  </details>
89
  </td>
90
  <td>
91
+ <?php if ( $font['loaded'] == $font['total'] ) : ?>
92
+ <?php printf( '%s %s', '<strong>✔</strong>', sprintf( esc_html__( 'loaded from %s', 'local-google-fonts' ), '<code>' . wp_parse_url( $font['stylesheet'], PHP_URL_HOST ) . '</code>' ) ); ?>
93
+ <?php elseif ( $font['loaded'] > 0 ) : ?>
94
+ <?php printf( '%s %s', '<strong class="wp-ui-text-notification">✕</strong>', sprintf( esc_html__( 'partially loaded, some files are loaded from %s', 'local-google-fonts' ), '<code>' . wp_parse_url( $data['src'], PHP_URL_HOST ) . '</code>' ) ); ?>
95
  <?php else : ?>
96
+ <?php printf( '%s %s', '<strong class="wp-ui-text-notification">✕</strong>', sprintf( esc_html__( 'loaded from %s', 'local-google-fonts' ), '<code>' . wp_parse_url( $data['src'], PHP_URL_HOST ) . '</code>' ) ); ?>
97
+ <?php endif; ?>
98
+ <?php if ( $font['filesize'] ) : ?>
99
+ <p><?php esc_html_e( size_format( $font['filesize'] ) ); ?></p>
100
  <?php endif; ?>
 
101
  </td>
102
 
103
  </tr>
104
  <?php endforeach ?>
105
  </tbody>
106
+ </table>
107
  <p>
108
+ <?php if ( is_dir( $folder . '/' . $data['id'] ) ) : ?>
109
  <button class="host-locally button button-primary" name="hostlocal" value="<?php echo esc_attr( $data['handle'] ); ?>"><?php esc_html_e( 'Reload Fonts', 'local-google-fonts' ); ?></button>
110
  <button class="host-locally button button-link-delete" name="removelocal" value="<?php echo esc_attr( $data['handle'] ); ?>"><?php esc_html_e( 'Remove hosted files', 'local-google-fonts' ); ?></button>
111
  <?php else : ?>
114
  </p>
115
  <?php endif; ?>
116
 
117
+
118
  <?php endforeach ?>
119
  <hr>
120
  <p class="textright">
121
+ <button class="check button button-secondary" name="check"><?php esc_html_e( 'Manually check Homepage', 'local-google-fonts' ); ?></button>
122
  <button class="host-locally button button-link-delete" name="flush" value="1"><?php esc_html_e( 'Remove all stored data', 'local-google-fonts' ); ?></button>
123
+ </p>
124
+ <?php submit_button(); ?>
125
 
126
  </form>
127
  </section>
128
  <aside class="lgf-side">
129
 
130
+ <h3><?php printf( esc_attr__( 'Optimize %s', 'local-google-fonts' ), wp_parse_url( get_option( 'home' ), PHP_URL_HOST ) ); ?></h3>
131
+ <p><?php printf( esc_attr__( 'We partner with %s to provide a trusted resource for hiring top quality premium support to help you optimize your site.', 'local-google-fonts' ), '<a href="https://codeable.io/?ref=ebTBq" ref="noopener noreferrer" target="_blank">Codeable</a>' ); ?></p>
132
 
133
+ <a href="https://codeable.io/?ref=ebTBq" class="codable-link" ref="noopener noreferrer" target="_blank" title="<?php esc_attr_e( 'visit Codeable', 'local-google-fonts' ); ?>">
134
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 498 127"><defs><path d="M0 126.968h499.874V0H0z"/></defs><g fill="none" fill-rule="evenodd"><path d="m193.5 52.009-8.951 4.146c-2.278-2.276-4.476-3.983-9.114-3.983-5.288 0-10.903 3.983-10.903 11.624 0 7.56 5.615 11.463 10.903 11.463 4.638 0 6.836-1.626 9.114-3.902l9.032 4.145c-4.07 6.829-10.416 9.999-18.308 9.999-9.439 0-22.05-6.828-22.05-21.705 0-14.714 12.611-21.949 22.05-21.949 7.73 0 14.239 3.333 18.226 10.162M205.273 63.878c0 7.478 5.613 11.462 10.903 11.462 5.207 0 10.903-3.984 10.903-11.462 0-7.723-5.696-11.707-10.903-11.707-5.29 0-10.903 3.984-10.903 11.707m33.035 0c0 14.795-12.531 21.786-22.132 21.786s-22.214-6.991-22.214-21.786c0-14.796 12.613-22.03 22.214-22.03 9.6 0 22.132 7.234 22.132 22.03M273.28 63.634c0-7.56-5.371-11.462-11.148-11.462-5.777 0-10.741 3.902-10.741 11.462 0 7.804 4.964 11.706 10.74 11.706 5.778 0 11.148-3.902 11.148-11.706Zm11.065-36.257v57.474H272.71v-6.666c0 3.008-5.451 7.479-12.611 7.479-8.87 0-20.017-6.991-20.017-22.03 0-14.552 11.148-21.787 20.017-21.787 7.16 0 12.611 4.715 12.611 6.666V27.377h11.636ZM299.95 59.57h20.18c-1.303-5.204-5.94-7.805-10.172-7.805-4.15 0-8.462 2.601-10.008 7.804m30.432 8.21h-30.514c1.384 5.284 5.696 8.049 11.31 8.049 5.29 0 7.324-1.22 10.335-2.845l6.427 6.259c-3.743 3.82-8.868 6.422-17.168 6.422-10.496 0-22.458-7.235-22.458-21.786 0-14.795 12.125-22.03 21.644-22.03 9.601 0 22.946 7.235 20.424 25.932M343.523 63.634c0 7.804 4.962 11.706 10.74 11.706 5.777 0 11.147-3.902 11.147-11.706 0-7.56-5.37-11.462-11.147-11.462-5.778 0-10.74 3.902-10.74 11.462m21.318-15.121v-5.934h11.635V84.85H364.84v-6.666c0 3.008-5.452 7.479-12.613 7.479-8.869 0-20.017-6.991-20.017-22.03 0-14.552 11.148-21.787 20.017-21.787 7.16 0 12.613 4.715 12.613 6.666M415.613 63.634c0-7.56-4.963-11.462-10.74-11.462-5.778 0-11.148 3.902-11.148 11.462 0 7.804 5.37 11.706 11.147 11.706 5.778 0 10.74-3.902 10.74-11.706m11.31 0c0 15.039-11.146 22.03-20.015 22.03-7.161 0-12.613-4.471-12.613-7.479v6.666h-11.635V27.377h11.635v21.136c0-1.95 5.452-6.666 12.613-6.666 8.869 0 20.016 7.235 20.016 21.787" fill="#151D23"/><path fill="#151D23" mask="url(#b)" d="M430.997 84.851h11.636V27.377h-11.636zM458.206 59.57h20.18c-1.302-5.204-5.94-7.805-10.171-7.805-4.15 0-8.462 2.601-10.009 7.804m30.432 8.21h-30.513c1.383 5.284 5.696 8.049 11.31 8.049 5.29 0 7.324-1.22 10.334-2.845l6.428 6.259c-3.742 3.82-8.87 6.422-17.168 6.422-10.497 0-22.458-7.235-22.458-21.786 0-14.795 12.124-22.03 21.644-22.03 9.601 0 22.946 7.235 20.423 25.932"/><path d="M42.362 84.645c0 23.375 18.966 42.323 42.362 42.323 23.397 0 42.362-18.948 42.362-42.323 0-23.374-18.965-42.322-42.362-42.322v42.322H42.362Z" fill="#FFB199" mask="url(#b)"/><path fill="#165260" mask="url(#b)" d="M84.724 42.323V0H0v84.645h42.362V42.323z"/></g></svg>
135
  </a>
136