PluginProbe ʕ •ᴥ•ʔ
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.16
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.16
4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 3.8.0 4.0.0 4.0.1 4.1.0 4.1.1 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 3.2.2 trunk 0.7.0 1.8.9.10 1.8.9.7 1.8.9.8 1.8.9.9 1.9 1.9.1 2.0.1 2.1.0 2.1.1 2.2.0 2.2.1 2.2.10 2.2.11 2.2.12 2.2.13 2.2.2 2.2.3 2.2.4 2.2.6 2.2.8 2.2.9 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 3.0.0 3.0.1 3.0.10 3.0.11 3.0.12 3.0.13 3.0.14 3.0.15 3.0.16 3.0.18 3.0.19 3.0.2 3.0.3 3.0.4 3.0.5 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.10 3.1.11 3.1.12 3.1.2 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.17 3.2.18 3.2.19
wp-optimize / minify / class-wp-optimize-minify-fonts.php
wp-optimize / minify Last commit date
class-wp-optimize-detect-minify-plugins.php 4 years ago class-wp-optimize-minify-admin.php 3 years ago class-wp-optimize-minify-cache-functions.php 3 years ago class-wp-optimize-minify-commands.php 2 years ago class-wp-optimize-minify-config.php 3 years ago class-wp-optimize-minify-fonts.php 3 years ago class-wp-optimize-minify-front-end.php 2 years ago class-wp-optimize-minify-functions.php 3 years ago class-wp-optimize-minify-load-url-task.php 3 years ago class-wp-optimize-minify-preloader.php 3 years ago class-wp-optimize-minify-print.php 2 years ago class-wp-optimize-minify.php 2 years ago
class-wp-optimize-minify-fonts.php
306 lines
1 <?php
2 if (!defined('ABSPATH')) die('No direct access allowed');
3
4 class WP_Optimize_Minify_Fonts {
5
6 private static $fonts = array();
7
8 private static $subsets = array();
9
10 /**
11 * Get a list of Google fonts
12 *
13 * @return Array
14 */
15 public static function get_google_fonts() {
16 // https://www.googleapis.com/webfonts/v1/webfonts?sort=alpha
17 $google_fonts_file = WPO_PLUGIN_MAIN_PATH.'google-fonts.json';
18 if (is_file($google_fonts_file) && is_readable($google_fonts_file)) {
19 return json_decode(file_get_contents($google_fonts_file), true);
20 }
21 return array();
22 }
23
24 /**
25 * Check if the google font exist or not
26 *
27 * @param string $font
28 * @return boolean
29 */
30 public static function concatenate_google_fonts_allowed($font) {
31 $gfonts_whitelist = self::get_google_fonts();
32
33 // normalize
34 $font = str_ireplace('+', ' ', strtolower($font));
35
36 return in_array($font, $gfonts_whitelist);
37 }
38
39 /**
40 * Concatenates Google Fonts tags (http://fonts.googleapis.com/css?...)
41 *
42 * @param array $gfonts_array
43 * @return string|boolean
44 */
45 public static function concatenate_google_fonts($gfonts_array) {
46 // Loop through fonts array
47 foreach ($gfonts_array as $font) {
48 self::parse_font_url($font);
49 }
50 self::convert_v1_font_specs_to_v2();
51 $merge = self::build();
52 $config = wp_optimize_minify_config();
53 /**
54 * Filters wether to add display=swap to Google fonts urls
55 *
56 * @param boolean $display - Default to true
57 */
58 if (apply_filters('wpo_minify_gfont_display_swap', $config->get('enable_display_swap'))) {
59 /**
60 * Filters the value of the display parameter.
61 *
62 * @param string $display_value - Default to 'swap'. https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display
63 */
64 $merge.= '&display='.apply_filters('wpo_minify_gfont_display_type', 'swap');
65 }
66
67 if (!empty($merge)) return 'https://fonts.googleapis.com/css2?' . $merge;
68
69 return false;
70 }
71
72 /**
73 * Parses font url based on whether it is API version 1 or 2
74 */
75 private static function parse_font_url($font) {
76 if (false !== strpos($font, 'css?')) {
77 self::parse_font_api1_url($font);
78 } else {
79 self::parse_font_api2_url($font);
80 }
81 }
82
83 /**
84 * Parses google font api version 1 url
85 */
86 private static function parse_font_api1_url($font) {
87 parse_str(parse_url(rtrim($font, '|'), PHP_URL_QUERY), $font_elements);
88 // Process each font family
89 foreach (explode('|', $font_elements['family']) as $font_family) {
90 // Separate font and sizes
91 $font_family = explode(':', $font_family);
92 // if the family wasn't added yet
93 if (!in_array($font_family[0], array_keys(self::$fonts))) {
94 self::$fonts[$font_family[0]]['specs'] = isset($font_family[1]) ? explode(',', rtrim($font_family[1], ',')) : array();
95 } else {
96 // if the family was already added, and this new one has weights, merge with previous
97 if (isset($font_family[1])) {
98 if (isset(self::$fonts[$font_family[0]]['version']) && 'V2' == self::$fonts[$font_family[0]]['version']) {
99 self::$fonts[$font_family[0]]['specs'] = explode(',', rtrim($font_family[1], ','));
100 } else {
101 self::$fonts[$font_family[0]]['specs'] = array_merge(self::$fonts[$font_family[0]]['specs'], explode(',', rtrim($font_family[1], ',')));
102 }
103 }
104 }
105 self::$fonts[$font_family[0]]['version'] = 'V1';
106 }
107
108 // Add subsets
109 if (isset($font_elements['subset'])) {
110 self::$subsets = array_merge(self::$subsets, explode(',', $font_elements['subset']));
111 }
112 }
113
114 /**
115 * Parses google font api version 2 url
116 */
117 private static function parse_font_api2_url($font) {
118 $parsed_url = parse_url($font, PHP_URL_QUERY);
119 $query_elements = explode('&', $parsed_url);
120 foreach ($query_elements as $element) {
121 $family_str = str_replace('family=', '', $element);
122 $family = explode(':', $family_str);
123 if (!empty($family)) {
124 $font_name = $family[0];
125 $font_elements = isset($family[1]) ? explode('@', $family[1]) : '';
126 if (!empty($font_elements) && !empty($font_elements[0]) && !empty($font_elements[1])) {
127 $font_styles = $font_elements[0];
128 $font_units = explode(',', $font_elements[1]);
129 }
130 } else {
131 $font_name = $family_str;
132 continue;
133 }
134
135 if (!isset(self::$fonts[$font_name])) {
136 self::$fonts[$font_name]['specs'] = array(
137 'wght' => array(),
138 'ital' => array(),
139 'ital,wght' => array(),
140 );
141 }
142
143 if (!isset(self::$fonts[$font_name]['version'])) {
144 self::$fonts[$font_name]['version'] = 'V2';
145 }
146 if (isset($font_styles) && isset($font_units) && isset($font_elements[1])) {
147 $font_units = explode(';', $font_elements[1]);
148 switch ($font_styles) {
149 case 'wght':
150 foreach ($font_units as $font_unit) {
151 if (!in_array($font_unit, self::$fonts[$font_name]['specs']['wght'])) {
152 array_push(self::$fonts[$font_name]['specs']['wght'], $font_unit);
153 }
154 }
155 break;
156 case 'ital':
157 foreach ($font_units as $font_unit) {
158 if (!in_array($font_unit, self::$fonts[$font_name]['specs']['ital'])) {
159 array_push(self::$fonts[$font_name]['specs']['ital'], $font_unit);
160 }
161 }
162 break;
163 case 'ital,wght':
164 foreach ($font_units as $font_unit) {
165 if (!in_array($font_unit, self::$fonts[$font_name]['specs']['ital,wght'])) {
166 array_push(self::$fonts[$font_name]['specs']['ital,wght'], $font_unit);
167 }
168 }
169 break;
170 }
171 }
172 }
173 }
174
175 /**
176 * Converts google font api version 1 font specification into API V2
177 */
178 private static function convert_v1_font_specs_to_v2() {
179 foreach (self::$fonts as $font_name => $font_details) {
180 if ('V2' == $font_details['version']) continue;
181 if (0 == count($font_details['specs'])) {
182 self::$fonts[$font_name]['specs'] = array(
183 'wght' => array(),
184 'ital' => array(),
185 'ital,wght' => array(),
186 );
187 } else {
188 foreach ($font_details['specs'] as $key => $detail) {
189 if (is_array($detail)) $detail = implode('', $detail);
190 switch ($detail) {
191 case 'i':
192 unset(self::$fonts[$font_name]['specs'][$key]);
193 self::$fonts[$font_name]['specs']['ital'] = array(1);
194 break;
195 case 'b':
196 unset(self::$fonts[$font_name]['specs'][$key]);
197 self::$fonts[$font_name]['specs']['wght'] = array();
198 break;
199 case 'bi':
200 unset(self::$fonts[$font_name]['specs'][$key]);
201 self::$fonts[$font_name]['specs']['ital'] = array('0;1');
202 break;
203 default:
204 unset(self::$fonts[$font_name]['specs'][$key]);
205 if (!isset(self::$fonts[$font_name]['specs']['ital,wght'])) {
206 self::$fonts[$font_name]['specs']['ital,wght'] = array();
207 }
208 if ('inherit' === $detail) {
209 array_push(self::$fonts[$font_name]['specs']['ital,wght'], '0,400');
210 array_push(self::$fonts[$font_name]['specs']['ital,wght'], '1,400');
211 } elseif ('regular' === $detail) {
212 $detail = 'regular' === $detail ? 400 : $detail;
213 array_push(self::$fonts[$font_name]['specs']['ital,wght'], '0,' . $detail);
214 } elseif (false !== strpos($detail, 'i')) {
215 $detail = str_replace(array('italic', 'i'), '', $detail);
216 $detail = '' === $detail ? 400 : $detail;
217 array_push(self::$fonts[$font_name]['specs']['ital,wght'], '1,' . $detail);
218 } else {
219 $detail = str_replace(array('normal'), '', $detail);
220 $detail = '' === $detail ? 400 : $detail;
221 array_push(self::$fonts[$font_name]['specs']['ital,wght'], '0,' . $detail);
222 }
223 break;
224 }
225 }
226 }
227 }
228 }
229
230 /**
231 * Build valid Google font api 2 url string
232 *
233 * @return string $result Url string
234 */
235 private static function build() {
236 $result = '';
237 foreach (self::$fonts as $font_name => $font_details) {
238 if ('display=swap' == $font_name) continue;
239 if ('' != $result) {
240 $result .= '&';
241 }
242 $result .= 'family=' . str_replace(' ', '+', $font_name);
243 $result .= self::specs_to_string($font_details['specs']);
244 }
245 return $result;
246 }
247
248 /**
249 * Converts font specifications into a valid google font api2 url string
250 *
251 * @param array $font_specs Font style and weight specifications
252 *
253 * @return string
254 */
255 private static function specs_to_string($font_specs) {
256 $result = array();
257 $weights = isset($font_specs['wght']) && count($font_specs['wght']);
258 $italic_weights = isset($font_specs['ital']) && count($font_specs['ital']);
259 $all_weights = isset($font_specs['ital,wght']) && count($font_specs['ital,wght']);
260
261 // Nothing is set, return
262 if (!$weights && !$italic_weights && !$all_weights) {
263 return '';
264 }
265
266 // Italic only
267 if ($italic_weights && !$weights && !$all_weights) {
268 if ('1' == $font_specs['ital'][0]) {
269 return ':ital@1';
270 } elseif ('0;1' == $font_specs['ital'][0]) {
271 return ':ital@0;1';
272 }
273 }
274
275 foreach ($font_specs as $style => $units) {
276 switch ($style) {
277 case 'wght':
278 foreach ($units as $unit) {
279 $multiple_units = explode(',', $unit);
280 if (count($multiple_units) > 0) {
281 foreach ($multiple_units as $single_unit) {
282 array_push($result, '0,' . $single_unit);
283 }
284 } else {
285 array_push($result, '0,' . $unit);
286 }
287 }
288 break;
289 case 'ital':
290 foreach ($units as $unit) {
291 array_push($result, 1 == $unit ? '1,400' : $unit);
292 }
293 break;
294 case 'ital,wght':
295 foreach ($units as $unit) {
296 array_push($result, $unit);
297 }
298 break;
299 }
300 }
301
302 sort($result);
303 return ':ital,wght@' . implode(';', array_unique($result));
304 }
305 }
306