Completed
Push — renovate/react-monorepo ( 545e89...65a81e )
by
unknown
268:48 queued 253:47
created

Jetpack_Custom_CSS   F

Complexity

Total Complexity 209

Size/Duplication

Total Lines 1602
Duplicated Lines 7.99 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
dl 128
loc 1602
rs 0.8
c 0
b 0
f 0
wmc 209
lcom 1
cbo 7

42 Methods

Rating   Name   Duplication   Size   Complexity  
F init() 0 138 27
C save() 34 178 12
A get_post() 0 8 2
B post_id() 43 43 5
A get_current_revision() 0 19 3
B save_revision() 0 53 5
B skip_stylesheet() 0 42 7
A is_preview() 0 3 2
A set_content_width() 8 8 5
A is_freetrial() 0 13 1
A get_preprocessor_key() 0 4 1
A get_preprocessor() 0 7 2
F get_css() 0 87 17
A replace_insecure_urls() 0 8 2
A print_css() 0 13 1
A should_we_inline_custom_css() 0 4 2
F link_tag() 14 119 19
A style_filter() 0 17 5
A buffer() 0 4 1
A preview_links() 0 9 2
A preview_flag() 0 48 3
A menu() 0 8 1
A update_title() 0 4 1
A prettify_post_revisions() 0 3 1
A post_title() 0 15 4
A enqueue_scripts() 0 34 4
A saved_message() 0 3 1
B admin() 0 62 5
C content_width_settings() 0 120 10
C publish_box() 0 108 8
B revisions_meta_box() 0 52 10
A disable() 0 4 1
A reset() 0 19 1
A is_customizer_preview() 0 6 2
A minify() 8 29 4
A restore_revision() 0 25 2
C upgrade() 13 78 12
A add_revision_redirect() 0 3 1
A revision_redirect() 0 13 4
A revision_post_link() 0 21 5
A editor_max_image_size() 8 8 3
A jetpack_content_width() 0 17 5

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Jetpack_Custom_CSS often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Jetpack_Custom_CSS, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
use Automattic\Jetpack\Assets;
4
use Automattic\Jetpack\Redirect;
5
use Automattic\Jetpack\Device_Detection\User_Agent_Info;
6
7
class Jetpack_Custom_CSS {
8
	static function init() {
9
		add_action( 'switch_theme', array( __CLASS__, 'reset' ) );
10
		add_action( 'wp_restore_post_revision', array( __CLASS__, 'restore_revision' ), 10, 2 );
11
12
		// Save revisions for posts of type safecss.
13
		add_action( 'load-revision.php', array( __CLASS__, 'add_revision_redirect' ) );
14
15
		// Override the edit link, the default link causes a redirect loop
16
		add_filter( 'get_edit_post_link', array( __CLASS__, 'revision_post_link' ), 10, 3 );
17
18
		// Overwrite the content width global variable if one is set in the custom css
19
		add_action( 'template_redirect', array( __CLASS__, 'set_content_width' ) );
20
		add_action( 'admin_init', array( __CLASS__, 'set_content_width' ) );
21
22
		if ( ! is_admin() )
23
			add_filter( 'stylesheet_uri', array( __CLASS__, 'style_filter' ) );
24
25
		define(
26
			'SAFECSS_USE_ACE',
27
			! jetpack_is_mobile() &&
28
			! User_Agent_Info::is_ipad() &&
29
			/**
30
			 * Should the Custom CSS module use ACE to process CSS.
31
			 * @see https://ace.c9.io/
32
			 *
33
			 * @module custom-css
34
			 *
35
			 * @since 1.7.0
36
			 *
37
			 * @param bool true Use ACE to process the Custom CSS. Default to true.
38
			 */
39
			apply_filters( 'safecss_use_ace', true )
40
		);
41
42
		// Register safecss as a custom post_type
43
		// Explicit capability definitions are largely unnecessary because the posts are manipulated in code via an options page, managing CSS revisions does check the capabilities, so let's ensure that the proper caps are checked.
44
		register_post_type( 'safecss', array(
45
	//		These are the defaults
46
	//		'exclude_from_search' => true,
47
	//		'public' => false,
48
	//		'publicly_queryable' => false,
49
	//		'show_ui' => false,
50
			'supports' => array( 'revisions' ),
51
			'label' => 'Custom CSS',
52
			'can_export' => false,
53
			'rewrite' => false,
54
			'capabilities' => array(
55
				'edit_post' => 'edit_theme_options',
56
				'read_post' => 'read',
57
				'delete_post' => 'edit_theme_options',
58
				'edit_posts' => 'edit_theme_options',
59
				'edit_others_posts' => 'edit_theme_options',
60
				'publish_posts' => 'edit_theme_options',
61
				'read_private_posts' => 'read'
62
			)
63
		) );
64
65
		// Short-circuit WP if this is a CSS stylesheet request
66
		if ( isset( $_GET['custom-css'] ) ) {
67
			header( 'Content-Type: text/css', true, 200 );
68
			header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + 31536000) . ' GMT' ); // 1 year
69
			Jetpack_Custom_CSS::print_css();
70
			exit;
71
		}
72
73
		add_action( 'admin_enqueue_scripts', array( 'Jetpack_Custom_CSS', 'enqueue_scripts' ) );
74
75
		if ( isset( $_GET['page'] ) && 'editcss' == $_GET['page'] && is_admin() ) {
76
			// Do migration routine if necessary
77
			Jetpack_Custom_CSS::upgrade();
78
79
			/**
80
			 * Allows additional work when migrating safecss from wp_options to wp_post.
81
			 *
82
			 * @module custom-css
83
			 *
84
			 * @since 1.7.0
85
			 */
86
			do_action( 'safecss_migrate_post' );
87
		}
88
89
		/**
90
		 * Never embed the style in the head on wpcom.
91
		 * Yes, this filter should be added to an unsynced file on wpcom, but
92
		 * there is no good syntactically-correct location to put it yet.
93
		 * @link https://github.com/Automattic/jetpack/commit/a1be114e9179f64d147124727a58e2cf76c7e5a1#commitcomment-7763921
94
		 */
95
		if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
96
			add_filter( 'safecss_embed_style', '__return_false' );
97
		} else {
98
			add_filter( 'safecss_embed_style', array( 'Jetpack_Custom_CSS', 'should_we_inline_custom_css' ), 10, 2 );
99
		}
100
101
		add_action( 'wp_head', array( 'Jetpack_Custom_CSS', 'link_tag' ), 101 );
102
103
		add_filter( 'jetpack_content_width', array( 'Jetpack_Custom_CSS', 'jetpack_content_width' ) );
104
		add_filter( 'editor_max_image_size', array( 'Jetpack_Custom_CSS', 'editor_max_image_size' ), 10, 3 );
105
106
		if ( !current_user_can( 'switch_themes' ) && !is_super_admin() )
107
			return;
108
109
		add_action( 'admin_menu', array( 'Jetpack_Custom_CSS', 'menu' ) );
110
111
		if ( isset( $_POST['safecss'] ) && false == strstr( $_SERVER[ 'REQUEST_URI' ], 'options.php' ) ) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing strstr($_SERVER['REQUEST_URI'], 'options.php') of type string to the boolean false. If you are specifically checking for an empty string, consider using the more explicit === '' instead.
Loading history...
112
			check_admin_referer( 'safecss' );
113
114
			$save_result = self::save( array(
115
				'css' => stripslashes( $_POST['safecss'] ),
116
				'is_preview' => isset( $_POST['action'] ) && $_POST['action'] == 'preview',
117
				'preprocessor' => isset( $_POST['custom_css_preprocessor'] ) ? $_POST['custom_css_preprocessor'] : '',
118
				'add_to_existing' => isset( $_POST['add_to_existing'] ) ? $_POST['add_to_existing'] == 'true' : true,
119
				'content_width' => isset( $_POST['custom_content_width'] ) ? $_POST['custom_content_width'] : false,
120
			) );
121
122
			if ( $_POST['action'] == 'preview' ) {
123
				wp_safe_redirect( add_query_arg( 'csspreview', 'true', get_option( 'home' ) ) );
124
				exit;
125
			}
126
127
			if ( $save_result )
128
				add_action( 'admin_notices', array( 'Jetpack_Custom_CSS', 'saved_message' ) );
129
		}
130
131
		// Prevent content filters running on CSS when restoring revisions
