Completed
Push — branch-4.5 ( 37e3cd...fc8be3 )
by
unknown
16:49 queued 08:28
created

wp_custom_css_cb()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 14
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 3
nop 0
dl 0
loc 14
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * Alternate Custom CSS source for 4.7 compat.
4
 *
5
 * @since 4.4.2
6
 *
7
 * @package Jetpack
8
 */
9
10
/**
11
 * Class Jetpack_Custom_CSS_Enhancements
12
 */
13
class Jetpack_Custom_CSS_Enhancements {
14
	/**
15
	 * Set up the actions and filters needed for our compatability layer on top of core's Custom CSS implementation.
16
	 */
17
	public static function add_hooks() {
18
		add_action( 'init', array( __CLASS__, 'init' ) );
19
		add_action( 'admin_menu', array( __CLASS__, 'admin_menu' ) );
20
		add_action( 'customize_controls_enqueue_scripts', array( __CLASS__, 'customize_controls_enqueue_scripts' ) );
21
		add_action( 'customize_register', array( __CLASS__, 'customize_register' ) );
22
		add_filter( 'map_meta_cap', array( __CLASS__, 'map_meta_cap' ), 20, 2 );
23
		add_action( 'customize_preview_init', array( __CLASS__, 'customize_preview_init' ) );
24
		add_filter( '_wp_post_revision_fields', array( __CLASS__, '_wp_post_revision_fields' ), 10, 2 );
25
		add_action( 'load-revision.php', array( __CLASS__, 'load_revision_php' ) );
26
27
		add_action( 'wp_enqueue_scripts', array( __CLASS__, 'wp_enqueue_scripts' ) );
28
29
		// Handle Sass/LESS.
30
		add_filter( 'customize_value_custom_css', array( __CLASS__, 'customize_value_custom_css' ), 10, 2 );
31
		add_filter( 'customize_update_custom_css_post_content_args', array( __CLASS__, 'customize_update_custom_css_post_content_args' ), 10, 3 );
32
		add_filter( 'update_custom_css_data', array( __CLASS__, 'update_custom_css_data' ), 10, 2 );
33
34
		// Handle Sass/LESS.
35
		add_filter( 'customize_value_custom_css', array( __CLASS__, 'customize_value_custom_css' ), 10, 2 );
36
		add_filter( 'customize_update_custom_css_post_content_args', array( __CLASS__, 'customize_update_custom_css_post_content_args' ), 10, 3 );
37
38
		// Stuff for stripping out the theme's default stylesheet...
39
		add_filter( 'stylesheet_uri', array( __CLASS__, 'style_filter' ) );
40
		add_filter( 'safecss_skip_stylesheet', array( __CLASS__, 'preview_skip_stylesheet' ) );
41
42
		// Stuff for overriding content width...
43
		add_action( 'customize_preview_init', array( __CLASS__, 'preview_content_width' ) );
44
		add_filter( 'jetpack_content_width', array( __CLASS__, 'jetpack_content_width' ) );
45
		add_filter( 'editor_max_image_size', array( __CLASS__, 'editor_max_image_size' ), 10, 3 );
46
		add_action( 'template_redirect', array( __CLASS__, 'set_content_width' ) );
47
		add_action( 'admin_init', array( __CLASS__, 'set_content_width' ) );
48
49
		// Stuff?
50
	}
51
52
	/**
53
	 * Things that we do on init.
54
	 */
55
	public static function init() {
56
		$min = '.min';
0 ignored issues
show
Unused Code introduced by
$min is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
57
		if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
58
			$min = '';
0 ignored issues
show
Unused Code introduced by
$min is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
59
		}
60
61
		wp_register_style( 'jetpack-codemirror',      plugins_url( 'custom-css/css/codemirror.css', __FILE__ ), array(), '20120905' );
62
		wp_register_style( 'jetpack-customizer-css',  plugins_url( 'custom-css/css/customizer-control.css', __FILE__ ), array( 'jetpack-codemirror' ), '20140728' );
63
		wp_register_script( 'jetpack-codemirror',     plugins_url( 'custom-css/js/codemirror.min.js', __FILE__ ), array(), '3.16', true );
64
		wp_register_script( 'jetpack-customizer-css', plugins_url( 'custom-css/js/core-customizer-css.js', __FILE__ ), array( 'customize-controls', 'underscore', 'jetpack-codemirror' ), JETPACK__VERSION, true );
65
66
		wp_register_script( 'jetpack-customizer-css-preview', plugins_url( 'custom-css/js/core-customizer-css-preview.js', __FILE__ ), array( 'customize-selective-refresh' ), JETPACK__VERSION, true );
67
68
		remove_action( 'wp_head', 'wp_custom_css_cb', 11 ); // 4.7.0 had it at 11, 4.7.1 moved it to 101.
69
		remove_action( 'wp_head', 'wp_custom_css_cb', 101 );
70
		add_action( 'wp_head', array( __CLASS__, 'wp_custom_css_cb' ), 101 );
71
72
		if ( isset( $_GET['custom-css'] ) ) {
73
			self::print_linked_custom_css();
74
		}
75
	}
76
77
	/**
78
	 * Things that we do on init when the Customize Preview is loading.
79
	 */
80
	public static function customize_preview_init() {
81
		add_filter( 'wp_get_custom_css', array( __CLASS__, 'customize_preview_wp_get_custom_css' ) );
82
	}
83
84
	/**
85
	 * Print the current Custom CSS. This is for linking instead of printing directly.
86
	 */
87
	public static function print_linked_custom_css() {
88
		header( 'Content-type: text/css' );
89
		header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + YEAR_IN_SECONDS ) . ' GMT' );
90
		echo wp_get_custom_css();
91
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method print_linked_custom_css() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
92
	}
