Completed
Push — master ( 7388a0...c197b7 )
by
unknown
45s
created
redux-core/inc/classes/class-redux-output.php 1 patch
Indentation   +358 added lines, -358 removed lines patch added patch discarded remove patch
@@ -12,362 +12,362 @@
 block discarded – undo
12 12
 
13 13
 if ( ! class_exists( 'Redux_Output', false ) ) {
14 14
 
15
-	/**
16
-	 * Class Redux_Output
17
-	 */
18
-	class Redux_Output extends Redux_Class {
19
-
20
-		/**
21
-		 * Redux_Output constructor.
22
-		 *
23
-		 * @param object $redux ReduxFramework pointer.
24
-		 */
25
-		public function __construct( $redux ) {
26
-			parent::__construct( $redux );
27
-
28
-			// Output dynamic CSS.
29
-			// Frontend: Maybe enqueue dynamic CSS and Google fonts.
30
-			if ( empty( $this->args['output_location'] ) || in_array( 'frontend', $this->args['output_location'], true ) ) {
31
-				add_action( 'wp_head', array( $this, 'output_css' ), 150 );
32
-				add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ), 150 );
33
-			}
34
-
35
-			// Login page: Maybe enqueue dynamic CSS and Google fonts.
36
-			if ( in_array( 'login', $this->args['output_location'], true ) ) {
37
-				add_action( 'login_head', array( $this, 'output_css' ), 150 );
38
-				add_action( 'login_enqueue_scripts', array( $this, 'enqueue' ), 150 );
39
-			}
40
-
41
-			// Admin area: Maybe enqueue dynamic CSS and Google fonts.
42
-			if ( in_array( 'admin', $this->args['output_location'], true ) ) {
43
-				add_action( 'admin_head', array( $this, 'output_css' ), 150 );
44
-				add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ), 150 );
45
-			}
46
-
47
-			// phpcs:ignore WordPress.NamingConventions.ValidHookName
48
-			do_action( "redux/output/{$this->parent->args['opt_name']}/construct", $this );
49
-			// Useful for adding different locations for CSS output.
50
-		}
51
-
52
-		/**
53
-		 * Enqueue CSS and Google fonts for front end
54
-		 *
55
-		 * @return void
56
-		 * @throws ReflectionException Exception.
57
-		 * @since  1.0.0
58
-		 * @access public
59
-		 */
60
-		public function enqueue() {
61
-			$core = $this->core();
62
-
63
-			if ( false === $core->args['output'] && false === $core->args['compiler'] ) {
64
-				return;
65
-			}
66
-
67
-			foreach ( $core->sections as $k => $section ) {
68
-				if ( isset( $section['type'] ) && ( 'divide' === $section['type'] ) ) {
69
-					continue;
70
-				}
71
-
72
-				if ( isset( $section['fields'] ) ) {
73
-					foreach ( $section['fields'] as $fieldk => $field ) {
74
-						if ( isset( $field['type'] ) && 'callback' !== $field['type'] ) {
75
-							$field_classes = array( 'Redux_' . $field['type'], 'ReduxFramework_' . $field['type'] );
76
-
77
-							$field_class = Redux_Functions::class_exists_ex( $field_classes );
78
-
79
-							if ( false === $field_class ) {
80
-								if ( ! isset( $field['compiler'] ) ) {
81
-									$field['compiler'] = '';
82
-								}
83
-
84
-								$field_type = str_replace( '_', '-', $field['type'] );
85
-								$core_path  = Redux_Core::$dir . "inc/fields/{$field['type']}/class-redux-$field_type.php";
86
-
87
-								if ( ! file_exists( $core_path ) ) {
88
-									$core_path = Redux_Core::$dir . "inc/fields/{$field['type']}/field_{$field['type']}.php";
89
-								}
90
-
91
-								$filter_path = $core_path;
92
-
93
-								/**
94
-								 * Field class file
95
-								 * filter 'redux/{opt_name}/field/class/{field.type}'
96
-								 *
97
-								 * @param string $file field class file.
98
-								 * @param array $field field config data
99
-								 */
100
-
101
-								// phpcs:ignore WordPress.NamingConventions.ValidHookName
102
-								$class_file = apply_filters( "redux/{$core->args['opt_name']}/field/class/{$field['type']}", $filter_path, $field );
103
-
104
-								if ( $class_file && file_exists( $class_file ) ) {
105
-									require_once $class_file;
106
-
107
-									$field_class = Redux_Functions::class_exists_ex( $field_classes );
108
-								}
109
-							}
110
-
111
-							$field['default'] = $field['default'] ?? '';
112
-							$value            = $core->options[ $field['id'] ] ?? $field['default'];
113
-							$style_data       = '';
114
-
115
-							if ( empty( $field_class ) ) {
116
-								continue;
117
-							}
118
-
119
-							$field_object = new $field_class( $field, $value, $core );
120
-
121
-							if ( ! empty( $core->options[ $field['id'] ] ) && class_exists( $field_class ) && method_exists( $field_class, 'output' ) && $this->can_output_css( $core, $field ) ) {
122
-
123
-								// phpcs:ignore WordPress.NamingConventions.ValidHookName
124
-								$field = apply_filters( "redux/field/{$core->args['opt_name']}/output_css", $field );
125
-
126
-								if ( ! empty( $field['output'] ) && ! is_array( $field['output'] ) ) {
127
-									$field['output'] = array( $field['output'] );
128
-								}
129
-
130
-								if ( ( ( isset( $field['output'] ) && ! empty( $field['output'] ) ) || ( isset( $field['compiler'] ) && ! empty( $field['compiler'] ) ) || ( isset( $field['media_query'] ) && ! empty( $field['media_query'] ) ) || 'typography' === $field['type'] || 'icon_select' === $field['type'] || 'social_profiles' === $field['type'] ) ) {
131
-									if ( method_exists( $field_class, 'css_style' ) ) {
132
-										$style_data = $field_object->css_style( $field_object->value );
133
-									}
134
-								}
135
-
136
-								if ( null !== $style_data ) {
137
-									if ( ( ( isset( $field['output'] ) && ! empty( $field['output'] ) ) || ( isset( $field['compiler'] ) && ! empty( $field['compiler'] ) ) || 'typography' === $field['type'] || 'icon_select' === $field['type'] || 'social_profiles' === $field['type'] ) ) {
138
-										$field_object->output( $style_data );
139
-									}
140
-
141
-									if ( isset( $field['media_query'] ) && ! empty( $field['media_query'] ) ) {
142
-										$field_object->media_query( $style_data );
143
-									}
144
-								}
145
-							}
146
-
147
-							// phpcs:ignore WordPress.NamingConventions.ValidHookName
148
-							do_action( "redux/field/{$core->args['opt_name']}/output_loop", $core, $field, $value, $style_data );
149
-
150
-							// phpcs:ignore WordPress.NamingConventions.ValidHookName
151
-							do_action( "redux/field/{$core->args['opt_name']}/output_loop/{$field['type']}", $core, $field, $value, $style_data );
152
-
153
-							if ( method_exists( $field_class, 'output_variables' ) && $this->can_output_css( $core, $field ) ) {
154
-								$passed_style_data = $field_object->output_variables( $style_data );
155
-								$this->output_variables( $core, $section, $field, $value, $passed_style_data );
156
-							}
157
-						}
158
-					}
159
-
160
-					if ( ! empty( $core->outputCSS ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
161
-						// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
162
-						$core->outputCSS = html_entity_decode( $core->outputCSS, ENT_QUOTES, 'UTF-8' );
163
-					}
164
-				}
165
-			}
166
-
167
-			// For use like in the customizer. Stops the output, but passes the CSS in the variable for the compiler.
168
-			if ( true === Redux_Core::$no_output ) {
169
-				return;
170
-			}
171
-
172
-			if ( ! empty( Redux_Core::$typography ) && filter_var( $core->args['output'], FILTER_VALIDATE_BOOLEAN ) ) {
173
-				$version = ! empty( $core->transients['last_save'] ) ? $core->transients['last_save'] : '';
174
-				if ( ! class_exists( 'Redux_Typography' ) ) {
175
-					require_once Redux_Core::$dir . '/inc/fields/typography/class-redux-typography.php';
176
-				}
177
-
178
-				$typography = new Redux_Typography( null, null, $core );
179
-
180
-				$core->args['disable_google_fonts_link'] = ( ! isset( $core->args['disable_google_fonts_link'] ) ? false : $core->args['disable_google_fonts_link'] );
181
-
182
-				if ( ! $core->args['disable_google_fonts_link'] ) {
183
-					$url = $typography->make_google_web_font_link( Redux_Core::$typography );
184
-					wp_enqueue_style( 'redux-google-fonts-' . $core->args['opt_name'], $url, array(), $version );
185
-					add_filter( 'style_loader_tag', array( $this, 'add_style_attributes' ), 10, 4 );
186
-					add_filter( 'wp_resource_hints', array( $this, 'google_fonts_preconnect' ), 10, 2 );
187
-				}
188
-			}
189
-		}
190
-
191
-		/**
192
-		 * Add a Google Fonts preconnect link.
193
-		 *
194
-		 * @param array  $urls              HTML to be added.
195
-		 * @param string $relationship_type Handle name.
196
-		 *
197
-		 * @return      array
198
-		 * @since       4.1.15
199
-		 * @access      public
200
-		 */
201
-		public function google_fonts_preconnect( array $urls, string $relationship_type ): array {
202
-			if ( 'preconnect' !== $relationship_type ) {
203
-				return $urls;
204
-			}
205
-			$urls[] = array(
206
-				'rel'  => 'preconnect',
207
-				'href' => 'https://fonts.gstatic.com',
208
-				'crossorigin',
209
-			);
210
-			return $urls;
211
-		}
212
-
213
-		/**
214
-		 * Filter to enhance the google fonts enqueue.
215
-		 *
216
-		 * @param string $html   HTML to be added.
217
-		 * @param string $handle Handle name.
218
-		 * @param string $href   HREF URL of a script.
219
-		 *
220
-		 * @return      string
221
-		 * @since       4.1.15
222
-		 * @access      public
223
-		 */
224
-		public function add_style_attributes( string $html = '', string $handle = '', string $href = '' ): string {
225
-			if ( Redux_Functions_Ex::string_starts_with( $handle, 'redux-google-fonts-' ) ) {
226
-				// Revamp thanks to Harry: https://csswizardry.com/2020/05/the-fastest-google-fonts/.
227
-				$href      = str_replace( array( '|', ' ' ), array( '%7C', '%20' ), urldecode( $href ) );
228
-				$new_html  = '<link rel="preload" as="style" href="' . esc_attr( $href ) . '" />';
229
-				$new_html .= '<link rel="stylesheet" href="' . esc_attr( $href ) . '" media="print" onload="this.media=\'all\'">';  // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
230
-				$new_html .= '<noscript><link rel="stylesheet" href="' . esc_attr( $href ) . '" /></noscript>'; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
231
-				$html      = $new_html;
232
-			}
233
-
234
-			return $html;
235
-		}
236
-
237
-		/**
238
-		 * Function to output output_variables to the dynamic output.
239
-		 *
240
-		 * @param ReduxFramework $core       ReduxFramework core pointer.
241
-		 * @param array          $section    Section containing this field.
242
-		 * @param array          $field      Field object.
243
-		 * @param array|string   $value      Current value of field.
244
-		 * @param string|null    $style_data CSS output string to append to the root output variable.
245
-		 *
246
-		 * @return      void
247
-		 * @since       4.0.3
248
-		 * @access      public
249
-		 */
250
-		private function output_variables( ReduxFramework $core, array $section = array(), array $field = array(), $value = array(), ?string $style_data = '' ) {
251
-			// Let's allow section overrides, please.
252
-			if ( isset( $section['output_variables'] ) && ! isset( $field['output_variables'] ) ) {
253
-				$field['output_variables'] = $section['output_variables'];
254
-			}
255
-			if ( isset( $section['output_variables_prefix'] ) && ! isset( $field['output_variables_prefix'] ) ) {
256
-				$field['output_variables_prefix'] = $section['output_variables_prefix'];
257
-			}
258
-			if ( isset( $field['output_variables'] ) && $field['output_variables'] ) {
259
-				$output_variables_prefix = $core->args['output_variables_prefix'];
260
-				if ( isset( $field['output_variables_prefix'] ) && ! empty( $field['output_variables_prefix'] ) ) {
261
-					$output_variables_prefix = $field['output_variables_prefix'];
262
-				} elseif ( isset( $section['output_variables_prefix'] ) && ! empty( $section['output_variables_prefix'] ) ) {
263
-					$output_variables_prefix = $section['output_variables_prefix'];
264
-				}
265
-
266
-				if ( is_array( $value ) ) {
267
-					$val_pieces = array_filter( $value, 'strlen' );
268
-					// We don't need to show the Google boolean.
269
-					if ( 'typography' === $field['type'] && isset( $val_pieces['google'] ) ) {
270
-						unset( $val_pieces['google'] );
271
-					}
272
-
273
-					foreach ( $val_pieces as $val_key => $val_val ) {
274
-						$val_key                            = $output_variables_prefix . sanitize_title_with_dashes( $field['id'] ) . '-' . $val_key;
275
-						$core->output_variables[ $val_key ] = $val_val;
276
-						if ( ! empty( $style_data ) ) {
277
-							$val_key                            = $output_variables_prefix . sanitize_title_with_dashes( $field['id'] );
278
-							$core->output_variables[ $val_key ] = $style_data;
279
-						}
280
-					}
281
-				} else {
282
-					$val_key = $output_variables_prefix . sanitize_title_with_dashes( $field['id'] );
283
-
284
-					if ( ! empty( $style_data ) ) {
285
-						$core->output_variables[ $val_key ] = $style_data;
286
-					} else {
287
-						$core->output_variables[ $val_key ] = $value;
288
-					}
289
-				}
290
-			}
291
-		}
292
-
293
-		/**
294
-		 * Output dynamic CSS at the bottom of HEAD
295
-		 *
296
-		 * @return      void
297
-		 * @since       3.2.8
298
-		 * @access      public
299
-		 */
300
-		public function output_css() {
301
-			$core = $this->core();
302
-
303
-			if ( false === $core->args['output'] && false === $core->args['compiler'] && empty( $core->output_variables ) ) {
304
-				return;
305
-			}
306
-
307
-			if ( true === Redux_Core::$no_output ) {
308
-				return;
309
-			}
310
-
311
-			if ( ! empty( $core->output_variables ) ) {
312
-				$root_css = ':root{';
313
-				foreach ( $core->output_variables as $key => $value ) {
314
-					$root_css .= "$key:$value;";
315
-				}
316
-				$root_css .= '}';
317
-				// phpcs:ignore WordPress.NamingConventions.ValidVariableName, WordPress.Security.EscapeOutput
318
-				$core->outputCSS = $root_css . $core->outputCSS;
319
-			}
320
-
321
-			// phpcs:ignore WordPress.NamingConventions.ValidVariableName
322
-			if ( ! empty( $core->outputCSS ) && ( true === $core->args['output_tag'] || ( isset( $_POST['customized'] ) && isset( $_POST['nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'preview-customize_' . wp_get_theme()->get_stylesheet() ) ) ) ) {
323
-				// phpcs:ignore WordPress.NamingConventions.ValidVariableName, WordPress.Security.EscapeOutput
324
-				echo '<style id="' . esc_attr( $core->args['opt_name'] ) . '-dynamic-css" title="dynamic-css" class="redux-options-output">' . $core->outputCSS . '</style>';
325
-			}
326
-		}
327
-
328
-		/**
329
-		 * Can Output CSS
330
-		 * Check if a field meets its requirements before outputting to CSS
331
-		 *
332
-		 * @param ReduxFramework $core  ReduxFramework core pointer.
333
-		 * @param array          $field Field array.
334
-		 *
335
-		 * @return bool
336
-		 */
337
-		private function can_output_css( ReduxFramework $core, array $field ): ?bool {
338
-			$return = true;
339
-
340
-			// phpcs:ignore WordPress.NamingConventions.ValidHookName
341
-			$field = apply_filters( "redux/field/{$core->args['opt_name']}/_can_output_css", $field );
342
-
343
-			if ( isset( $field['force_output'] ) && true === $field['force_output'] ) {
344
-				return true;
345
-			}
346
-
347
-			if ( ! empty( $field['required'] ) ) {
348
-				if ( isset( $field['required'][0] ) ) {
349
-					if ( ! is_array( $field['required'][0] ) && 3 === count( $field['required'] ) ) {
350
-						$parent_value = $GLOBALS[ $core->args['global_variable'] ][ $field['required'][0] ] ?? '';
351
-						$check_value  = $field['required'][2];
352
-						$operation    = $field['required'][1];
353
-						$return       = $core->required_class->compare_value_dependencies( $parent_value, $check_value, $operation );
354
-					} elseif ( is_array( $field['required'][0] ) ) {
355
-						foreach ( $field['required'] as $required ) {
356
-							if ( isset( $required[0] ) && ! is_array( $required[0] ) && 3 === count( $required ) ) {
357
-								$parent_value = $GLOBALS[ $core->args['global_variable'] ][ $required[0] ] ?? '';
358
-								$check_value  = $required[2];
359
-								$operation    = $required[1];
360
-								$return       = $core->required_class->compare_value_dependencies( $parent_value, $check_value, $operation );
361
-							}
362
-							if ( ! $return ) {
363
-								return $return;
364
-							}
365
-						}
366
-					}
367
-				}
368
-			}
369
-
370
-			return $return;
371
-		}
372
-	}
15
+    /**
16
+     * Class Redux_Output
17
+     */
18
+    class Redux_Output extends Redux_Class {
19
+
20
+        /**
21
+         * Redux_Output constructor.
22
+         *
23
+         * @param object $redux ReduxFramework pointer.
24
+         */
25
+        public function __construct( $redux ) {
26
+            parent::__construct( $redux );
27
+
28
+            // Output dynamic CSS.
29
+            // Frontend: Maybe enqueue dynamic CSS and Google fonts.
30
+            if ( empty( $this->args['output_location'] ) || in_array( 'frontend', $this->args['output_location'], true ) ) {
31
+                add_action( 'wp_head', array( $this, 'output_css' ), 150 );
32
+                add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ), 150 );
33
+            }
34
+
35
+            // Login page: Maybe enqueue dynamic CSS and Google fonts.
36
+            if ( in_array( 'login', $this->args['output_location'], true ) ) {
37
+                add_action( 'login_head', array( $this, 'output_css' ), 150 );
38
+                add_action( 'login_enqueue_scripts', array( $this, 'enqueue' ), 150 );
39
+            }
40
+
41
+            // Admin area: Maybe enqueue dynamic CSS and Google fonts.
42
+            if ( in_array( 'admin', $this->args['output_location'], true ) ) {
43
+                add_action( 'admin_head', array( $this, 'output_css' ), 150 );
44
+                add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ), 150 );
45
+            }
46
+
47
+            // phpcs:ignore WordPress.NamingConventions.ValidHookName
48
+            do_action( "redux/output/{$this->parent->args['opt_name']}/construct", $this );
49
+            // Useful for adding different locations for CSS output.
50
+        }
51
+
52
+        /**
53
+         * Enqueue CSS and Google fonts for front end
54
+         *
55
+         * @return void
56
+         * @throws ReflectionException Exception.
57
+         * @since  1.0.0
58
+         * @access public
59
+         */
60
+        public function enqueue() {
61
+            $core = $this->core();
62
+
63
+            if ( false === $core->args['output'] && false === $core->args['compiler'] ) {
64
+                return;
65
+            }
66
+
67
+            foreach ( $core->sections as $k => $section ) {
68
+                if ( isset( $section['type'] ) && ( 'divide' === $section['type'] ) ) {
69
+                    continue;
70
+                }
71
+
72
+                if ( isset( $section['fields'] ) ) {
73
+                    foreach ( $section['fields'] as $fieldk => $field ) {
74
+                        if ( isset( $field['type'] ) && 'callback' !== $field['type'] ) {
75
+                            $field_classes = array( 'Redux_' . $field['type'], 'ReduxFramework_' . $field['type'] );
76
+
77
+                            $field_class = Redux_Functions::class_exists_ex( $field_classes );
78
+
79
+                            if ( false === $field_class ) {
80
+                                if ( ! isset( $field['compiler'] ) ) {
81
+                                    $field['compiler'] = '';
82
+                                }
83
+
84
+                                $field_type = str_replace( '_', '-', $field['type'] );
85
+                                $core_path  = Redux_Core::$dir . "inc/fields/{$field['type']}/class-redux-$field_type.php";
86
+
87
+                                if ( ! file_exists( $core_path ) ) {
88
+                                    $core_path = Redux_Core::$dir . "inc/fields/{$field['type']}/field_{$field['type']}.php";
89
+                                }
90
+
91
+                                $filter_path = $core_path;
92
+
93
+                                /**
94
+                                 * Field class file
95
+                                 * filter 'redux/{opt_name}/field/class/{field.type}'
96
+                                 *
97
+                                 * @param string $file field class file.
98
+                                 * @param array $field field config data
99
+                                 */
100
+
101
+                                // phpcs:ignore WordPress.NamingConventions.ValidHookName
102
+                                $class_file = apply_filters( "redux/{$core->args['opt_name']}/field/class/{$field['type']}", $filter_path, $field );
103
+
104
+                                if ( $class_file && file_exists( $class_file ) ) {
105
+                                    require_once $class_file;
106
+
107
+                                    $field_class = Redux_Functions::class_exists_ex( $field_classes );
108
+                                }
109
+                            }
110
+
111
+                            $field['default'] = $field['default'] ?? '';
112
+                            $value            = $core->options[ $field['id'] ] ?? $field['default'];
113
+                            $style_data       = '';
114
+
115
+                            if ( empty( $field_class ) ) {
116
+                                continue;
117
+                            }
118
+
119
+                            $field_object = new $field_class( $field, $value, $core );
120
+
121
+                            if ( ! empty( $core->options[ $field['id'] ] ) && class_exists( $field_class ) && method_exists( $field_class, 'output' ) && $this->can_output_css( $core, $field ) ) {
122
+
123
+                                // phpcs:ignore WordPress.NamingConventions.ValidHookName
124
+                                $field = apply_filters( "redux/field/{$core->args['opt_name']}/output_css", $field );
125
+
126
+                                if ( ! empty( $field['output'] ) && ! is_array( $field['output'] ) ) {
127
+                                    $field['output'] = array( $field['output'] );
128
+                                }
129
+
130
+                                if ( ( ( isset( $field['output'] ) && ! empty( $field['output'] ) ) || ( isset( $field['compiler'] ) && ! empty( $field['compiler'] ) ) || ( isset( $field['media_query'] ) && ! empty( $field['media_query'] ) ) || 'typography' === $field['type'] || 'icon_select' === $field['type'] || 'social_profiles' === $field['type'] ) ) {
131
+                                    if ( method_exists( $field_class, 'css_style' ) ) {
132
+                                        $style_data = $field_object->css_style( $field_object->value );
133
+                                    }
134
+                                }
135
+
136
+                                if ( null !== $style_data ) {
137
+                                    if ( ( ( isset( $field['output'] ) && ! empty( $field['output'] ) ) || ( isset( $field['compiler'] ) && ! empty( $field['compiler'] ) ) || 'typography' === $field['type'] || 'icon_select' === $field['type'] || 'social_profiles' === $field['type'] ) ) {
138
+                                        $field_object->output( $style_data );
139
+                                    }
140
+
141
+                                    if ( isset( $field['media_query'] ) && ! empty( $field['media_query'] ) ) {
142
+                                        $field_object->media_query( $style_data );
143
+                                    }
144
+                                }
145
+                            }
146
+
147
+                            // phpcs:ignore WordPress.NamingConventions.ValidHookName
148
+                            do_action( "redux/field/{$core->args['opt_name']}/output_loop", $core, $field, $value, $style_data );
149
+
150
+                            // phpcs:ignore WordPress.NamingConventions.ValidHookName
151
+                            do_action( "redux/field/{$core->args['opt_name']}/output_loop/{$field['type']}", $core, $field, $value, $style_data );
152
+
153
+                            if ( method_exists( $field_class, 'output_variables' ) && $this->can_output_css( $core, $field ) ) {
154
+                                $passed_style_data = $field_object->output_variables( $style_data );
155
+                                $this->output_variables( $core, $section, $field, $value, $passed_style_data );
156
+                            }
157
+                        }
158
+                    }
159
+
160
+                    if ( ! empty( $core->outputCSS ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
161
+                        // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
162
+                        $core->outputCSS = html_entity_decode( $core->outputCSS, ENT_QUOTES, 'UTF-8' );
163
+                    }
164
+                }
165
+            }
166
+
167
+            // For use like in the customizer. Stops the output, but passes the CSS in the variable for the compiler.
168
+            if ( true === Redux_Core::$no_output ) {
169
+                return;
170
+            }
171
+
172
+            if ( ! empty( Redux_Core::$typography ) && filter_var( $core->args['output'], FILTER_VALIDATE_BOOLEAN ) ) {
173
+                $version = ! empty( $core->transients['last_save'] ) ? $core->transients['last_save'] : '';
174
+                if ( ! class_exists( 'Redux_Typography' ) ) {
175
+                    require_once Redux_Core::$dir . '/inc/fields/typography/class-redux-typography.php';
176
+                }
177
+
178
+                $typography = new Redux_Typography( null, null, $core );
179
+
180
+                $core->args['disable_google_fonts_link'] = ( ! isset( $core->args['disable_google_fonts_link'] ) ? false : $core->args['disable_google_fonts_link'] );
181
+
182
+                if ( ! $core->args['disable_google_fonts_link'] ) {
183
+                    $url = $typography->make_google_web_font_link( Redux_Core::$typography );
184
+                    wp_enqueue_style( 'redux-google-fonts-' . $core->args['opt_name'], $url, array(), $version );
185
+                    add_filter( 'style_loader_tag', array( $this, 'add_style_attributes' ), 10, 4 );
186
+                    add_filter( 'wp_resource_hints', array( $this, 'google_fonts_preconnect' ), 10, 2 );
187
+                }
188
+            }
189
+        }
190
+
191
+        /**
192
+         * Add a Google Fonts preconnect link.
193
+         *
194
+         * @param array  $urls              HTML to be added.
195
+         * @param string $relationship_type Handle name.
196
+         *
197
+         * @return      array
198
+         * @since       4.1.15
199
+         * @access      public
200
+         */
201
+        public function google_fonts_preconnect( array $urls, string $relationship_type ): array {
202
+            if ( 'preconnect' !== $relationship_type ) {
203
+                return $urls;
204
+            }
205
+            $urls[] = array(
206
+                'rel'  => 'preconnect',
207
+                'href' => 'https://fonts.gstatic.com',
208
+                'crossorigin',
209
+            );
210
+            return $urls;
211
+        }
212
+
213
+        /**
214
+         * Filter to enhance the google fonts enqueue.
215
+         *
216
+         * @param string $html   HTML to be added.
217
+         * @param string $handle Handle name.
218
+         * @param string $href   HREF URL of a script.
219
+         *
220
+         * @return      string
221
+         * @since       4.1.15
222
+         * @access      public
223
+         */
224
+        public function add_style_attributes( string $html = '', string $handle = '', string $href = '' ): string {
225
+            if ( Redux_Functions_Ex::string_starts_with( $handle, 'redux-google-fonts-' ) ) {
226
+                // Revamp thanks to Harry: https://csswizardry.com/2020/05/the-fastest-google-fonts/.
227
+                $href      = str_replace( array( '|', ' ' ), array( '%7C', '%20' ), urldecode( $href ) );
228
+                $new_html  = '<link rel="preload" as="style" href="' . esc_attr( $href ) . '" />';
229
+                $new_html .= '<link rel="stylesheet" href="' . esc_attr( $href ) . '" media="print" onload="this.media=\'all\'">';  // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
230
+                $new_html .= '<noscript><link rel="stylesheet" href="' . esc_attr( $href ) . '" /></noscript>'; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
231
+                $html      = $new_html;
232
+            }
233
+
234
+            return $html;
235
+        }
236
+
237
+        /**
238
+         * Function to output output_variables to the dynamic output.
239
+         *
240
+         * @param ReduxFramework $core       ReduxFramework core pointer.
241
+         * @param array          $section    Section containing this field.
242
+         * @param array          $field      Field object.
243
+         * @param array|string   $value      Current value of field.
244
+         * @param string|null    $style_data CSS output string to append to the root output variable.
245
+         *
246
+         * @return      void
247
+         * @since       4.0.3
248
+         * @access      public
249
+         */
250
+        private function output_variables( ReduxFramework $core, array $section = array(), array $field = array(), $value = array(), ?string $style_data = '' ) {
251
+            // Let's allow section overrides, please.
252
+            if ( isset( $section['output_variables'] ) && ! isset( $field['output_variables'] ) ) {
253
+                $field['output_variables'] = $section['output_variables'];
254
+            }
255
+            if ( isset( $section['output_variables_prefix'] ) && ! isset( $field['output_variables_prefix'] ) ) {
256
+                $field['output_variables_prefix'] = $section['output_variables_prefix'];
257
+            }
258
+            if ( isset( $field['output_variables'] ) && $field['output_variables'] ) {
259
+                $output_variables_prefix = $core->args['output_variables_prefix'];
260
+                if ( isset( $field['output_variables_prefix'] ) && ! empty( $field['output_variables_prefix'] ) ) {
261
+                    $output_variables_prefix = $field['output_variables_prefix'];
262
+                } elseif ( isset( $section['output_variables_prefix'] ) && ! empty( $section['output_variables_prefix'] ) ) {
263
+                    $output_variables_prefix = $section['output_variables_prefix'];
264
+                }
265
+
266
+                if ( is_array( $value ) ) {
267
+                    $val_pieces = array_filter( $value, 'strlen' );
268
+                    // We don't need to show the Google boolean.
269
+                    if ( 'typography' === $field['type'] && isset( $val_pieces['google'] ) ) {
270
+                        unset( $val_pieces['google'] );
271
+                    }
272
+
273
+                    foreach ( $val_pieces as $val_key => $val_val ) {
274
+                        $val_key                            = $output_variables_prefix . sanitize_title_with_dashes( $field['id'] ) . '-' . $val_key;
275
+                        $core->output_variables[ $val_key ] = $val_val;
276
+                        if ( ! empty( $style_data ) ) {
277
+                            $val_key                            = $output_variables_prefix . sanitize_title_with_dashes( $field['id'] );
278
+                            $core->output_variables[ $val_key ] = $style_data;
279
+                        }
280
+                    }
281
+                } else {
282
+                    $val_key = $output_variables_prefix . sanitize_title_with_dashes( $field['id'] );
283
+
284
+                    if ( ! empty( $style_data ) ) {
285
+                        $core->output_variables[ $val_key ] = $style_data;
286
+                    } else {
287
+                        $core->output_variables[ $val_key ] = $value;
288
+                    }
289
+                }
290
+            }
291
+        }
292
+
293
+        /**
294
+         * Output dynamic CSS at the bottom of HEAD
295
+         *
296
+         * @return      void
297
+         * @since       3.2.8
298
+         * @access      public
299
+         */
300
+        public function output_css() {
301
+            $core = $this->core();
302
+
303
+            if ( false === $core->args['output'] && false === $core->args['compiler'] && empty( $core->output_variables ) ) {
304
+                return;
305
+            }
306
+
307
+            if ( true === Redux_Core::$no_output ) {
308
+                return;
309
+            }
310
+
311
+            if ( ! empty( $core->output_variables ) ) {
312
+                $root_css = ':root{';
313
+                foreach ( $core->output_variables as $key => $value ) {
314
+                    $root_css .= "$key:$value;";
315
+                }
316
+                $root_css .= '}';
317
+                // phpcs:ignore WordPress.NamingConventions.ValidVariableName, WordPress.Security.EscapeOutput
318
+                $core->outputCSS = $root_css . $core->outputCSS;
319
+            }
320
+
321
+            // phpcs:ignore WordPress.NamingConventions.ValidVariableName
322
+            if ( ! empty( $core->outputCSS ) && ( true === $core->args['output_tag'] || ( isset( $_POST['customized'] ) && isset( $_POST['nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'preview-customize_' . wp_get_theme()->get_stylesheet() ) ) ) ) {
323
+                // phpcs:ignore WordPress.NamingConventions.ValidVariableName, WordPress.Security.EscapeOutput
324
+                echo '<style id="' . esc_attr( $core->args['opt_name'] ) . '-dynamic-css" title="dynamic-css" class="redux-options-output">' . $core->outputCSS . '</style>';
325
+            }
326
+        }
327
+
328
+        /**
329
+         * Can Output CSS
330
+         * Check if a field meets its requirements before outputting to CSS
331
+         *
332
+         * @param ReduxFramework $core  ReduxFramework core pointer.
333
+         * @param array          $field Field array.
334
+         *
335
+         * @return bool
336
+         */
337
+        private function can_output_css( ReduxFramework $core, array $field ): ?bool {
338
+            $return = true;
339
+
340
+            // phpcs:ignore WordPress.NamingConventions.ValidHookName
341
+            $field = apply_filters( "redux/field/{$core->args['opt_name']}/_can_output_css", $field );
342
+
343
+            if ( isset( $field['force_output'] ) && true === $field['force_output'] ) {
344
+                return true;
345
+            }
346
+
347
+            if ( ! empty( $field['required'] ) ) {
348
+                if ( isset( $field['required'][0] ) ) {
349
+                    if ( ! is_array( $field['required'][0] ) && 3 === count( $field['required'] ) ) {
350
+                        $parent_value = $GLOBALS[ $core->args['global_variable'] ][ $field['required'][0] ] ?? '';
351
+                        $check_value  = $field['required'][2];
352
+                        $operation    = $field['required'][1];
353
+                        $return       = $core->required_class->compare_value_dependencies( $parent_value, $check_value, $operation );
354
+                    } elseif ( is_array( $field['required'][0] ) ) {
355
+                        foreach ( $field['required'] as $required ) {
356
+                            if ( isset( $required[0] ) && ! is_array( $required[0] ) && 3 === count( $required ) ) {
357
+                                $parent_value = $GLOBALS[ $core->args['global_variable'] ][ $required[0] ] ?? '';
358
+                                $check_value  = $required[2];
359
+                                $operation    = $required[1];
360
+                                $return       = $core->required_class->compare_value_dependencies( $parent_value, $check_value, $operation );
361
+                            }
362
+                            if ( ! $return ) {
363
+                                return $return;
364
+                            }
365
+                        }
366
+                    }
367
+                }
368
+            }
369
+
370
+            return $return;
371
+        }
372
+    }
373 373
 }
Please login to merge, or discard this patch.
redux-core/inc/fields/typography/class-redux-typography.php 1 patch
Indentation   +1350 added lines, -1350 removed lines patch added patch discarded remove patch
@@ -12,357 +12,357 @@  discard block
 block discarded – undo
12 12
 
13 13
 if ( ! class_exists( 'Redux_Typography', false ) ) {
14 14
 
15
-	/**
16
-	 * Class Redux_Typography
17
-	 */
18
-	class Redux_Typography extends Redux_Field {
19
-
20
-		/**
21
-		 * Array of data for typography preview.
22
-		 *
23
-		 * @var array
24
-		 */
25
-		private $typography_preview = array();
26
-
27
-		/**
28
-		 *  Standard font array.
29
-		 *
30
-		 * @var array $std_fonts
31
-		 */
32
-		private $std_fonts = array(
33
-			'Arial, Helvetica, sans-serif'            => 'Arial, Helvetica, sans-serif',
34
-			'\'Arial Black\', Gadget, sans-serif'     => '\'Arial Black\', Gadget, sans-serif',
35
-			'\'Bookman Old Style\', serif'            => '\'Bookman Old Style\', serif',
36
-			'\'Comic Sans MS\', cursive'              => '\'Comic Sans MS\', cursive',
37
-			'Courier, monospace'                      => 'Courier, monospace',
38
-			'Garamond, serif'                         => 'Garamond, serif',
39
-			'Georgia, serif'                          => 'Georgia, serif',
40
-			'Impact, Charcoal, sans-serif'            => 'Impact, Charcoal, sans-serif',
41
-			'\'Lucida Console\', Monaco, monospace'   => '\'Lucida Console\', Monaco, monospace',
42
-			'\'Lucida Sans Unicode\', \'Lucida Grande\', sans-serif' => '\'Lucida Sans Unicode\', \'Lucida Grande\', sans-serif',
43
-			'\'MS Sans Serif\', Geneva, sans-serif'   => '\'MS Sans Serif\', Geneva, sans-serif',
44
-			'\'MS Serif\', \'New York\', sans-serif'  => '\'MS Serif\', \'New York\', sans-serif',
45
-			'\'Palatino Linotype\', \'Book Antiqua\', Palatino, serif' => '\'Palatino Linotype\', \'Book Antiqua\', Palatino, serif',
46
-			'Tahoma,Geneva, sans-serif'               => 'Tahoma, Geneva, sans-serif',
47
-			'\'Times New Roman\', Times,serif'        => '\'Times New Roman\', Times, serif',
48
-			'\'Trebuchet MS\', Helvetica, sans-serif' => '\'Trebuchet MS\', Helvetica, sans-serif',
49
-			'Verdana, Geneva, sans-serif'             => 'Verdana, Geneva, sans-serif',
50
-		);
51
-
52
-		/**
53
-		 * Default font weights.
54
-		 *
55
-		 * @var string[]
56
-		 */
57
-		private $default_font_weights = array(
58
-			'400'       => 'Normal 400',
59
-			'700'       => 'Bold 700',
60
-			'400italic' => 'Normal 400 Italic',
61
-			'700italic' => 'Bold 700 Italic',
62
-		);
63
-
64
-		/**
65
-		 * User font array.
66
-		 *
67
-		 * @var bool $user_fonts
68
-		 */
69
-		private $user_fonts = true;
70
-
71
-		/**
72
-		 * Redux_Field constructor.
73
-		 *
74
-		 * @param array  $field  Field array.
75
-		 * @param string $value  Field values.
76
-		 * @param null   $redux  ReduxFramework object pointer.
77
-		 *
78
-		 * @throws ReflectionException Exception.
79
-		 */
80
-		public function __construct( $field = array(), $value = null, $redux = null ) { // phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod
81
-			parent::__construct( $field, $value, $redux );
82
-
83
-			$this->parent = $redux;
84
-			$this->field  = $field;
85
-			$this->value  = $value;
86
-
87
-			$this->set_defaults();
88
-
89
-			$path_info = Redux_Helpers::path_info( __FILE__ );
90
-			$this->dir = trailingslashit( dirname( $path_info['real_path'] ) );
91
-			$this->url = trailingslashit( dirname( $path_info['url'] ) );
92
-
93
-			$this->timestamp = Redux_Core::$version;
94
-			if ( $redux->args['dev_mode'] ) {
95
-				$this->timestamp .= '.' . time();
96
-			}
97
-		}
98
-
99
-		/**
100
-		 * Sets default values for field.
101
-		 */
102
-		public function set_defaults() {
103
-			// Shim out old arg to new.
104
-			if ( isset( $this->field['all_styles'] ) && ! empty( $this->field['all_styles'] ) ) {
105
-				$this->field['all-styles'] = $this->field['all_styles'];
106
-				unset( $this->field['all_styles'] );
107
-			}
108
-
109
-			$defaults = array(
110
-				'font-family'             => true,
111
-				'font-size'               => true,
112
-				'font-weight'             => true,
113
-				'font-style'              => true,
114
-				'font-backup'             => false,
115
-				'subsets'                 => true,
116
-				'custom_fonts'            => true,
117
-				'text-align'              => true,
118
-				'text-transform'          => false,
119
-				'font-variant'            => false,
120
-				'text-decoration'         => false,
121
-				'color'                   => true,
122
-				'preview'                 => true,
123
-				'line-height'             => true,
124
-				'multi'                   => array(
125
-					'subsets' => false,
126
-					'weight'  => false,
127
-				),
128
-				'word-spacing'            => false,
129
-				'letter-spacing'          => false,
130
-				'google'                  => true,
131
-				'font_family_clear'       => true,
132
-				'allow_empty_line_height' => false,
133
-				'margin-top'              => false,
134
-				'margin-bottom'           => false,
135
-				'text-shadow'             => false,
136
-				'word-spacing-unit'       => '',
137
-				'letter-spacing-unit'     => '',
138
-				'font-size-unit'          => '',
139
-				'margin-top-unit'         => '',
140
-				'margin-bottom-unit'      => '',
141
-			);
142
-
143
-			$this->field = wp_parse_args( $this->field, $defaults );
144
-
145
-			if ( isset( $this->field['color_alpha'] ) ) {
146
-				if ( is_array( $this->field['color_alpha'] ) ) {
147
-					$this->field['color_alpha']['color']        = $this->field['color_alpha']['color'] ?? false;
148
-					$this->field['color_alpha']['shadow-color'] = $this->field['color_alpha']['shadow-color'] ?? false;
149
-				} else {
150
-					$mode                                       = $this->field['color_alpha'];
151
-					$this->field['color_alpha']                 = array();
152
-					$this->field['color_alpha']['color']        = $mode;
153
-					$this->field['color_alpha']['shadow-color'] = $mode;
154
-				}
155
-			} else {
156
-				$this->field['color_alpha']['color']        = false;
157
-				$this->field['color_alpha']['shadow-color'] = false;
158
-			}
159
-
160
-			// Set value defaults.
161
-			$defaults = array(
162
-				'font-family'       => '',
163
-				'font-options'      => '',
164
-				'font-backup'       => '',
165
-				'text-align'        => '',
166
-				'text-transform'    => '',
167
-				'font-variant'      => '',
168
-				'text-decoration'   => '',
169
-				'line-height'       => '',
170
-				'word-spacing'      => '',
171
-				'letter-spacing'    => '',
172
-				'subsets'           => '',
173
-				'google'            => false,
174
-				'font-script'       => '',
175
-				'font-weight'       => '',
176
-				'font-style'        => '',
177
-				'color'             => '',
178
-				'font-size'         => '',
179
-				'margin-top'        => '',
180
-				'margin-bottom'     => '',
181
-				'shadow-color'      => '#000000',
182
-				'shadow-horizontal' => '1',
183
-				'shadow-vertical'   => '1',
184
-				'shadow-blur'       => '4',
185
-			);
186
-
187
-			$this->value = wp_parse_args( $this->value, $defaults );
188
-
189
-			if ( empty( $this->field['units'] ) || ! in_array( $this->field['units'], Redux_Helpers::$array_units, true ) ) {
190
-				$this->field['units'] = 'px';
191
-			}
192
-
193
-			// Get the Google array.
194
-			$this->get_google_array();
195
-
196
-			if ( empty( $this->field['fonts'] ) ) {
197
-				$this->user_fonts     = false;
198
-				$this->field['fonts'] = $this->std_fonts;
199
-			}
200
-
201
-			$this->field['weights'] = $this->field['weights'] ?? $this->default_font_weights;
202
-
203
-			// Localize std fonts.
204
-			$this->localize_std_fonts();
205
-		}
206
-
207
-		/**
208
-		 * Localize font array
209
-		 *
210
-		 * @param array  $field Field array.
211
-		 * @param string $value Value.
212
-		 *
213
-		 * @return array
214
-		 */
215
-		public function localize( array $field, string $value = '' ): array {
216
-			$params = array();
217
-
218
-			if ( true === $this->user_fonts && ! empty( $this->field['fonts'] ) ) {
219
-				$params['std_font'] = $this->field['fonts'];
220
-			}
221
-
222
-			return $params;
223
-		}
224
-
225
-		/**
226
-		 * Field Render Function.
227
-		 * Takes the vars and outputs the HTML for the field in the settings
228
-		 *
229
-		 * @since ReduxFramework 1.0.0
230
-		 */
231
-		public function render() {
232
-			// Since fonts declared is CSS (@font-face) are not rendered in the preview,
233
-			// they can be declared in a CSS file and passed here, so they DO display in
234
-			// font preview.  Do NOT pass style.css in your theme, as that will mess up
235
-			// admin page styling.  It's recommended to pass a CSS file with ONLY font
236
-			// declarations.
237
-			// If field is set and not blank, then enqueue field.
238
-			if ( isset( $this->field['ext-font-css'] ) && '' !== $this->field['ext-font-css'] ) {
239
-				wp_enqueue_style( 'redux-external-fonts', $this->field['ext-font-css'], array(), $this->timestamp );
240
-			}
241
-
242
-			if ( empty( $this->field['units'] ) && ! empty( $this->field['default']['units'] ) ) {
243
-				$this->field['units'] = $this->field['default']['units'];
244
-			}
245
-
246
-			$unit = $this->field['units'];
247
-
248
-			echo '<div id="' . esc_attr( $this->field['id'] ) . '" class="redux-typography-container" data-id="' . esc_attr( $this->field['id'] ) . '" data-units="' . esc_attr( $unit ) . '">';
249
-
250
-			$this->select2_config['allowClear'] = true;
251
-
252
-			if ( isset( $this->field['select2'] ) ) {
253
-				$this->field['select2'] = wp_parse_args( $this->field['select2'], $this->select2_config );
254
-			} else {
255
-				$this->field['select2'] = $this->select2_config;
256
-			}
257
-
258
-			$this->field['select2'] = Redux_Functions::sanitize_camel_case_array_keys( $this->field['select2'] );
259
-
260
-			$select2_data = Redux_Functions::create_data_string( $this->field['select2'] );
261
-
262
-			$google_set     = false;
263
-			$is_google_font = '0';
264
-
265
-			// If no fontFamily array exists, create one and set array 0
266
-			// with font value.
267
-			if ( ! isset( $font_family ) ) {
268
-				$font_family    = array();
269
-				$font_family[0] = $this->value['font-family'];
270
-				$font_family[1] = '';
271
-			}
272
-
273
-			/* Font Family */
274
-			if ( true === $this->field['font-family'] ) {
275
-				if ( filter_var( $this->value['google'], FILTER_VALIDATE_BOOLEAN ) ) {
276
-
277
-					// Divide and conquer.
278
-					$font_family = explode( ', ', $this->value['font-family'], 2 );
279
-
280
-					// If array 0 is empty and array 1 is not.
281
-					if ( empty( $font_family[0] ) && ! empty( $font_family[1] ) ) {
282
-
283
-						// Make array 0 = array 1.
284
-						$font_family[0] = $font_family[1];
285
-					}
286
-				}
287
-
288
-				// Is selected font a Google font.
289
-				if ( isset( Redux_Core::$fonts['google'][ $font_family[0] ] ) ) {
290
-					$is_google_font = '1';
291
-				}
292
-
293
-				// If not a Google font, show all font families.
294
-				if ( '1' !== $is_google_font ) {
295
-					$font_family[0] = $this->value['font-family'];
296
-				}
297
-
298
-				$user_fonts = '0';
299
-				if ( true === $this->user_fonts ) {
300
-					$user_fonts = '1';
301
-				}
302
-
303
-				echo '<input
15
+    /**
16
+     * Class Redux_Typography
17
+     */
18
+    class Redux_Typography extends Redux_Field {
19
+
20
+        /**
21
+         * Array of data for typography preview.
22
+         *
23
+         * @var array
24
+         */
25
+        private $typography_preview = array();
26
+
27
+        /**
28
+         *  Standard font array.
29
+         *
30
+         * @var array $std_fonts
31
+         */
32
+        private $std_fonts = array(
33
+            'Arial, Helvetica, sans-serif'            => 'Arial, Helvetica, sans-serif',
34
+            '\'Arial Black\', Gadget, sans-serif'     => '\'Arial Black\', Gadget, sans-serif',
35
+            '\'Bookman Old Style\', serif'            => '\'Bookman Old Style\', serif',
36
+            '\'Comic Sans MS\', cursive'              => '\'Comic Sans MS\', cursive',
37
+            'Courier, monospace'                      => 'Courier, monospace',
38
+            'Garamond, serif'                         => 'Garamond, serif',
39
+            'Georgia, serif'                          => 'Georgia, serif',
40
+            'Impact, Charcoal, sans-serif'            => 'Impact, Charcoal, sans-serif',
41
+            '\'Lucida Console\', Monaco, monospace'   => '\'Lucida Console\', Monaco, monospace',
42
+            '\'Lucida Sans Unicode\', \'Lucida Grande\', sans-serif' => '\'Lucida Sans Unicode\', \'Lucida Grande\', sans-serif',
43
+            '\'MS Sans Serif\', Geneva, sans-serif'   => '\'MS Sans Serif\', Geneva, sans-serif',
44
+            '\'MS Serif\', \'New York\', sans-serif'  => '\'MS Serif\', \'New York\', sans-serif',
45
+            '\'Palatino Linotype\', \'Book Antiqua\', Palatino, serif' => '\'Palatino Linotype\', \'Book Antiqua\', Palatino, serif',
46
+            'Tahoma,Geneva, sans-serif'               => 'Tahoma, Geneva, sans-serif',
47
+            '\'Times New Roman\', Times,serif'        => '\'Times New Roman\', Times, serif',
48
+            '\'Trebuchet MS\', Helvetica, sans-serif' => '\'Trebuchet MS\', Helvetica, sans-serif',
49
+            'Verdana, Geneva, sans-serif'             => 'Verdana, Geneva, sans-serif',
50
+        );
51
+
52
+        /**
53
+         * Default font weights.
54
+         *
55
+         * @var string[]
56
+         */
57
+        private $default_font_weights = array(
58
+            '400'       => 'Normal 400',
59
+            '700'       => 'Bold 700',
60
+            '400italic' => 'Normal 400 Italic',
61
+            '700italic' => 'Bold 700 Italic',
62
+        );
63
+
64
+        /**
65
+         * User font array.
66
+         *
67
+         * @var bool $user_fonts
68
+         */
69
+        private $user_fonts = true;
70
+
71
+        /**
72
+         * Redux_Field constructor.
73
+         *
74
+         * @param array  $field  Field array.
75
+         * @param string $value  Field values.
76
+         * @param null   $redux  ReduxFramework object pointer.
77
+         *
78
+         * @throws ReflectionException Exception.
79
+         */
80
+        public function __construct( $field = array(), $value = null, $redux = null ) { // phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod
81
+            parent::__construct( $field, $value, $redux );
82
+
83
+            $this->parent = $redux;
84
+            $this->field  = $field;
85
+            $this->value  = $value;
86
+
87
+            $this->set_defaults();
88
+
89
+            $path_info = Redux_Helpers::path_info( __FILE__ );
90
+            $this->dir = trailingslashit( dirname( $path_info['real_path'] ) );
91
+            $this->url = trailingslashit( dirname( $path_info['url'] ) );
92
+
93
+            $this->timestamp = Redux_Core::$version;
94
+            if ( $redux->args['dev_mode'] ) {
95
+                $this->timestamp .= '.' . time();
96
+            }
97
+        }
98
+
99
+        /**
100
+         * Sets default values for field.
101
+         */
102
+        public function set_defaults() {
103
+            // Shim out old arg to new.
104
+            if ( isset( $this->field['all_styles'] ) && ! empty( $this->field['all_styles'] ) ) {
105
+                $this->field['all-styles'] = $this->field['all_styles'];
106
+                unset( $this->field['all_styles'] );
107
+            }
108
+
109
+            $defaults = array(
110
+                'font-family'             => true,
111
+                'font-size'               => true,
112
+                'font-weight'             => true,
113
+                'font-style'              => true,
114
+                'font-backup'             => false,
115
+                'subsets'                 => true,
116
+                'custom_fonts'            => true,
117
+                'text-align'              => true,
118
+                'text-transform'          => false,
119
+                'font-variant'            => false,
120
+                'text-decoration'         => false,
121
+                'color'                   => true,
122
+                'preview'                 => true,
123
+                'line-height'             => true,
124
+                'multi'                   => array(
125
+                    'subsets' => false,
126
+                    'weight'  => false,
127
+                ),
128
+                'word-spacing'            => false,
129
+                'letter-spacing'          => false,
130
+                'google'                  => true,
131
+                'font_family_clear'       => true,
132
+                'allow_empty_line_height' => false,
133
+                'margin-top'              => false,
134
+                'margin-bottom'           => false,
135
+                'text-shadow'             => false,
136
+                'word-spacing-unit'       => '',
137
+                'letter-spacing-unit'     => '',
138
+                'font-size-unit'          => '',
139
+                'margin-top-unit'         => '',
140
+                'margin-bottom-unit'      => '',
141
+            );
142
+
143
+            $this->field = wp_parse_args( $this->field, $defaults );
144
+
145
+            if ( isset( $this->field['color_alpha'] ) ) {
146
+                if ( is_array( $this->field['color_alpha'] ) ) {
147
+                    $this->field['color_alpha']['color']        = $this->field['color_alpha']['color'] ?? false;
148
+                    $this->field['color_alpha']['shadow-color'] = $this->field['color_alpha']['shadow-color'] ?? false;
149
+                } else {
150
+                    $mode                                       = $this->field['color_alpha'];
151
+                    $this->field['color_alpha']                 = array();
152
+                    $this->field['color_alpha']['color']        = $mode;
153
+                    $this->field['color_alpha']['shadow-color'] = $mode;
154
+                }
155
+            } else {
156
+                $this->field['color_alpha']['color']        = false;
157
+                $this->field['color_alpha']['shadow-color'] = false;
158
+            }
159
+
160
+            // Set value defaults.
161
+            $defaults = array(
162
+                'font-family'       => '',
163
+                'font-options'      => '',
164
+                'font-backup'       => '',
165
+                'text-align'        => '',
166
+                'text-transform'    => '',
167
+                'font-variant'      => '',
168
+                'text-decoration'   => '',
169
+                'line-height'       => '',
170
+                'word-spacing'      => '',
171
+                'letter-spacing'    => '',
172
+                'subsets'           => '',
173
+                'google'            => false,
174
+                'font-script'       => '',
175
+                'font-weight'       => '',
176
+                'font-style'        => '',
177
+                'color'             => '',
178
+                'font-size'         => '',
179
+                'margin-top'        => '',
180
+                'margin-bottom'     => '',
181
+                'shadow-color'      => '#000000',
182
+                'shadow-horizontal' => '1',
183
+                'shadow-vertical'   => '1',
184
+                'shadow-blur'       => '4',
185
+            );
186
+
187
+            $this->value = wp_parse_args( $this->value, $defaults );
188
+
189
+            if ( empty( $this->field['units'] ) || ! in_array( $this->field['units'], Redux_Helpers::$array_units, true ) ) {
190
+                $this->field['units'] = 'px';
191
+            }
192
+
193
+            // Get the Google array.
194
+            $this->get_google_array();
195
+
196
+            if ( empty( $this->field['fonts'] ) ) {
197
+                $this->user_fonts     = false;
198
+                $this->field['fonts'] = $this->std_fonts;
199
+            }
200
+
201
+            $this->field['weights'] = $this->field['weights'] ?? $this->default_font_weights;
202
+
203
+            // Localize std fonts.
204
+            $this->localize_std_fonts();
205
+        }
206
+
207
+        /**
208
+         * Localize font array
209
+         *
210
+         * @param array  $field Field array.
211
+         * @param string $value Value.
212
+         *
213
+         * @return array
214
+         */
215
+        public function localize( array $field, string $value = '' ): array {
216
+            $params = array();
217
+
218
+            if ( true === $this->user_fonts && ! empty( $this->field['fonts'] ) ) {
219
+                $params['std_font'] = $this->field['fonts'];
220
+            }
221
+
222
+            return $params;
223
+        }
224
+
225
+        /**
226
+         * Field Render Function.
227
+         * Takes the vars and outputs the HTML for the field in the settings
228
+         *
229
+         * @since ReduxFramework 1.0.0
230
+         */
231
+        public function render() {
232
+            // Since fonts declared is CSS (@font-face) are not rendered in the preview,
233
+            // they can be declared in a CSS file and passed here, so they DO display in
234
+            // font preview.  Do NOT pass style.css in your theme, as that will mess up
235
+            // admin page styling.  It's recommended to pass a CSS file with ONLY font
236
+            // declarations.
237
+            // If field is set and not blank, then enqueue field.
238
+            if ( isset( $this->field['ext-font-css'] ) && '' !== $this->field['ext-font-css'] ) {
239
+                wp_enqueue_style( 'redux-external-fonts', $this->field['ext-font-css'], array(), $this->timestamp );
240
+            }
241
+
242
+            if ( empty( $this->field['units'] ) && ! empty( $this->field['default']['units'] ) ) {
243
+                $this->field['units'] = $this->field['default']['units'];
244
+            }
245
+
246
+            $unit = $this->field['units'];
247
+
248
+            echo '<div id="' . esc_attr( $this->field['id'] ) . '" class="redux-typography-container" data-id="' . esc_attr( $this->field['id'] ) . '" data-units="' . esc_attr( $unit ) . '">';
249
+
250
+            $this->select2_config['allowClear'] = true;
251
+
252
+            if ( isset( $this->field['select2'] ) ) {
253
+                $this->field['select2'] = wp_parse_args( $this->field['select2'], $this->select2_config );
254
+            } else {
255
+                $this->field['select2'] = $this->select2_config;
256
+            }
257
+
258
+            $this->field['select2'] = Redux_Functions::sanitize_camel_case_array_keys( $this->field['select2'] );
259
+
260
+            $select2_data = Redux_Functions::create_data_string( $this->field['select2'] );
261
+
262
+            $google_set     = false;
263
+            $is_google_font = '0';
264
+
265
+            // If no fontFamily array exists, create one and set array 0
266
+            // with font value.
267
+            if ( ! isset( $font_family ) ) {
268
+                $font_family    = array();
269
+                $font_family[0] = $this->value['font-family'];
270
+                $font_family[1] = '';
271
+            }
272
+
273
+            /* Font Family */
274
+            if ( true === $this->field['font-family'] ) {
275
+                if ( filter_var( $this->value['google'], FILTER_VALIDATE_BOOLEAN ) ) {
276
+
277
+                    // Divide and conquer.
278
+                    $font_family = explode( ', ', $this->value['font-family'], 2 );
279
+
280
+                    // If array 0 is empty and array 1 is not.
281
+                    if ( empty( $font_family[0] ) && ! empty( $font_family[1] ) ) {
282
+
283
+                        // Make array 0 = array 1.
284
+                        $font_family[0] = $font_family[1];
285
+                    }
286
+                }
287
+
288
+                // Is selected font a Google font.
289
+                if ( isset( Redux_Core::$fonts['google'][ $font_family[0] ] ) ) {
290
+                    $is_google_font = '1';
291
+                }
292
+
293
+                // If not a Google font, show all font families.
294
+                if ( '1' !== $is_google_font ) {
295
+                    $font_family[0] = $this->value['font-family'];
296
+                }
297
+
298
+                $user_fonts = '0';
299
+                if ( true === $this->user_fonts ) {
300
+                    $user_fonts = '1';
301
+                }
302
+
303
+                echo '<input
304 304
 						type="hidden"
305 305
 						class="redux-typography-font-family ' . esc_attr( $this->field['class'] ) . '"
306 306
 						data-user-fonts="' . esc_attr( $user_fonts ) . '" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-family]"
307 307
 						value="' . esc_attr( $this->value['font-family'] ) . '"
308 308
 						data-id="' . esc_attr( $this->field['id'] ) . '"  />';
309 309
 
310
-				echo '<input
310
+                echo '<input
311 311
 						type="hidden"
312 312
 						class="redux-typography-font-options ' . esc_attr( $this->field['class'] ) . '"
313 313
 						name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-options]"
314 314
 						value="' . esc_attr( $this->value['font-options'] ) . '"
315 315
 						data-id="' . esc_attr( $this->field['id'] ) . '"  />';
316 316
 
317
-				echo '<input
317
+                echo '<input
318 318
 						type="hidden"
319 319
 						class="redux-typography-google-font" value="' . esc_attr( $is_google_font ) . '"
320 320
 						id="' . esc_attr( $this->field['id'] ) . '-google-font">';
321 321
 
322
-				echo '<div class="select_wrapper typography-family" style="width: 220px; margin-right: 5px;">';
323
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-family">' . esc_html__( 'Font Family', 'redux-framework' ) . '</label>';
322
+                echo '<div class="select_wrapper typography-family" style="width: 220px; margin-right: 5px;">';
323
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-family">' . esc_html__( 'Font Family', 'redux-framework' ) . '</label>';
324 324
 
325
-				$placeholder = esc_html__( 'Font family', 'redux-framework' );
325
+                $placeholder = esc_html__( 'Font family', 'redux-framework' );
326 326
 
327
-				$new_arr                = $this->field['select2'];
328
-				$new_arr['allow-clear'] = $this->field['font_family_clear'];
329
-				$new_data               = Redux_Functions::create_data_string( $new_arr );
327
+                $new_arr                = $this->field['select2'];
328
+                $new_arr['allow-clear'] = $this->field['font_family_clear'];
329
+                $new_data               = Redux_Functions::create_data_string( $new_arr );
330 330
 
331
-				echo '<select class=" redux-typography redux-typography-family select2-container ' . esc_attr( $this->field['class'] ) . '" id="' . esc_attr( $this->field['id'] ) . '-family" data-placeholder="' . esc_attr( $placeholder ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" data-value="' . esc_attr( $font_family[0] ) . '"' . esc_html( $new_data ) . '>';
331
+                echo '<select class=" redux-typography redux-typography-family select2-container ' . esc_attr( $this->field['class'] ) . '" id="' . esc_attr( $this->field['id'] ) . '-family" data-placeholder="' . esc_attr( $placeholder ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" data-value="' . esc_attr( $font_family[0] ) . '"' . esc_html( $new_data ) . '>';
332 332
 
333
-				echo '</select>';
334
-				echo '</div>';
333
+                echo '</select>';
334
+                echo '</div>';
335 335
 
336
-				if ( true === $this->field['google'] ) {
336
+                if ( true === $this->field['google'] ) {
337 337
 
338
-					// Set a flag, so we know to set a header style or not.
339
-					echo '<input
338
+                    // Set a flag, so we know to set a header style or not.
339
+                    echo '<input
340 340
 							type="hidden"
341 341
 							class="redux-typography-google ' . esc_attr( $this->field['class'] ) . '"
342 342
 							id="' . esc_attr( $this->field['id'] ) . '-google" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[google]"
343 343
 							type="text" value="' . esc_attr( $this->field['google'] ) . '"
344 344
 							data-id="' . esc_attr( $this->field['id'] ) . '" />';
345 345
 
346
-					$google_set = true;
347
-				}
348
-			}
346
+                    $google_set = true;
347
+                }
348
+            }
349 349
 
350
-			/* Backup Font */
351
-			if ( true === $this->field['font-family'] && true === $this->field['google'] ) {
352
-				if ( false === $google_set ) {
353
-					// Set a flag, so we know to set a header style or not.
354
-					echo '<input
350
+            /* Backup Font */
351
+            if ( true === $this->field['font-family'] && true === $this->field['google'] ) {
352
+                if ( false === $google_set ) {
353
+                    // Set a flag, so we know to set a header style or not.
354
+                    echo '<input
355 355
 							type="hidden"
356 356
 							class="redux-typography-google ' . esc_attr( $this->field['class'] ) . '"
357 357
 							id="' . esc_attr( $this->field['id'] ) . '-google" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[google]"
358 358
 							type="text" value="' . esc_attr( $this->field['google'] ) . '"
359 359
 							data-id="' . esc_attr( $this->field['id'] ) . '"  />';
360
-				}
360
+                }
361 361
 
362
-				if ( true === $this->field['font-backup'] ) {
363
-					echo '<div class="select_wrapper typography-family-backup" style="width: 220px; margin-right: 5px;">';
364
-					echo '<label for="' . esc_attr( $this->field['id'] ) . '-family-backup">' . esc_html__( 'Backup Font Family', 'redux-framework' ) . '</label>';
365
-					echo '<select
362
+                if ( true === $this->field['font-backup'] ) {
363
+                    echo '<div class="select_wrapper typography-family-backup" style="width: 220px; margin-right: 5px;">';
364
+                    echo '<label for="' . esc_attr( $this->field['id'] ) . '-family-backup">' . esc_html__( 'Backup Font Family', 'redux-framework' ) . '</label>';
365
+                    echo '<select
366 366
 							data-placeholder="' . esc_html__( 'Backup Font Family', 'redux-framework' ) . '"
367 367
 							name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-backup]"
368 368
 							class="redux-typography redux-typography-family-backup ' . esc_attr( $this->field['class'] ) . '"
@@ -370,62 +370,62 @@  discard block
 block discarded – undo
370 370
 							data-id="' . esc_attr( $this->field['id'] ) . '"
371 371
 							data-value="' . esc_attr( $this->value['font-backup'] ) . '"' . esc_attr( $select2_data ) . '>';
372 372
 
373
-					echo '<option data-google="false" data-details="" value=""></option>';
373
+                    echo '<option data-google="false" data-details="" value=""></option>';
374 374
 
375
-					foreach ( $this->field['fonts'] as $i => $family ) {
376
-						echo '<option data-google="true" value="' . esc_attr( $i ) . '" ' . selected( $this->value['font-backup'], $i, false ) . '>' . esc_html( $family ) . '</option>';
377
-					}
375
+                    foreach ( $this->field['fonts'] as $i => $family ) {
376
+                        echo '<option data-google="true" value="' . esc_attr( $i ) . '" ' . selected( $this->value['font-backup'], $i, false ) . '>' . esc_html( $family ) . '</option>';
377
+                    }
378 378
 
379
-					echo '</select></div>';
380
-				}
381
-			}
379
+                    echo '</select></div>';
380
+                }
381
+            }
382 382
 
383
-			/* Font Style/Weight */
384
-			if ( true === $this->field['font-style'] || true === $this->field['font-weight'] ) {
385
-				echo '<div data-weights="' . rawurlencode( wp_json_encode( $this->field['weights'] ) ) . '" class="select_wrapper typography-style" original-title="' . esc_html__( 'Font style', 'redux-framework' ) . '">';
386
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '_style">' . esc_html__( 'Font Weight &amp; Style', 'redux-framework' ) . '</label>';
383
+            /* Font Style/Weight */
384
+            if ( true === $this->field['font-style'] || true === $this->field['font-weight'] ) {
385
+                echo '<div data-weights="' . rawurlencode( wp_json_encode( $this->field['weights'] ) ) . '" class="select_wrapper typography-style" original-title="' . esc_html__( 'Font style', 'redux-framework' ) . '">';
386
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '_style">' . esc_html__( 'Font Weight &amp; Style', 'redux-framework' ) . '</label>';
387 387
 
388
-				$style = $this->value['font-weight'] . $this->value['font-style'];
388
+                $style = $this->value['font-weight'] . $this->value['font-style'];
389 389
 
390
-				echo '<input
390
+                echo '<input
391 391
 						type="hidden"
392 392
 						class="typography-font-weight" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-weight]"
393 393
 						value="' . esc_attr( $this->value['font-weight'] ) . '"
394 394
 						data-id="' . esc_attr( $this->field['id'] ) . '"  /> ';
395 395
 
396
-				echo '<input
396
+                echo '<input
397 397
 						type="hidden"
398 398
 						class="typography-font-style" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-style]"
399 399
 						value="' . esc_attr( $this->value['font-style'] ) . '"
400 400
 						data-id="' . esc_attr( $this->field['id'] ) . '"  /> ';
401
-				$multi = ( isset( $this->field['multi']['weight'] ) && $this->field['multi']['weight'] ) ? ' multiple="multiple"' : '';
402
-				echo '<select' . esc_html( $multi ) . '
401
+                $multi = ( isset( $this->field['multi']['weight'] ) && $this->field['multi']['weight'] ) ? ' multiple="multiple"' : '';
402
+                echo '<select' . esc_html( $multi ) . '
403 403
 				        data-placeholder="' . esc_html__( 'Style', 'redux-framework' ) . '"
404 404
 				        class="redux-typography redux-typography-style select ' . esc_attr( $this->field['class'] ) . '"
405 405
 				        original-title="' . esc_html__( 'Font style', 'redux-framework' ) . '"
406 406
 				        id="' . esc_attr( $this->field['id'] ) . '_style" data-id="' . esc_attr( $this->field['id'] ) . '"
407 407
 				        data-value="' . esc_attr( $style ) . '"' . esc_attr( $select2_data ) . '>';
408 408
 
409
-				if ( empty( $this->value['subsets'] ) || empty( $this->value['font-weight'] ) ) {
410
-					echo '<option value=""></option>';
411
-				}
409
+                if ( empty( $this->value['subsets'] ) || empty( $this->value['font-weight'] ) ) {
410
+                    echo '<option value=""></option>';
411
+                }
412 412
 
413
-				echo '</select></div>';
414
-			}
413
+                echo '</select></div>';
414
+            }
415 415
 
416
-			/* Font Script */
417
-			if ( true === $this->field['font-family'] && true === $this->field['subsets'] && true === $this->field['google'] ) {
418
-				echo '<div class="select_wrapper typography-script tooltip" original-title="' . esc_html__( 'Font subsets', 'redux-framework' ) . '">';
419
-				echo '<input
416
+            /* Font Script */
417
+            if ( true === $this->field['font-family'] && true === $this->field['subsets'] && true === $this->field['google'] ) {
418
+                echo '<div class="select_wrapper typography-script tooltip" original-title="' . esc_html__( 'Font subsets', 'redux-framework' ) . '">';
419
+                echo '<input
420 420
 						type="hidden"
421 421
 						class="typography-subsets"
422 422
 						name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[subsets]"
423 423
 						value="' . esc_attr( $this->value['subsets'] ) . '"
424 424
 						data-id="' . esc_attr( $this->field['id'] ) . '"  /> ';
425 425
 
426
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-subsets">' . esc_html__( 'Font Subsets', 'redux-framework' ) . '</label>';
427
-				$multi = ( isset( $this->field['multi']['subsets'] ) && $this->field['multi']['subsets'] ) ? ' multiple="multiple"' : '';
428
-				echo '<select' . esc_html( $multi ) . '
426
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-subsets">' . esc_html__( 'Font Subsets', 'redux-framework' ) . '</label>';
427
+                $multi = ( isset( $this->field['multi']['subsets'] ) && $this->field['multi']['subsets'] ) ? ' multiple="multiple"' : '';
428
+                echo '<select' . esc_html( $multi ) . '
429 429
 						data-placeholder="' . esc_html__( 'Subsets', 'redux-framework' ) . '"
430 430
 						class="redux-typography redux-typography-subsets ' . esc_attr( $this->field['class'] ) . '"
431 431
 						original-title="' . esc_html__( 'Font script', 'redux-framework' ) . '"
@@ -433,18 +433,18 @@  discard block
 block discarded – undo
433 433
 						data-value="' . esc_attr( $this->value['subsets'] ) . '"
434 434
 						data-id="' . esc_attr( $this->field['id'] ) . '"' . esc_attr( $select2_data ) . '>';
435 435
 
436
-				if ( empty( $this->value['subsets'] ) ) {
437
-					echo '<option value=""></option>';
438
-				}
436
+                if ( empty( $this->value['subsets'] ) ) {
437
+                    echo '<option value=""></option>';
438
+                }
439 439
 
440
-				echo '</select></div>';
441
-			}
440
+                echo '</select></div>';
441
+            }
442 442
 
443
-			/* Font Align */
444
-			if ( true === $this->field['text-align'] ) {
445
-				echo '<div class="select_wrapper typography-align tooltip" original-title="' . esc_html__( 'Text Align', 'redux-framework' ) . '">';
446
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-align">' . esc_html__( 'Text Align', 'redux-framework' ) . '</label>';
447
-				echo '<select
443
+            /* Font Align */
444
+            if ( true === $this->field['text-align'] ) {
445
+                echo '<div class="select_wrapper typography-align tooltip" original-title="' . esc_html__( 'Text Align', 'redux-framework' ) . '">';
446
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-align">' . esc_html__( 'Text Align', 'redux-framework' ) . '</label>';
447
+                echo '<select
448 448
 						data-placeholder="' . esc_html__( 'Text Align', 'redux-framework' ) . '"
449 449
 						class="redux-typography redux-typography-align ' . esc_attr( $this->field['class'] ) . '"
450 450
 						original-title="' . esc_html__( 'Text Align', 'redux-framework' ) . '"
@@ -453,29 +453,29 @@  discard block
 block discarded – undo
453 453
 						data-value="' . esc_attr( $this->value['text-align'] ) . '"
454 454
 						data-id="' . esc_attr( $this->field['id'] ) . '"' . esc_attr( $select2_data ) . '>';
455 455
 
456
-				echo '<option value=""></option>';
457
-
458
-				$align = array(
459
-					esc_html__( 'inherit', 'redux-framework' ),
460
-					esc_html__( 'left', 'redux-framework' ),
461
-					esc_html__( 'right', 'redux-framework' ),
462
-					esc_html__( 'center', 'redux-framework' ),
463
-					esc_html__( 'justify', 'redux-framework' ),
464
-					esc_html__( 'initial', 'redux-framework' ),
465
-				);
466
-
467
-				foreach ( $align as $v ) {
468
-					echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['text-align'], $v, false ) . '>' . esc_html( ucfirst( $v ) ) . '</option>';
469
-				}
470
-
471
-				echo '</select></div>';
472
-			}
473
-
474
-			/* Text Transform */
475
-			if ( true === $this->field['text-transform'] ) {
476
-				echo '<div class="select_wrapper typography-transform tooltip" original-title="' . esc_html__( 'Text Transform', 'redux-framework' ) . '">';
477
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-transform">' . esc_html__( 'Text Transform', 'redux-framework' ) . '</label>';
478
-				echo '<select
456
+                echo '<option value=""></option>';
457
+
458
+                $align = array(
459
+                    esc_html__( 'inherit', 'redux-framework' ),
460
+                    esc_html__( 'left', 'redux-framework' ),
461
+                    esc_html__( 'right', 'redux-framework' ),
462
+                    esc_html__( 'center', 'redux-framework' ),
463
+                    esc_html__( 'justify', 'redux-framework' ),
464
+                    esc_html__( 'initial', 'redux-framework' ),
465
+                );
466
+
467
+                foreach ( $align as $v ) {
468
+                    echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['text-align'], $v, false ) . '>' . esc_html( ucfirst( $v ) ) . '</option>';
469
+                }
470
+
471
+                echo '</select></div>';
472
+            }
473
+
474
+            /* Text Transform */
475
+            if ( true === $this->field['text-transform'] ) {
476
+                echo '<div class="select_wrapper typography-transform tooltip" original-title="' . esc_html__( 'Text Transform', 'redux-framework' ) . '">';
477
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-transform">' . esc_html__( 'Text Transform', 'redux-framework' ) . '</label>';
478
+                echo '<select
479 479
 						data-placeholder="' . esc_html__( 'Text Transform', 'redux-framework' ) . '"
480 480
 						class="redux-typography redux-typography-transform ' . esc_attr( $this->field['class'] ) . '"
481 481
 						original-title="' . esc_html__( 'Text Transform', 'redux-framework' ) . '"
@@ -484,29 +484,29 @@  discard block
 block discarded – undo
484 484
 						data-value="' . esc_attr( $this->value['text-transform'] ) . '"
485 485
 						data-id="' . esc_attr( $this->field['id'] ) . '"' . esc_attr( $select2_data ) . '>';
486 486
 
487
-				echo '<option value=""></option>';
488
-
489
-				$values = array(
490
-					esc_html__( 'none', 'redux-framework' ),
491
-					esc_html__( 'capitalize', 'redux-framework' ),
492
-					esc_html__( 'uppercase', 'redux-framework' ),
493
-					esc_html__( 'lowercase', 'redux-framework' ),
494
-					esc_html__( 'initial', 'redux-framework' ),
495
-					esc_html__( 'inherit', 'redux-framework' ),
496
-				);
497
-
498
-				foreach ( $values as $v ) {
499
-					echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['text-transform'], $v, false ) . '>' . esc_html( ucfirst( $v ) ) . '</option>';
500
-				}
501
-
502
-				echo '</select></div>';
503
-			}
504
-
505
-			/* Font Variant */
506
-			if ( true === $this->field['font-variant'] ) {
507
-				echo '<div class="select_wrapper typography-font-variant tooltip" original-title="' . esc_html__( 'Font Variant', 'redux-framework' ) . '">';
508
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-font-variant">' . esc_html__( 'Font Variant', 'redux-framework' ) . '</label>';
509
-				echo '<select
487
+                echo '<option value=""></option>';
488
+
489
+                $values = array(
490
+                    esc_html__( 'none', 'redux-framework' ),
491
+                    esc_html__( 'capitalize', 'redux-framework' ),
492
+                    esc_html__( 'uppercase', 'redux-framework' ),
493
+                    esc_html__( 'lowercase', 'redux-framework' ),
494
+                    esc_html__( 'initial', 'redux-framework' ),
495
+                    esc_html__( 'inherit', 'redux-framework' ),
496
+                );
497
+
498
+                foreach ( $values as $v ) {
499
+                    echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['text-transform'], $v, false ) . '>' . esc_html( ucfirst( $v ) ) . '</option>';
500
+                }
501
+
502
+                echo '</select></div>';
503
+            }
504
+
505
+            /* Font Variant */
506
+            if ( true === $this->field['font-variant'] ) {
507
+                echo '<div class="select_wrapper typography-font-variant tooltip" original-title="' . esc_html__( 'Font Variant', 'redux-framework' ) . '">';
508
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-font-variant">' . esc_html__( 'Font Variant', 'redux-framework' ) . '</label>';
509
+                echo '<select
510 510
 						data-placeholder="' . esc_html__( 'Font Variant', 'redux-framework' ) . '"
511 511
 						class="redux-typography redux-typography-font-variant ' . esc_attr( $this->field['class'] ) . '"
512 512
 						original-title="' . esc_html__( 'Font Variant', 'redux-framework' ) . '"
@@ -515,26 +515,26 @@  discard block
 block discarded – undo
515 515
 						data-value="' . esc_attr( $this->value['font-variant'] ) . '"
516 516
 						data-id="' . esc_attr( $this->field['id'] ) . '"' . esc_attr( $select2_data ) . '>';
517 517
 
518
-				echo '<option value=""></option>';
518
+                echo '<option value=""></option>';
519 519
 
520
-				$values = array(
521
-					esc_html__( 'inherit', 'redux-framework' ),
522
-					esc_html__( 'normal', 'redux-framework' ),
523
-					esc_html__( 'small-caps', 'redux-framework' ),
524
-				);
520
+                $values = array(
521
+                    esc_html__( 'inherit', 'redux-framework' ),
522
+                    esc_html__( 'normal', 'redux-framework' ),
523
+                    esc_html__( 'small-caps', 'redux-framework' ),
524
+                );
525 525
 
526
-				foreach ( $values as $v ) {
527
-					echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['font-variant'], $v, false ) . '>' . esc_attr( ucfirst( $v ) ) . '</option>';
528
-				}
526
+                foreach ( $values as $v ) {
527
+                    echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['font-variant'], $v, false ) . '>' . esc_attr( ucfirst( $v ) ) . '</option>';
528
+                }
529 529
 
530
-				echo '</select></div>';
531
-			}
530
+                echo '</select></div>';
531
+            }
532 532
 