132
		if ( isset( $_REQUEST[ 'action' ] ) && 'restore' === $_REQUEST[ 'action' ] && false !== strstr( $_SERVER[ 'REQUEST_URI' ], 'revision.php' ) ) {
133
			$parent_post = get_post( wp_get_post_parent_id( (int) $_REQUEST['revision'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
134
			if ( $parent_post && ! is_wp_error( $parent_post ) && 'safecss' === $parent_post->post_type ) {
135
				// Remove wp_filter_post_kses, this causes CSS escaping issues
136
				remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
137
				remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );
138
				remove_all_filters( 'content_save_pre' );
139
			}
140
		}
141
142
		// Modify all internal links so that preview state persists
143
		if ( Jetpack_Custom_CSS::is_preview() )
144
			ob_start( array( 'Jetpack_Custom_CSS', 'buffer' ) );
145
	}
146
147
	/**
148
	 * Save new custom CSS. This should be the entry point for any third-party code using Jetpack_Custom_CSS
149
	 * to save CSS.
150
	 *
151
	 * @param array $args Array of arguments:
152
	 *        string $css The CSS (or LESS or Sass)
153
	 *        bool $is_preview Whether this CSS is preview or published
154
	 *        string preprocessor Which CSS preprocessor to use
155
	 *        bool $add_to_existing Whether this CSS replaces the theme's CSS or supplements it.
156
	 *        int $content_width A custom $content_width to go along with this CSS.
157
	 * @return int The post ID of the saved Custom CSS post.
158
	 */
159
	public static function save( $args = array() ) {
160
		$defaults = array(
161
			'css' => '',
162
			'is_preview' => false,
163
			'preprocessor' => '',
164
			'add_to_existing' => true,
165
			'content_width' => false,
166
		);
167
168
		$args = wp_parse_args( $args, $defaults );
0 ignored issues
show
Documentation introduced by
$defaults is of type array<string,string|bool...ontent_width":"false"}>, but the function expects a string.

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...
169
170
		if (
171
			$args['content_width']
172
			&& (int) $args['content_width'] > 0
173
			&& (
174
				! isset( $GLOBALS['content_width'] )
175
				|| $args['content_width'] !== $GLOBALS['content_width']
176
			)
177
		) {
178
			$args['content_width'] = (int) $args['content_width'];
179
		} else {
180
			$args['content_width'] = false;
181
		}
182
183
		// Remove wp_filter_post_kses, this causes CSS escaping issues
184
		remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
185
		remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );
186
		remove_all_filters( 'content_save_pre' );
187
188
		/**
189
		 * Fires prior to saving custom css values. Necessitated because the
190
		 * core WordPress save_pre filters were removed:
191
		 * - content_save_pre
192
		 * - content_filtered_save_pre
193
		 *
194
		 * @module custom-css
195
		 *
196
		 * @since 1.7.0
197
		 *
198
		 * @param array $args {
199
		 * Array of custom CSS arguments.
200
		 * 	@type string $css The CSS (or LESS or Sass).
201
		 * 	@type bool $is_preview Whether this CSS is preview or published.
202
		 * 	@type string preprocessor Which CSS preprocessor to use.
203
		 * 	@type bool $add_to_existing Whether this CSS replaces the theme's CSS or supplements it.
204
		 * 	@type int $content_width A custom $content_width to go along with this CSS.
205
		 * }
206
		 */
207
		do_action( 'safecss_save_pre', $args );
208
209
		$warnings = array();
210
211
		safecss_class();
212
		$csstidy = new csstidy();
213
		$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...
214
215
		$csstidy->set_cfg( 'remove_bslash',              false );
216
		$csstidy->set_cfg( 'compress_colors',            false );
217
		$csstidy->set_cfg( 'compress_font-weight',       false );
218
		$csstidy->set_cfg( 'optimise_shorthands',        0 );
219
		$csstidy->set_cfg( 'remove_last_;',              false );
220
		$csstidy->set_cfg( 'case_properties',            false );
221
		$csstidy->set_cfg( 'discard_invalid_properties', true );
222
		$csstidy->set_cfg( 'css_level',                  'CSS3.0' );
223
		$csstidy->set_cfg( 'preserve_css',               true );
224
		$csstidy->set_cfg( 'template',                   dirname( __FILE__ ) . '/csstidy/wordpress-standard.tpl' );
225
226
		$css = $orig = $args['css'];
0 ignored issues
show
Unused Code introduced by
$orig 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...
227
228
		$css = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $prev = $css );
229
		// prevent content: '\3434' from turning into '\\3434'
230
		$css = str_replace( array( '\'\\\\', '"\\\\' ), array( '\'\\', '"\\' ), $css );
231
232
		if ( $css != $prev )
233
			$warnings[] = 'preg_replace found stuff';
234
235
		// Some people put weird stuff in their CSS, KSES tends to be greedy
236
		$css = str_replace( '<=', '&lt;=', $css );
237
		// Why KSES instead of strip_tags?  Who knows?
238
		$css = wp_kses_split( $prev = $css, array(), array() );
239
		$css = str_replace( '&gt;', '>', $css ); // kses replaces lone '>' with &gt;
240
		// Why both KSES and strip_tags?  Because we just added some '>'.
241
		$css = strip_tags( $css );
242
243
		if ( $css != $prev )
244
			$warnings[] = 'kses found stuff';
245
246
		// if we're not using a preprocessor
247 View Code Duplication
		if ( ! $args['preprocessor'] ) {
248
249
			/**
250
			 * Fires before parsing the css with CSSTidy, but only if
251
			 * the preprocessor is not configured for use.
252
			 *
253
			 * @module custom-css
254
			 *
255
			 * @since 1.7.0
256
			 *
257
			 * @param obj $csstidy The csstidy object.
258
			 * @param string $css Custom CSS.
259
			 * @param array $args Array of custom CSS arguments.
260
			 */
261
			do_action( 'safecss_parse_pre', $csstidy, $css, $args );
262
263
			$csstidy->parse( $css );
264
265
			/**
266
			 * Fires after parsing the css with CSSTidy, but only if
267
			 * the preprocessor is not cinfigured for use.
268
			 *
269
			 * @module custom-css
270
			 *
271
			 * @since 1.7.0
272
			 *
273
			 * @param obj $csstidy The csstidy object.
274
			 * @param array $warnings Array of warnings.
275
			 * @param array $args Array of custom CSS arguments.
276
			 */
277
			do_action( 'safecss_parse_post', $csstidy, $warnings, $args );
278
279
			$css = $csstidy->print->plain();
280
		}
281
282
		if ( $args['add_to_existing'] )
283
			$add_to_existing = 'yes';
284
		else
285
			$add_to_existing = 'no';
286
287
		if ( $args['is_preview'] || Jetpack_Custom_CSS::is_freetrial() ) {
288
			// Save the CSS
289
			$safecss_revision_id = Jetpack_Custom_CSS::save_revision( $css, true, $args['preprocessor'] );
290
291
			// Cache Buster
292
			update_option( 'safecss_preview_rev', (int) get_option( 'safecss_preview_rev' ) + 1 );
293
294
			update_metadata( 'post', $safecss_revision_id, 'custom_css_add', $add_to_existing );
295
			update_metadata( 'post', $safecss_revision_id, 'content_width', $args['content_width'] );
296
			update_metadata( 'post', $safecss_revision_id, 'custom_css_preprocessor', $args['preprocessor'] );
297
298
			delete_option( 'safecss_add' );
299
			delete_option( 'safecss_content_width' );
300
301
			if ( $args['is_preview'] ) {
302
				return $safecss_revision_id;
303
			}
304
305
			/**
306
			 * Fires after saving Custom CSS.
307
			 *
308
			 * @module custom-css
309
			 *
310
			 * @since 1.7.0
311
			 */
312
			do_action( 'safecss_save_preview_post' );
313
		}
314
315
		// Save the CSS
316
		$safecss_post_id = Jetpack_Custom_CSS::save_revision( $css, false, $args['preprocessor'] );
317
318
		$safecss_post_revision = Jetpack_Custom_CSS::get_current_revision();
319
320
		update_option( 'safecss_rev', (int) get_option( 'safecss_rev' ) + 1 );
321
322
		update_post_meta( $safecss_post_id, 'custom_css_add', $add_to_existing );
323
		update_post_meta( $safecss_post_id, 'content_width', $args['content_width'] );
324
		update_post_meta( $safecss_post_id, 'custom_css_preprocessor', $args['preprocessor'] );
325
326
		delete_option( 'safecss_add' );
327
		delete_option( 'safecss_content_width' );
328
329
		update_metadata( 'post', $safecss_post_revision['ID'], 'custom_css_add', $add_to_existing );
330
		update_metadata( 'post', $safecss_post_revision['ID'], 'content_width', $args['content_width'] );
331
		update_metadata( 'post', $safecss_post_revision['ID'], 'custom_css_preprocessor', $args['preprocessor'] );
332
333
		delete_option( 'safecss_preview_add' );
334
335
		return $safecss_post_id;
336
	}
337
338
	/**
339
	 * Get the published custom CSS post.
340
	 *
341
	 * @return array
342
	 */
343
	static function get_post() {
344
		$custom_css_post_id = Jetpack_Custom_CSS::post_id();
345
346
		if ( $custom_css_post_id )
347
			return get_post( $custom_css_post_id, ARRAY_A );
348
349
		return array();
350
	}
351
352
	/**
353
	 * Get the post ID of the published custom CSS post.
354
	 *
355
	 * @return int|bool The post ID if it exists; false otherwise.
356
	 */
357 View Code Duplication
	static function post_id() {
358
		/**
359
		 * Filter the ID of the post where Custom CSS is stored, before the ID is retrieved.
360
		 *
361
		 * If the callback function returns a non-null value, then post_id() will immediately
362
		 * return that value, instead of retrieving the normal post ID.
363
		 *
364
		 * @module custom-css
365
		 *
366
		 * @since 3.8.1
367
		 *
368
		 * @param null null The ID to return instead of the normal ID.
369
		 */
370
		$custom_css_post_id = apply_filters( 'jetpack_custom_css_pre_post_id', null );
371
		if ( ! is_null( $custom_css_post_id ) ) {
372
			return $custom_css_post_id;
373
		}
374
375
		$custom_css_post_id = wp_cache_get( 'custom_css_post_id' );
376
377
		if ( false === $custom_css_post_id ) {
378
			$custom_css_posts = get_posts( array(
379
				'posts_per_page' => 1,
380
				'post_type' => 'safecss',
381
				'post_status' => 'publish',
382
				'orderby' => 'date',
383
				'order' => 'DESC'
384
			) );
385
386
			if ( count( $custom_css_posts ) > 0 )
387
				$custom_css_post_id = $custom_css_posts[0]->ID;
388
			else
389
				$custom_css_post_id = 0;
390
391
			// Save post_id=0 to note that no safecss post exists.
392
			wp_cache_set( 'custom_css_post_id', $custom_css_post_id );
393
		}
394
395
		if ( ! $custom_css_post_id )
396
			return false;
397
398
		return $custom_css_post_id;
399
	}
400
401
	/**
402
	 * Get the current revision of the original safecss record
403
	 *
404
	 * @return object
405
	 */
406
	static function get_current_revision() {
407
		$safecss_post = Jetpack_Custom_CSS::get_post();
408
409
		if ( empty( $safecss_post ) ) {
410
			return false;
411
		}
412
413
		$revisions = wp_get_post_revisions( $safecss_post['ID'], array( 'posts_per_page' => 1, 'orderby' => 'date', 'order' => 'DESC' ) );
414
415
		// Empty array if no revisions exist
416
		if ( empty( $revisions ) ) {
417
			// Return original post
418
			return $safecss_post;
419
		} else {
420
			// Return the first entry in $revisions, this will be the current revision
421
			$current_revision = get_object_vars( array_shift( $revisions ) );
422
			return $current_revision;
423
		}
424
	}