93
94
	/**
95
	 * Re-map the Edit CSS capability.
96
	 *
97
	 * Core, by default, restricts this to users that have `unfiltered_html` which
98
	 * would make the feature unusable in multi-site by non-super-admins, due to Core
99
	 * not shipping any solid sanitization.
100
	 *
101
	 * We're expanding who can use it, and then conditionally applying CSSTidy
102
	 * sanitization to users that do not have the `unfiltered_html` capability.
103
	 *
104
	 * @param array  $caps Returns the user's actual capabilities.
105
	 * @param string $cap  Capability name.
106
	 *
107
	 * @return array $caps
108
	 */
109
	public static function map_meta_cap( $caps, $cap ) {
110
		if ( 'edit_css' === $cap ) {
111
			$caps = array( 'edit_theme_options' );
112
		}
113
		return $caps;
114
	}
115
116
	/**
117
	 * Handle our admin menu item and legacy page declaration.
118
	 */
119
	public static function admin_menu() {
120
		// Add in our legacy page to support old bookmarks and such.
121
		add_submenu_page( null, __( 'CSS', 'jetpack' ), __( 'Edit CSS', 'jetpack' ), 'edit_theme_options', 'editcss', array( __CLASS__, 'admin_page' ) );
122
123
		// Add in our new page slug that will redirect to the customizer.
124
		$hook = add_theme_page( __( 'CSS', 'jetpack' ), __( 'Edit CSS', 'jetpack' ), 'edit_theme_options', 'editcss-customizer-redirect', array( __CLASS__, 'admin_page' ) );
125
		add_action( "load-{$hook}", array( __CLASS__, 'customizer_redirect' ) );
126
	}
127
128
	/**
129
	 * Handle the redirect for the customizer.  This is necessary because
130
	 * we can't directly add customizer links to the admin menu.
131
	 *
132
	 * There is a core patch in trac that would make this unnecessary.
133
	 *
134
	 * @link https://core.trac.wordpress.org/ticket/39050
135
	 */
136
	public static function customizer_redirect() {
137
		wp_safe_redirect( self::customizer_link( array(
138
			'return_url' => wp_get_referer(),
139
		) ) );
140
	}
141
142
	/**
143
	 * Shows Preprocessor code in the Revisions screen, and ensures that post_content_filtered
144
	 * is maintained on revisions
145
	 *
146
	 * @param array $fields  Post fields pertinent to revisions.
147
	 * @param array $post    A post array being processed for insertion as a post revision.
148
	 *
149
	 * @return array $fields Modified array to include post_content_filtered.
150
	 */
151
	public static function _wp_post_revision_fields( $fields, $post ) {
152
		// If we're passed in a revision, go get the main post instead.
153
		if ( 'revision' === $post['post_type'] ) {
154
			$main_post_id = wp_is_post_revision( $post['ID'] );
155
			$post = get_post( $main_post_id, ARRAY_A );
156
		}
157
		if ( 'custom_css' === $post['post_type'] ) {
158
			$fields['post_content'] = __( 'CSS', 'jetpack' );
159
			$fields['post_content_filtered'] = __( 'Preprocessor', 'jetpack' );
160
		}
161
		return $fields;
162
	}
163
164
	/**
165
	 * Get the published custom CSS post.
166
	 *
167
	 * @param string $stylesheet Optional. A theme object stylesheet name. Defaults to the current theme.
168
	 * @return WP_Post|null
169
	 */
170
	public static function get_css_post( $stylesheet = '' ) {
171
		return wp_get_custom_css_post( $stylesheet );
172
	}
173
174
	/**
175
	 * Override Core's `wp_custom_css_cb` method to provide linking to custom css.
176
	 */
177
	public static function wp_custom_css_cb() {
178
		$styles = wp_get_custom_css();
179
		if ( strlen( $styles ) > 2000 && ! is_customize_preview() ) :
180
			// Add a cache buster to the url.
181
			$url = home_url( '/' );
182
			$url = add_query_arg( 'custom-css', substr( md5( $styles ), -10 ), $url );
183
			?>
184
			<link rel="stylesheet" type="text/css" id="wp-custom-css" href="<?php echo esc_url( $url ); ?>" />
185
		<?php elseif ( $styles || is_customize_preview() ) : ?>
186
			<style type="text/css" id="wp-custom-css">
187
				<?php echo strip_tags( $styles ); // Note that esc_html() cannot be used because `div &gt; span` is not interpreted properly. ?>
188
			</style>
189
		<?php endif;
190
	}
191
192
	/**
193
	 * Get the ID of a Custom CSS post tying to a given stylesheet.
194
	 *
195
	 * @param string $stylesheet Stylesheet name.
196
	 *
197
	 * @return int $post_id Post ID.
198
	 */
199
	public static function post_id( $stylesheet = '' ) {
200
		$post = self::get_css_post( $stylesheet );
201
		if ( $post instanceof WP_Post ) {
0 ignored issues
show
Bug introduced by
The class WP_Post does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
202
			return $post->ID;
203
		}
204
		return 0;
205
	}
206
207
	/**
208
	 * Partial for use in the Customizer.
209
	 */
210
	public static function echo_custom_css_partial() {
211
		echo wp_get_custom_css();
212
	}
213
214
	/**
215
	 * Admin page!
216
	 *
217
	 * This currently has two main uses -- firstly to display the css for an inactive
218
	 * theme if there are no revisions attached it to a legacy bug, and secondly to
219
	 * handle folks that have bookmarkes in their browser going to the old page for
220
	 * managing Custom CSS in Jetpack.
221
	 *
222
	 * If we ever add back in a non-Customizer CSS editor, this would be the place.
223
	 */