533
-			/* Text Decoration */
534
-			if ( true === $this->field['text-decoration'] ) {
535
-				echo '<div class="select_wrapper typography-decoration tooltip" original-title="' . esc_html__( 'Text Decoration', 'redux-framework' ) . '">';
536
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-decoration">' . esc_html__( 'Text Decoration', 'redux-framework' ) . '</label>';
537
-				echo '<select
533
+            /* Text Decoration */
534
+            if ( true === $this->field['text-decoration'] ) {
535
+                echo '<div class="select_wrapper typography-decoration tooltip" original-title="' . esc_html__( 'Text Decoration', 'redux-framework' ) . '">';
536
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-decoration">' . esc_html__( 'Text Decoration', 'redux-framework' ) . '</label>';
537
+                echo '<select
538 538
 						data-placeholder="' . esc_html__( 'Text Decoration', 'redux-framework' ) . '"
539 539
 						class="redux-typography redux-typography-decoration ' . esc_attr( $this->field['class'] ) . '"
540 540
 						original-title="' . esc_html__( 'Text Decoration', 'redux-framework' ) . '"
@@ -543,32 +543,32 @@  discard block
 block discarded – undo
543 543
 						data-value="' . esc_attr( $this->value['text-decoration'] ) . '"
544 544
 						data-id="' . esc_attr( $this->field['id'] ) . '"' . esc_attr( $select2_data ) . '>';
545 545
 
546
-				echo '<option value=""></option>';
546
+                echo '<option value=""></option>';
547 547
 
548
-				$values = array(
549
-					esc_html__( 'none', 'redux-framework' ),
550
-					esc_html__( 'inherit', 'redux-framework' ),
551
-					esc_html__( 'underline', 'redux-framework' ),
552
-					esc_html__( 'overline', 'redux-framework' ),
553
-					esc_html__( 'line-through', 'redux-framework' ),
554
-					esc_html__( 'blink', 'redux-framework' ),
555
-				);
548
+                $values = array(
549
+                    esc_html__( 'none', 'redux-framework' ),
550
+                    esc_html__( 'inherit', 'redux-framework' ),
551
+                    esc_html__( 'underline', 'redux-framework' ),
552
+                    esc_html__( 'overline', 'redux-framework' ),
553
+                    esc_html__( 'line-through', 'redux-framework' ),
554
+                    esc_html__( 'blink', 'redux-framework' ),
555
+                );
556 556
 
557
-				foreach ( $values as $v ) {
558
-					echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['text-decoration'], $v, false ) . '>' . esc_html( ucfirst( $v ) ) . '</option>';
559
-				}
557
+                foreach ( $values as $v ) {
558
+                    echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['text-decoration'], $v, false ) . '>' . esc_html( ucfirst( $v ) ) . '</option>';
559
+                }
560 560
 