425
426
	/**
427
	 * Save new revision of CSS
428
	 * Checks to see if content was modified before really saving
429
	 *
430
	 * @param string $css
431
	 * @param bool $is_preview
432
	 * @return bool|int If nothing was saved, returns false. If a post
433
	 *                  or revision was saved, returns the post ID.
434
	 */
435
	static function save_revision( $css, $is_preview = false, $preprocessor = '' ) {
436
		$safecss_post = Jetpack_Custom_CSS::get_post();
437
438
		$compressed_css = Jetpack_Custom_CSS::minify( $css, $preprocessor );
439
440
		// If null, there was no original safecss record, so create one
441
		if ( null == $safecss_post ) {
442
			if ( ! $css )
443
				return false;
444
445
			$post = array();
446
			$post['post_content'] = wp_slash( $css );
447
			$post['post_title'] = 'safecss';
448
			$post['post_status'] = 'publish';
449
			$post['post_type'] = 'safecss';
450
			$post['post_content_filtered'] = wp_slash( $compressed_css );
451
452
			// Set excerpt to current theme, for display in revisions list
453
			$current_theme = wp_get_theme();
454
			$post['post_excerpt'] = $current_theme->Name;
455
456
			// Insert the CSS into wp_posts
457
			$post_id = wp_insert_post( $post );
458
			wp_cache_set( 'custom_css_post_id', $post_id );
459
			return $post_id;
460
		}
461
462
		// Update CSS in post array with new value passed to this function
463
		$safecss_post['post_content'] = $css;
464
		$safecss_post['post_content_filtered'] = $compressed_css;
465
466
		// Set excerpt to current theme, for display in revisions list
467
		$current_theme = wp_get_theme();
468
		$safecss_post['post_excerpt'] = $current_theme->Name;
469
470
		// Don't carry over last revision's timestamps, otherwise revisions all have matching timestamps
471
		unset( $safecss_post['post_date'] );
472
		unset( $safecss_post['post_date_gmt'] );
473
		unset( $safecss_post['post_modified'] );
474
		unset( $safecss_post['post_modified_gmt'] );
475
476
		// Do not update post if we are only saving a preview
477
		if ( false === $is_preview ) {
478
			$safecss_post['post_content'] = wp_slash( $safecss_post['post_content'] );
479
			$safecss_post['post_content_filtered'] = wp_slash( $safecss_post['post_content_filtered'] );
480
			$post_id = wp_update_post( $safecss_post );
481
			wp_cache_set( 'custom_css_post_id', $post_id );
482
			return $post_id;
483
		}
484
		else if ( ! defined( 'DOING_MIGRATE' ) ) {
485
			return _wp_put_post_revision( $safecss_post );
486
		}
487
	}
488
489
	static function skip_stylesheet() {
490
		/**
491
		 * Prevent the Custom CSS stylesheet from being enqueued.
492
		 *
493
		 * @module custom-css
494
		 *
495
		 * @since 2.2.1
496
		 *
497
		 * @param null Should the stylesheet be skipped. Default to null. Anything else will force the stylesheet to be skipped.
498
		 */
499
		$skip_stylesheet = apply_filters( 'safecss_skip_stylesheet', null );
500
501
		if ( null !== $skip_stylesheet ) {
502
			return $skip_stylesheet;
503
		} elseif ( Jetpack_Custom_CSS::is_customizer_preview() ) {
504
			return false;
505
		} else {
506
			if ( Jetpack_Custom_CSS::is_preview() ) {
507
				$safecss_post = Jetpack_Custom_CSS::get_current_revision();
508
509
				if ( $safecss_post )
510
					return (bool) ( get_post_meta( $safecss_post['ID'], 'custom_css_add', true ) == 'no' );
511
				else
512
					return (bool) ( get_option( 'safecss_preview_add' ) == 'no' );
513
			}
514
			else {
515
				$custom_css_post_id = Jetpack_Custom_CSS::post_id();
516
517
				if ( $custom_css_post_id ) {
518
					$custom_css_add = get_post_meta( $custom_css_post_id, 'custom_css_add', true );
519
520
					// It is possible for the CSS to be stored in a post but for the safecss_add option
521
					// to have not been upgraded yet if the user hasn't opened their Custom CSS editor
522
					// since October 2012.
523
					if ( ! empty( $custom_css_add ) )
524
						return (bool) ( $custom_css_add === 'no' );
525
				}
526
527
				return (bool) ( Jetpack_Options::get_option_and_ensure_autoload( 'safecss_add', '' ) == 'no' );
528
			}
529
		}
530
	}
531
532
	static function is_preview() {
533
		return isset( $_GET['csspreview'] ) && $_GET['csspreview'] === 'true';
534
	}
535
536
	/**
537
	 * Currently this filter function gets called on
538
	 * 'template_redirect' action and
539
	 * 'admin_init' action
540
	 */
541 View Code Duplication
	static function set_content_width(){
542
		// Don't apply this filter on the Edit CSS page
543
		if ( isset( $_GET ) && isset( $_GET['page'] ) &&  'editcss' == $_GET['page'] && is_admin() ) {
544
			return;
545
		}
546
547
		$GLOBALS['content_width'] = Jetpack::get_content_width();
548
	}
549
550
	/*
551
	 * False when the site has the Custom Design upgrade.
552
	 * Used only on WordPress.com.
553
	 */
554
	static function is_freetrial() {
555
		/**
556
		 * Determine if a WordPress.com site uses a Free trial of the Custom Design Upgrade.
557
		 * Used only on WordPress.com.
558
		 *
559
		 * @module custom-css
560
		 *
561
		 * @since 1.7.0
562
		 *
563
		 * @param bool false Does the site use a Free trial of the Custom Design Upgrade. Default to false.
564
		 */
565
		return apply_filters( 'safecss_is_freetrial', false );
566
	}
567
568
	static function get_preprocessor_key() {
569
		$safecss_post = Jetpack_Custom_CSS::get_current_revision();
570
		return get_post_meta( $safecss_post['ID'], 'custom_css_preprocessor', true );
571
	}
572
573
	static function get_preprocessor() {
574
		/** This filter is documented in modules/custom-css/custom-css.php */
575
		$preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
576
		$selected_preprocessor_key = self::get_preprocessor_key();
577
		$selected_preprocessor = isset( $preprocessors[ $selected_preprocessor_key ] ) ? $preprocessors[ $selected_preprocessor_key ] : null;
578
		return $selected_preprocessor;
579
	}
580
581
	static function get_css( $compressed = false ) {
582
		/**
583
		 * Filter the Custom CSS returned.
584
		 * Can be used to return an error, or no CSS at all.
585
		 *
586
		 * @module custom-css
587
		 *
588
		 * @since 1.7.0
589
		 *
590
		 * @param bool false Should we return an error instead of the Custom CSS. Default to false.
591
		 */
592
		$default_css = apply_filters( 'safecss_get_css_error', false );
593
594
		if ( $default_css !== false )
595
			return $default_css;
596
597
		$option = ( Jetpack_Custom_CSS::is_preview() || Jetpack_Custom_CSS::is_freetrial() ) ? 'safecss_preview' : 'safecss';
598
		$css = '';
599
600
		if ( 'safecss' == $option ) {
601
			// Don't bother checking for a migrated 'safecss' option if it never existed.
602
			if ( false === get_option( 'safecss' ) || get_option( 'safecss_revision_migrated' ) ) {
603
				$safecss_post = Jetpack_Custom_CSS::get_post();
604
				if ( ! empty( $safecss_post ) ) {
605
					$css = ( $compressed && $safecss_post['post_content_filtered'] ) ? $safecss_post['post_content_filtered'] : $safecss_post['post_content'];
606
				}
607
			} else {
608
				$current_revision = Jetpack_Custom_CSS::get_current_revision();
609
				if ( false === $current_revision ) {
610
					$css = '';
611
				} else {
612
					$css = ( $compressed && $current_revision['post_content_filtered'] ) ? $current_revision['post_content_filtered'] : $current_revision['post_content'];
613
				}
614
			}
615
616
			// Fix for un-migrated Custom CSS
617
			if ( empty( $safecss_post ) ) {
618
				$_css = get_option( 'safecss' );
619
				if ( !empty( $_css ) ) {
620
					$css = $_css;
621
				}
622
			}
623
		}
624
		else if ( 'safecss_preview' == $option ) {
625
			$safecss_post = Jetpack_Custom_CSS::get_current_revision();
626
			$css = $safecss_post['post_content'];
627
			$css = Jetpack_Custom_CSS::minify( $css, get_post_meta( $safecss_post['ID'], 'custom_css_preprocessor', true ) );
628
		}
629
630
		$css = str_replace( array( '\\\00BB \\\0020', '\0BB \020', '0BB 020' ), '\00BB \0020', $css );
631
632
		if ( empty( $css ) ) {
633
			$css = "/*\n"
634
				. wordwrap(
635
					/**
636
					 * Filter the default message displayed in the Custom CSS editor.
637
					 *
638
					 * @module custom-css
639
					 *
640
					 * @since 1.7.0
641
					 *
642
					 * @param string $str Default Custom CSS editor content.
643
					 */
644
					apply_filters(
645
						'safecss_default_css',
646
						__(
647
							"Welcome to Custom CSS!\n\nTo learn how this works, see https://wp.me/PEmnE-Bt",
648
							'jetpack'
649
						)
650
					)
651
				)
652
				. "\n*/";
653
		}
654
655
		/**
656
		 * Filter the Custom CSS returned from the editor.
657
		 *
658
		 * @module custom-css
659
		 *
660
		 * @since 1.7.0
661
		 *
662
		 * @param string $css Custom CSS.
663
		 */
664
		$css = apply_filters( 'safecss_css', $css );
665
666
		return $css;
667
	}