224
	public static function admin_page() {
225
		$post = null;
226
		$stylesheet = null;
227
		if ( isset( $_GET['id'] ) ) {
228
			$post_id = absint( $_GET['id'] );
229
			$post = get_post( $post_id );
230
			if ( $post instanceof WP_Post && 'custom_css' === $post->post_type ) {
0 ignored issues
show
Bug introduced by
The class WP_Post does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
231
				$stylesheet = $post->post_title;
232
			}
233
		}
234
		?>
235
		<div class="wrap">
236
			<?php self::revisions_switcher_box( $stylesheet ); ?>
237
			<h1>
238
				<?php
239
				if ( $post ) {
240
					printf( 'Custom CSS for &#8220;%1$s&#8221;', wp_get_theme( $stylesheet )->Name );
241
				} else {
242
					esc_html_e( 'Custom CSS', 'jetpack' );
243
				}
244
				if ( current_user_can( 'customize' ) ) {
245
					printf(
246
						' <a class="page-title-action hide-if-no-customize" href="%1$s">%2$s</a>',
247
						esc_url( self::customizer_link() ),
248
						esc_html__( 'Manage with Live Preview', 'jetpack' )
249
					);
250
				}
251
				?>
252
			</h1>
253
			<p><?php esc_html_e( 'Custom CSS is now managed in the Customizer.', 'jetpack' ); ?></p>
254
			<?php if ( $post ) : ?>
255
				<div class="revisions">
256
					<h3><?php esc_html_e( 'CSS', 'jetpack' ); ?></h3>
257
					<textarea class="widefat" readonly><?php echo esc_textarea( $post->post_content ); ?></textarea>
258
					<?php if ( $post->post_content_filtered ) : ?>
259
						<h3><?php esc_html_e( 'Preprocessor', 'jetpack' ); ?></h3>
260
						<textarea class="widefat" readonly><?php echo esc_textarea( $post->post_content_filtered ); ?></textarea>
261
					<?php endif; ?>
262
				</div>
263
			<?php endif; ?>
264
		</div>
265
266
		<style>
267
			.other-themes-wrap {
268
				float: right;
269
				background-color: #fff;
270
				-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.1);
271
				box-shadow: 0 1px 3px rgba(0,0,0,0.1);
272
				padding: 5px 10px;
273
				margin-bottom: 10px;
274
			}
275
			.other-themes-wrap label {
276
				display: block;
277
				margin-bottom: 10px;
278
			}
279
			.other-themes-wrap select {
280
				float: left;
281
				width: 77%;
282
			}
283
			.other-themes-wrap button {
284
				float: right;
285
				width: 20%;
286
			}
287
			.revisions {
288
				clear: both;
289
			}
290
			.revisions textarea {
291
				min-height: 300px;
292
				background: #fff;
293
			}
294
		</style>
295
		<script>
296
			(function($){
297
				var $switcher = $('.other-themes-wrap');
298
				$switcher.find('button').on('click', function(e){
299
					e.preventDefault();
300
					if ( $switcher.find('select').val() ) {
301
						window.location.href = $switcher.find('select').val();
302
					}
303
				});
304
			})(jQuery);
305
		</script>
306
		<?php
307
	}
308
309
	/**
310
	 * Build the URL to deep link to the Customizer.
311
	 *
312
	 * You can modify the return url via $args.
313
	 *
314
	 * @param array $args Array of parameters.
315
	 * @return string
316
	 */
317
	public static function customizer_link( $args = array() ) {
318
		$args = wp_parse_args( $args, array(
319
			'return_url' => urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ),
320
		) );
321
322
		return add_query_arg(
323
			array(
324
				array(
325
					'autofocus' => array(
326
						'section' => 'custom_css',
327
					),
328
				),
329
				'return' => $args['return_url'],
330
			),
331
			admin_url( 'customize.php' )
332
		);
333
	}
334
335
	/**
336
	 * Handle the enqueueing and localizing for scripts to be used in the Customizer.
337
	 */
338
	public static function customize_controls_enqueue_scripts() {
339
		wp_enqueue_style( 'jetpack-customizer-css' );
340
		wp_enqueue_script( 'jetpack-customizer-css' );
341
342
		$content_help = __( 'Set a different content width for full size images.', 'jetpack' );
343
		if ( ! empty( $GLOBALS['content_width'] ) ) {
344
			$content_help .= sprintf(
345
				__( ' The default content width for the <strong>%1$s</strong> theme is %2$d pixels.', 'jetpack' ),
346
				wp_get_theme()->Name,
347
				intval( $GLOBALS['content_width'] )
348
			);
349
		}
350
351
		wp_localize_script( 'jetpack-customizer-css', '_jp_css_settings', array(
352
			/** This filter is documented in modules/custom-css/custom-css.php */
353
			'useRichEditor' => ! jetpack_is_mobile() && apply_filters( 'safecss_use_ace', true ),
354
			'areThereCssRevisions' => self::are_there_css_revisions(),
355
			'revisionsUrl' => self::get_revisions_url(),
356
			'cssHelpUrl' => '//en.support.wordpress.com/custom-design/editing-css/',
357
			'l10n' => array(
358
				'mode'           => __( 'Start Fresh', 'jetpack' ),
359
				'mobile'         => __( 'On Mobile', 'jetpack' ),
360
				'contentWidth'   => $content_help,
361
				'revisions'      => _x( 'See full history', 'Toolbar button to see full CSS revision history', 'jetpack' ),
362
				'css_help_title' => _x( 'Help', 'Toolbar button to get help with custom CSS', 'jetpack' ),
363
			),
364
		));
365
	}
366
367
	/**
368
	 * Check whether there are CSS Revisions for a given theme.
369
	 *
370
	 * Going forward, there should always be, but this was necessitated
371
	 * early on by https://core.trac.wordpress.org/ticket/30854
372
	 *
373
	 * @param string $stylesheet Stylesheet name.
374
	 *
375
	 * @return bool|null|WP_Post
376
	 */