561
-				echo '</select></div>';
562
-			}
561
+                echo '</select></div>';
562
+            }
563 563
 
564
-			/* Font Size */
565
-			if ( true === $this->field['font-size'] ) {
566
-				$the_unit = '' !== $this->field['font-size-unit'] ? $this->field['font-size-unit'] : $unit;
564
+            /* Font Size */
565
+            if ( true === $this->field['font-size'] ) {
566
+                $the_unit = '' !== $this->field['font-size-unit'] ? $this->field['font-size-unit'] : $unit;
567 567
 
568
-				echo '<div class="input_wrapper font-size redux-container-typography">';
569
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-size">' . esc_html__( 'Font Size', 'redux-framework' ) . '</label>';
570
-				echo '<div class="input-append">';
571
-				echo '<input
568
+                echo '<div class="input_wrapper font-size redux-container-typography">';
569
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-size">' . esc_html__( 'Font Size', 'redux-framework' ) . '</label>';
570
+                echo '<div class="input-append">';
571
+                echo '<input
572 572
 						type="text"
573 573
 						class="span2 redux-typography redux-typography-size mini typography-input ' . esc_attr( $this->field['class'] ) . '"
574 574
 						title="' . esc_html__( 'Font Size', 'redux-framework' ) . '"
@@ -577,20 +577,20 @@  discard block
 block discarded – undo
577 577
 						value="' . esc_attr( str_replace( Redux_Helpers::$array_units, '', $this->value['font-size'] ) ) . '"
578 578
 						data-unit="' . esc_attr( $the_unit ) . '"
579 579
 						data-value="' . esc_attr( str_replace( Redux_Helpers::$array_units, '', $this->value['font-size'] ) ) . '">';
580
-				echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>';
581
-				echo '</div>';
582
-				echo '<input type="hidden" class="typography-font-size" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-size]" value="' . esc_attr( $this->value['font-size'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"/>';
583
-				echo '</div>';
584
-			}
585
-
586
-			/* Line Height */
587
-			if ( true === $this->field['line-height'] ) {
588
-				$the_unit = $this->field['line-height-unit'] ?? $unit;
589
-
590
-				echo '<div class="input_wrapper line-height redux-container-typography">';
591
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-height">' . esc_html__( 'Line Height', 'redux-framework' ) . '</label>';
592
-				echo '<div class="input-append">';
593
-				echo '<input
580
+                echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>';
581
+                echo '</div>';
582
+                echo '<input type="hidden" class="typography-font-size" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-size]" value="' . esc_attr( $this->value['font-size'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"/>';
583
+                echo '</div>';
584
+            }
585
+
586
+            /* Line Height */
587
+            if ( true === $this->field['line-height'] ) {
588
+                $the_unit = $this->field['line-height-unit'] ?? $unit;
589
+
590
+                echo '<div class="input_wrapper line-height redux-container-typography">';
591
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-height">' . esc_html__( 'Line Height', 'redux-framework' ) . '</label>';
592
+                echo '<div class="input-append">';
593
+                echo '<input
594 594
 						type="text"
595 595
 						class="span2 redux-typography redux-typography-height mini typography-input ' . esc_attr( $this->field['class'] ) . '"
596 596
 						title="' . esc_html__( 'Line Height', 'redux-framework' ) . '"
@@ -600,25 +600,25 @@  discard block
 block discarded – undo
600 600
 						data-allow-empty="' . esc_attr( $this->field['allow_empty_line_height'] ) . '"
601 601
 						data-unit="' . esc_attr( $the_unit ) . '"
602 602
 						data-value="' . esc_attr( str_replace( Redux_Helpers::$array_units, '', $this->value['line-height'] ) ) . '">';
603
-				echo '<span class="add-on">' . esc_html( '' === $the_unit ? '&nbsp;' : $the_unit ) . '</span>';
604
-				echo '</div>';
605
-				echo '<input
603
+                echo '<span class="add-on">' . esc_html( '' === $the_unit ? '&nbsp;' : $the_unit ) . '</span>';
604
+                echo '</div>';
605
+                echo '<input
606 606
 						type="hidden"
607 607
 						class="typography-line-height"
608 608
 						name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[line-height]"
609 609
 						value="' . esc_attr( $this->value['line-height'] ) . '"
610 610
 						data-id="' . esc_attr( $this->field['id'] ) . '"/>';
611
-				echo '</div>';
612
-			}
611
+                echo '</div>';
612
+            }
613 613
 
614
-			/* Word Spacing */
615
-			if ( true === $this->field['word-spacing'] ) {
616
-				$the_unit = '' !== $this->field['word-spacing-unit'] ? $this->field['word-spacing-unit'] : $unit;
614
+            /* Word Spacing */
615
+            if ( true === $this->field['word-spacing'] ) {
616
+                $the_unit = '' !== $this->field['word-spacing-unit'] ? $this->field['word-spacing-unit'] : $unit;
617 617
 
618
-				echo '<div class="input_wrapper word-spacing redux-container-typography">';
619
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-word">' . esc_html__( 'Word Spacing', 'redux-framework' ) . '</label>';
620
-				echo '<div class="input-append">';
621
-				echo '<input
618
+                echo '<div class="input_wrapper word-spacing redux-container-typography">';
619
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-word">' . esc_html__( 'Word Spacing', 'redux-framework' ) . '</label>';
620
+                echo '<div class="input-append">';
621
+                echo '<input
622 622
 						type="text"
623 623
 						class="span2 redux-typography redux-typography-word mini typography-input ' . esc_attr( $this->field['class'] ) . '"
624 624
 						title="' . esc_html__( 'Word Spacing', 'redux-framework' ) . '"
@@ -628,20 +628,20 @@  discard block
 block discarded – undo
628 628
 						value="' . esc_attr( str_replace( $the_unit, '', $this->value['word-spacing'] ) ) . '"
629 629
 						data-value="' . esc_attr( str_replace( $the_unit, '', $this->value['word-spacing'] ) ) . '">';
630 630
 
631
-				echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>';
632
-				echo '</div>';
633
-				echo '<input type="hidden" class="typography-word-spacing" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[word-spacing] " value="' . esc_attr( $this->value['word-spacing'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"/>';
634
-				echo '</div>';
635
-			}
631
+                echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>';
632
+                echo '</div>';
633
+                echo '<input type="hidden" class="typography-word-spacing" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[word-spacing] " value="' . esc_attr( $this->value['word-spacing'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"/>';
634
+                echo '</div>';
635
+            }
636 636
 
637
-			/* Letter Spacing */
638
-			if ( true === $this->field['letter-spacing'] ) {
639
-				$the_unit = '' !== $this->field['letter-spacing-unit'] ? $this->field['letter-spacing-unit'] : $unit;
637
+            /* Letter Spacing */
638
+            if ( true === $this->field['letter-spacing'] ) {
639
+                $the_unit = '' !== $this->field['letter-spacing-unit'] ? $this->field['letter-spacing-unit'] : $unit;
640 640
 
641
-				echo '<div class="input_wrapper letter-spacing redux-container-typography">';
642
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-letter">' . esc_html__( 'Letter Spacing', 'redux-framework' ) . '</label>';
643
-				echo '<div class="input-append">';
644
-				echo '<input
641
+                echo '<div class="input_wrapper letter-spacing redux-container-typography">';
642
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-letter">' . esc_html__( 'Letter Spacing', 'redux-framework' ) . '</label>';
643
+                echo '<div class="input-append">';
644
+                echo '<input
645 645
 						type="text"
646 646
 						class="span2 redux-typography redux-typography-letter mini typography-input ' . esc_attr( $this->field['class'] ) . '"
647 647
 						title="' . esc_html__( 'Letter Spacing', 'redux-framework' ) . '"
@@ -651,28 +651,28 @@  discard block
 block discarded – undo
651 651
 						value="' . esc_attr( str_replace( $the_unit, '', $this->value['letter-spacing'] ) ) . '"
652 652
 						data-value="' . esc_attr( str_replace( $the_unit, '', $this->value['letter-spacing'] ) ) . '">';
653 653
 
654
-				echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>';
655
-				echo '</div>';
656
-				echo '<input
654
+                echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>';
655
+                echo '</div>';
656
+                echo '<input
657 657
 						type="hidden"
658 658
 						class="typography-letter-spacing"
659 659
 						name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[letter-spacing]"
660 660
 						value="' . esc_attr( $this->value['letter-spacing'] ) . '"
661 661
 						data-id="' . esc_attr( $this->field['id'] ) . '"  />';
662 662
 
663
-				echo '</div>';
664
-			}
663
+                echo '</div>';
664
+            }
665 665
 
666
-			echo '<div class="clearfix"></div>';
666
+            echo '<div class="clearfix"></div>';
667 667
 
668
-			// Margins.
669
-			if ( $this->field['margin-top'] ) {
670
-				$the_unit = '' !== $this->field['margin-top-unit'] ? $this->field['margin-top-unit'] : $unit;
668
+            // Margins.
669
+            if ( $this->field['margin-top'] ) {
670
+                $the_unit = '' !== $this->field['margin-top-unit'] ? $this->field['margin-top-unit'] : $unit;
671 671
 
672
-				echo '<div class="input_wrapper margin-top redux-container-typography">';
673
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-margin-top">' . esc_html__( 'Margin Top', 'redux-framework' ) . '</label>';
674
-				echo '<div class="input-append">';
675
-				echo '<input
672
+                echo '<div class="input_wrapper margin-top redux-container-typography">';
673
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-margin-top">' . esc_html__( 'Margin Top', 'redux-framework' ) . '</label>';
674
+                echo '<div class="input-append">';
675
+                echo '<input
676 676
 						type="text"
677 677
 						class="span2 redux-typography redux-typography-margin-top mini typography-input ' . esc_attr( $this->field['class'] ) . '"
678 678
 						title="' . esc_html__( 'Margin Top', 'redux-framework' ) . '"
@@ -681,25 +681,25 @@  discard block
 block discarded – undo
681 681
 						data-unit="' . esc_attr( $the_unit ) . '"
682 682
 						value="' . esc_attr( str_replace( $the_unit, '', $this->value['margin-top'] ) ) . '"
683 683
 						data-value="' . esc_attr( str_replace( $the_unit, '', $this->value['margin-top'] ) ) . '">';
684
-				echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>';
685
-				echo '</div>';
686
-				echo '<input
684
+                echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>';
685
+                echo '</div>';
686
+                echo '<input
687 687
 						type="hidden"
688 688
 						class="typography-margin-top"
689 689
 						name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[margin-top]"
690 690
 						value="' . esc_attr( $this->value['margin-top'] ) . '"
691 691
 						data-id="' . esc_attr( $this->field['id'] ) . '"  />';
692
-				echo '</div>';
693
-			}
692
+                echo '</div>';
693
+            }
694 694
 
695
-			/* Bottom Margin */
696
-			if ( $this->field['margin-bottom'] ) {
697
-				$the_unit = '' !== $this->field['margin-bottom-unit'] ? $this->field['margin-bottom-unit'] : $unit;
695
+            /* Bottom Margin */
696
+            if ( $this->field['margin-bottom'] ) {
697
+                $the_unit = '' !== $this->field['margin-bottom-unit'] ? $this->field['margin-bottom-unit'] : $unit;
698 698
 
699
-				echo '<div class="input_wrapper margin-bottom redux-container-typography">';
700
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-margin-bottom">' . esc_html__( 'Margin Bottom', 'redux-framework' ) . '</label>';
701
-				echo '<div class="input-append">';
702
-				echo '<input
699
+                echo '<div class="input_wrapper margin-bottom redux-container-typography">';
700
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-margin-bottom">' . esc_html__( 'Margin Bottom', 'redux-framework' ) . '</label>';
701
+                echo '<div class="input-append">';
702
+                echo '<input
703 703
 						type="text"
704 704
 						class="span2 redux-typography redux-typography-margin-bottom mini typography-input ' . esc_attr( $this->field['class'] ) . '"
705 705
 						title="' . esc_html__( 'Margin Bottom', 'redux-framework' ) . '"
@@ -708,106 +708,106 @@  discard block
 block discarded – undo
708 708
 						data-unit="' . esc_attr( $the_unit ) . '"
709 709
 						value="' . esc_attr( str_replace( $the_unit, '', $this->value['margin-bottom'] ) ) . '"
710 710
 						data-value="' . esc_attr( str_replace( $the_unit, '', $this->value['margin-bottom'] ) ) . '">';
711
-				echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>';
712
-				echo '</div>';
713
-				echo '<input type="hidden" class="typography-margin-bottom" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[margin-bottom]" value="' . esc_attr( $this->value['margin-bottom'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"  />';
714
-				echo '</div>';
715
-			}
716
-
717
-			if ( $this->field['margin-top'] || $this->field['margin-bottom'] ) {
718
-				echo '<div class="clearfix"></div>';
719
-			}
720
-
721
-			/* Font Color */
722
-			if ( true === $this->field['color'] ) {
723
-				$default = '';
724
-
725
-				if ( empty( $this->field['default']['color'] ) && ! empty( $this->field['color'] ) ) {
726
-					$default = $this->value['color'];
727
-				} elseif ( ! empty( $this->field['default']['color'] ) ) {
728
-					$default = $this->field['default']['color'];
729
-				}
730
-
731
-				echo '<div class="picker-wrapper">';
732
-				echo '<label for="' . esc_attr( $this->field['id'] ) . '-color">' . esc_html__( 'Font Color', 'redux-framework' ) . '</label>';
733
-				echo '<div id="' . esc_attr( $this->field['id'] ) . '_color_picker" class="colorSelector typography-color">';
734
-				echo '<div style="background-color: ' . esc_attr( $this->value['color'] ) . '"></div>';
735
-				echo '</div>';
736
-				echo '<input ';
737
-				echo 'data-default-color="' . esc_attr( $default ) . '"';
738
-				echo 'class="color-picker redux-color redux-typography-color ' . esc_attr( $this->field['class'] ) . '"';
739
-				echo 'original-title="' . esc_html__( 'Font color', 'redux-framework' ) . '"';
740
-				echo 'id="' . esc_attr( $this->field['id'] ) . '-color"';
741
-				echo 'name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[color]"';
742
-				echo 'type="text"';
743
-				echo 'value="' . esc_attr( $this->value['color'] ) . '"';
744
-				echo 'data-id="' . esc_attr( $this->field['id'] ) . '"';
745
-
746
-				$data = array(
747
-					'field' => $this->field,
748
-					'index' => 'color',
749
-				);
750
-
751
-				echo Redux_Functions_Ex::output_alpha_data( $data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
752
-
753
-				echo '>';
754
-				echo '</div>';
755
-			}
756
-
757
-			echo '<div class="clearfix"></div>';
758
-
759
-			/* Font Preview */
760
-			if ( ! isset( $this->field['preview'] ) || false !== $this->field['preview'] ) {
761
-				$g_text = $this->field['preview']['text'] ?? '1 2 3 4 5 6 7 8 9 0 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z';
762
-
763
-				$style = '';
764
-				if ( isset( $this->field['preview']['always_display'] ) ) {
765
-					if ( true === filter_var( $this->field['preview']['always_display'], FILTER_VALIDATE_BOOLEAN ) ) {
766
-						if ( true === (bool) $is_google_font ) {
767
-							$this->typography_preview[ $font_family[0] ] = array(
768
-								'font-style' => array( $this->value['font-weight'] . $this->value['font-style'] ),
769
-								'subset'     => array( $this->value['subsets'] ),
770
-							);
771
-
772
-							wp_deregister_style( 'redux-typography-preview' );
773
-							wp_dequeue_style( 'redux-typography-preview' );
774
-
775
-							wp_enqueue_style( 'redux-typography-preview', $this->make_google_web_font_link( $this->typography_preview ), array(), $this->timestamp );
776
-						}
777
-
778
-						$style = 'display: block; font-family: ' . esc_attr( $this->value['font-family'] ) . '; font-weight: ' . esc_attr( $this->value['font-weight'] ) . ';';
779
-					}
780
-				}
781
-
782
-				if ( isset( $this->field['preview']['font-size'] ) ) {
783
-					$style .= 'font-size: ' . $this->field['preview']['font-size'] . ';';
784
-					$in_use = '1';
785
-				} else {
786
-					$in_use = '0';
787
-				}
788
-
789
-				// Filter to disable Google font updates.
790
-				if ( apply_filters( "redux/{$this->parent->args['opt_name']}/field/typography/google_font_update", true ) ) { // phpcs:ignored WordPress.NamingConventions.ValidHookName
791
-					if ( Redux_Helpers::google_fonts_update_needed() && ! get_option( 'auto_update_redux_google_fonts', false ) && $this->field['font-family'] && $this->field['google'] ) {
792
-						$nonce = wp_create_nonce( 'redux_update_google_fonts' );
793
-
794
-						echo '<div data-nonce="' . esc_attr( $nonce ) . '" class="redux-update-google-fonts update-message notice inline notice-warning notice-alt">';
795
-						echo '<p>' . esc_html__( 'Your Google Fonts are out of date. To update them, please click one of the following:', 'redux-framework' );
796
-						echo '&nbsp;<a href="#" class="update-google-fonts" data-action="automatic" aria-label="' . esc_attr__( 'Automated updates', 'redux-framework' ) . '">' . esc_html__( 'Automated updates', 'redux-framework' ) . '</a> ' . esc_html__( 'or', 'redux-framework' ) . ' <a href="#" class="update-google-fonts" data-action="manual" aria-label="' . esc_attr__( 'one-time update', 'redux-framework' ) . '">' . esc_html__( 'one-time update', 'redux-framework' ) . '</a>.';
797
-						echo '</p>';
798
-						echo '</div>';
799
-					}
800
-				}
801
-
802
-				echo '<p data-preview-size="' . esc_attr( $in_use ) . '" class="clear ' . esc_attr( $this->field['id'] ) . '_previewer typography-preview" style="' . esc_attr( $style ) . '">' . esc_html( $g_text ) . '</p>';
803
-
804
-				if ( $this->field['text-shadow'] ) {
805
-
806
-					/* Shadow Colour */
807
-					echo '<div class="picker-wrapper">';
808
-					echo '<label for="' . esc_attr( $this->field['id'] ) . '-shadow-color">' . esc_html__( 'Shadow Color', 'redux-framework' ) . '</label>';
809
-					echo '<div id="' . esc_attr( $this->field['id'] ) . '_color_picker" class="colorSelector typography-shadow-color"><div style="background-color: ' . esc_attr( $this->value['color'] ) . '"></div></div>';
810
-					echo '<input
711
+                echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>';
712
+                echo '</div>';
713
+                echo '<input type="hidden" class="typography-margin-bottom" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[margin-bottom]" value="' . esc_attr( $this->value['margin-bottom'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"  />';
714
+                echo '</div>';
715
+            }
716
+
717
+            if ( $this->field['margin-top'] || $this->field['margin-bottom'] ) {
718
+                echo '<div class="clearfix"></div>';
719
+            }
720
+
721
+            /* Font Color */
722
+            if ( true === $this->field['color'] ) {
723
+                $default = '';
724
+
725
+                if ( empty( $this->field['default']['color'] ) && ! empty( $this->field['color'] ) ) {
726
+                    $default = $this->value['color'];
727
+                } elseif ( ! empty( $this->field['default']['color'] ) ) {
728
+                    $default = $this->field['default']['color'];
729
+                }
730
+
731
+                echo '<div class="picker-wrapper">';
732
+                echo '<label for="' . esc_attr( $this->field['id'] ) . '-color">' . esc_html__( 'Font Color', 'redux-framework' ) . '</label>';
733
+                echo '<div id="' . esc_attr( $this->field['id'] ) . '_color_picker" class="colorSelector typography-color">';
734
+                echo '<div style="background-color: ' . esc_attr( $this->value['color'] ) . '"></div>';
735
+                echo '</div>';
736
+                echo '<input ';
737
+                echo 'data-default-color="' . esc_attr( $default ) . '"';
738
+                echo 'class="color-picker redux-color redux-typography-color ' . esc_attr( $this->field['class'] ) . '"';
739
+                echo 'original-title="' . esc_html__( 'Font color', 'redux-framework' ) . '"';
740
+                echo 'id="' . esc_attr( $this->field['id'] ) . '-color"';
741
+                echo 'name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[color]"';
742
+                echo 'type="text"';
743
+                echo 'value="' . esc_attr( $this->value['color'] ) . '"';
744
+                echo 'data-id="' . esc_attr( $this->field['id'] ) . '"';
745
+
746
+                $data = array(
747
+                    'field' => $this->field,
748
+                    'index' => 'color',
749
+                );
750
+
751
+                echo Redux_Functions_Ex::output_alpha_data( $data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
752
+
753
+                echo '>';
754
+                echo '</div>';
755
+            }
756
+
757
+            echo '<div class="clearfix"></div>';
758
+
759
+            /* Font Preview */
760
+            if ( ! isset( $this->field['preview'] ) || false !== $this->field['preview'] ) {
761
+                $g_text = $this->field['preview']['text'] ?? '1 2 3 4 5 6 7 8 9 0 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z';
762
+
763
+                $style = '';
764
+                if ( isset( $this->field['preview']['always_display'] ) ) {
765
+                    if ( true === filter_var( $this->field['preview']['always_display'], FILTER_VALIDATE_BOOLEAN ) ) {
766
+                        if ( true === (bool) $is_google_font ) {
767
+                            $this->typography_preview[ $font_family[0] ] = array(
768
+                                'font-style' => array( $this->value['font-weight'] . $this->value['font-style'] ),
769
+                                'subset'     => array( $this->value['subsets'] ),
770
+                            );
771
+
772
+                            wp_deregister_style( 'redux-typography-preview' );
773
+                            wp_dequeue_style( 'redux-typography-preview' );
774
+
775
+                            wp_enqueue_style( 'redux-typography-preview', $this->make_google_web_font_link( $this->typography_preview ), array(), $this->timestamp );
776
+                        }
777
+
778
+                        $style = 'display: block; font-family: ' . esc_attr( $this->value['font-family'] ) . '; font-weight: ' . esc_attr( $this->value['font-weight'] ) . ';';
779
+                    }
780
+                }
781
+
782
+                if ( isset( $this->field['preview']['font-size'] ) ) {
783
+                    $style .= 'font-size: ' . $this->field['preview']['font-size'] . ';';
784
+                    $in_use = '1';
785
+                } else {
786
+                    $in_use = '0';
787
+                }
788
+
789
+                // Filter to disable Google font updates.
790
+                if ( apply_filters( "redux/{$this->parent->args['opt_name']}/field/typography/google_font_update", true ) ) { // phpcs:ignored WordPress.NamingConventions.ValidHookName
791
+                    if ( Redux_Helpers::google_fonts_update_needed() && ! get_option( 'auto_update_redux_google_fonts', false ) && $this->field['font-family'] && $this->field['google'] ) {
792
+                        $nonce = wp_create_nonce( 'redux_update_google_fonts' );
793
+
794
+                        echo '<div data-nonce="' . esc_attr( $nonce ) . '" class="redux-update-google-fonts update-message notice inline notice-warning notice-alt">';
795
+                        echo '<p>' . esc_html__( 'Your Google Fonts are out of date. To update them, please click one of the following:', 'redux-framework' );
796
+                        echo '&nbsp;<a href="#" class="update-google-fonts" data-action="automatic" aria-label="' . esc_attr__( 'Automated updates', 'redux-framework' ) . '">' . esc_html__( 'Automated updates', 'redux-framework' ) . '</a> ' . esc_html__( 'or', 'redux-framework' ) . ' <a href="#" class="update-google-fonts" data-action="manual" aria-label="' . esc_attr__( 'one-time update', 'redux-framework' ) . '">' . esc_html__( 'one-time update', 'redux-framework' ) . '</a>.';
797
+                        echo '</p>';
798
+                        echo '</div>';
799
+                    }
800
+                }
801
+
802
+                echo '<p data-preview-size="' . esc_attr( $in_use ) . '" class="clear ' . esc_attr( $this->field['id'] ) . '_previewer typography-preview" style="' . esc_attr( $style ) . '">' . esc_html( $g_text ) . '</p>';
803
+
804
+                if ( $this->field['text-shadow'] ) {
805
+
806
+                    /* Shadow Colour */
807
+                    echo '<div class="picker-wrapper">';
808
+                    echo '<label for="' . esc_attr( $this->field['id'] ) . '-shadow-color">' . esc_html__( 'Shadow Color', 'redux-framework' ) . '</label>';
809
+                    echo '<div id="' . esc_attr( $this->field['id'] ) . '_color_picker" class="colorSelector typography-shadow-color"><div style="background-color: ' . esc_attr( $this->value['color'] ) . '"></div></div>';
810
+                    echo '<input
811 811
 		                    data-default-color="' . esc_attr( $this->value['shadow-color'] ) . '"
812 812
 		                    class="color-picker redux-color redux-typography-shadow-color ' . esc_attr( $this->field['class'] ) . '"
813 813
 		                    original-title="' . esc_html__( 'Shadow color', 'redux-framework' ) . '"
@@ -818,12 +818,12 @@  discard block
 block discarded – undo
818 818
 		                    data-alpha="' . esc_attr( $this->field['color_alpha']['shadow-color'] ) . '"
819 819
 		                    data-id="' . esc_attr( $this->field['id'] ) . '"
820 820
 		                  />';
821
-					echo '</div>';
821
+                    echo '</div>';
822 822
 
823
-					/* Shadow Horizontal Length */
824
-					echo '<div class="input_wrapper shadow-horizontal redux-container-typography" style="top:-60px;margin-left:20px;width:20%">';
825
-					echo '<div class="label">' . esc_html__( 'Horizontal', 'redux-framework' ) . ': <strong>' . esc_attr( $this->value['shadow-horizontal'] ) . 'px</strong></div>';
826
-					echo '<div
823
+                    /* Shadow Horizontal Length */
824
+                    echo '<div class="input_wrapper shadow-horizontal redux-container-typography" style="top:-60px;margin-left:20px;width:20%">';
825
+                    echo '<div class="label">' . esc_html__( 'Horizontal', 'redux-framework' ) . ': <strong>' . esc_attr( $this->value['shadow-horizontal'] ) . 'px</strong></div>';
826
+                    echo '<div
827 827
                             class="redux-typography-slider span2 redux-typography redux-typography-shadow-horizontal mini typography-input ' . esc_attr( $this->field['class'] ) . '"
828 828
                             id="' . esc_attr( $this->field['id'] ) . '"
829 829
                             data-id="' . esc_attr( $this->field['id'] ) . '-h"
@@ -834,13 +834,13 @@  discard block
 block discarded – undo
834 834
                             data-label="' . esc_attr__( 'Horizontal', 'redux-framework' ) . '"
835 835
                             data-default = "' . esc_attr( $this->value['shadow-horizontal'] ) . '">
836 836
                         </div>';
837
-					echo '<input type="hidden" id="redux-slider-value-' . esc_attr( $this->field['id'] ) . '-h" class="typography-shadow-horizontal" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[shadow-horizontal]" value="' . esc_attr( $this->value['shadow-horizontal'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"  />';
838
-					echo '</div>';
837
+                    echo '<input type="hidden" id="redux-slider-value-' . esc_attr( $this->field['id'] ) . '-h" class="typography-shadow-horizontal" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[shadow-horizontal]" value="' . esc_attr( $this->value['shadow-horizontal'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"  />';
838
+                    echo '</div>';
839 839
 
840
-					/* Shadow Vertical Length */
841
-					echo '<div class="input_wrapper shadow-vertical redux-container-typography" style="top:-60px;margin-left:20px;width:20%">';
842
-					echo '<div>' . esc_html__( 'Vertical', 'redux-framework' ) . ': <strong>' . esc_attr( $this->value['shadow-vertical'] ) . 'px</strong></div>';
843
-					echo '<div
840
+                    /* Shadow Vertical Length */
841
+                    echo '<div class="input_wrapper shadow-vertical redux-container-typography" style="top:-60px;margin-left:20px;width:20%">';
842
+                    echo '<div>' . esc_html__( 'Vertical', 'redux-framework' ) . ': <strong>' . esc_attr( $this->value['shadow-vertical'] ) . 'px</strong></div>';
843
+                    echo '<div
844 844
                             class="redux-typography-slider span2 redux-typography redux-typography-shadow-vertical mini typography-input ' . esc_attr( $this->field['class'] ) . '"
845 845
                             id="' . esc_attr( $this->field['id'] ) . '"
846 846
                             data-id="' . esc_attr( $this->field['id'] ) . '-v"
@@ -851,13 +851,13 @@  discard block
 block discarded – undo
851 851
                             data-label="' . esc_attr__( 'Vertical', 'redux-framework' ) . '"
852 852
                             data-default = "' . esc_attr( $this->value['shadow-vertical'] ) . '">
853 853
                         </div>';
854
-					echo '<input type="hidden" id="redux-slider-value-' . esc_attr( $this->field['id'] ) . '-v" class="typography-shadow-vertical" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[shadow-vertical]" value="' . esc_attr( $this->value['shadow-vertical'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"  />';
855
-					echo '</div>';
854
+                    echo '<input type="hidden" id="redux-slider-value-' . esc_attr( $this->field['id'] ) . '-v" class="typography-shadow-vertical" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[shadow-vertical]" value="' . esc_attr( $this->value['shadow-vertical'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"  />';
855
+                    echo '</div>';
856 856
 
857
-					/* Shadow Blur */
858
-					echo '<div class="input_wrapper shadow-blur redux-container-typography" style="top:-60px;margin-left:20px;width:20%">';
859
-					echo '<div>' . esc_html__( 'Blur', 'redux-framework' ) . ': <strong>' . esc_attr( $this->value['shadow-blur'] ) . 'px</strong></div>';
860
-					echo '<div
857
+                    /* Shadow Blur */
858
+                    echo '<div class="input_wrapper shadow-blur redux-container-typography" style="top:-60px;margin-left:20px;width:20%">';
859
+                    echo '<div>' . esc_html__( 'Blur', 'redux-framework' ) . ': <strong>' . esc_attr( $this->value['shadow-blur'] ) . 'px</strong></div>';
860
+                    echo '<div
861 861
                             class="redux-typography-slider span2 redux-typography redux-typography-shadow-blur mini typography-input ' . esc_attr( $this->field['class'] ) . '"
862 862
                             id="' . esc_attr( $this->field['id'] ) . '"
863 863
                             data-id="' . esc_attr( $this->field['id'] ) . '-b"
@@ -868,739 +868,739 @@  discard block
 block discarded – undo
868 868
                             data-label="' . esc_attr__( 'Blur', 'redux-framework' ) . '"
869 869
                             data-default = "' . esc_attr( $this->value['shadow-blur'] ) . '">
870 870
                         </div>';
871
-					echo '<input type="hidden" id="redux-slider-value-' . esc_attr( $this->field['id'] ) . '-b" class="typography-shadow-blur" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[shadow-blur]" value="' . esc_attr( $this->value['shadow-blur'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"  />';
872
-					echo '</div>';
873
-				}
874
-
875
-				echo '</div>'; // end typography container.
876
-			}
877
-		}
878
-
879
-		/**
880
-		 * Enqueue for every field instance.
881
-		 */
882
-		public function always_enqueue() {
883
-			$min = Redux_Functions::is_min();
884
-
885
-			if ( isset( $this->field['color_alpha'] ) && is_array( $this->field['color_alpha'] ) ) {
886
-				if ( $this->field['color_alpha']['color'] || $this->field['color_alpha']['shadow-color'] ) {
887
-					wp_enqueue_script( 'redux-wp-color-picker-alpha' );
888
-				}
889
-			}
890
-
891
-			if ( ! wp_style_is( 'redux-nouislider' ) && isset( $this->field['text-shadow'] ) && $this->field['text-shadow'] ) {
892
-				wp_enqueue_style(
893
-					'redux-nouislider',
894
-					Redux_Core::$url . "assets/css/vendor/nouislider$min.css",
895
-					array(),
896
-					'5.0.0'
897
-				);
898
-
899
-				wp_enqueue_script(
900
-					'redux-nouislider',
901
-					Redux_Core::$url . "assets/js/vendor/nouislider/redux.jquery.nouislider$min.js",
902
-					array( 'jquery' ),
903
-					'5.0.0',
904
-					true
905
-				);
906
-			}
907
-		}
908
-
909
-		/**
910
-		 * Enqueue Function.
911
-		 * If this field requires any scripts, or CSS define this function and register/enqueue the scripts/css
912
-		 *
913
-		 * @since ReduxFramework 1.0.0
914
-		 */
915
-		public function enqueue() {
916
-			$min = Redux_Functions::is_min();
917
-
918
-			if ( ! wp_style_is( 'select2-css' ) ) {
919
-				wp_enqueue_style( 'select2-css' );
920
-			}
921
-
922
-			if ( ! wp_style_is( 'wp-color-picker' ) ) {
923
-				wp_enqueue_style( 'wp-color-picker' );
924
-			}
925
-
926
-			wp_enqueue_script(
927
-				'redux-webfont',
928
-				'//' . 'ajax' . '.googleapis' . '.com/ajax/libs/webfont/1.6.26/webfont.js', // phpcs:ignore Generic.Strings.UnnecessaryStringConcat
929
-				array(),
930
-				'1.6.26',
931
-				true
932
-			);
933
-
934
-			$dep_array = array( 'jquery', 'wp-color-picker', 'select2-js', 'redux-js', 'redux-webfont' );
935
-
936
-			wp_enqueue_script(
937
-				'redux-field-typography',
938
-				Redux_Core::$url . "inc/fields/typography/redux-typography$min.js",
939
-				$dep_array,
940
-				$this->timestamp,
941
-				true
942
-			);
943
-
944
-			wp_localize_script(
945
-				'redux-field-typography',
946
-				'redux_typography_ajax',
947
-				array(
948
-					'ajaxurl'             => esc_url( admin_url( 'admin-ajax.php' ) ),
949
-					'update_google_fonts' => array(
950
-						'updating' => esc_html__( 'Downloading Google Fonts...', 'redux-framework' ),
951
-						// translators: Aria title, link title.
952
-						'error'    => sprintf( esc_html__( 'Update Failed|msg. %1$s', 'redux-framework' ), sprintf( '<a href="#" class="update-google-fonts" data-action="manual" aria-label="%s">%s</a>', esc_html__( 'Retry?', 'redux-framework' ), esc_html__( 'Retry?', 'redux-framework' ) ) ),
953
-						// translators: Javascript reload command, link title.
954
-						'success'  => sprintf( esc_html__( 'Updated! %1$s to start using your updated fonts.', 'redux-framework' ), sprintf( '<a href="	%1$s">%2$s</a>', 'javascript:location.reload();', esc_html__( 'Reload the page', 'redux-framework' ) ) ),
955
-					),
956
-				)
957
-			);
958
-
959
-			if ( $this->parent->args['dev_mode'] ) {
960
-				wp_enqueue_style( 'redux-color-picker' );
961
-
962
-				wp_enqueue_style(
963
-					'redux-field-typography',
964
-					Redux_Core::$url . 'inc/fields/typography/redux-typography.css',
965
-					array(),
966
-					$this->timestamp
967
-				);
968
-			}
969
-		}
970
-
971
-		/**
972
-		 * Make_google_web_font_link Function.
973
-		 * Creates the Google fonts link.
974
-		 *
975
-		 * @param array $fonts Array of google fonts.
976
-		 *
977
-		 * @return string
978
-		 *
979
-		 * @since ReduxFramework 3.0.0
980
-		 */
981
-		public function make_google_web_font_link( array $fonts ): string {
982
-			$link    = '';
983
-			$subsets = array();
984
-
985
-			foreach ( $fonts as $family => $font ) {
986
-				if ( ! empty( $link ) ) {
987
-					$link .= '|'; // Append a new font to the string.
988
-				}
989
-				$link .= $family;
990
-
991
-				if ( ! empty( $font['font-style'] ) || ! empty( $font['all-styles'] ) ) {
992
-					$link .= ':';
993
-					if ( ! empty( $font['all-styles'] ) ) {
994
-						$link .= implode( ',', $font['all-styles'] );
995
-					} elseif ( ! empty( $font['font-style'] ) ) {
996
-						$link .= implode( ',', $font['font-style'] );
997
-					}
998
-				}
999
-
1000
-				if ( ! empty( $font['subset'] ) || ! empty( $font['all-subsets'] ) ) {
1001
-					if ( ! empty( $font['all-subsets'] ) ) {
1002
-						foreach ( $font['all-subsets'] as $subset ) {
1003
-							if ( ! in_array( $subset, $subsets, true ) ) {
1004
-								$subsets[] = $subset;
1005
-							}
1006
-						}
1007
-					} elseif ( ! empty( $font['subset'] ) ) {
1008
-						foreach ( $font['subset'] as $subset ) {
1009
-							if ( ! in_array( $subset, $subsets, true ) ) {
1010
-								$subsets[] = $subset;
1011
-							}
1012
-						}
1013
-					}
1014
-				}
1015
-			}
1016
-
1017
-			if ( ! empty( $subsets ) ) {
1018
-				$link .= '&subset=' . implode( ',', $subsets );
1019
-			}
1020
-
1021
-			$display = $this->parent->args['font_display'] ?? 'swap';
1022
-
1023
-			$link .= '&display=' . $display;
1024
-
1025
-			// return 'https://fonts.bunny.net/css?family=' . $link;
1026
-			return 'https://fonts.googleapis.com/css?family=' . $link;
1027
-		}
1028
-
1029
-		/**
1030
-		 * Make_google_web_font_string Function.
1031
-		 * Creates the Google fonts link.
1032
-		 *
1033
-		 * @param array $fonts Array of Google fonts.
1034
-		 *
1035
-		 * @return string
1036
-		 *
1037
-		 * @since ReduxFramework 3.1.8
1038
-		 */
1039
-		public function make_google_web_font_string( array $fonts ): string {
1040
-			$link    = '';
1041
-			$subsets = array();
1042
-
1043
-			foreach ( $fonts as $family => $font ) {
1044
-				if ( ! empty( $link ) ) {
1045
-					$link .= "', '"; // Append a new font to the string.
1046
-				}
1047
-				$link .= $family;
1048
-
1049
-				if ( ! empty( $font['font-style'] ) || ! empty( $font['all-styles'] ) ) {
1050
-					$link .= ':';
1051
-					if ( ! empty( $font['all-styles'] ) ) {
1052
-						$link .= implode( ',', $font['all-styles'] );
1053
-					} elseif ( ! empty( $font['font-style'] ) ) {
1054
-						$link .= implode( ',', $font['font-style'] );
1055
-					}
1056
-				}
1057
-
1058
-				if ( ! empty( $font['subset'] ) || ! empty( $font['all-subsets'] ) ) {
1059
-					if ( ! empty( $font['all-subsets'] ) ) {
1060
-						foreach ( $font['all-subsets'] as $subset ) {
1061
-							if ( ! in_array( $subset, $subsets, true ) && ! is_numeric( $subset ) ) {
1062
-								$subsets[] = $subset;
1063
-							}
1064
-						}
1065
-					} elseif ( ! empty( $font['subset'] ) ) {
1066
-						foreach ( $font['subset'] as $subset ) {
1067
-							if ( ! in_array( $subset, $subsets, true ) && ! is_numeric( $subset ) ) {
1068
-								$subsets[] = $subset;
1069
-							}
1070
-						}
1071
-					}
1072
-				}
1073
-			}
1074
-
1075
-			if ( ! empty( $subsets ) ) {
1076
-				$link .= '&subset=' . implode( ',', $subsets );
1077
-			}
1078
-
1079
-			return "'" . $link . "'";
1080
-		}
1081
-
1082
-		/**
1083
-		 * Compiles field CSS for output.
1084
-		 *
1085
-		 * @param array $data Array of data to process.
1086
-		 *
1087
-		 * @return string
1088
-		 */
1089
-		public function css_style( $data ): string {
1090
-			$style = '';
1091
-
1092
-			$font = $data;
1093
-
1094
-			// Shim out old arg to new.
1095
-			if ( isset( $this->field['all_styles'] ) && ! empty( $this->field['all_styles'] ) ) {
1096
-				$this->field['all-styles'] = $this->field['all_styles'];
1097
-				unset( $this->field['all_styles'] );
1098
-			}
1099
-
1100
-			// Check for font-backup.  If it's set, stick it on a variable for
1101
-			// later use.
1102
-			if ( ! empty( $font['font-family'] ) && ! empty( $font['font-backup'] ) ) {
1103
-				$font['font-family'] = str_replace( ', ' . $font['font-backup'], '', $font['font-family'] );
1104
-				$font_backup         = ',' . $font['font-backup'];
1105
-			}
1106
-
1107
-			$font_value_set = false;
1108
-
1109
-			if ( ! empty( $font ) ) {
1110
-				foreach ( $font as $key => $value ) {
1111
-					if ( ! empty( $value ) && in_array( $key, array( 'font-family', 'font-weight' ), true ) ) {
1112
-						$font_value_set = true;
1113
-					}
1114
-				}
1115
-			}
1116
-
1117
-			if ( ! empty( $font ) ) {
1118
-				foreach ( $font as $key => $value ) {
1119
-					if ( 'font-options' === $key ) {
1120
-						continue;
1121
-					}
1122
-
1123
-					// Check for font-family key.
1124
-					if ( 'font-family' === $key ) {
1125
-
1126
-						// Enclose font family in quotes if spaces are in the
1127
-						// name.  This is necessary because if there are numerics
1128
-						// in the font name, they will not render properly.
1129
-						// Google should know better.
1130
-						if ( strpos( $value, ' ' ) && ! strpos( $value, ',' ) ) {
1131
-							$value = '"' . $value . '"';
1132
-						}
1133
-
1134
-						// Ensure fontBackup isn't empty. We already option
1135
-						// checked this earlier.  No need to do it again.
1136
-						if ( ! empty( $font_backup ) ) {
1137
-
1138
-							// Apply the backup font to the font-family element
1139
-							// via the saved variable.  We do this here, so it
1140
-							// doesn't get appended to the Google stuff below.
1141
-							$value .= $font_backup;
1142
-						}
1143
-					}
1144
-
1145
-					if ( empty( $value ) && in_array(
1146
-						$key,
1147
-						array(
1148
-							'font-weight',
1149
-							'font-style',
1150
-						),
1151
-						true
1152
-					) && true === $font_value_set ) {
1153
-						$value = 'normal';
1154
-					}
1155
-
1156
-					if ( 'font-weight' === $key && false === $this->field['font-weight'] ) {
1157
-						continue;
1158
-					}
1159
-
1160
-					if ( 'font-style' === $key && false === $this->field['font-style'] ) {
1161
-						continue;
1162
-					}
1163
-
1164
-					if ( 'google' === $key || 'subsets' === $key || 'font-backup' === $key || empty( $value ) ) {
1165
-						continue;
1166
-					}
1167
-
1168
-					if ( isset( $data['key'] ) ) {
1169
-						return $data;
1170
-					}
1171
-
1172
-					$continue = false;
1173
-
1174
-					if ( 'shadow-horizontal' === $key || 'shadow-vertical' === $key || 'shadow-blur' === $key ) {
1175
-						$continue = true;
1176
-					}
1177
-
1178
-					if ( 'shadow-color' === $key ) {
1179
-						if ( $this->field['text-shadow'] ) {
1180
-							$key   = 'text-shadow';
1181
-							$value = $data['shadow-horizontal'] . 'px ' . $data['shadow-vertical'] . 'px ' . $data['shadow-blur'] . 'px ' . $data['shadow-color'];
1182
-						} else {
1183
-							$continue = true;
1184
-						}
1185
-					}
1186
-
1187
-					if ( $continue ) {
1188
-						continue;
1189
-					}
1190
-
1191
-					$style .= $key . ':' . $value . ';';
1192
-				}
1193
-			}
1194
-
1195
-			return $style;
1196
-		}
1197
-
1198
-		/**
1199
-		 * CSS Output to send to the page.
1200
-		 *
1201
-		 * @param string|null|array $style CSS styles.
1202
-		 */
1203
-		public function output( $style = '' ) {
1204
-			$font = $this->value;
1205
-
1206
-			if ( '' !== $style ) {
1207
-				if ( ! empty( $this->field['output'] ) && ! is_array( $this->field['output'] ) ) {
1208
-					$this->field['output'] = array( $this->field['output'] );
1209
-				}
1210
-
1211
-				if ( ! empty( $this->field['output'] ) && is_array( $this->field['output'] ) ) {
1212
-					$keys                     = implode( ',', $this->field['output'] );
1213
-					$this->parent->outputCSS .= $keys . '{' . $style . '}';
1214
-				}
1215
-
1216
-				if ( ! empty( $this->field['compiler'] ) && ! is_array( $this->field['compiler'] ) ) {
1217
-					$this->field['compiler'] = array( $this->field['compiler'] );
1218
-				}
1219
-
1220
-				if ( ! empty( $this->field['compiler'] ) && is_array( $this->field['compiler'] ) ) {
1221
-					$keys                       = implode( ',', $this->field['compiler'] );
1222
-					$this->parent->compilerCSS .= $keys . '{' . $style . '}';
1223
-				}
1224
-			}
1225
-
1226
-			$this->set_google_fonts( (array) $font );
1227
-		}
1228
-
1229
-		/**
1230
-		 * Set global Google font data for global pointer.
1231
-		 *
1232
-		 * @param array $font Array of font data.
1233
-		 */
1234
-		private function set_google_fonts( array $font ) {
1235
-			// Google only stuff!
1236
-			if ( ! empty( $font['font-family'] ) && ! empty( $this->field['google'] ) && filter_var( $this->field['google'], FILTER_VALIDATE_BOOLEAN ) ) {
1237
-
1238
-				// Added standard font matching check to avoid output to Google fonts call - kp
1239
-				// If no custom font array was supplied, then load it with default
1240
-				// standard fonts.
1241
-				if ( empty( $this->field['fonts'] ) ) {
1242
-					$this->field['fonts'] = $this->std_fonts;
1243
-				}
1244
-
1245
-				// Ensure the fonts array is NOT empty.
1246
-				if ( ! empty( $this->field['fonts'] ) ) {
1247
-
1248
-					// Make the font keys in the array lowercase, for case-insensitive matching.
1249
-					$lc_fonts = array_change_key_case( $this->field['fonts'] );
1250
-
1251
-					// Rebuild font array with all keys stripped of spaces.
1252
-					$arr = array();
1253
-					foreach ( $lc_fonts as $key => $value ) {
1254
-						$key         = str_replace( ', ', ',', $key );
1255
-						$arr[ $key ] = $value;
1256
-					}
1257
-
1258
-					if ( is_array( $this->field['custom_fonts'] ) ) {
1259
-						$lc_fonts = array_change_key_case( $this->field['custom_fonts'] );
1260
-
1261
-						foreach ( $lc_fonts as $font_arr ) {
1262
-							foreach ( $font_arr as $key => $value ) {
1263
-								$arr[ Redux_Core::strtolower( $key ) ] = $key;
1264
-							}
1265
-						}
1266
-					}
1267
-
1268
-					$lc_fonts = $arr;
1269
-
1270
-					unset( $arr );
1271
-
1272
-					// lowercase chosen font for matching purposes.
1273
-					$lc_font = Redux_Core::strtolower( $font['font-family'] );
1274
-
1275
-					// Remove spaces after commas in chosen font for matching purposes.
1276
-					$lc_font = str_replace( ', ', ',', $lc_font );
1277
-
1278
-					// If the lower cased passed font-family is NOT found in the standard font array
1279
-					// Then it's a Google font, so process it for output.
1280
-					if ( ! array_key_exists( $lc_font, $lc_fonts ) ) {
1281
-						$family = $font['font-family'];
1282
-
1283
-						// TODO: This method doesn't respect spaces after commas, hence the reason
1284
-						// Strip out spaces in font names and replace with with plus signs
1285
-						// for the std_font array keys having no spaces after commas.  This could be
1286
-						// fixed with RegEx in the future.
1287
-						$font['font-family'] = str_replace( ' ', '+', $font['font-family'] );
1288
-
1289
-						// Push data to parent typography variable.
1290
-						if ( empty( Redux_Core::$typography[ $font['font-family'] ] ) ) {
1291
-							Redux_Core::$typography[ $font['font-family'] ] = array();
1292
-						}
1293
-
1294
-						if ( isset( $this->field['all-styles'] ) || isset( $this->field['all-subsets'] ) ) {
1295
-							if ( empty( $font['font-options'] ) ) {
1296
-								$this->get_google_array();
1297
-
1298
-								if ( isset( Redux_Core::$google_array ) && ! empty( Redux_Core::$google_array ) && isset( Redux_Core::$google_array[ $family ] ) ) {
1299
-									$font['font-options'] = Redux_Core::$google_array[ $family ];
1300
-								}
1301
-							} else {
1302
-								$font['font-options'] = json_decode( $font['font-options'], true );
1303
-							}
1304
-						}
1305
-
1306
-						if ( isset( $font['font-options'] ) && ! empty( $font['font-options'] ) && isset( $this->field['all-styles'] ) && filter_var( $this->field['all-styles'], FILTER_VALIDATE_BOOLEAN ) ) {
1307
-							if ( ! empty( $font['font-options']['variants'] ) ) {
1308
-								if ( ! isset( Redux_Core::$typography[ $font['font-family'] ]['all-styles'] ) || empty( Redux_Core::$typography[ $font['font-family'] ]['all-styles'] ) ) {
1309
-									Redux_Core::$typography[ $font['font-family'] ]['all-styles'] = array();
1310
-									foreach ( $font['font-options']['variants'] as $variant ) {
1311
-										Redux_Core::$typography[ $font['font-family'] ]['all-styles'][] = $variant['id'];
1312
-									}
1313
-								}
1314
-							}
1315
-						}
1316
-
1317
-						if ( isset( $font['font-options'] ) && ! empty( $font['font-options'] ) && isset( $this->field['all-subsets'] ) && $this->field['all-styles'] ) {
1318
-							if ( ! empty( $font['font-options']['subsets'] ) ) {
1319
-								if ( ! isset( Redux_Core::$typography[ $font['font-family'] ]['all-subsets'] ) || empty( Redux_Core::$typography[ $font['font-family'] ]['all-subsets'] ) ) {
1320
-									Redux_Core::$typography[ $font['font-family'] ]['all-subsets'] = array();
1321
-									foreach ( $font['font-options']['subsets'] as $variant ) {
1322
-										Redux_Core::$typography[ $font['font-family'] ]['all-subsets'][] = $variant['id'];
1323
-									}
1324
-								}
1325
-							}
1326
-						}
1327
-
1328
-						$style = '';
1329
-
1330
-						if ( ! empty( $font['font-weight'] ) ) {
1331
-							if ( empty( Redux_Core::$typography[ $font['font-family'] ]['font-weight'] ) || ! in_array( $font['font-weight'], Redux_Core::$typography[ $font['font-family'] ]['font-weight'], true ) ) {
1332
-								$style = $font['font-weight'];
1333
-							}
1334
-
1335
-							if ( ! empty( $font['font-style'] ) ) {
1336
-								$style .= $font['font-style'];
1337
-							}
1338
-
1339
-							if ( empty( Redux_Core::$typography[ $font['font-family'] ]['font-style'] ) || ! in_array( $style, Redux_Core::$typography[ $font['font-family'] ]['font-style'], true ) ) {
1340
-								Redux_Core::$typography[ $font['font-family'] ]['font-style'][] = $style;
1341
-							}
1342
-						}
1343
-
1344
-						if ( ! empty( $font['subsets'] ) ) {
1345
-							if ( empty( Redux_Core::$typography[ $font['font-family'] ]['subset'] ) || ! in_array( $font['subsets'], Redux_Core::$typography[ $font['font-family'] ]['subset'], true ) ) {
1346
-								Redux_Core::$typography[ $font['font-family'] ]['subset'][] = $font['subsets'];
1347
-							}
1348
-						}
1349
-					}
1350
-				}
1351
-			}
1352
-		}
1353
-
1354
-		/**
1355
-		 * Localize standard, custom and typekit fonts.
1356
-		 */
1357
-		private function localize_std_fonts() {
1358
-			if ( false === $this->user_fonts ) {
1359
-				if ( isset( Redux_Core::$fonts['std'] ) && ! empty( Redux_Core::$fonts['std'] ) ) {
1360
-					return;
1361
-				}
1362
-
1363
-				Redux_Core::$font_groups['std'] = array(
1364
-					'text'     => esc_html__( 'Standard Fonts', 'redux-framework' ),
1365
-					'children' => array(),
1366
-				);
1367
-
1368
-				foreach ( $this->field['fonts'] as $font => $extra ) {
1369
-					Redux_Core::$font_groups['std']['children'][] = array(
1370
-						'id'          => $font,
1371
-						'text'        => $font,
1372
-						'data-google' => 'false',
1373
-					);
1374
-				}
1375
-			}
1376
-
1377
-			if ( false !== $this->field['custom_fonts'] ) {
1378
-				// phpcs:ignored WordPress.NamingConventions.ValidHookName
1379
-				$this->field['custom_fonts'] = apply_filters( "redux/{$this->parent->args['opt_name']}/field/typography/custom_fonts", array() );
1380
-
1381
-				if ( ! empty( $this->field['custom_fonts'] ) ) {
1382
-					foreach ( $this->field['custom_fonts'] as $group => $fonts ) {
1383
-						Redux_Core::$font_groups['customfonts'] = array(
1384
-							'text'     => $group,
1385
-							'children' => array(),
1386
-						);
1387
-
1388
-						foreach ( $fonts as $family => $v ) {
1389
-							Redux_Core::$font_groups['customfonts']['children'][] = array(
1390
-								'id'          => $family,
1391
-								'text'        => $family,
1392
-								'data-google' => 'false',
1393
-							);
1394
-						}
1395
-					}
1396
-				}
1397
-			}
1398
-
1399
-			// Typekit.
1400
-			// phpcs:ignored WordPress.NamingConventions.ValidHookName
1401
-			$typekit_fonts = apply_filters( "redux/{$this->parent->args['opt_name']}/field/typography/typekit_fonts", array() );
1402
-
1403
-			if ( ! empty( $typekit_fonts ) ) {
1404
-				foreach ( $typekit_fonts as $group => $fonts ) {
1405
-					Redux_Core::$font_groups['typekitfonts'] = array(
1406
-						'text'     => $group,
1407
-						'children' => array(),
1408
-					);
1409
-
1410
-					foreach ( $fonts as $family => $v ) {
1411
-						Redux_Core::$font_groups['typekitfonts']['children'][] = array(
1412
-							'text'        => $family,
1413
-							'id'          => $family,
1414
-							'data-google' => 'false',
1415
-						);
1416
-					}
1417
-				}
1418
-			}
1419
-		}
1420
-
1421
-		/**
1422
-		 *   Construct the Google array from the stored JSON/HTML
1423
-		 */
1424
-		private function get_google_array() {
1425
-			if ( ( ( isset( Redux_Core::$fonts['google'] ) && ! empty( Redux_Core::$fonts['google'] ) ) ) || ( isset( Redux_Core::$fonts['google'] ) && false === Redux_Core::$fonts['google'] ) ) {
1426
-				return;
1427
-			}
1428
-
1429
-			$fonts = Redux_Helpers::google_fonts_array( get_option( 'auto_update_redux_google_fonts', false ) );
1430
-			if ( empty( $fonts ) ) {
1431
-				$google_font = __DIR__ . '/googlefonts.php';
1432
-				$fonts       = include $google_font;
1433
-			}
1434
-
1435
-			if ( true === $fonts ) {
1436
-				Redux_Core::$fonts['google'] = false;
1437
-
1438
-				return;
1439
-			}
1440
-
1441
-			if ( isset( $fonts ) && ! empty( $fonts ) && is_array( $fonts ) ) {
1442
-				Redux_Core::$fonts['google'] = $fonts;
1443
-				Redux_Core::$google_array    = $fonts;
1444
-
1445
-				// optgroup.
1446
-				Redux_Core::$font_groups['google'] = array(
1447
-					'text'     => esc_html__( 'Google Webfonts', 'redux-framework' ),
1448
-					'children' => array(),
1449
-				);
1450
-
1451
-				// options.
1452
-				foreach ( Redux_Core::$fonts['google'] as $font => $extra ) {
1453
-					Redux_Core::$font_groups['google']['children'][] = array(
1454
-						'id'          => $font,
1455
-						'text'        => $font,
1456
-						'data-google' => 'true',
1457
-					);
1458
-				}
1459
-			}
1460
-		}
1461
-
1462
-		/**
1463
-		 * Clean up the Google Webfonts subsets to be human-readable
1464
-		 *
1465
-		 * @param array $var Font subset array.
1466
-		 *
1467
-		 * @return array
1468
-		 *
1469
-		 * @since ReduxFramework 0.2.0
1470
-		 */
1471
-		private function get_subsets( array $var ): array {
1472
-			$result = array();
1473
-
1474
-			foreach ( $var as $v ) {
1475
-				if ( strpos( $v, '-ext' ) ) {
1476
-					$name = ucfirst( str_replace( '-ext', ' Extended', $v ) );
1477
-				} else {
1478
-					$name = ucfirst( $v );
1479
-				}
1480
-
1481
-				$result[] = array(
1482
-					'id'   => $v,
1483
-					'name' => $name,
1484
-				);
1485
-			}
1486
-
1487
-			return array_filter( $result );
1488
-		}
1489
-
1490
-		/**
1491
-		 * Clean up the Google Webfonts variants to be human-readable
1492
-		 *
1493
-		 * @param array $var Font variant array.
1494
-		 *
1495
-		 * @return array
1496
-		 *
1497
-		 * @since ReduxFramework 0.2.0
1498
-		 */
1499
-		private function get_variants( array $var ): array {
1500
-			$result = array();
1501
-			$italic = array();
1502
-
1503
-			foreach ( $var as $v ) {
1504
-				$name = '';
1505
-				if ( 1 === $v[0] ) {
1506
-					$name = 'Ultra-Light 100';
1507
-				} elseif ( 2 === $v[0] ) {
1508
-					$name = 'Light 200';
1509
-				} elseif ( 3 === $v[0] ) {
1510
-					$name = 'Book 300';
1511
-				} elseif ( 4 === $v[0] || 'r' === $v[0] || 'i' === $v[0] ) {
1512
-					$name = 'Normal 400';
1513
-				} elseif ( 5 === $v[0] ) {
1514
-					$name = 'Medium 500';
1515
-				} elseif ( 6 === $v[0] ) {
1516
-					$name = 'Semi-Bold 600';
1517
-				} elseif ( 7 === $v[0] ) {
1518
-					$name = 'Bold 700';
1519
-				} elseif ( 8 === $v[0] ) {
1520
-					$name = 'Extra-Bold 800';
1521
-				} elseif ( 9 === $v[0] ) {
1522
-					$name = 'Ultra-Bold 900';
1523
-				}
1524
-
1525
-				if ( 'regular' === $v ) {
1526
-					$v = '400';
1527
-				}
1528
-
1529
-				if ( strpos( $v, 'italic' ) || 'italic' === $v ) {
1530
-					$name .= ' Italic';
1531
-					$name  = trim( $name );
1532
-					if ( 'italic' === $v ) {
1533
-						$v = '400italic';
1534
-					}
1535
-					$italic[] = array(
1536
-						'id'   => $v,
1537
-						'name' => $name,
1538
-					);
1539
-				} else {
1540
-					$result[] = array(
1541
-						'id'   => $v,
1542
-						'name' => $name,
1543
-					);
1544
-				}
1545
-			}
1546
-
1547
-			foreach ( $italic as $item ) {
1548
-				$result[] = $item;
1549
-			}
1550
-
1551
-			return array_filter( $result );
1552
-		}
1553
-
1554
-		/**
1555
-		 * Update google font array via AJAX call.
1556
-		 */
1557
-		public function google_fonts_update_ajax() {
1558
-			if ( ! isset( $_POST['nonce'] ) || ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), 'redux_update_google_fonts' ) ) ) {
1559
-				die( 'Security check' );
1560
-			}
1561
-
1562
-			if ( isset( $_POST['data'] ) && 'automatic' === $_POST['data'] ) {
1563
-				update_option( 'auto_update_redux_google_fonts', true );
1564
-			}
1565
-
1566
-			$fonts = Redux_Helpers::google_fonts_array( true );
1567
-
1568
-			if ( ! empty( $fonts ) && ! is_wp_error( $fonts ) ) {
1569
-				echo wp_json_encode(
1570
-					array(
1571
-						'status' => 'success',
1572
-						'fonts'  => $fonts,
1573
-					)
1574
-				);
1575
-			} else {
1576
-				$err_msg = '';
1577
-
1578
-				if ( is_wp_error( $fonts ) ) {
1579
-					$err_msg = $fonts->get_error_code();
1580
-				}
1581
-
1582
-				echo wp_json_encode(
1583
-					array(
1584
-						'status' => 'error',
1585
-						'error'  => $err_msg,
1586
-					)
1587
-				);
1588
-			}
1589
-
1590
-			die();
1591
-		}
1592
-
1593
-		/**
1594
-		 * Enable output_variables to be generated.
1595
-		 *
1596
-		 * @since       4.0.3
1597
-		 * @return void
1598
-		 */
1599
-		public function output_variables() {
1600
-			// No code needed, just defining the method is enough.
1601
-		}
1602
-	}
871
+                    echo '<input type="hidden" id="redux-slider-value-' . esc_attr( $this->field['id'] ) . '-b" class="typography-shadow-blur" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[shadow-blur]" value="' . esc_attr( $this->value['shadow-blur'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"  />';
872
+                    echo '</div>';
873
+                }
874
+
875
+                echo '</div>'; // end typography container.
876
+            }
877
+        }
878
+
879
+        /**
880
+         * Enqueue for every field instance.
881
+         */
882
+        public function always_enqueue() {
883
+            $min = Redux_Functions::is_min();
884
+
885
+            if ( isset( $this->field['color_alpha'] ) && is_array( $this->field['color_alpha'] ) ) {
886
+                if ( $this->field['color_alpha']['color'] || $this->field['color_alpha']['shadow-color'] ) {
887
+                    wp_enqueue_script( 'redux-wp-color-picker-alpha' );
888
+                }
889
+            }
890
+
891
+            if ( ! wp_style_is( 'redux-nouislider' ) && isset( $this->field['text-shadow'] ) && $this->field['text-shadow'] ) {
892
+                wp_enqueue_style(
893
+                    'redux-nouislider',
894
+                    Redux_Core::$url . "assets/css/vendor/nouislider$min.css",
895
+                    array(),
896
+                    '5.0.0'
897
+                );
898
+
899
+                wp_enqueue_script(
900
+                    'redux-nouislider',
901
+                    Redux_Core::$url . "assets/js/vendor/nouislider/redux.jquery.nouislider$min.js",
902
+                    array( 'jquery' ),
903
+                    '5.0.0',
904
+                    true
905
+                );
906
+            }
907
+        }
908
+
909
+        /**
910
+         * Enqueue Function.
911
+         * If this field requires any scripts, or CSS define this function and register/enqueue the scripts/css
912
+         *
913
+         * @since ReduxFramework 1.0.0
914
+         */
915
+        public function enqueue() {
916
+            $min = Redux_Functions::is_min();
917
+
918
+            if ( ! wp_style_is( 'select2-css' ) ) {
919
+                wp_enqueue_style( 'select2-css' );
920
+            }
921
+
922
+            if ( ! wp_style_is( 'wp-color-picker' ) ) {
923
+                wp_enqueue_style( 'wp-color-picker' );
924
+            }
925
+
926
+            wp_enqueue_script(
927
+                'redux-webfont',
928
+                '//' . 'ajax' . '.googleapis' . '.com/ajax/libs/webfont/1.6.26/webfont.js', // phpcs:ignore Generic.Strings.UnnecessaryStringConcat
929
+                array(),
930
+                '1.6.26',
931
+                true
932
+            );
933
+
934
+            $dep_array = array( 'jquery', 'wp-color-picker', 'select2-js', 'redux-js', 'redux-webfont' );
935
+
936
+            wp_enqueue_script(
937
+                'redux-field-typography',
938
+                Redux_Core::$url . "inc/fields/typography/redux-typography$min.js",
939
+                $dep_array,
940
+                $this->timestamp,
941
+                true
942
+            );
943
+
944
+            wp_localize_script(
945
+                'redux-field-typography',
946
+                'redux_typography_ajax',
947
+                array(
948
+                    'ajaxurl'             => esc_url( admin_url( 'admin-ajax.php' ) ),
949
+                    'update_google_fonts' => array(
950
+                        'updating' => esc_html__( 'Downloading Google Fonts...', 'redux-framework' ),
951
+                        // translators: Aria title, link title.
952
+                        'error'    => sprintf( esc_html__( 'Update Failed|msg. %1$s', 'redux-framework' ), sprintf( '<a href="#" class="update-google-fonts" data-action="manual" aria-label="%s">%s</a>', esc_html__( 'Retry?', 'redux-framework' ), esc_html__( 'Retry?', 'redux-framework' ) ) ),
953
+                        // translators: Javascript reload command, link title.
954
+                        'success'  => sprintf( esc_html__( 'Updated! %1$s to start using your updated fonts.', 'redux-framework' ), sprintf( '<a href="	%1$s">%2$s</a>', 'javascript:location.reload();', esc_html__( 'Reload the page', 'redux-framework' ) ) ),
955
+                    ),
956
+                )
957
+            );
958
+
959
+            if ( $this->parent->args['dev_mode'] ) {
960
+                wp_enqueue_style( 'redux-color-picker' );
961
+
962
+                wp_enqueue_style(
963
+                    'redux-field-typography',
964
+                    Redux_Core::$url . 'inc/fields/typography/redux-typography.css',
965
+                    array(),
966
+                    $this->timestamp
967
+                );
968
+            }
969
+        }
970
+
971
+        /**
972
+         * Make_google_web_font_link Function.
973
+         * Creates the Google fonts link.
974
+         *
975
+         * @param array $fonts Array of google fonts.
976
+         *
977
+         * @return string
978
+         *
979
+         * @since ReduxFramework 3.0.0
980
+         */
981
+        public function make_google_web_font_link( array $fonts ): string {
982
+            $link    = '';
983
+            $subsets = array();
984
+
985
+            foreach ( $fonts as $family => $font ) {
986
+                if ( ! empty( $link ) ) {
987
+                    $link .= '|'; // Append a new font to the string.
988
+                }
989
+                $link .= $family;
990
+
991
+                if ( ! empty( $font['font-style'] ) || ! empty( $font['all-styles'] ) ) {
992
+                    $link .= ':';
993
+                    if ( ! empty( $font['all-styles'] ) ) {
994
+                        $link .= implode( ',', $font['all-styles'] );
995
+                    } elseif ( ! empty( $font['font-style'] ) ) {
996
+                        $link .= implode( ',', $font['font-style'] );
997
+                    }
998
+                }
999
+
1000
+                if ( ! empty( $font['subset'] ) || ! empty( $font['all-subsets'] ) ) {
1001
+                    if ( ! empty( $font['all-subsets'] ) ) {
1002
+                        foreach ( $font['all-subsets'] as $subset ) {
1003
+                            if ( ! in_array( $subset, $subsets, true ) ) {
1004
+                                $subsets[] = $subset;
1005
+                            }
1006
+                        }
1007
+                    } elseif ( ! empty( $font['subset'] ) ) {
1008
+                        foreach ( $font['subset'] as $subset ) {
1009
+                            if ( ! in_array( $subset, $subsets, true ) ) {
1010
+                                $subsets[] = $subset;
1011
+                            }
1012
+                        }
1013
+                    }
1014
+                }
1015
+            }
1016
+
1017
+            if ( ! empty( $subsets ) ) {
1018
+                $link .= '&subset=' . implode( ',', $subsets );
1019
+            }
1020
+
1021
+            $display = $this->parent->args['font_display'] ?? 'swap';
1022
+
1023
+            $link .= '&display=' . $display;
1024
+
1025
+            // return 'https://fonts.bunny.net/css?family=' . $link;
1026
+            return 'https://fonts.googleapis.com/css?family=' . $link;
1027
+        }
1028
+
1029
+        /**
1030
+         * Make_google_web_font_string Function.
1031
+         * Creates the Google fonts link.
1032
+         *
1033
+         * @param array $fonts Array of Google fonts.
1034
+         *
1035
+         * @return string
1036
+         *
1037
+         * @since ReduxFramework 3.1.8
1038
+         */
1039
+        public function make_google_web_font_string( array $fonts ): string {
1040
+            $link    = '';
1041
+            $subsets = array();
1042
+
1043
+            foreach ( $fonts as $family => $font ) {
1044
+                if ( ! empty( $link ) ) {
1045
+                    $link .= "', '"; // Append a new font to the string.
1046
+                }
1047
+                $link .= $family;
1048
+
1049
+                if ( ! empty( $font['font-style'] ) || ! empty( $font['all-styles'] ) ) {
1050
+                    $link .= ':';
1051
+                    if ( ! empty( $font['all-styles'] ) ) {
1052
+                        $link .= implode( ',', $font['all-styles'] );
1053
+                    } elseif ( ! empty( $font['font-style'] ) ) {
1054
+                        $link .= implode( ',', $font['font-style'] );
1055
+                    }
1056
+                }
1057
+
1058
+                if ( ! empty( $font['subset'] ) || ! empty( $font['all-subsets'] ) ) {
1059
+                    if ( ! empty( $font['all-subsets'] ) ) {
1060
+                        foreach ( $font['all-subsets'] as $subset ) {
1061
+                            if ( ! in_array( $subset, $subsets, true ) && ! is_numeric( $subset ) ) {
1062
+                                $subsets[] = $subset;
1063
+                            }
1064
+                        }
1065
+                    } elseif ( ! empty( $font['subset'] ) ) {
1066
+                        foreach ( $font['subset'] as $subset ) {
1067
+                            if ( ! in_array( $subset, $subsets, true ) && ! is_numeric( $subset ) ) {
1068
+                                $subsets[] = $subset;
1069
+                            }
1070
+                        }
1071
+                    }
1072
+                }
1073
+            }
1074
+
1075
+            if ( ! empty( $subsets ) ) {
1076
+                $link .= '&subset=' . implode( ',', $subsets );
1077
+            }
1078
+
1079
+            return "'" . $link . "'";
1080
+        }
1081
+
1082
+        /**
1083
+         * Compiles field CSS for output.
1084
+         *
1085
+         * @param array $data Array of data to process.
1086
+         *
1087
+         * @return string
1088
+         */
1089
+        public function css_style( $data ): string {
1090
+            $style = '';
1091
+
1092
+            $font = $data;
1093
+
1094
+            // Shim out old arg to new.
1095
+            if ( isset( $this->field['all_styles'] ) && ! empty( $this->field['all_styles'] ) ) {
1096
+                $this->field['all-styles'] = $this->field['all_styles'];
1097
+                unset( $this->field['all_styles'] );
1098
+            }
1099
+
1100
+            // Check for font-backup.  If it's set, stick it on a variable for
1101
+            // later use.
1102
+            if ( ! empty( $font['font-family'] ) && ! empty( $font['font-backup'] ) ) {
1103
+                $font['font-family'] = str_replace( ', ' . $font['font-backup'], '', $font['font-family'] );
1104
+                $font_backup         = ',' . $font['font-backup'];
1105
+            }
1106
+
1107
+            $font_value_set = false;
1108
+
1109
+            if ( ! empty( $font ) ) {
1110
+                foreach ( $font as $key => $value ) {
1111
+                    if ( ! empty( $value ) && in_array( $key, array( 'font-family', 'font-weight' ), true ) ) {
1112
+                        $font_value_set = true;
1113
+                    }
1114
+                }
1115
+            }
1116
+
1117
+            if ( ! empty( $font ) ) {
1118
+                foreach ( $font as $key => $value ) {
1119
+                    if ( 'font-options' === $key ) {
1120
+                        continue;
1121
+                    }
1122
+
1123
+                    // Check for font-family key.
1124
+                    if ( 'font-family' === $key ) {
1125
+
1126
+                        // Enclose font family in quotes if spaces are in the
1127
+                        // name.  This is necessary because if there are numerics
1128
+                        // in the font name, they will not render properly.
1129
+                        // Google should know better.
1130
+                        if ( strpos( $value, ' ' ) && ! strpos( $value, ',' ) ) {
1131
+                            $value = '"' . $value . '"';
1132
+                        }
1133
+
1134
+                        // Ensure fontBackup isn't empty. We already option
1135
+                        // checked this earlier.  No need to do it again.
1136
+                        if ( ! empty( $font_backup ) ) {
1137
+
1138
+                            // Apply the backup font to the font-family element
1139
+                            // via the saved variable.  We do this here, so it
1140
+                            // doesn't get appended to the Google stuff below.
1141
+                            $value .= $font_backup;
1142
+                        }
1143
+                    }
1144
+
1145
+                    if ( empty( $value ) && in_array(
1146
+                        $key,
1147
+                        array(
1148
+                            'font-weight',
1149
+                            'font-style',
1150
+                        ),
1151
+                        true
1152
+                    ) && true === $font_value_set ) {
1153
+                        $value = 'normal';
1154
+                    }
1155
+
1156
+                    if ( 'font-weight' === $key && false === $this->field['font-weight'] ) {
1157
+                        continue;
1158
+                    }
1159
+
1160
+                    if ( 'font-style' === $key && false === $this->field['font-style'] ) {
1161
+                        continue;
1162
+                    }
1163
+
1164
+                    if ( 'google' === $key || 'subsets' === $key || 'font-backup' === $key || empty( $value ) ) {
1165
+                        continue;
1166
+                    }
1167
+
1168
+                    if ( isset( $data['key'] ) ) {
1169
+                        return $data;
1170
+                    }
1171
+
1172
+                    $continue = false;
1173
+
1174
+                    if ( 'shadow-horizontal' === $key || 'shadow-vertical' === $key || 'shadow-blur' === $key ) {
1175
+                        $continue = true;
1176
+                    }
1177
+
1178
+                    if ( 'shadow-color' === $key ) {
1179
+                        if ( $this->field['text-shadow'] ) {
1180
+                            $key   = 'text-shadow';
1181
+                            $value = $data['shadow-horizontal'] . 'px ' . $data['shadow-vertical'] . 'px ' . $data['shadow-blur'] . 'px ' . $data['shadow-color'];
1182
+                        } else {
1183
+                            $continue = true;
1184
+                        }
1185
+                    }
1186
+
1187
+                    if ( $continue ) {
1188
+                        continue;
1189
+                    }
1190
+
1191
+                    $style .= $key . ':' . $value . ';';
1192
+                }
1193
+            }
1194
+
1195
+            return $style;
1196
+        }
1197
+
1198
+        /**
1199
+         * CSS Output to send to the page.
1200
+         *
1201
+         * @param string|null|array $style CSS styles.
1202
+         */
1203
+        public function output( $style = '' ) {
1204
+            $font = $this->value;
1205
+
1206
+            if ( '' !== $style ) {
1207
+                if ( ! empty( $this->field['output'] ) && ! is_array( $this->field['output'] ) ) {
1208
+                    $this->field['output'] = array( $this->field['output'] );
1209
+                }
1210
+
1211
+                if ( ! empty( $this->field['output'] ) && is_array( $this->field['output'] ) ) {
1212
+                    $keys                     = implode( ',', $this->field['output'] );
1213
+                    $this->parent->outputCSS .= $keys . '{' . $style . '}';
1214
+                }
1215
+
1216
+                if ( ! empty( $this->field['compiler'] ) && ! is_array( $this->field['compiler'] ) ) {
1217
+                    $this->field['compiler'] = array( $this->field['compiler'] );
1218
+                }
1219
+
1220
+                if ( ! empty( $this->field['compiler'] ) && is_array( $this->field['compiler'] ) ) {
1221
+                    $keys                       = implode( ',', $this->field['compiler'] );
1222
+                    $this->parent->compilerCSS .= $keys . '{' . $style . '}';
1223
+                }
1224
+            }
1225
+
1226
+            $this->set_google_fonts( (array) $font );
1227
+        }
1228
+
1229
+        /**
1230
+         * Set global Google font data for global pointer.
1231
+         *
1232
+         * @param array $font Array of font data.
1233
+         */
1234
+        private function set_google_fonts( array $font ) {
1235
+            // Google only stuff!
1236
+            if ( ! empty( $font['font-family'] ) && ! empty( $this->field['google'] ) && filter_var( $this->field['google'], FILTER_VALIDATE_BOOLEAN ) ) {
1237
+
1238
+                // Added standard font matching check to avoid output to Google fonts call - kp
1239
+                // If no custom font array was supplied, then load it with default
1240
+                // standard fonts.
1241
+                if ( empty( $this->field['fonts'] ) ) {
1242
+                    $this->field['fonts'] = $this->std_fonts;
1243
+                }
1244
+
1245
+                // Ensure the fonts array is NOT empty.
1246
+                if ( ! empty( $this->field['fonts'] ) ) {
1247
+
1248
+                    // Make the font keys in the array lowercase, for case-insensitive matching.
1249
+                    $lc_fonts = array_change_key_case( $this->field['fonts'] );
1250
+
1251
+                    // Rebuild font array with all keys stripped of spaces.
1252
+                    $arr = array();
1253
+                    foreach ( $lc_fonts as $key => $value ) {
1254
+                        $key         = str_replace( ', ', ',', $key );
1255
+                        $arr[ $key ] = $value;
1256
+                    }
1257
+
1258
+                    if ( is_array( $this->field['custom_fonts'] ) ) {
1259
+                        $lc_fonts = array_change_key_case( $this->field['custom_fonts'] );
1260
+
1261
+                        foreach ( $lc_fonts as $font_arr ) {
1262
+                            foreach ( $font_arr as $key => $value ) {
1263
+                                $arr[ Redux_Core::strtolower( $key ) ] = $key;
1264
+                            }
1265
+                        }
1266
+                    }
1267
+
1268
+                    $lc_fonts = $arr;
1269
+
1270
+                    unset( $arr );
1271
+
1272
+                    // lowercase chosen font for matching purposes.
1273
+                    $lc_font = Redux_Core::strtolower( $font['font-family'] );
1274
+
1275
+                    // Remove spaces after commas in chosen font for matching purposes.
1276
+                    $lc_font = str_replace( ', ', ',', $lc_font );
1277
+
1278
+                    // If the lower cased passed font-family is NOT found in the standard font array
1279
+                    // Then it's a Google font, so process it for output.
1280
+                    if ( ! array_key_exists( $lc_font, $lc_fonts ) ) {
1281
+                        $family = $font['font-family'];
1282
+
1283
+                        // TODO: This method doesn't respect spaces after commas, hence the reason
1284
+                        // Strip out spaces in font names and replace with with plus signs
1285
+                        // for the std_font array keys having no spaces after commas.  This could be
1286
+                        // fixed with RegEx in the future.
1287
+                        $font['font-family'] = str_replace( ' ', '+', $font['font-family'] );
1288
+
1289
+                        // Push data to parent typography variable.
1290
+                        if ( empty( Redux_Core::$typography[ $font['font-family'] ] ) ) {
1291
+                            Redux_Core::$typography[ $font['font-family'] ] = array();
1292
+                        }
1293
+
1294
+                        if ( isset( $this->field['all-styles'] ) || isset( $this->field['all-subsets'] ) ) {
1295
+                            if ( empty( $font['font-options'] ) ) {
1296
+                                $this->get_google_array();
1297
+
1298
+                                if ( isset( Redux_Core::$google_array ) && ! empty( Redux_Core::$google_array ) && isset( Redux_Core::$google_array[ $family ] ) ) {
1299
+                                    $font['font-options'] = Redux_Core::$google_array[ $family ];
1300
+                                }
1301
+                            } else {
1302
+                                $font['font-options'] = json_decode( $font['font-options'], true );
1303
+                            }
1304
+                        }
1305
+
1306
+                        if ( isset( $font['font-options'] ) && ! empty( $font['font-options'] ) && isset( $this->field['all-styles'] ) && filter_var( $this->field['all-styles'], FILTER_VALIDATE_BOOLEAN ) ) {
1307
+                            if ( ! empty( $font['font-options']['variants'] ) ) {
1308
+                                if ( ! isset( Redux_Core::$typography[ $font['font-family'] ]['all-styles'] ) || empty( Redux_Core::$typography[ $font['font-family'] ]['all-styles'] ) ) {
1309
+                                    Redux_Core::$typography[ $font['font-family'] ]['all-styles'] = array();
1310
+                                    foreach ( $font['font-options']['variants'] as $variant ) {
1311
+                                        Redux_Core::$typography[ $font['font-family'] ]['all-styles'][] = $variant['id'];
1312
+                                    }
1313
+                                }
1314
+                            }
1315
+                        }
1316
+
1317
+                        if ( isset( $font['font-options'] ) && ! empty( $font['font-options'] ) && isset( $this->field['all-subsets'] ) && $this->field['all-styles'] ) {
1318
+                            if ( ! empty( $font['font-options']['subsets'] ) ) {
1319
+                                if ( ! isset( Redux_Core::$typography[ $font['font-family'] ]['all-subsets'] ) || empty( Redux_Core::$typography[ $font['font-family'] ]['all-subsets'] ) ) {
1320
+                                    Redux_Core::$typography[ $font['font-family'] ]['all-subsets'] = array();
1321
+                                    foreach ( $font['font-options']['subsets'] as $variant ) {
1322
+                                        Redux_Core::$typography[ $font['font-family'] ]['all-subsets'][] = $variant['id'];
1323
+                                    }
1324
+                                }
1325
+                            }
1326
+                        }
1327
+
1328
+                        $style = '';
1329
+
1330
+                        if ( ! empty( $font['font-weight'] ) ) {
1331
+                            if ( empty( Redux_Core::$typography[ $font['font-family'] ]['font-weight'] ) || ! in_array( $font['font-weight'], Redux_Core::$typography[ $font['font-family'] ]['font-weight'], true ) ) {
1332
+                                $style = $font['font-weight'];
1333
+                            }
1334
+
1335
+                            if ( ! empty( $font['font-style'] ) ) {
1336
+                                $style .= $font['font-style'];
1337
+                            }
1338
+
1339
+                            if ( empty( Redux_Core::$typography[ $font['font-family'] ]['font-style'] ) || ! in_array( $style, Redux_Core::$typography[ $font['font-family'] ]['font-style'], true ) ) {
1340
+                                Redux_Core::$typography[ $font['font-family'] ]['font-style'][] = $style;
1341
+                            }
1342
+                        }
1343
+
1344
+                        if ( ! empty( $font['subsets'] ) ) {
1345
+                            if ( empty( Redux_Core::$typography[ $font['font-family'] ]['subset'] ) || ! in_array( $font['subsets'], Redux_Core::$typography[ $font['font-family'] ]['subset'], true ) ) {
1346
+                                Redux_Core::$typography[ $font['font-family'] ]['subset'][] = $font['subsets'];
1347
+                            }
1348
+                        }
1349
+                    }
1350
+                }
1351
+            }
1352
+        }
1353
+
1354
+        /**
1355
+         * Localize standard, custom and typekit fonts.
1356
+         */
1357
+        private function localize_std_fonts() {
1358
+            if ( false === $this->user_fonts ) {
1359
+                if ( isset( Redux_Core::$fonts['std'] ) && ! empty( Redux_Core::$fonts['std'] ) ) {
1360
+                    return;
1361
+                }
1362
+
1363
+                Redux_Core::$font_groups['std'] = array(
1364
+                    'text'     => esc_html__( 'Standard Fonts', 'redux-framework' ),
1365
+                    'children' => array(),
1366
+                );
1367
+
1368
+                foreach ( $this->field['fonts'] as $font => $extra ) {
1369
+                    Redux_Core::$font_groups['std']['children'][] = array(
1370
+                        'id'          => $font,
1371
+                        'text'        => $font,
1372
+                        'data-google' => 'false',
1373
+                    );
1374
+                }
1375
+            }
1376
+
1377
+            if ( false !== $this->field['custom_fonts'] ) {
1378
+                // phpcs:ignored WordPress.NamingConventions.ValidHookName
1379
+                $this->field['custom_fonts'] = apply_filters( "redux/{$this->parent->args['opt_name']}/field/typography/custom_fonts", array() );
1380
+
1381
+                if ( ! empty( $this->field['custom_fonts'] ) ) {
1382
+                    foreach ( $this->field['custom_fonts'] as $group => $fonts ) {
1383
+                        Redux_Core::$font_groups['customfonts'] = array(
1384
+                            'text'     => $group,
1385
+                            'children' => array(),
1386
+                        );
1387
+
1388
+                        foreach ( $fonts as $family => $v ) {
1389
+                            Redux_Core::$font_groups['customfonts']['children'][] = array(
1390
+                                'id'          => $family,
1391
+                                'text'        => $family,
1392
+                                'data-google' => 'false',
1393
+                            );
1394
+                        }
1395
+                    }
1396
+                }
1397
+            }
1398
+
1399
+            // Typekit.
1400
+            // phpcs:ignored WordPress.NamingConventions.ValidHookName
1401
+            $typekit_fonts = apply_filters( "redux/{$this->parent->args['opt_name']}/field/typography/typekit_fonts", array() );
1402
+
1403
+            if ( ! empty( $typekit_fonts ) ) {
1404
+                foreach ( $typekit_fonts as $group => $fonts ) {
1405
+                    Redux_Core::$font_groups['typekitfonts'] = array(
1406
+                        'text'     => $group,
1407
+                        'children' => array(),
1408
+                    );
1409
+
1410
+                    foreach ( $fonts as $family => $v ) {
1411
+                        Redux_Core::$font_groups['typekitfonts']['children'][] = array(
1412
+                            'text'        => $family,
1413
+                            'id'          => $family,
1414
+                            'data-google' => 'false',
1415
+                        );
1416
+                    }
1417
+                }
1418
+            }
1419
+        }
1420
+
1421
+        /**
1422
+         *   Construct the Google array from the stored JSON/HTML
1423
+         */
1424
+        private function get_google_array() {
1425
+            if ( ( ( isset( Redux_Core::$fonts['google'] ) && ! empty( Redux_Core::$fonts['google'] ) ) ) || ( isset( Redux_Core::$fonts['google'] ) && false === Redux_Core::$fonts['google'] ) ) {
1426
+                return;
1427
+            }
1428
+
1429
+            $fonts = Redux_Helpers::google_fonts_array( get_option( 'auto_update_redux_google_fonts', false ) );
1430
+            if ( empty( $fonts ) ) {
1431
+                $google_font = __DIR__ . '/googlefonts.php';
1432
+                $fonts       = include $google_font;
1433
+            }
1434
+
1435
+            if ( true === $fonts ) {
1436
+                Redux_Core::$fonts['google'] = false;
1437
+
1438
+                return;
1439
+            }
1440
+
1441
+            if ( isset( $fonts ) && ! empty( $fonts ) && is_array( $fonts ) ) {
1442
+                Redux_Core::$fonts['google'] = $fonts;
1443
+                Redux_Core::$google_array    = $fonts;
1444
+
1445
+                // optgroup.
1446
+                Redux_Core::$font_groups['google'] = array(
1447
+                    'text'     => esc_html__( 'Google Webfonts', 'redux-framework' ),
1448
+                    'children' => array(),
1449
+                );
1450
+
1451
+                // options.
1452
+                foreach ( Redux_Core::$fonts['google'] as $font => $extra ) {
1453
+                    Redux_Core::$font_groups['google']['children'][] = array(
1454
+                        'id'          => $font,
1455
+                        'text'        => $font,
1456
+                        'data-google' => 'true',
1457
+                    );
1458
+                }
1459
+            }
1460
+        }
1461
+
1462
+        /**
1463
+         * Clean up the Google Webfonts subsets to be human-readable
1464
+         *
1465
+         * @param array $var Font subset array.
1466
+         *
1467
+         * @return array
1468
+         *
1469
+         * @since ReduxFramework 0.2.0
1470
+         */
1471
+        private function get_subsets( array $var ): array {
1472
+            $result = array();
1473
+
1474
+            foreach ( $var as $v ) {
1475
+                if ( strpos( $v, '-ext' ) ) {
1476
+                    $name = ucfirst( str_replace( '-ext', ' Extended', $v ) );
1477
+                } else {
1478
+                    $name = ucfirst( $v );
1479
+                }
1480
+
1481
+                $result[] = array(
1482
+                    'id'   => $v,
1483
+                    'name' => $name,
1484
+                );
1485
+            }
1486
+
1487
+            return array_filter( $result );
1488
+        }
1489
+
1490
+        /**
1491
+         * Clean up the Google Webfonts variants to be human-readable
1492
+         *
1493
+         * @param array $var Font variant array.
1494
+         *
1495
+         * @return array
1496
+         *
1497
+         * @since ReduxFramework 0.2.0
1498
+         */
1499
+        private function get_variants( array $var ): array {
1500
+            $result = array();
1501
+            $italic = array();
1502
+
1503
+            foreach ( $var as $v ) {
1504
+                $name = '';
1505
+                if ( 1 === $v[0] ) {
1506
+                    $name = 'Ultra-Light 100';
1507
+                } elseif ( 2 === $v[0] ) {
1508
+                    $name = 'Light 200';
1509
+                } elseif ( 3 === $v[0] ) {
1510
+                    $name = 'Book 300';
1511
+                } elseif ( 4 === $v[0] || 'r' === $v[0] || 'i' === $v[0] ) {
1512
+                    $name = 'Normal 400';
1513
+                } elseif ( 5 === $v[0] ) {
1514
+                    $name = 'Medium 500';
1515
+                } elseif ( 6 === $v[0] ) {
1516
+                    $name = 'Semi-Bold 600';
1517
+                } elseif ( 7 === $v[0] ) {
1518
+                    $name = 'Bold 700';
1519
+                } elseif ( 8 === $v[0] ) {
1520
+                    $name = 'Extra-Bold 800';
1521
+                } elseif ( 9 === $v[0] ) {
1522
+                    $name = 'Ultra-Bold 900';
1523
+                }
1524
+
1525
+                if ( 'regular' === $v ) {
1526
+                    $v = '400';
1527
+                }
1528
+
1529
+                if ( strpos( $v, 'italic' ) || 'italic' === $v ) {
1530
+                    $name .= ' Italic';
1531
+                    $name  = trim( $name );
1532
+                    if ( 'italic' === $v ) {
1533
+                        $v = '400italic';
1534
+                    }
1535
+                    $italic[] = array(
1536
+                        'id'   => $v,
1537
+                        'name' => $name,
1538
+                    );
1539
+                } else {
1540
+                    $result[] = array(
1541
+                        'id'   => $v,
1542
+                        'name' => $name,
1543
+                    );
1544
+                }
1545
+            }
1546
+
1547
+            foreach ( $italic as $item ) {
1548
+                $result[] = $item;
1549
+            }
1550
+
1551
+            return array_filter( $result );
1552
+        }
1553
+
1554
+        /**
1555
+         * Update google font array via AJAX call.
1556
+         */
1557
+        public function google_fonts_update_ajax() {
1558
+            if ( ! isset( $_POST['nonce'] ) || ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), 'redux_update_google_fonts' ) ) ) {
1559
+                die( 'Security check' );
1560
+            }
1561
+
1562
+            if ( isset( $_POST['data'] ) && 'automatic' === $_POST['data'] ) {
1563
+                update_option( 'auto_update_redux_google_fonts', true );
1564
+            }
1565
+
1566
+            $fonts = Redux_Helpers::google_fonts_array( true );
1567
+
1568
+            if ( ! empty( $fonts ) && ! is_wp_error( $fonts ) ) {
1569
+                echo wp_json_encode(
1570
+                    array(
1571
+                        'status' => 'success',
1572
+                        'fonts'  => $fonts,
1573
+                    )
1574
+                );
1575
+            } else {
1576
+                $err_msg = '';
1577
+
1578
+                if ( is_wp_error( $fonts ) ) {
1579
+                    $err_msg = $fonts->get_error_code();
1580
+                }
1581
+
1582
+                echo wp_json_encode(
1583
+                    array(
1584
+                        'status' => 'error',
1585
+                        'error'  => $err_msg,
1586
+                    )
1587
+                );
1588
+            }
1589
+
1590
+            die();
1591
+        }
1592
+
1593
+        /**
1594
+         * Enable output_variables to be generated.
1595
+         *
1596
+         * @since       4.0.3
1597
+         * @return void
1598
+         */
1599
+        public function output_variables() {
1600
+            // No code needed, just defining the method is enough.
1601
+        }
1602
+    }
1603 1603
 }
1604 1604
 if ( ! class_exists( 'ReduxFramework_Typography' ) ) {
1605
-	class_alias( 'Redux_Typography', 'ReduxFramework_Typography' );
1605
+    class_alias( 'Redux_Typography', 'ReduxFramework_Typography' );
1606 1606
 }
Please login to merge, or discard this patch.