668
669
	static function replace_insecure_urls( $css ) {
670
		if ( ! function_exists( '_sa_get_frontend_https_url_replacement_map' ) ) {
671
			return $css;
672
		}
673
		list( $http_urls, $secure_urls ) = _sa_get_frontend_https_url_replacement_map();
674
675
		return str_replace( $http_urls, $secure_urls, $css );
676
	}
677
678
	static function print_css() {
679
680
		/**
681
		 * Fires right before printing the custom CSS inside the <head> element.
682
		 *
683
		 * @module custom-css
684
		 *
685
		 * @since 1.7.0
686
		 */
687
		do_action( 'safecss_print_pre' );
688
		$css = Jetpack_Custom_CSS::get_css( true );
689
		echo self::replace_insecure_urls( $css );
690
	}
691
692
	static function should_we_inline_custom_css( $should_we, $css ) {
693
		// If the CSS is less than 2,000 characters, inline it! otherwise return what was passed in.
694
		return ( strlen( $css ) < 2000 ) ? true : $should_we;
695
	}
696
697
	static function link_tag() {
698
		global $blog_id, $current_blog;
699
700
		if (
701
			/**
702
			 * Do not include any CSS on the page if the CSS includes an error.
703
			 * Setting this filter to true stops any Custom CSS from being enqueued.
704
			 *
705
			 * @module custom-css
706
			 *
707
			 * @since 1.7.0
708
			 *
709
			 * @param bool false Does the CSS include an error. Default to false.
710
			 */
711
			apply_filters( 'safecss_style_error', false )
712
		) {
713
			return;
714
		}
715
716
		if ( ! is_super_admin() && isset( $current_blog ) && ( 1 == $current_blog->spam || 1 == $current_blog->deleted ) )
717
			return;
718
719
		if ( Jetpack_Custom_CSS::is_customizer_preview() )
720
			return;
721
722
		$css    = '';
723
		$option = Jetpack_Custom_CSS::is_preview() ? 'safecss_preview' : 'safecss';
724
725
		if ( 'safecss' == $option ) {
726
			if ( Jetpack_Options::get_option_and_ensure_autoload( 'safecss_revision_migrated', '0' ) ) {
727
				$safecss_post = Jetpack_Custom_CSS::get_post();
728
729
				if ( ! empty( $safecss_post['post_content'] ) ) {
730
					$css = $safecss_post['post_content'];
731
				}
732 View Code Duplication
			} else {
733
				$current_revision = Jetpack_Custom_CSS::get_current_revision();
734
735
				if ( ! empty( $current_revision['post_content'] ) ) {
736
					$css = $current_revision['post_content'];
737
				}
738
			}
739
740
			// Fix for un-migrated Custom CSS
741
			if ( empty( $safecss_post ) ) {
742
				$_css = Jetpack_Options::get_option_and_ensure_autoload( 'safecss', '' );
743
				if ( !empty( $_css ) ) {
744
					$css = $_css;
745
				}
746
			}
747
		}
748
749 View Code Duplication
		if ( 'safecss_preview' == $option ) {
750
			$safecss_post = Jetpack_Custom_CSS::get_current_revision();
751
752
			if ( !empty( $safecss_post['post_content'] ) ) {
753
				$css = $safecss_post['post_content'];
754
			}
755
		}
756
757
		$css = str_replace( array( '\\\00BB \\\0020', '\0BB \020', '0BB 020' ), '\00BB \0020', $css );
758
759
		if ( $css == '' )
760
			return;
761
762
		if (
763
			/**
764
			 * Allow inserting CSS inline instead of through a separate file.
765
			 *
766
			 * @module custom-css
767
			 *
768
			 * @since 3.4.0
769
			 *
770
			 * @param bool false Should the CSS be added inline instead of through a separate file. Default to false.
771
			 * @param string $css Custom CSS.
772
			 */
773
			apply_filters( 'safecss_embed_style', false, $css )
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $css.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
774
		) {
775
776
			echo "\r\n" . '<style id="custom-css-css">' . Jetpack_Custom_CSS::get_css( true ) . "</style>\r\n";
777
778
		} else {
779
780
			$href = home_url( '/' );
781
			$href = add_query_arg( 'custom-css', 1, $href );
782
			$href = add_query_arg( 'csblog', $blog_id, $href );
783
			$href = add_query_arg( 'cscache', 6, $href );
784
			$href = add_query_arg( 'csrev', (int) get_option( $option . '_rev' ), $href );
785
786
			/**
787
			 * Filter the Custom CSS link enqueued in the head.
788
			 *
789
			 * @module custom-css
790
			 *
791
			 * @since 1.7.0
792
			 *
793
			 * @param string $href Custom CSS link enqueued in the head.
794
			 * @param string $blog_id Blog ID.
795
			 */
796
			$href = apply_filters( 'safecss_href', $href, $blog_id );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $blog_id.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
797
798
			if ( Jetpack_Custom_CSS::is_preview() )
799
				$href = add_query_arg( 'csspreview', 'true', $href );
800
801
			?>
802
			<link rel="stylesheet" id="custom-css-css" type="text/css" href="<?php echo esc_url( $href ); ?>" />
803
			<?php
804
805
		}
806
807
		/**
808
		 * Fires after creating the <link> in the <head> element for the custom css stylesheet.
809
		 *
810
		 * @module custom-css
811
		 *
812
		 * @since 2.2.2
813
		 */
814
		do_action( 'safecss_link_tag_post' );
815
	}
816
817
	static function style_filter( $current ) {
818
		if ( Jetpack_Custom_CSS::is_freetrial() && ( ! Jetpack_Custom_CSS::is_preview() || ! current_user_can( 'switch_themes' ) ) )
819
			return $current;
820
		else if ( Jetpack_Custom_CSS::skip_stylesheet() )
821
			/**
822
			 * Filter the default blank Custom CSS URL.
823
			 *
824
			 * @module custom-css
825
			 *
826
			 * @since 2.2.1
827
			 *
828
			 * @param string $url Default blank Custom CSS URL.
829
			 */
830
			return apply_filters( 'safecss_style_filter_url', plugins_url( 'custom-css/css/blank.css', __FILE__ ) );
831
832
		return $current;
833
	}
834
835
	static function buffer( $html ) {
836
		$html = str_replace( '</body>', Jetpack_Custom_CSS::preview_flag(), $html );
837
		return preg_replace_callback( '!href=([\'"])(.*?)\\1!', array( 'Jetpack_Custom_CSS', 'preview_links' ), $html );
838
	}
839
840
	static function preview_links( $matches ) {
841
		if ( 0 !== strpos( $matches[2], get_option( 'home' ) ) )
842
			return $matches[0];
843
844
		$link = wp_specialchars_decode( $matches[2] );
845
		$link = add_query_arg( 'csspreview', 'true', $link );
846
		$link = esc_url( $link );
847
		return "href={$matches[1]}$link{$matches[1]}";
848
	}
849
850
	/**
851
	 * Places a black bar above every preview page
852
	 */
853
	static function preview_flag() {
854
		if ( is_admin() )
855
			return;
856
857
		$message = esc_html__( 'Preview: changes must be saved or they will be lost', 'jetpack' );
858
		/**
859
		 * Filter the Preview message displayed on the site when previewing custom CSS, before to save it.
860
		 *
861
		 * @module custom-css
862
		 *
863
		 * @since 1.7.0
864
		 *
865
		 * @param string $message Custom CSS preview message.
866
		 */
867
		$message = apply_filters( 'safecss_preview_message', $message );
868
869
		$preview_flag_js = "var flag = document.createElement('div');
870
		flag.innerHTML = " . json_encode( $message ) . ";
871
		flag.style.background = '#FF6600';
872
		flag.style.color = 'white';
873
		flag.style.textAlign = 'center';
874
		flag.style.fontSize = '15px';
875
		flag.style.padding = '2px';
876
		flag.style.fontFamily = 'sans-serif';
877
		document.body.style.paddingTop = '0px';
878
		document.body.insertBefore(flag, document.body.childNodes[0]);
879
		";
880
881
		/**
882
		 * Filter the Custom CSS preview message JS styling.
883
		 *
884
		 * @module custom-css
885
		 *
886
		 * @since 1.7.0
887
		 *
888
		 * @param string $preview_flag_js Custom CSS preview message JS styling.
889
		 */
890
		$preview_flag_js = apply_filters( 'safecss_preview_flag_js', $preview_flag_js );
891
		if ( $preview_flag_js ) {
892
			$preview_flag_js = '<script type="text/javascript">
893
	// <![CDATA[
894
	' . $preview_flag_js . '
895
	// ]]>
896
	</script>';
897
		}
898
899
		return $preview_flag_js;
900
	}
901
902
	static function menu() {
903
		$parent = 'themes.php';
0 ignored issues
show
Unused Code introduced by
$parent 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...
904
		$title = __( 'Edit CSS', 'jetpack' );
905
		$hook = add_theme_page( $title, $title, 'edit_theme_options', 'editcss', array( 'Jetpack_Custom_CSS', 'admin' ) );
906
907
		add_action( "load-revision.php", array( 'Jetpack_Custom_CSS', 'prettify_post_revisions' ) );
908
		add_action( "load-$hook", array( 'Jetpack_Custom_CSS', 'update_title' ) );
909
	}
910
911
	/**
912
	 * Adds a menu item in the appearance section for this plugin's administration
913
	 * page. Also adds hooks to enqueue the CSS and JS for the admin page.
914
	 */
915
	static function update_title() {
916
		global $title;
917
		$title = __( 'CSS', 'jetpack' );
918
	}
919
920
	static function prettify_post_revisions() {
921
		add_filter( 'the_title', array( 'Jetpack_Custom_CSS', 'post_title' ), 10, 2 );
922
	}
923
924
	static function post_title( $title, $post_id ) {
925
		if ( !$post_id = (int) $post_id ) {
926
			return $title;
927
		}
928
929
		if ( !$post = get_post( $post_id ) ) {
930
			return $title;
931
		}
932
933
		if ( 'safecss' != $post->post_type ) {
934
			return $title;
935
		}
936
937
		return __( 'Custom CSS Stylesheet', 'jetpack' );
938
	}