377
	public static function are_there_css_revisions( $stylesheet = '' ) {
378
		$post = wp_get_custom_css_post( $stylesheet );
379
		if ( empty( $post ) ) {
380
			return $post;
381
		}
382
		return (bool) wp_get_post_revisions( $post );
383
	}
384
385
	/**
386
	 * Core doesn't have a function to get the revisions url for a given post ID.
387
	 *
388
	 * @param string $stylesheet Stylesheet name.
389
	 *
390
	 * @return null|string|void
391
	 */
392
	public static function get_revisions_url( $stylesheet = '' ) {
393
		$post = wp_get_custom_css_post( $stylesheet );
394
395
		// If we have any currently saved customizations...
396
		if ( $post instanceof WP_Post ) {
0 ignored issues
show
Bug introduced by
The class WP_Post does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
397
			$revisions = wp_get_post_revisions( $post->ID, array( 'posts_per_page' => 1 ) );
398
			if ( empty( $revisions ) || is_wp_error( $revisions ) ) {
399
				return admin_url( 'themes.php?page=editcss' );
400
			}
401
			$revision = reset( $revisions );
402
			return get_edit_post_link( $revision->ID );
403
		}
404
405
		return admin_url( 'themes.php?page=editcss' );
406
	}
407
408
	/**
409
	 * Get a map of all theme names and theme stylesheets for mapping stuff.
410
	 *
411
	 * @return array
412
	 */
413
	public static function get_themes() {
414
		$themes = wp_get_themes( array( 'errors' => null ) );
415
		$all = array();
416
		foreach ( $themes as $theme ) {
417
			$all[ $theme->name ] = $theme->stylesheet;
418
		}
419
		return $all;
420
	}
421
422
	/**
423
	 * When we need to get all themes that have Custom CSS saved.
424
	 *
425
	 * @return array
426
	 */
427
	public static function get_all_themes_with_custom_css() {
428
		$themes = self::get_themes();
429
		$custom_css = get_posts( array(
430
			'post_type'   => 'custom_css',
431
			'post_status' => get_post_stati(),
432
			'number'      => -1,
433
			'order'       => 'DESC',
434
			'orderby'     => 'modified',
435
		) );
436
		$return = array();
437
438
		foreach ( $custom_css as $post ) {
439
			$stylesheet = $post->post_title;
440
			$label      = array_search( $stylesheet, $themes );
441
442
			if ( ! $label ) {
443
				continue;
444
			}
445
446
			$return[ $stylesheet ] = array(
447
				'label' => $label,
448
				'post'  => $post,
449
			);
450
		}
451
452
		return $return;
453
	}
454
455
	/**
456
	 * Handle the enqueueing of scripts for customize previews.
457
	 */
458
	public static function wp_enqueue_scripts() {
459
		if ( is_customize_preview() ) {
460
			wp_enqueue_script( 'jetpack-customizer-css-preview' );
461
			wp_localize_script( 'jetpack-customizer-css-preview', 'jpCustomizerCssPreview', array(
462
				/** This filter is documented in modules/custom-css/custom-css.php */
463
				'preprocessors' => apply_filters( 'jetpack_custom_css_preprocessors', array() ),
464
			));
465
		}
466
	}
467
468
	/**
469
	 * Sanitize the CSS for users without `unfiltered_html`.
470
	 *
471
	 * @param string $css  Input CSS.
472
	 * @param array  $args Array of CSS options.
473
	 *
474
	 * @return mixed|string
475
	 */
476
	public static function sanitize_css( $css, $args = array() ) {
477
		$args = wp_parse_args( $args, array(
478
			'force'        => false,
479
			'preprocessor' => null,
480
		) );
481
482
		if ( $args['force'] || ! current_user_can( 'unfiltered_html' ) ) {
483
484
			$warnings = array();
485
486
			safecss_class();
487
			$csstidy = new csstidy();
488
			$csstidy->optimise = new safecss( $csstidy );
0 ignored issues
show
Documentation introduced by
$csstidy is of type object<csstidy>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
489
490
			$csstidy->set_cfg( 'remove_bslash',              false );
491
			$csstidy->set_cfg( 'compress_colors',            false );
492
			$csstidy->set_cfg( 'compress_font-weight',       false );
493
			$csstidy->set_cfg( 'optimise_shorthands',        0 );
494
			$csstidy->set_cfg( 'remove_last_;',              false );
495
			$csstidy->set_cfg( 'case_properties',            false );
496
			$csstidy->set_cfg( 'discard_invalid_properties', true );
497
			$csstidy->set_cfg( 'css_level',                  'CSS3.0' );
498
			$csstidy->set_cfg( 'preserve_css',               true );
499
			$csstidy->set_cfg( 'template',                   dirname( __FILE__ ) . '/csstidy/wordpress-standard.tpl' );
500
501
			// Test for some preg_replace stuff.
502
			{
503
				$prev = $css;
504
				$css = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $css );
505
				// prevent content: '\3434' from turning into '\\3434'.
506
				$css = str_replace( array( '\'\\\\', '"\\\\' ), array( '\'\\', '"\\' ), $css );
507
				if ( $css !== $prev ) {
508
					$warnings[] = 'preg_replace found stuff';
509
				}
510
			}
511
512
			// Some people put weird stuff in their CSS, KSES tends to be greedy.
513
			$css = str_replace( '<=', '&lt;=', $css );
514
515
			// Test for some kses stuff.
516
			{
517
				$prev = $css;
518
				// Why KSES instead of strip_tags?  Who knows?
519
				$css = wp_kses_split( $css, array(), array() );
520
				$css = str_replace( '&gt;', '>', $css ); // kses replaces lone '>' with &gt;
521
				// Why both KSES and strip_tags?  Because we just added some '>'.
522
				$css = strip_tags( $css );
523
524
				if ( $css != $prev ) {
525
					$warnings[] = 'kses found stuff';
526
				}
527
			}
528
529
			// if we're not using a preprocessor.
530 View Code Duplication
			if ( ! $args['preprocessor'] ) {
531
532
				/** This action is documented in modules/custom-css/custom-css.php */
533
				do_action( 'safecss_parse_pre', $csstidy, $css, $args );
534
535
				$csstidy->parse( $css );
536
537
				/** This action is documented in modules/custom-css/custom-css.php */
538
				do_action( 'safecss_parse_post', $csstidy, $warnings, $args );
539
540
				$css = $csstidy->print->plain();
541
			}
542
		}
