Issues (377)

modules/css/class-kirki-modules-css.php (1 issue)

1
<?php
2
/**
3
 * Handles the CSS Output of fields.
4
 *
5
 * @package     Kirki
6
 * @category    Modules
7
 * @author      Aristeides Stathopoulos
8
 * @copyright   Copyright (c) 2017, Aristeides Stathopoulos
9
 * @license    https://opensource.org/licenses/MIT
10
 * @since       3.0.0
11
 */
12
13
/**
14
 * The Kirki_Modules_CSS object.
15
 */
16
class Kirki_Modules_CSS {
17
18
	/**
19
	 * The object instance.
20
	 *
21
	 * @static
22
	 * @access private
23
	 * @since 3.0.0
24
	 * @var object
25
	 */
26
	private static $instance;
27
28
	/**
29
	 * Whether we've already processed this or not.
30
	 *
31
	 * @access public
32
	 * @var bool
33
	 */
34
	public $processed = false;
35
36
	/**
37
	 * The CSS array
38
	 *
39
	 * @access public
40
	 * @var array
41
	 */
42
	public static $css_array = array();
43
44
	/**
45
	 * Set to true if you want to use the AJAX method.
46
	 *
47
	 * @access public
48
	 * @var bool
49
	 */
50
	public static $ajax = false;
51
52
	/**
53
	 * The Kirki_CSS_To_File object.
54
	 *
55
	 * @access protected
56
	 * @since 3.0.0
57
	 * @var object
58
	 */
59
	protected $css_to_file;
60
61
	/**
62
	 * Should we enqueue font-awesome?
63
	 *
64
	 * @static
65
	 * @access protected
66
	 * @since 3.0.26
67
	 * @var bool
68
	 */
69
	protected static $enqueue_fa = false;
70
71
	/**
72
	 * Constructor
73
	 *
74
	 * @access protected
75
	 */
76
	protected function __construct() {
77
		$class_files = array(
78
			'Kirki_CSS_To_File'                         => '/class-kirki-css-to-file.php',
79
			'Kirki_Modules_CSS_Generator'               => '/class-kirki-modules-css-generator.php',
80
			'Kirki_Output'                              => '/class-kirki-output.php',
81
			'Kirki_Output_Field_Background'             => '/field/class-kirki-output-field-background.php',
82
			'Kirki_Output_Field_Image'                  => '/field/class-kirki-output-field-image.php',
83
			'Kirki_Output_Field_Multicolor'             => '/field/class-kirki-output-field-multicolor.php',
84
			'Kirki_Output_Field_Dimensions'             => '/field/class-kirki-output-field-dimensions.php',
85
			'Kirki_Output_Field_Typography'             => '/field/class-kirki-output-field-typography.php',
86
			'Kirki_Output_Property'                     => '/property/class-kirki-output-property.php',
87
			'Kirki_Output_Property_Background_Image'    => '/property/class-kirki-output-property-background-image.php',
88
			'Kirki_Output_Property_Background_Position' => '/property/class-kirki-output-property-background-position.php',
89
			'Kirki_Output_Property_Font_Family'         => '/property/class-kirki-output-property-font-family.php',
90
		);
91
92
		foreach ( $class_files as $class_name => $file ) {
93
			if ( ! class_exists( $class_name ) ) {
94
				include_once wp_normalize_path( dirname( __FILE__ ) . $file );
95
			}
96
		}
97
		add_action( 'init', array( $this, 'init' ) );
98
	}
99
100
	/**
101
	 * Gets an instance of this object.
102
	 * Prevents duplicate instances which avoid artefacts and improves performance.
103
	 *
104
	 * @static
105
	 * @access public
106
	 * @since 3.0.0
107
	 * @return object
108
	 */
109
	public static function get_instance() {
110
		if ( ! self::$instance ) {
111
			self::$instance = new self();
112
		}
113
		return self::$instance;
114
	}
115
116
	/**
117
	 * Init.
118
	 *
119
	 * @access public
120
	 */
121
	public function init() {
122
		global $wp_customize;
123
124
		Kirki_Modules_Webfonts::get_instance();
125
126
		$config   = apply_filters( 'kirki_config', array() );
127
		$priority = 999;
128
		if ( isset( $config['styles_priority'] ) ) {
129
			$priority = absint( $config['styles_priority'] );
130
		}
131
132
		// Allow completely disabling Kirki CSS output.
133
		if ( ( defined( 'KIRKI_NO_OUTPUT' ) && true === KIRKI_NO_OUTPUT ) || ( isset( $config['disable_output'] ) && true === $config['disable_output'] ) ) {
134
			return;
135
		}
136
137
		$method = apply_filters( 'kirki_dynamic_css_method', 'inline' );
138
		if ( $wp_customize ) {
139
140
			// If we're in the customizer, load inline no matter what.
141
			add_action( 'wp_enqueue_scripts', array( $this, 'inline_dynamic_css' ), $priority );
142
			add_action( 'enqueue_block_editor_assets', array( $this, 'inline_dynamic_css' ), $priority );
143
144
			// If we're using file method, on save write the new styles.
145
			if ( 'file' === $method ) {
146
				$this->css_to_file = new Kirki_CSS_To_File();
147
				add_action( 'customize_save_after', array( $this->css_to_file, 'write_file' ) );
148
			}
149
			return;
150
		}
151
152
		if ( 'file' === $method ) {
153
154
			// Attempt to write the CSS to file.
155
			$this->css_to_file = new Kirki_CSS_To_File();
156
157
			// If we succesd, load this file.
158
			$failed = get_transient( 'kirki_css_write_to_file_failed' );
159
160
			// If writing CSS to file hasn't failed, just enqueue this file.
161
			if ( ! $failed ) {
162
				add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_compiled_file' ), $priority );
163
				return;
164
			}
165
		}
166
167
		// If we are in the customizer, load CSS using inline-styles.
168
		// If we are in the frontend AND self::$ajax is true, then load dynamic CSS using AJAX.
169
		if ( ( true === self::$ajax ) || ( isset( $config['inline_css'] ) && false === $config['inline_css'] ) ) {
170
			add_action( 'wp_enqueue_scripts', array( $this, 'frontend_styles' ), $priority );
171
			add_action( 'wp_ajax_kirki_dynamic_css', array( $this, 'ajax_dynamic_css' ) );
172
			add_action( 'wp_ajax_nopriv_kirki_dynamic_css', array( $this, 'ajax_dynamic_css' ) );
173
			return;
174
		}
175
176
		// If we got this far then add styles inline.
177
		add_action( 'wp_enqueue_scripts', array( $this, 'inline_dynamic_css' ), $priority );
178
179
		// Admin styles, adds Gutenberg compatibility.
180
		add_action( 'admin_enqueue_scripts', array( $this, 'inline_dynamic_css' ), $priority );
181
	}
182
183
	/**
184
	 * Enqueues compiled CSS file.
185
	 *
186
	 * @access public
187
	 * @since 3.0.0
188
	 */
189
	public function enqueue_compiled_file() {
190
		wp_enqueue_style( 'kirki-styles', $this->css_to_file->get_url(), array(), $this->css_to_file->get_timestamp() );
191
	}
192
	/**
193
	 * Adds inline styles.
194
	 *
195
	 * @access public
196
	 */
197
	public function inline_dynamic_css() {
198
		$configs = Kirki::$config;
199
		if ( ! $this->processed ) {
200
			foreach ( $configs as $config_id => $args ) {
201
				if ( isset( $args['disable_output'] ) && true === $args['disable_output'] ) {
202
					continue;
203
				}
204
				$styles = self::loop_controls( $config_id );
205
				$styles = apply_filters( "kirki_{$config_id}_dynamic_css", $styles );
206
				if ( ! empty( $styles ) ) {
207
					$stylesheet = apply_filters( "kirki_{$config_id}_stylesheet", false );
208
					if ( $stylesheet ) {
209
						wp_add_inline_style( $stylesheet, $styles );
210
						continue;
211
					}
212
					wp_enqueue_style( 'kirki-styles-' . $config_id, trailingslashit( Kirki::$url ) . 'assets/css/kirki-styles.css', array(), KIRKI_VERSION );
213
					wp_add_inline_style( 'kirki-styles-' . $config_id, $styles );
214
				}
215
			}
216
			$this->processed = true;
217
		}
218
219
		if ( self::$enqueue_fa && apply_filters( 'kirki_load_fontawesome', true ) ) {
220
			wp_enqueue_script( 'kirki-fontawesome-font', 'https://use.fontawesome.com/30858dc40a.js', array(), '4.0.7', true );
221
		}
222
	}
223
224
	/**
225
	 * Get the dynamic-css.php file
226
	 *
227
	 * @access public
228
	 */
229
	public function ajax_dynamic_css() {
230
		require wp_normalize_path( Kirki::$path . '/modules/css/dynamic-css.php' );
231
		exit;
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
232
	}
233
234
	/**
235
	 * Enqueues the ajax stylesheet.
236
	 *
237
	 * @access public
238
	 */
239
	public function frontend_styles() {
240
		wp_enqueue_style( 'kirki-styles-php', admin_url( 'admin-ajax.php' ) . '?action=kirki_dynamic_css', array(), KIRKI_VERSION );
241
	}
242
243
	/**
244
	 * Loop through all fields and create an array of style definitions.
245
	 *
246
	 * @static
247
	 * @access public
248
	 * @param string $config_id The configuration ID.
249
	 */
250
	public static function loop_controls( $config_id ) {
251
252
		// Get an instance of the Kirki_Modules_CSS_Generator class.
253
		// This will make sure google fonts and backup fonts are loaded.
254
		Kirki_Modules_CSS_Generator::get_instance();
255
256
		$fields = Kirki::$fields;
257
		$css    = array();
258
259
		// Early exit if no fields are found.
260
		if ( empty( $fields ) ) {
261
			return;
262
		}
263
264
		foreach ( $fields as $field ) {
265
266
			// Only process fields that belong to $config_id.
267
			if ( $config_id !== $field['kirki_config'] ) {
268
				continue;
269
			}
270
271
			if ( true === apply_filters( "kirki_{$config_id}_css_skip_hidden", true ) ) {
272
273
				// Only continue if field dependencies are met.
274
				if ( ! empty( $field['required'] ) ) {
275
					$valid = true;
276
277
					foreach ( $field['required'] as $requirement ) {
278
						if ( isset( $requirement['setting'] ) && isset( $requirement['value'] ) && isset( $requirement['operator'] ) ) {
279
							$controller_value = Kirki_Values::get_value( $config_id, $requirement['setting'] );
280
							if ( ! Kirki_Helper::compare_values( $controller_value, $requirement['value'], $requirement['operator'] ) ) {
281
								$valid = false;
282
							}
283
						}
284
					}
285
286
					if ( ! $valid ) {
287
						continue;
288
					}
289
				}
290
			}
291
292
			// Only continue if $field['output'] is set.
293
			if ( isset( $field['output'] ) && ! empty( $field['output'] ) ) {
294
				$css = Kirki_Helper::array_replace_recursive( $css, Kirki_Modules_CSS_Generator::css( $field ) );
295
296
				// Add the globals.
297
				if ( isset( self::$css_array[ $config_id ] ) && ! empty( self::$css_array[ $config_id ] ) ) {
298
					Kirki_Helper::array_replace_recursive( $css, self::$css_array[ $config_id ] );
299
				}
300
			}
301
		}
302
303
		$css = apply_filters( "kirki_{$config_id}_styles", $css );
304
305
		if ( is_array( $css ) ) {
306
			return Kirki_Modules_CSS_Generator::styles_parse( Kirki_Modules_CSS_Generator::add_prefixes( $css ) );
307
		}
308
	}
309
310
	/**
311
	 * Runs when we're adding a font-awesome field to allow enqueueing the
312
	 * fontawesome script on the frontend.
313
	 *
314
	 * @static
315
	 * @since 3.0.26
316
	 * @access public
317
	 * @return void
318
	 */
319
	public static function add_fontawesome_script() {
320
		self::$enqueue_fa = true;
321
	}
322
323
	/**
324
	 * Check if FontAwesome should be loaded.
325
	 *
326
	 * @static
327
	 * @since 3.0.35
328
	 * @access public
329
	 * @return void
330
	 */
331
	public static function get_enqueue_fa() {
332
		return self::$enqueue_fa;
333
	}
334
}
335