939
940
	static function enqueue_scripts( $hook ) {
941
		if ( 'appearance_page_editcss' != $hook )
942
			return;
943
944
		wp_enqueue_script( 'postbox' );
945
		wp_enqueue_script(
946
			'custom-css-editor',
947
			Assets::get_file_url_for_environment(
948
				'_inc/build/custom-css/custom-css/js/css-editor.min.js',
949
				'modules/custom-css/custom-css/js/css-editor.js'
950
			),
951
			'jquery',
952
			'20130325',
953
			true
954
		);
955
		wp_enqueue_style( 'custom-css-editor', plugins_url( 'custom-css/css/css-editor.css', __FILE__ ) );
956
957
		if ( defined( 'SAFECSS_USE_ACE' ) && SAFECSS_USE_ACE ) {
958
			wp_register_style( 'jetpack-css-codemirror', plugins_url( 'custom-css/css/codemirror.css', __FILE__ ), array(), '20120905' );
959
			wp_enqueue_style( 'jetpack-css-use-codemirror', plugins_url( 'custom-css/css/use-codemirror.css', __FILE__ ), array( 'jetpack-css-codemirror' ), '20120905' );
960
961
			wp_register_script( 'jetpack-css-codemirror', plugins_url( 'custom-css/js/codemirror.min.js', __FILE__ ), array(), '3.16', true );
962
			wp_enqueue_script(
963
				'jetpack-css-use-codemirror',
964
				Assets::get_file_url_for_environment(
965
					'_inc/build/custom-css/custom-css/js/use-codemirror.min.js',
966
					'modules/custom-css/custom-css/js/use-codemirror.js'
967
				),
968
				array( 'jquery', 'underscore', 'jetpack-css-codemirror' ),
969
				'20131009',
970
				true
971
			);
972
		}
973
	}
974
975
	static function saved_message() {
976
		echo '<div id="message" class="updated fade"><p><strong>' . __( 'Stylesheet saved.', 'jetpack' ) . '</strong></p></div>';
977
	}