543
		return $css;
544
	}
545
546
	/**
547
	 * Override $content_width in customizer previews.
548
	 */
549
	public static function preview_content_width() {
550
		global $wp_customize;
551
		if ( ! is_customize_preview() ) {
552
			return;
553
		}
554
555
		$setting = $wp_customize->get_setting( 'jetpack_custom_css[content_width]' );
556
		if ( ! $setting ) {
557
			return;
558
		}
559
560
		$customized_content_width = (int) $setting->post_value();
561
		if ( ! empty( $customized_content_width ) ) {
562
			$GLOBALS['content_width'] = $customized_content_width;
563
		}
564
	}
565
566
	/**
567
	 * Filter the current theme's stylesheet for potentially nullifying it.
568
	 *
569
	 * @param string $current Stylesheet URI for the current theme/child theme.
570
	 *
571
	 * @return mixed|void
572
	 */
573
	static function style_filter( $current ) {
574
		if ( is_admin() ) {
575
			return $current;
576
		} elseif ( self::is_freetrial() && ( ! self::is_preview() || ! current_user_can( 'switch_themes' ) ) ) {
577
			return $current;
578
		} elseif ( self::skip_stylesheet() ) {
579
			/** This filter is documented in modules/custom-css/custom-css.php */
580
			return apply_filters( 'safecss_style_filter_url', plugins_url( 'custom-css/css/blank.css', __FILE__ ) );
581
		}
582
583
		return $current;
584
	}
585
586
	/**
587
	 * Determine whether or not we should have the theme skip its main stylesheet.
588
	 *
589
	 * @return mixed The truthiness of this value determines whether the stylesheet should be skipped.
590
	 */
591
	static function skip_stylesheet() {
592
		/** This filter is documented in modules/custom-css/custom-css.php */
593
		$skip_stylesheet = apply_filters( 'safecss_skip_stylesheet', null );
594
		if ( ! is_null( $skip_stylesheet ) ) {
595
			return $skip_stylesheet;
596
		}
597
598
		$jetpack_custom_css = get_theme_mod( 'jetpack_custom_css', array() );
599
		if ( isset( $jetpack_custom_css['replace'] ) ) {
600
			return $jetpack_custom_css['replace'];
601
		}
602
603
		return false;
604
	}
605
606
	/**
607
	 * Override $content_width in customizer previews.
608
	 *
609
	 * Runs on `safecss_skip_stylesheet` filter.
610
	 *
611
	 * @param bool $skip_value Should the stylesheet be skipped.
612
	 *
613
	 * @return null|bool
614
	 */
615
	public static function preview_skip_stylesheet( $skip_value ) {
616
		global $wp_customize;
617
		if ( ! is_customize_preview() ) {
618
			return $skip_value;
619
		}
620
621
		$setting = $wp_customize->get_setting( 'jetpack_custom_css[replace]' );
622
		if ( ! $setting ) {
623
			return $skip_value;
624
		}
625
626
		$customized_replace = $setting->post_value();
627
		if ( null !== $customized_replace ) {
628
			return $customized_replace;
629
		}
630
631
		return $skip_value;
632
	}
633
634
	/**
635
	 * Add Custom CSS section and controls.
636
	 *
637
	 * @param WP_Customize_Manager $wp_customize WP_Customize_Manager instance.
638
	 */
639
	public static function customize_register( $wp_customize ) {
640
641
		/**
642
		 * SETTINGS.
643
		 */
644
645
		$wp_customize->add_setting( 'jetpack_custom_css[preprocessor]', array(
646
			'default' => '',
647
			'transport' => 'postMessage',
648
			'sanitize_callback' => array( __CLASS__, 'sanitize_preprocessor' ),
649
		) );
650
651
		$wp_customize->add_setting( 'jetpack_custom_css[replace]', array(
652
			'default' => false,
653
			'transport' => 'refresh',
654
		) );
655
656
		$wp_customize->add_setting( 'jetpack_custom_css[content_width]', array(
657
			'default' => '',
658
			'transport' => 'refresh',
659
			'sanitize_callback' => array( __CLASS__, 'intval_base10' ),
660
		) );
661
662
		// Add custom sanitization to the core css customizer setting.
663
		foreach ( $wp_customize->settings() as $setting ) {
664
			if ( $setting instanceof WP_Customize_Custom_CSS_Setting ) {
0 ignored issues
show
Bug introduced by
The class WP_Customize_Custom_CSS_Setting does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
665
				add_filter( "customize_sanitize_{$setting->id}", array( __CLASS__, 'sanitize_css_callback' ), 10, 2 );
666
			}
667
		}
668
669
		/**
670
		 * CONTROLS.
671
		 */
672
673
		// Overwrite the Core Control.
674
		$core_custom_css = $wp_customize->get_control( 'custom_css' );
675
		if ( $core_custom_css ) {
676
			$wp_customize->remove_control( 'custom_css' );
677
			$core_custom_css->type = 'jetpackCss';
678
			$wp_customize->add_control( $core_custom_css );
679
		}
680
681
		$wp_customize->selective_refresh->add_partial( 'custom_css', array(
682
			'type'                => 'custom_css',
683
			'selector'            => '#wp-custom-css',
684
			'container_inclusive' => false,
685
			'fallback_refresh'    => false,
686
			'settings'            => array(
687
				'custom_css[' . $wp_customize->get_stylesheet() . ']',
688
				'jetpack_custom_css[preprocessor]',
689
			),
690
			'render_callback' => array( __CLASS__, 'echo_custom_css_partial' ),
691
		) );
692
693
		$wp_customize->add_control( 'wpcom_custom_css_content_width_control', array(
694
			'type'     => 'text',
695
			'label'    => __( 'Media Width', 'jetpack' ),
696
			'section'  => 'custom_css',
697
			'settings' => 'jetpack_custom_css[content_width]',
698
		) );
699
700
		$wp_customize->add_control( 'jetpack_css_mode_control', array(
701
			'type'     => 'checkbox',
702
			'label'    => __( 'Don\'t use the theme\'s original CSS.', 'jetpack' ),
703
			'section'  => 'custom_css',
704
			'settings' => 'jetpack_custom_css[replace]',
705
		) );
706
707
		/**
708
		 * An action to grab on to if another Jetpack Module would like to add its own controls.
709
		 *
710
		 * @module custom-css
711
		 *
712
		 * @since 4.4.2
713
		 *
714
		 * @param $wp_customize The WP_Customize object.
715
		 */
716
		do_action( 'jetpack_custom_css_customizer_controls', $wp_customize );
717
718
		/** This filter is documented in modules/custom-css/custom-css.php */
719
		$preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
720
		if ( ! empty( $preprocessors ) ) {
721
			$preprocessor_choices = array(
722
				'' => __( 'None', 'jetpack' ),
723
			);
724
725
			foreach ( $preprocessors as $preprocessor_key => $processor ) {
726
				$preprocessor_choices[ $preprocessor_key ] = $processor['name'];
727
			}
728
729
			$wp_customize->add_control( 'jetpack_css_preprocessors_control', array(
730
				'type'     => 'select',
731
				'choices'  => $preprocessor_choices,
732
				'label'    => __( 'Preprocessor', 'jetpack' ),
733
				'section'  => 'custom_css',
734
				'settings' => 'jetpack_custom_css[preprocessor]',
735
			) );
736
		}
737
738
	}
739
740
	/**
741
	 * The callback to handle sanitizing the CSS. Takes different arguments, hence the proxy function.
742
	 *
743
	 * @param mixed                $css     Value of the setting.
744
	 * @param WP_Customize_Setting $setting WP_Customize_Setting instance.
745
	 *
746
	 * @return mixed|string
747
	 */
748
	public static function sanitize_css_callback( $css, $setting ) {
0 ignored issues
show
Unused Code introduced by
The parameter $setting is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
749
		global $wp_customize;
750
		return self::sanitize_css( $css, array(
751
			'preprocessor' => $wp_customize->get_setting( 'jetpack_custom_css[preprocessor]' )->value(),
752
		) );
753
	}
754
755
	/**
756
	 * Flesh out for wpcom.
757
	 *
758
	 * @todo
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
759
	 *
760
	 * @return bool
761
	 */
762
	public static function is_freetrial() {
763
		return false;
764
	}
765
766
	/**
767
	 * Flesh out for wpcom.
768
	 *
769
	 * @todo
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
770
	 *
771
	 * @return bool
772
	 */
773
	public static function is_preview() {
774
		return false;
775
	}
776
777
	/**
778
	 * Output the custom css for customize preview.
779
	 *
780
	 * @param string $css Custom CSS content.
781
	 *
782
	 * @return mixed
783
	 */
784
	public static function customize_preview_wp_get_custom_css( $css ) {
785
		global $wp_customize;
786
787
		$preprocessor = $wp_customize->get_setting( 'jetpack_custom_css[preprocessor]' )->value();
788
789
		// If it's empty, just return.
790
		if ( empty( $preprocessor ) ) {
791
			return $css;
792
		}
793
794
		/** This filter is documented in modules/custom-css/custom-css.php */
795
		$preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
796
		if ( isset( $preprocessors[ $preprocessor ] ) ) {
797
			return call_user_func( $preprocessors[ $preprocessor ]['callback'], $css );
798
		}
799
800
		return $css;
801
	}
802
803
	/**
804
	 * Add CSS preprocessing to our CSS if it is supported.
805
	 *
806
	 * @param mixed                $css     Value of the setting.
807
	 * @param WP_Customize_Setting $setting WP_Customize_Setting instance.
808
	 *
809
	 * @return string
810
	 */
811
	public static function customize_value_custom_css( $css, $setting ) {
812
		// Find the current preprocessor.
813
		$jetpack_custom_css = get_theme_mod( 'jetpack_custom_css', array() );
814
		if ( isset( $jetpack_custom_css['preprocessor'] ) ) {
815
			$preprocessor = $jetpack_custom_css['preprocessor'];
816
		}
817
818
		// If it's not supported, just return.
819
		/** This filter is documented in modules/custom-css/custom-css.php */
820
		$preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
821
		if ( ! isset( $preprocessors[ $preprocessor ] ) ) {
822
			return $css;
823
		}
824
825
		// Swap it for the `post_content_filtered` instead.
826
		$post = wp_get_custom_css_post( $setting->stylesheet );
827
		if ( $post && ! empty( $post->post_content_filtered ) ) {
828
			$css = $post->post_content_filtered;
829
		}
830
831
		return $css;
832
	}