978
979
	static function admin() {
980
		add_meta_box( 'submitdiv', __( 'Publish', 'jetpack' ), array( __CLASS__, 'publish_box' ), 'editcss', 'side' );
981
		add_action( 'custom_css_submitbox_misc_actions', array( __CLASS__, 'content_width_settings' ) );
982
983
		$safecss_post = Jetpack_Custom_CSS::get_post();
984
985
		if ( ! empty( $safecss_post ) && 0 < $safecss_post['ID'] && wp_get_post_revisions( $safecss_post['ID'], array( 'posts_per_page' => 1 ) ) )
986
			add_meta_box( 'revisionsdiv', __( 'CSS Revisions', 'jetpack' ), array( __CLASS__, 'revisions_meta_box' ), 'editcss', 'side' );
987
		?>
988
		<div class="wrap">
989
			<?php
990
991
			/**
992
			 * Fires right before the custom css page begins.
993
			 *
994
			 * @module custom-css
995
			 *
996
			 * @since 1.7.0
997
			 */
998
			do_action( 'custom_design_header' );
999
1000
			?>
1001
			<h1><?php _e( 'CSS Stylesheet Editor', 'jetpack' ); ?></h1>
1002
			<form id="safecssform" action="" method="post">
1003
				<?php wp_nonce_field( 'safecss' ) ?>
1004
				<?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
1005
				<?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
1006
				<input type="hidden" name="action" value="save" />
1007
				<div id="poststuff">
1008
					<p class="css-support">
1009
					<?php
1010
						/**
1011
						 * Filter the intro text appearing above the Custom CSS Editor.
1012
						 *
1013
						 * @module custom-css
1014
						 *
1015
						 * @since 1.7.0
1016
						 *
1017
						 * @param string $str Intro text appearing above the Custom CSS editor.
1018
						 */
1019
						echo apply_filters( 'safecss_intro_text', __( 'New to CSS? Start with a <a href="https://www.htmldog.com/guides/css/beginner/" rel="noopener noreferrer" target="_blank">beginner tutorial</a>. Questions?
1020
		Ask in the <a href="https://wordpress.org/support/forum/themes-and-templates" rel="noopener noreferrer" target="_blank">Themes and Templates forum</a>.', 'jetpack' ) );
1021
					?></p>
1022
					<p class="css-support"><?php echo __( 'Note: Custom CSS will be reset when changing themes.', 'jetpack' ); ?></p>
1023
1024
					<div id="post-body" class="metabox-holder columns-2">
1025
						<div id="post-body-content">
1026
							<div class="postarea">
1027
								<textarea id="safecss" name="safecss"<?php if ( SAFECSS_USE_ACE ) echo ' class="hide-if-js"'; ?>><?php echo esc_textarea( Jetpack_Custom_CSS::get_css() ); ?></textarea>
1028
								<div class="clear"></div>
1029
							</div>
1030
						</div>
1031
						<div id="postbox-container-1" class="postbox-container">
1032
						<?php do_meta_boxes( 'editcss', 'side', $safecss_post ); ?>
1033
					</div>
1034
					</div>
1035
					<br class="clear" />
1036
				</div>
1037
			</form>
1038
		</div>
1039
		<?php
1040
	}
1041
1042
	/**
1043
	 * Content width setting callback
1044
	 */
1045
	static function content_width_settings() {
1046
		$safecss_post = Jetpack_Custom_CSS::get_current_revision();
1047
1048
		$custom_content_width = get_post_meta( $safecss_post['ID'], 'content_width', true );
1049
1050
		// If custom content width hasn't been overridden and the theme has a content_width value, use that as a default.
1051
		if ( $custom_content_width <= 0 && ! empty( $GLOBALS['content_width'] ) )
1052
			$custom_content_width = $GLOBALS['content_width'];
1053
1054
		if ( ! $custom_content_width || ( isset( $GLOBALS['content_width'] ) && $custom_content_width == $GLOBALS['content_width'] ) )
1055
			$custom_content_width = '';
1056
1057
		?>
1058
		<div class="misc-pub-section">
1059
			<label><?php esc_html_e( 'Media Width:', 'jetpack' ); ?></label>
1060
			<span id="content-width-display" data-default-text="<?php esc_attr_e( 'Default', 'jetpack' ); ?>" data-custom-text="<?php esc_attr_e( '%s px', 'jetpack' ); ?>"><?php echo $custom_content_width ? sprintf( esc_html__( '%s px', 'jetpack' ), $custom_content_width ) : esc_html_e( 'Default', 'jetpack' ); ?></span>
1061
			<a class="edit-content-width hide-if-no-js" href="#content-width"><?php echo esc_html_e( 'Edit', 'jetpack' ); ?></a>
1062
			<div id="content-width-select" class="hide-if-js">
1063
				<input type="hidden" name="custom_content_width" id="custom_content_width" value="<?php echo esc_attr( $custom_content_width ); ?>" />
1064
				<p>
1065
					<?php
1066
1067
					printf( /* translators: %1$s is replaced with an input field for numbers. */
1068
						__( 'Limit width to %1$s pixels for full size images. (<a href="%2$s" rel="noopener noreferrer" target="_blank">More info</a>.)', 'jetpack' ),
1069
						'<input type="text" id="custom_content_width_visible" value="' . esc_attr( $custom_content_width ) . '" size="4" />',
1070
						/**
1071
						 * Filter the Custom CSS limited width's support doc URL.
1072
						 *
1073
						 * @module custom-css
1074
						 *
1075
						 * @since 2.2.3
1076
						 *
1077
						 * @param string $url Custom CSS limited width's support doc URL.
1078
						 */
1079
						esc_url(
1080
							apply_filters( 'safecss_limit_width_link', Redirect::get_url( 'jetpack-support-custom-css', array( 'anchor' => 'limited-width' ) ) )
1081
						)
1082
					);
1083
1084
					?>
1085
				</p>
1086
				<?php
1087
1088
				if (
1089
					! empty( $GLOBALS['content_width'] )
1090
					&& $custom_content_width != $GLOBALS['content_width']
1091
				) {
1092
					$current_theme = wp_get_theme()->Name;
1093
1094
					?>
1095
					<p>
1096
					<?php
1097
					echo esc_html(
1098
						sprintf(
1099
							/* translators: %1$s is the theme name, %2$d is an amount of pixels. */
1100
							_n(
1101
								'The default content width for the %1$s theme is %2$d pixel.',
1102
								'The default content width for the %1$s theme is %2$d pixels.',
1103
								(int) $GLOBALS['content_width'],
1104
								'jetpack'
1105
							),
1106
							$current_theme,
1107
							(int) $GLOBALS['content_width']
1108
						)
1109
					);
1110
					?>
1111
					</p>
1112
					<?php
1113
				}
1114
1115
				?>
1116
				<a class="save-content-width hide-if-no-js button" href="#content-width"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
1117
				<a class="cancel-content-width hide-if-no-js" href="#content-width"><?php esc_html_e( 'Cancel', 'jetpack' ); ?></a>
1118
			</div>
1119
			<script type="text/javascript">
1120
				jQuery( function ( $ ) {
1121
					var defaultContentWidth = <?php echo isset( $GLOBALS['content_width'] ) ? json_encode( (int) $GLOBALS['content_width'] ) : 0; ?>;
1122
1123
					$( '.edit-content-width' ).bind( 'click', function ( e ) {
1124
						e.preventDefault();
1125
1126
						$( '#content-width-select' ).slideDown();
1127
						$( this ).hide();
1128
					} );
1129
1130
					$( '.cancel-content-width' ).bind( 'click', function ( e ) {
1131
						e.preventDefault();
1132
1133
						$( '#content-width-select' ).slideUp( function () {
1134
							$( '.edit-content-width' ).show();
1135
							$( '#custom_content_width_visible' ).val( $( '#custom_content_width' ).val() );
1136
						} );
1137
					} );
1138
1139
					$( '.save-content-width' ).bind( 'click', function ( e ) {
1140
						e.preventDefault();
1141
1142
						$( '#content-width-select' ).slideUp();
1143
1144
						var newContentWidth = parseInt( $( '#custom_content_width_visible' ).val(), 10 );
1145
1146
						if ( newContentWidth && newContentWidth != defaultContentWidth ) {
1147
							$( '#content-width-display' ).text(
1148
								$( '#content-width-display' )
1149
									.data( 'custom-text' )
1150
										.replace( '%s', $( '#custom_content_width_visible' ).val() )
1151
							);
1152
						}
1153
						else {
1154
							$( '#content-width-display' ).text( $( '#content-width-display' ).data( 'default-text' ) );
1155
						}
1156
1157
						$( '#custom_content_width' ).val( $( '#custom_content_width_visible' ).val() );
1158
						$( '.edit-content-width' ).show();
1159
					} );
1160
				} );
1161
			</script>
1162
		</div>
1163
		<?php
1164
	}
1165
1166
	static function publish_box() {
1167
		?>
1168
		<div id="minor-publishing">
1169
			<div id="misc-publishing-actions">
1170
				<?php
1171
1172
				/**
1173
				 * Filter the array of available Custom CSS preprocessors.
1174
				 *
1175
				 * @module custom-css
1176
				 *
1177
				 * @since 2.0.3
1178
				 *
1179
				 * @param array array() Empty by default.
1180
				 */
1181
				$preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
1182
1183
				if ( ! empty( $preprocessors ) ) {
1184
					$safecss_post = Jetpack_Custom_CSS::get_current_revision();
1185
					$selected_preprocessor_key = get_post_meta( $safecss_post['ID'], 'custom_css_preprocessor', true );
1186
					$selected_preprocessor = isset( $preprocessors[$selected_preprocessor_key] ) ? $preprocessors[$selected_preprocessor_key] : null;
1187
1188
					?>
1189
					<div class="misc-pub-section">
1190
						<label><?php esc_html_e( 'Preprocessor:', 'jetpack' ); ?></label>
1191
						<span id="preprocessor-display"><?php echo esc_html( $selected_preprocessor ? $selected_preprocessor['name'] : __( 'None', 'jetpack' ) ); ?></span>
1192
						<a class="edit-preprocessor hide-if-no-js" href="#preprocessor"><?php echo esc_html_e( 'Edit', 'jetpack' ); ?></a>
1193
						<div id="preprocessor-select" class="hide-if-js">
1194
							<input type="hidden" name="custom_css_preprocessor" id="custom_css_preprocessor" value="<?php echo esc_attr( $selected_preprocessor_key ); ?>" />
1195
							<select id="preprocessor_choices">
1196
								<option value=""><?php esc_html_e( 'None', 'jetpack' ); ?></option>
1197
								<?php
1198
1199
								foreach ( $preprocessors as $preprocessor_key => $preprocessor ) {
1200
								?>
1201
									<option value="<?php echo esc_attr( $preprocessor_key ); ?>" <?php selected( $selected_preprocessor_key, $preprocessor_key ); ?>><?php echo esc_html( $preprocessor['name'] ); ?></option>
1202
									<?php
1203
								}
1204
1205
								?>
1206
							</select>
1207
							<a class="save-preprocessor hide-if-no-js button" href="#preprocessor"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
1208
							<a class="cancel-preprocessor hide-if-no-js" href="#preprocessor"><?php esc_html_e( 'Cancel', 'jetpack' ); ?></a>
1209
						</div>
1210
					</div>
1211
					<?php
1212
				}
1213
1214
				$safecss_post = Jetpack_Custom_CSS::get_current_revision();
1215
1216
				$add_css = ( get_post_meta( $safecss_post['ID'], 'custom_css_add', true ) != 'no' );
1217
1218
				?>
1219
				<div class="misc-pub-section">
1220
					<label><?php esc_html_e( 'Mode:', 'jetpack' ); ?></label>
1221
					<span id="css-mode-display"><?php echo esc_html( $add_css ? __( 'Add-on', 'jetpack' ) : __( 'Replacement', 'jetpack' ) ); ?></span>
1222
					<a class="edit-css-mode hide-if-no-js" href="#css-mode"><?php echo esc_html_e( 'Edit', 'jetpack' ); ?></a>
1223
					<div id="css-mode-select" class="hide-if-js">
1224
						<input type="hidden" name="add_to_existing" id="add_to_existing" value="<?php echo $add_css ? 'true' : 'false'; ?>" />
1225
						<p>
1226
							<label>
1227
								<input type="radio" name="add_to_existing_display" value="true" <?php checked( $add_css ); ?>/>
1228
								<?php _e( 'Add-on CSS <b>(Recommended)</b>', 'jetpack' ); ?>
1229
							</label>
1230
							<br />
1231
							<label>
1232
								<input type="radio" name="add_to_existing_display" value="false" <?php checked( ! $add_css ); ?>/>
1233
								<?php printf(
1234
									__( 'Replace <a href="%s">theme\'s CSS</a> <b>(Advanced)</b>', 'jetpack' ),
1235
									/**
1236
									 * Filter the theme's stylesheet URL.
1237
									 *
1238
									 * @module custom-css
1239
									 *
1240
									 * @since 1.7.0
1241
									 *
1242
									 * @param string $url Active theme's stylesheet URL. Default to get_stylesheet_uri().
1243
									 */
1244
									apply_filters( 'safecss_theme_stylesheet_url', get_stylesheet_uri() )
1245
								); ?>
1246
							</label>
1247
						</p>
1248
						<a class="save-css-mode hide-if-no-js button" href="#css-mode"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
1249
						<a class="cancel-css-mode hide-if-no-js" href="#css-mode"><?php esc_html_e( 'Cancel', 'jetpack' ); ?></a>
1250
					</div>
1251
				</div>
1252
				<?php
1253
1254
				/**
1255
				 * Allows addition of elements to the submit box for custom css on the wp-admin side.
1256
				 *
1257
				 * @module custom-css
1258
				 *
1259
				 * @since 2.0.3
1260
				 */
1261
				do_action( 'custom_css_submitbox_misc_actions' );
1262
1263
				?>
1264
			</div>
1265
		</div>
1266
		<div id="major-publishing-actions">
1267
			<input type="button" class="button" id="preview" name="preview" value="<?php esc_attr_e( 'Preview', 'jetpack' ) ?>" />
1268
			<div id="publishing-action">
1269
				<input type="submit" class="button-primary" id="save" name="save" value="<?php ( Jetpack_Custom_CSS::is_freetrial() ) ? esc_attr_e( 'Save &amp; Buy Upgrade', 'jetpack' ) : esc_attr_e( 'Save Stylesheet', 'jetpack' ); ?>" />
1270
			</div>
1271
		</div>
1272
		<?php
1273
	}
1274
1275
	/**
1276
	 * Render metabox listing CSS revisions and the themes that correspond to the revisions.
1277
	 * Called by safecss_admin
1278
	 *
1279
	 * @global $post
1280
	 * @param array $safecss_post
1281
	 * @uses wp_revisions_to_keep
1282
	 * @uses WP_Query
1283
	 * @uses wp_post_revision_title
1284
	 * @uses esc_html
1285
	 * @uses add_query_arg
1286
	 * @uses menu_page_url
1287
	 * @uses wp_reset_query
1288
	 * @return string
1289
	 */
1290
	static function revisions_meta_box( $safecss_post ) {
1291
1292
		$show_all_revisions = isset( $_GET['show_all_rev'] );
1293
1294
		if ( function_exists( 'wp_revisions_to_keep' ) ) {
1295
			$max_revisions = wp_revisions_to_keep( (object) $safecss_post );
1296
		} else {
1297
			$max_revisions = defined( 'WP_POST_REVISIONS' ) && is_numeric( WP_POST_REVISIONS ) ? (int) WP_POST_REVISIONS : 25;
1298
		}
1299
1300
		$posts_per_page = $show_all_revisions ? $max_revisions : 6;
1301
1302
		$revisions = new WP_Query( array(
1303
			'posts_per_page' => $posts_per_page,
1304
			'post_type' => 'revision',
1305
			'post_status' => 'inherit',
1306
			'post_parent' => $safecss_post['ID'],
1307
			'orderby' => 'date',
1308
			'order' => 'DESC'
1309
		) );
1310
1311
		if ( $revisions->have_posts() ) { ?>
1312
			<ul class="post-revisions"><?php
1313
1314
			global $post;
1315
1316
			while ( $revisions->have_posts() ) :
1317
				$revisions->the_post();
1318
1319
				?><li>
1320
					<?php
1321
						echo wp_post_revision_title( $post );
1322
1323
						if ( ! empty( $post->post_excerpt ) )
1324
							echo ' (' . esc_html( $post->post_excerpt ) . ')';
1325
					?>
1326
				</li><?php
1327
1328
			endwhile;
1329
1330
			?></ul><?php
1331
1332
			if ( $revisions->found_posts > 6 && !$show_all_revisions ) {
1333
				?>
1334
				<br>
1335
				<a href="<?php echo add_query_arg( 'show_all_rev', 'true', menu_page_url( 'editcss', false ) ); ?>"><?php esc_html_e( 'Show all', 'jetpack' ); ?></a>
1336
				<?php
1337
			}
1338
		}
1339
1340
		wp_reset_query();
1341
	}
1342
1343
	/**
1344
	 * Hook in init at priority 11 to disable custom CSS.
1345
	 */
1346
	static function disable() {
1347
		remove_action( 'wp_head', array( 'Jetpack_Custom_CSS', 'link_tag' ), 101 );
1348
	    remove_filter( 'stylesheet_uri', array( 'Jetpack_Custom_CSS', 'style_filter' ) );
1349
	}
1350
1351
	/**
1352
	 * Reset all aspects of Custom CSS on a theme switch so that changing
1353
	 * themes is a sure-fire way to get a clean start.
1354
	 */
1355
	static function reset() {
1356
		$safecss_post_id = Jetpack_Custom_CSS::save_revision( '' );
1357
		$safecss_revision = Jetpack_Custom_CSS::get_current_revision();
1358
1359
		update_option( 'safecss_rev', (int) get_option( 'safecss_rev' ) + 1 );
1360
1361
		update_post_meta( $safecss_post_id, 'custom_css_add', 'yes' );
1362
		update_post_meta( $safecss_post_id, 'content_width', false );
1363
		update_post_meta( $safecss_post_id, 'custom_css_preprocessor', '' );
1364
1365
		delete_option( 'safecss_add' );
1366
		delete_option( 'safecss_content_width' );
1367
1368
		update_metadata( 'post', $safecss_revision['ID'], 'custom_css_add', 'yes' );
1369
		update_metadata( 'post', $safecss_revision['ID'], 'content_width', false );
1370
		update_metadata( 'post', $safecss_revision['ID'], 'custom_css_preprocessor', '' );
1371
1372
		delete_option( 'safecss_preview_add' );
1373
	}
1374
1375
	static function is_customizer_preview() {
1376
		if ( isset ( $GLOBALS['wp_customize'] ) )
1377
			return ! $GLOBALS['wp_customize']->is_theme_active();
1378
1379
		return false;
1380
	}
1381
1382
	static function minify( $css, $preprocessor = '' ) {
1383
		if ( ! $css )
1384
			return '';
1385
1386 View Code Duplication
		if ( $preprocessor ) {
1387
			/** This filter is documented in modules/custom-css/custom-css.php */
1388
			$preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
1389
1390
			if ( isset( $preprocessors[$preprocessor] ) ) {
1391
				$css = call_user_func( $preprocessors[$preprocessor]['callback'], $css );
1392
			}
1393
		}
1394
1395
		safecss_class();
1396
		$csstidy = new csstidy();
1397
		$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...
1398
1399
		$csstidy->set_cfg( 'remove_bslash',              false );
1400
		$csstidy->set_cfg( 'compress_colors',            true );
1401
		$csstidy->set_cfg( 'compress_font-weight',       true );
1402
		$csstidy->set_cfg( 'remove_last_;',              true );
1403
		$csstidy->set_cfg( 'case_properties',            true );
1404
		$csstidy->set_cfg( 'discard_invalid_properties', true );
1405
		$csstidy->set_cfg( 'css_level',                  'CSS3.0' );
1406
		$csstidy->set_cfg( 'template', 'highest');
1407
		$csstidy->parse( $css );
1408
1409
		return $csstidy->print->plain();
1410
	}
1411
1412
	/**
1413
	 * When restoring a SafeCSS post revision, also copy over the
1414
	 * content_width and custom_css_add post metadata.
1415
	 */
1416
	static function restore_revision( $_post_id, $_revision_id ) {
1417
		$_post = get_post( $_post_id );
1418
1419
		if ( 'safecss' != $_post->post_type )
1420
			return;
1421
1422
		$safecss_revision = Jetpack_Custom_CSS::get_current_revision();
1423
1424
		$content_width = get_post_meta( $_revision_id, 'content_width', true );
1425
		$custom_css_add = get_post_meta( $_revision_id, 'custom_css_add', true );
1426
		$preprocessor = get_post_meta( $_revision_id, 'custom_css_preprocessor', true );
1427
1428
		update_metadata( 'post', $safecss_revision['ID'], 'content_width', $content_width );
1429
		update_metadata( 'post', $safecss_revision['ID'], 'custom_css_add', $custom_css_add );
1430
		update_metadata( 'post', $safecss_revision['ID'], 'custom_css_preprocessor', $preprocessor );
1431
1432
		delete_option( 'safecss_add' );
1433
		delete_option( 'safecss_content_width' );
1434
1435
		update_post_meta( $_post->ID, 'content_width', $content_width );
1436
		update_post_meta( $_post->ID, 'custom_css_add', $custom_css_add );
1437
		update_post_meta( $_post->ID, 'custom_css_preprocessor', $preprocessor );
1438
1439
		delete_option( 'safecss_preview_add' );
1440
	}
1441
1442
	/**
1443
	 * Migration routine for moving safecss from wp_options to wp_posts to support revisions
1444
	 *
1445
	 * @return void
1446
	 */
1447
	static function upgrade() {
1448
		$css = get_option( 'safecss' );
1449
1450
		if ( get_option( 'safecss_revision_migrated' ) ) {
1451
			return false;
1452
		}
1453
1454
		// Check if CSS is stored in wp_options
1455
		if ( $css ) {
1456
			// Remove the async actions from publish_post
1457
			remove_action( 'publish_post', 'queue_publish_post' );
1458
1459
			$post = array();
1460
			$post['post_content'] = $css;
1461
			$post['post_title'] = 'safecss';
1462
			$post['post_status'] = 'publish';
1463
			$post['post_type'] = 'safecss';
1464
1465
			// Insert the CSS into wp_posts
1466
			$post_id = wp_insert_post( $post );
1467
			// Check for errors
1468
			if ( !$post_id or is_wp_error( $post_id ) )
1469
				die( $post_id->get_error_message() );
1470
1471
			// Delete safecss option
1472
			delete_option( 'safecss' );
1473
		}
1474
1475
		unset( $css );
1476
1477
		// Check if we have already done this
1478
		if ( !get_option( 'safecss_revision_migrated' ) ) {
1479
			define( 'DOING_MIGRATE', true );
1480
1481
			// Get hashes of safecss post and current revision
1482
			$safecss_post = Jetpack_Custom_CSS::get_post();
1483
1484
			if ( empty( $safecss_post ) )
1485
				return;
1486
1487
			$safecss_post_hash = md5( $safecss_post['post_content'] );
1488
			$current_revision = Jetpack_Custom_CSS::get_current_revision();
1489
1490
			if ( null == $current_revision )
1491
				return;
1492
1493
			$current_revision_hash = md5( $current_revision['post_content'] );
1494
1495
			// If hashes are not equal, set safecss post with content from current revision
1496
			if ( $safecss_post_hash !== $current_revision_hash ) {
1497
				Jetpack_Custom_CSS::save_revision( $current_revision['post_content'] );
1498
				// Reset post_content to display the migrated revsion
1499
				$safecss_post['post_content'] = $current_revision['post_content'];
1500
			}
1501
1502
			// Set option so that we dont keep doing this
1503
			update_option( 'safecss_revision_migrated', time() );
1504
		}
1505
1506
		$newest_safecss_post = Jetpack_Custom_CSS::get_current_revision();
1507
1508
		if ( $newest_safecss_post ) {
1509 View Code Duplication
			if ( get_option( 'safecss_content_width' ) ) {
1510
				// Add the meta to the post and the latest revision.
1511
				update_post_meta( $newest_safecss_post['ID'], 'content_width', get_option( 'safecss_content_width' ) );
1512
				update_metadata( 'post', $newest_safecss_post['ID'], 'content_width', get_option( 'safecss_content_width' ) );
1513
1514
				delete_option( 'safecss_content_width' );
1515
			}
1516
1517 View Code Duplication
			if ( get_option( 'safecss_add' ) ) {
1518
				update_post_meta( $newest_safecss_post['ID'], 'custom_css_add', get_option( 'safecss_add' ) );
1519
				update_metadata( 'post', $newest_safecss_post['ID'], 'custom_css_add', get_option( 'safecss_add' ) );
1520
1521
				delete_option( 'safecss_add' );
1522
			}
1523
		}
1524
	}
1525
1526
	/**
1527
	 * Adds a filter to the redirect location in `wp-admin/revisions.php`.
1528
	 */
1529
	static function add_revision_redirect() {
1530
		add_filter( 'wp_redirect', array( __CLASS__, 'revision_redirect' ) );
1531
	}
1532
1533
	/**
1534
	 * Filters the redirect location in `wp-admin/revisions.php`.
1535
	 *
1536
	 * @param string $location The path to redirect to.
1537
	 * @return string
1538
	 */
1539
	static function revision_redirect( $location ) {
1540
		$post = get_post();
1541
1542
		if ( ! empty( $post->post_type ) && 'safecss' == $post->post_type ) {
1543
			$location = 'themes.php?page=editcss';
1544
1545
			if ( 'edit.php' == $location ) {
1546
				$location = '';
1547
			}
1548
		}
1549
1550
		return $location;
1551
	}
1552
1553
	static function revision_post_link( $post_link, $post_id, $context ) {
1554
		if ( !$post_id = (int) $post_id ) {
1555
			return $post_link;
1556
		}
1557
1558
		if ( !$post = get_post( $post_id ) ) {
1559
			return $post_link;
1560
		}
1561
1562
		if ( 'safecss' != $post->post_type ) {
1563
			return $post_link;
1564
		}
1565
1566
		$post_link = admin_url( 'themes.php?page=editcss' );
1567
1568
		if ( 'display' == $context ) {
1569
			return esc_url( $post_link );
1570
		}
1571
1572
		return esc_url_raw( $post_link );
1573
	}
1574
1575
	/**
1576
	 * When on the edit screen, make sure the custom content width
1577
	 * setting is applied to the large image size.
1578
	 */
1579 View Code Duplication
	static function editor_max_image_size( $dims, $size = 'medium', $context = null ) {
1580
		list( $width, $height ) = $dims;
1581
1582
		if ( 'large' == $size && 'edit' == $context )
1583
			$width = Jetpack::get_content_width();
1584
1585
		return array( $width, $height );
1586
	}
1587
1588
	/**
1589
	 * Override the content_width with a custom value if one is set.
1590
	 */
1591
	static function jetpack_content_width( $content_width ) {
1592
		$custom_content_width = 0;
1593
1594
		if ( Jetpack_Custom_CSS::is_preview() ) {
1595
			$safecss_post = Jetpack_Custom_CSS::get_current_revision();
1596
			$custom_content_width = (int) get_post_meta( $safecss_post['ID'], 'content_width', true );
1597
		} else if ( ! Jetpack_Custom_CSS::is_freetrial() ) {
1598
			$custom_css_post_id = Jetpack_Custom_CSS::post_id();
1599
			if ( $custom_css_post_id )
1600
				$custom_content_width = (int) get_post_meta( $custom_css_post_id, 'content_width', true );
1601
		}
1602
1603
		if ( $custom_content_width > 0 )
1604
			$content_width = $custom_content_width;
1605
1606
		return $content_width;
1607
	}
1608
}
1609
1610
class Jetpack_Safe_CSS {
1611
	static function filter_attr( $css, $element = 'div' ) {
1612
		safecss_class();
1613
1614
		$css = $element . ' {' . $css . '}';
1615
1616
		$csstidy = new csstidy();
1617
		$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...
1618
		$csstidy->set_cfg( 'remove_bslash', false );
1619
		$csstidy->set_cfg( 'compress_colors', false );
1620
		$csstidy->set_cfg( 'compress_font-weight', false );
1621
		$csstidy->set_cfg( 'discard_invalid_properties', true );
1622
		$csstidy->set_cfg( 'merge_selectors', false );
1623
		$csstidy->set_cfg( 'remove_last_;', false );
1624
		$csstidy->set_cfg( 'css_level', 'CSS3.0' );
1625
1626
		$css = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $css );
1627
		$css = wp_kses_split( $css, array(), array() );
1628
		$csstidy->parse( $css );
1629
1630
		$css = $csstidy->print->plain();
1631
1632
		$css = str_replace( array( "\n","\r","\t" ), '', $css );
1633
1634
		preg_match( "/^{$element}\s*{(.*)}\s*$/", $css, $matches );
1635
1636
		if ( empty( $matches[1] ) )
1637
			return '';
1638
1639
		return $matches[1];
1640
	}
1641
}
1642
1643
function migrate() {
1644
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::upgrade()' );
1645
1646
	return Jetpack_Custom_CSS::upgrade();
1647
}
1648
1649
function safecss_revision_redirect( $redirect ) {
1650
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::revision_redirect()' );
1651
1652
	return Jetpack_Custom_CSS::revision_redirect( $redirect );
1653
}
1654
1655
function safecss_revision_post_link( $post_link, $post_id, $context ) {
1656
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::revision_post_link()' );
1657
1658
	return Jetpack_Custom_CSS::revision_post_link( $post_link, $post_id, $context );
1659
}
1660
1661
function get_safecss_post() {
1662
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::get_post()' );
1663
1664
	return Jetpack_Custom_CSS::get_post();
1665
}
1666
1667
function custom_css_post_id() {
1668
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::post_id()' );
1669
1670
	return Jetpack_Custom_CSS::post_id();
1671
}
1672
1673
function get_current_revision() {
1674
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::get_current_revision()' );
1675
1676
	return Jetpack_Custom_CSS::get_current_revision();
1677
}
1678
1679
function save_revision( $css, $is_preview = false, $preprocessor = '' ) {
1680
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::save_revision()' );
1681
1682
	return Jetpack_Custom_CSS::save_revision( $css, $is_preview, $preprocessor );
1683
}
1684
1685
function safecss_skip_stylesheet() {
1686
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::skip_stylesheet()' );
1687
1688
	return Jetpack_Custom_CSS::skip_stylesheet();
1689
}
1690
1691
function safecss_init() {
1692
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::init()' );
1693
1694
	return Jetpack_Custom_CSS::init();
1695
}
1696
1697
function safecss_is_preview() {
1698
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::is_preview()' );
1699
1700
	return Jetpack_Custom_CSS::is_preview();
1701
}
1702
1703
function safecss_is_freetrial() {
1704
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::is_freetrial()' );
1705
1706
	return Jetpack_Custom_CSS::is_freetrial();
1707
}
1708
1709
function safecss( $compressed = false ) {
1710
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::get_css()' );
1711
1712
	return Jetpack_Custom_CSS::get_css( $compressed );
1713
}
1714
1715
function safecss_print() {
1716
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::print_css()' );
1717
1718
	return Jetpack_Custom_CSS::print_css();
1719
}
1720
1721
function safecss_style() {
1722
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::link_tag()' );
1723
1724
	return Jetpack_Custom_CSS::link_tag();
1725
}
1726
1727
function safecss_style_filter( $current ) {
1728
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::style_filter()' );
1729
1730
	return Jetpack_Custom_CSS::style_filter( $current );
1731
}
1732
1733
function safecss_buffer( $html ) {
1734
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::buffer()' );
1735
1736
	return Jetpack_Custom_CSS::buffer( $html );
1737
}
1738
1739
function safecss_preview_links( $matches ) {
1740
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::preview_links()' );
1741
1742
	return Jetpack_Custom_CSS::preview_links( $matches );
1743
}
1744
1745
function safecss_preview_flag() {
1746
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::preview_flag()' );
1747
1748
	return Jetpack_Custom_CSS::preview_flag();
1749
}
1750
1751
function safecss_menu() {
1752
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::menu()' );
1753
1754
	return Jetpack_Custom_CSS::menu();
1755
}
1756
1757
function update_title() {
1758
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::update_title()' );
1759
1760
	return Jetpack_Custom_CSS::update_title();
1761
}
1762
1763
function safecss_prettify_post_revisions() {
1764
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::prettify_post_revisions()' );
1765
1766
	return Jetpack_Custom_CSS::prettify_post_revisions();
1767
}
1768
1769
function safecss_remove_title_excerpt_from_revisions() {
1770
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::remove_title_excerpt_from_revisions()' );
1771
1772
	return Jetpack_Custom_CSS::remove_title_excerpt_from_revisions();
0 ignored issues
show
Bug introduced by
The method remove_title_excerpt_from_revisions() does not seem to exist on object<Jetpack_Custom_CSS>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1773
}
1774
1775
function safecss_post_title( $title, $post_id ) {
1776
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::post_title()' );
1777
1778
	return Jetpack_Custom_CSS::post_title( $title, $post_id );
1779
}
1780
1781
function safe_css_enqueue_scripts() {
1782
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::enqueue_scripts()' );
1783
1784
	return Jetpack_Custom_CSS::enqueue_scripts( null );
1785
}
1786
1787
function safecss_admin_head() {
1788
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::admin_head()' );
1789
1790
	return Jetpack_Custom_CSS::admin_head();
0 ignored issues
show
Bug introduced by
The method admin_head() does not seem to exist on object<Jetpack_Custom_CSS>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1791
}
1792
1793
function safecss_saved() {
1794
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::saved_message()' );
1795
1796
	return Jetpack_Custom_CSS::saved_message();
1797
}
1798
1799
function safecss_admin() {
1800
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::admin()' );
1801
1802
	return Jetpack_Custom_CSS::admin();
1803
}
1804
1805
function custom_css_meta_box() {
1806
	_deprecated_function( __FUNCTION__, '2.1', 'add_meta_box( $id, $title, $callback, \'editcss\', \'side\' )' );
1807
}
1808
1809
function custom_css_post_revisions_meta_box( $safecss_post ) {
1810
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::revisions_meta_box()' );
1811
1812
	return Jetpack_Custom_CSS::revisions_meta_box( $safecss_post );
1813
}
1814
1815
function disable_safecss_style() {
1816
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::disable()' );
1817
1818
	return Jetpack_Custom_CSS::disable();
1819
}
1820
1821
function custom_css_reset() {
1822
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::reset()' );
1823
1824
	return Jetpack_Custom_CSS::reset();
1825
}
1826
1827
function custom_css_is_customizer_preview() {
1828
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::is_customizer_preview()' );
1829
1830
	return Jetpack_Custom_CSS::is_customizer_preview();
1831
}
1832
1833
function custom_css_minify( $css, $preprocessor = '' ) {
1834
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::minify()' );
1835
1836
	return Jetpack_Custom_CSS::minify( $css, $preprocessor );
1837
}
1838
1839
function custom_css_restore_revision( $_post_id, $_revision_id ) {
1840
	_deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::restore_revision()' );
1841
1842
	return Jetpack_Custom_CSS::restore_revision( $_post_id, $_revision_id );
1843
}
1844
1845 View Code Duplication
if ( ! function_exists( 'safecss_class' ) ) :
1846
function safecss_class() {
0 ignored issues
show
Best Practice introduced by
The function safecss_class() has been defined more than once; this definition is ignored, only the first definition in projects/plugins/jetpack...-css/custom-css-4.7.php (L1137-1172) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
1847
	// Wrapped so we don't need the parent class just to load the plugin
1848
	if ( class_exists('safecss') )
1849
		return;
1850
1851
	require_once( dirname( __FILE__ ) . '/csstidy/class.csstidy.php' );
1852
1853
	class safecss extends csstidy_optimise {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type safecss has been defined more than once; this definition is ignored, only the first definition in projects/plugins/jetpack...-css/custom-css-4.7.php (L1148-1171) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
1854
1855
		function postparse() {
1856
1857
			/**
1858
			 * Fires after parsing the css.
1859
			 *
1860
			 * @module custom-css
1861
			 *
1862
			 * @since 1.8.0
1863
			 *
1864
			 * @param obj $this CSSTidy object.
1865
			 */
1866
			do_action( 'csstidy_optimize_postparse', $this );
1867
1868
			return parent::postparse();
1869
		}
1870
1871
		function subvalue() {
1872
1873
			/**
1874
			 * Fires before optimizing the Custom CSS subvalue.
1875
			 *
1876
			 * @module custom-css
1877
			 *
1878
			 * @since 1.8.0
1879
			 *
1880
			 * @param obj $this CSSTidy object.
1881
			 **/
1882
			do_action( 'csstidy_optimize_subvalue', $this );
1883
1884
			return parent::subvalue();
1885
		}
1886
	}
1887
}
1888
endif;
1889
1890
if ( ! function_exists( 'safecss_filter_attr' ) ) {
1891
	function safecss_filter_attr( $css, $element = 'div' ) {
1892
		return Jetpack_Safe_CSS::filter_attr( $css, $element );
1893
	}
1894
}
1895
1896
include_once dirname( __FILE__ ) . '/custom-css/preprocessors.php';
1897