833
834
	/**
835
	 * Store the original pre-processed CSS in `post_content_filtered`
836
	 * and then store processed CSS in `post_content`.
837
	 *
838
	 * @param array                           $args    Content post args.
839
	 * @param string                          $css     Original CSS being updated.
840
	 * @param WP_Customize_Custom_CSS_Setting $setting Custom CSS Setting.
841
	 *
842
	 * @return mixed
843
	 */
844
	public static function customize_update_custom_css_post_content_args( $args, $css, $setting ) {
0 ignored issues
show
Unused Code introduced by
The parameter $setting is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
845
		// Find the current preprocessor.
846
		$jetpack_custom_css = get_theme_mod( 'jetpack_custom_css', array() );
847
		if ( empty( $jetpack_custom_css['preprocessor'] ) ) {
848
			return $args;
849
		}
850
851
		$preprocessor = $jetpack_custom_css['preprocessor'];
852
		/** This filter is documented in modules/custom-css/custom-css.php */
853
		$preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
854
855
		// If it's empty, just return.
856
		if ( empty( $preprocessor ) ) {
857
			return $args;
858
		}
859
860 View Code Duplication
		if ( isset( $preprocessors[ $preprocessor ] ) ) {
861
			$args['post_content_filtered'] = $css;
862
			$args['post_content'] = call_user_func( $preprocessors[ $preprocessor ]['callback'], $css );
863
		}
864
865
		return $args;
866
	}
867
868
	/**
869
	 * Filter to handle the processing of preprocessed css on save.
870
	 *
871
	 * @param array  $args       Custom CSS options.
872
	 * @param string $stylesheet Original CSS to be updated.
873
	 *
874
	 * @return mixed
875
	 */
876
	public static function update_custom_css_data( $args, $stylesheet ) {
0 ignored issues
show
Unused Code introduced by
The parameter $stylesheet is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
877
		// Find the current preprocessor.
878
		$jetpack_custom_css = get_theme_mod( 'jetpack_custom_css', array() );
879
		if ( empty( $jetpack_custom_css['preprocessor'] ) ) {
880
			return $args;
881
		}
882
883
		/** This filter is documented in modules/custom-css/custom-css.php */
884
		$preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
885
		$preprocessor = $jetpack_custom_css['preprocessor'];
886
887
		// If we have a preprocessor specified ...
888
		if ( isset( $preprocessors[ $preprocessor ] ) ) {
889
			// And no other preprocessor has run ...
890
			if ( empty( $args['preprocessed'] ) ) {
891
				$args['preprocessed'] = $args['css'];
892
				$args['css'] = call_user_func( $preprocessors[ $preprocessor ]['callback'], $args['css'] );
893
			} else {
894
				trigger_error( 'Jetpack CSS Preprocessor specified, but something else has already modified the argument.', E_USER_WARNING );
895
			}
896
		}
897
898
		return $args;
899
	}
900
901
	/**
902
	 * When on the edit screen, make sure the custom content width
903
	 * setting is applied to the large image size.
904
	 *
905
	 * @param array  $dims    Array of image dimensions (width and height).
906
	 * @param string $size    Size of the resulting image.
907
	 * @param null   $context Context the image is being resized for. `edit` or `display`.
908
	 *
909
	 * @return array
910
	 */
911 View Code Duplication
	static function editor_max_image_size( $dims, $size = 'medium', $context = null ) {
912
		list( $width, $height ) = $dims;
913
914
		if ( 'large' === $size && 'edit' === $context ) {
915
			$width = Jetpack::get_content_width();
916
		}
917
918
		return array( $width, $height );
919
	}
920
921
	/**
922
	 * Override the content_width with a custom value if one is set.
923
	 *
924
	 * @param int $content_width Content Width value to be updated.
925
	 *
926
	 * @return int
927
	 */
928
	static function jetpack_content_width( $content_width ) {
929
		$custom_content_width = 0;
930
931
		$jetpack_custom_css = get_theme_mod( 'jetpack_custom_css', array() );
932
		if ( isset( $jetpack_custom_css['content_width'] ) ) {
933
			$custom_content_width = $jetpack_custom_css['content_width'];
934
		}
935
936
		if ( $custom_content_width > 0 ) {
937
			return $custom_content_width;
938
		}
939
940
		return $content_width;
941
	}
942
943
	/**
944
	 * Currently this filter function gets called on
945
	 * 'template_redirect' action and
946
	 * 'admin_init' action
947
	 */
948 View Code Duplication
	static function set_content_width() {
949
		// Don't apply this filter on the Edit CSS page.
950
		if ( isset( $_GET['page'] ) && 'editcss' === $_GET['page'] && is_admin() ) {
951
			return;
952
		}
953
954
		$GLOBALS['content_width'] = Jetpack::get_content_width();
955
	}
956
957
	/**
958
	 * Make sure the preprocessor we're saving is one we know about.
959
	 *
960
	 * @param string $preprocessor The preprocessor to sanitize.
961
	 *
962
	 * @return null|string
963
	 */
964
	public static function sanitize_preprocessor( $preprocessor ) {
965
		/** This filter is documented in modules/custom-css/custom-css.php */
966
		$preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
967
		if ( empty( $preprocessor ) || array_key_exists( $preprocessor, $preprocessors ) ) {
968
			return $preprocessor;
969
		}
970
		return null;
971
	}
972
973
	/**
974
	 * Get the base10 intval.
975
	 *
976
	 * This is used as a setting's sanitize_callback; we can't use just plain
977
	 * intval because the second argument is not what intval() expects.
978
	 *
979
	 * @access public
980
	 *
981
	 * @param mixed $value Number to convert.
982
	 * @return int Integer.
983
	 */
984
	public static function intval_base10( $value ) {
985
		return intval( $value, 10 );
986
	}
987
988
	/**
989
	 * Add a footer action on revision.php to print some customizations for the theme switcher.
990
	 */
991
	public static function load_revision_php() {
992
		add_action( 'admin_footer', array( __CLASS__, 'revision_admin_footer' ) );
993
	}
994
995
	/**
996
	 * Print the theme switcher on revision.php and move it into place.
997
	 */
998
	public static function revision_admin_footer() {
999
		$post = get_post();
1000
		if ( 'custom_css' !== $post->post_type ) {
1001
			return;
1002
		}
1003
		$stylesheet = $post->post_title;
1004
		?>
1005
<script type="text/html" id="tmpl-other-themes-switcher">
1006
	<?php self::revisions_switcher_box( $stylesheet ); ?>
1007
</script>
1008
<style>
1009
.other-themes-wrap {
1010
	float: right;
1011
	background-color: #fff;
1012
	-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.1);
1013
	box-shadow: 0 1px 3px rgba(0,0,0,0.1);
1014
	padding: 5px 10px;
1015
	margin-bottom: 10px;
1016
}
1017
.other-themes-wrap label {
1018
	display: block;
1019
	margin-bottom: 10px;
1020
}
1021
.other-themes-wrap select {
1022
	float: left;
1023
	width: 77%;
1024
}
1025
.other-themes-wrap button {
1026
	float: right;
1027
	width: 20%;
1028
}
1029
.revisions {
1030
	clear: both;
1031
}
1032
/* Hide the back-to-post link */
1033
.long-header + a {
1034
	display: none;
1035
}
1036
</style>
1037
<script>
1038
(function($){
1039
	var switcher = $('#tmpl-other-themes-switcher').html(),
1040
		qty = $( switcher ).find('select option').length,
1041
		$switcher;
1042
1043
	if ( qty >= 3 ) {
1044
		$('h1.long-header').before( switcher );
1045
		$switcher = $('.other-themes-wrap');
1046
		$switcher.find('button').on('click', function(e){
1047
			e.preventDefault();
1048
			if ( $switcher.find('select').val() ) {
1049
				window.location.href = $switcher.find('select').val();
1050
			}
1051
		})
1052
	}
1053
})(jQuery);
1054
</script>
1055
		<?php
1056
	}
1057
1058
	/**
1059
	 * The HTML for the theme revision switcher box.
1060
	 *
1061
	 * @param string $stylesheet Stylesheet name.
1062
	 */
1063
	public static function revisions_switcher_box( $stylesheet = '' ) {
1064
		$themes = self::get_all_themes_with_custom_css();
1065
		?>
1066
		<div class="other-themes-wrap">
1067
			<label for="other-themes"><?php esc_html_e( 'Select another theme to view its custom CSS.', 'jetpack' ); ?></label>
1068
			<select id="other-themes">
1069
				<option value=""><?php esc_html_e( 'Select a theme&hellip;', 'jetpack' ); ?></option>
1070
				<?php
1071
				foreach ( $themes as $theme_stylesheet => $data ) {
1072
					$revisions = wp_get_post_revisions( $data['post']->ID, array( 'posts_per_page' => 1 ) );
1073
					if ( ! $revisions ) {
1074
						?>
1075
						<option value="<?php echo esc_url( add_query_arg( 'id', $data['post']->ID, menu_page_url( 'editcss', 0 ) ) ); ?>" <?php disabled( $stylesheet, $theme_stylesheet ); ?>>
1076
							<?php echo esc_html( $data['label'] ); ?>
1077
							<?php printf( esc_html__( '(modified %s ago)', 'jetpack' ), human_time_diff( strtotime( $data['post']->post_modified_gmt ) ) ); ?></option>
1078
						<?php
1079
						continue;
1080
					}
1081
					$revision = array_shift( $revisions );
1082
					?>
1083
					<option value="<?php echo esc_url( get_edit_post_link( $revision->ID ) ); ?>" <?php disabled( $stylesheet, $theme_stylesheet ); ?>>
1084
						<?php echo esc_html( $data['label'] ); ?>
1085
						<?php printf( esc_html__( '(modified %s ago)', 'jetpack' ), human_time_diff( strtotime( $data['post']->post_modified_gmt ) ) ); ?></option>
1086
					<?php
1087
				}
1088
				?>
1089
			</select>
1090
			<button class="button" id="other_theme_custom_css_switcher"><?php esc_html_e( 'Switch', 'jetpack' ); ?></button>
1091
		</div>
1092
		<?php
1093
	}
1094
}
1095
1096
Jetpack_Custom_CSS_Enhancements::add_hooks();
1097
1098 View Code Duplication
if ( ! function_exists( 'safecss_class' ) ) :
1099
	/**
1100
	 * Load in the class only when needed.  Makes lighter load by having one less class in memory.
1101
	 */
1102
	function safecss_class() {
1103
		// Wrapped so we don't need the parent class just to load the plugin.
1104
		if ( class_exists( 'safecss' ) ) {
1105
			return;
1106
		}
1107
1108
		require_once( dirname( __FILE__ ) . '/csstidy/class.csstidy.php' );
1109
1110
		/**
1111
		 * Class safecss
1112
		 */
1113
		class safecss extends csstidy_optimise {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
1114
1115
			/**
1116
			 * Optimises $css after parsing.
1117
			 */
1118
			function postparse() {
1119
1120
				/** This action is documented in modules/custom-css/custom-css.php */
1121
				do_action( 'csstidy_optimize_postparse', $this );
1122
1123
				return parent::postparse();
1124
			}
1125
1126
			/**
1127
			 * Optimises a sub-value.
1128
			 */
1129
			function subvalue() {
1130
1131
				/** This action is documented in modules/custom-css/custom-css.php */
1132
				do_action( 'csstidy_optimize_subvalue', $this );
1133
1134
				return parent::subvalue();
1135
			}
1136
		}
1137
	}
1138
endif;
1139