Completed
Push — fix/related-posts-for-fse ( 3831fb...7b801c )
by Jeremy
173:05 queued 163:56
created

Jetpack_WPCOM_Block_Editor::maybe_send_cookies()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 1
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
1
<?php
2
/**
3
 * WordPress.com Block Editor
4
 * Allow new block editor posts to be composed on WordPress.com.
5
 * This is auto-loaded as of Jetpack v7.4 for sites connected to WordPress.com only.
6
 *
7
 * @package automattic/jetpack
8
 */
9
10
use Automattic\Jetpack\Connection\Tokens;
11
/**
12
 * WordPress.com Block editor for Jetpack
13
 */
14
class Jetpack_WPCOM_Block_Editor {
15
	/**
16
	 * ID of the user who signed the nonce.
17
	 *
18
	 * @var int
19
	 */
20
	private $nonce_user_id;
21
22
	/**
23
	 * An array to store auth cookies until we can determine if they should be sent
24
	 *
25
	 * @var array
26
	 */
27
	private $set_cookie_args;
28
29
	/**
30
	 * Singleton
31
	 */
32
	public static function init() {
33
		static $instance = false;
34
35
		if ( ! $instance ) {
36
			$instance = new Jetpack_WPCOM_Block_Editor();
37
		}
38
39
		return $instance;
40
	}
41
42
	/**
43
	 * Jetpack_WPCOM_Block_Editor constructor.
44
	 */
45
	private function __construct() {
46
		$this->set_cookie_args = array();
47
		add_action( 'init', array( $this, 'init_actions' ) );
48
	}
49
50
	/**
51
	 * Add in all hooks.
52
	 */
53
	public function init_actions() {
54
		// Bail early if Jetpack's block editor extensions are disabled on the site.
55
		/* This filter is documented in class.jetpack-gutenberg.php */
56
		if ( ! apply_filters( 'jetpack_gutenberg', true ) ) {
57
			return;
58
		}
59
60
		if ( $this->is_iframed_block_editor() ) {
61
			add_action( 'admin_init', array( $this, 'disable_send_frame_options_header' ), 9 );
62
			add_filter( 'admin_body_class', array( $this, 'add_iframed_body_class' ) );
63
		}
64
65
		require_once __DIR__ . '/functions.editor-type.php';
66
		add_action( 'edit_form_top', 'Jetpack\EditorType\remember_classic_editor' );
67
		add_filter( 'block_editor_settings', 'Jetpack\EditorType\remember_block_editor', 10, 2 );
68
		add_action( 'login_init', array( $this, 'allow_block_editor_login' ), 1 );
69
		add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ), 9 );
70
		add_action( 'enqueue_block_assets', array( $this, 'enqueue_block_assets' ) );
71
		add_filter( 'mce_external_plugins', array( $this, 'add_tinymce_plugins' ) );
72
73
		$this->enable_cross_site_auth_cookies();
74
	}
75
76
	/**
77
	 * Checks if we are embedding the block editor in an iframe in WordPress.com.
78
	 *
79
	 * @return bool Whether the current request is from the iframed block editor.
80
	 */
81
	public function is_iframed_block_editor() {
82
		global $pagenow;
83
84
		// phpcs:ignore WordPress.Security.NonceVerification
85
		return ( 'post.php' === $pagenow || 'post-new.php' === $pagenow ) && ! empty( $_GET['frame-nonce'] );
86
	}
87
88
	/**
89
	 * Prevents frame options header from firing if this is a allowed iframe request.
90
	 */
91
	public function disable_send_frame_options_header() {
92
		// phpcs:ignore WordPress.Security.NonceVerification
93
		if ( $this->framing_allowed( $_GET['frame-nonce'] ) ) {
94
			remove_action( 'admin_init', 'send_frame_options_header' );
95
		}
96
	}
97
98
	/**
99
	 * Adds custom admin body class if this is a allowed iframe request.
100
	 *
101
	 * @param string $classes Admin body classes.
102
	 * @return string
103
	 */
104
	public function add_iframed_body_class( $classes ) {
105
		// phpcs:ignore WordPress.Security.NonceVerification
106
		if ( $this->framing_allowed( $_GET['frame-nonce'] ) ) {
107
			$classes .= ' is-iframed ';
108
		}
109
110
		return $classes;
111
	}
112
113
	/**
114
	 * Checks to see if cookie can be set in current context. If 3rd party cookie blocking
115
	 * is enabled the editor can't load in iFrame, so emiting X-Frame-Options: DENY will
116
	 * force the editor to break out of the iFrame.
117
	 */
118
	private function check_iframe_cookie_setting() {
119
		if ( ! isset( $_SERVER['QUERY_STRING'] ) || ! strpos( $_SERVER['QUERY_STRING'], 'calypsoify%3D1%26block-editor' ) || isset( $_COOKIE['wordpress_test_cookie'] ) ) {
120
			return;
121
		}
122
123
		if ( empty( $_GET['calypsoify_cookie_check'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
124
			header( 'Location: ' . esc_url_raw( $_SERVER['REQUEST_URI'] . '&calypsoify_cookie_check=true' ) );
125
			exit;
126
		}
127
128
		header( 'X-Frame-Options: DENY' );
129
		exit;
130
	}
131
132
	/**
133
	 * Allows to iframe the login page if a user is logged out
134
	 * while trying to access the block editor from wordpress.com.
135
	 */
136
	public function allow_block_editor_login() {
137
		// phpcs:ignore WordPress.Security.NonceVerification
138
		if ( empty( $_REQUEST['redirect_to'] ) ) {
139
			return;
140
		}
141
142
		$this->check_iframe_cookie_setting();
143
144
		// phpcs:ignore WordPress.Security.NonceVerification
145
		$query = wp_parse_url( urldecode( $_REQUEST['redirect_to'] ), PHP_URL_QUERY );
146
		$args  = wp_parse_args( $query );
147
148
		// Check nonce and make sure this is a Gutenframe request.
149
		if ( ! empty( $args['frame-nonce'] ) && $this->framing_allowed( $args['frame-nonce'] ) ) {
150
151
			// If SSO is active, we'll let WordPress.com handle authentication...
152
			if ( Jetpack::is_module_active( 'sso' ) ) {
153
				// ...but only if it's not an Atomic site. They already do that.
154
				if ( ! jetpack_is_atomic_site() ) {
155
					add_filter( 'jetpack_sso_bypass_login_forward_wpcom', '__return_true' );
156
				}
157
			} else {
158
				$_REQUEST['interim-login'] = true;
159
				add_action( 'wp_login', array( $this, 'do_redirect' ) );
160
				add_action( 'login_form', array( $this, 'add_login_html' ) );
161
				add_filter( 'wp_login_errors', array( $this, 'add_login_message' ) );
162
				remove_action( 'login_init', 'send_frame_options_header' );
163
				wp_add_inline_style( 'login', '.interim-login #login{padding-top:8%}' );
164
			}
165
		}
166
	}
167
168
	/**
169
	 * Adds a login message.
170
	 *
171
	 * Intended to soften the expectation mismatch of ending up with a login screen rather than the editor.
172
	 *
173
	 * @param WP_Error $errors WP Error object.
174
	 * @return \WP_Error
175
	 */
176
	public function add_login_message( $errors ) {
177
		$errors->remove( 'expired' );
0 ignored issues
show
Bug introduced by
The method remove() does not seem to exist on object<WP_Error>.

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...
178
		$errors->add( 'info', __( 'Before we continue, please log in to your Jetpack site.', 'jetpack' ), 'message' );
0 ignored issues
show
Bug introduced by
The method add() does not seem to exist on object<WP_Error>.

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...
179
180
		return $errors;
181
	}
182
183
	/**
184
	 * Maintains the `redirect_to` parameter in login form links.
185
	 * Adds visual feedback of login in progress.
186
	 */
187
	public function add_login_html() {
188
		?>
189
		<input type="hidden" name="redirect_to" value="<?php echo esc_url( $_REQUEST['redirect_to'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended ?>" />
190
		<script type="application/javascript">
191
			document.getElementById( 'loginform' ).addEventListener( 'submit' , function() {
192
				document.getElementById( 'wp-submit' ).setAttribute( 'disabled', 'disabled' );
193
				document.getElementById( 'wp-submit' ).value = '<?php echo esc_js( __( 'Logging In...', 'jetpack' ) ); ?>';
194
			} );
195
		</script>
196
		<?php
197
	}
198
199
	/**
200
	 * Does the redirect to the block editor.
201
	 */
202
	public function do_redirect() {
203
		wp_safe_redirect( $GLOBALS['redirect_to'] );
204
		exit;
205
	}
206
207
	/**
208
	 * Checks whether this is an allowed iframe request.
209
	 *
210
	 * @param string $nonce Nonce to verify.
211
	 * @return bool
212
	 */
213
	public function framing_allowed( $nonce ) {
214
		$verified = $this->verify_frame_nonce( $nonce, 'frame-' . Jetpack_Options::get_option( 'id' ) );
215
216
		if ( is_wp_error( $verified ) ) {
217
			wp_die( $verified ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
218
		}
219
220
		if ( $verified && ! defined( 'IFRAME_REQUEST' ) ) {
221
			define( 'IFRAME_REQUEST', true );
222
		}
223
224
		return (bool) $verified;
225
	}
226
227
	/**
228
	 * Verify that correct nonce was used with time limit.
229
	 *
230
	 * The user is given an amount of time to use the token, so therefore, since the
231
	 * UID and $action remain the same, the independent variable is the time.
232
	 *
233
	 * @param string $nonce Nonce that was used in the form to verify.
234
	 * @param string $action Should give context to what is taking place and be the same when nonce was created.
235
	 * @return boolean|WP_Error Whether the nonce is valid.
236
	 */
237
	public function verify_frame_nonce( $nonce, $action ) {
238
		if ( empty( $nonce ) ) {
239
			return false;
240
		}
241
242
		list( $expiration, $user_id, $hash ) = explode( ':', $nonce, 3 );
243
244
		$this->nonce_user_id = (int) $user_id;
245
		if ( ! $this->nonce_user_id ) {
246
			return false;
247
		}
248
249
		$token = ( new Tokens() )->get_access_token( $this->nonce_user_id );
250
		if ( ! $token ) {
251
			return false;
252
		}
253
254
		/*
255
		 * Failures must return `false` (blocking the iframe) prior to the
256
		 * signature verification.
257
		 */
258
259
		add_filter( 'salt', array( $this, 'filter_salt' ), 10, 2 );
260
		$expected_hash = wp_hash( "$expiration|$action|{$this->nonce_user_id}", 'jetpack_frame_nonce' );
261
		remove_filter( 'salt', array( $this, 'filter_salt' ) );
262
263
		if ( ! hash_equals( $hash, $expected_hash ) ) {
264
			return false;
265
		}
266
267
		/*
268
		 * Failures may return `WP_Error` (showing an error in the iframe) after the
269
		 * signature verification passes.
270
		 */
271
272
		if ( time() > $expiration ) {
273
			return new WP_Error( 'nonce_invalid_expired', 'Expired nonce.', array( 'status' => 401 ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'nonce_invalid_expired'.

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...
274
		}
275
276
		// Check if it matches the current user, unless they're trying to log in.
277
		if ( get_current_user_id() !== $this->nonce_user_id && ! doing_action( 'login_init' ) ) {
278
			return new WP_Error( 'nonce_invalid_user_mismatch', 'User ID mismatch.', array( 'status' => 401 ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'nonce_invalid_user_mismatch'.

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...
279
		}
280
281
		return true;
282
	}
283
284
	/**
285
	 * Filters the WordPress salt.
286
	 *
287
	 * @param string $salt Salt for the given scheme.
288
	 * @param string $scheme Authentication scheme.
289
	 * @return string
290
	 */
291 View Code Duplication
	public function filter_salt( $salt, $scheme ) {
292
		if ( 'jetpack_frame_nonce' === $scheme ) {
293
			$token = ( new Tokens() )->get_access_token( $this->nonce_user_id );
294
295
			if ( $token ) {
296
				$salt = $token->secret;
297
			}
298
		}
299
300
		return $salt;
301
	}
302
303
	/**
304
	 * Enqueues the WordPress.com block editor integration assets for the editor.
305
	 */
306
	public function enqueue_block_editor_assets() {
307
		$debug   = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG;
308
		$version = gmdate( 'Ymd' );
309
310
		wp_enqueue_script(
311
			'wpcom-block-editor-default-editor-script',
312
			$debug
313
				? '//widgets.wp.com/wpcom-block-editor/default.editor.js?minify=false'
314
				: '//widgets.wp.com/wpcom-block-editor/default.editor.min.js',
315
			array(
316
				'jquery',
317
				'lodash',
318
				'wp-annotations',
319
				'wp-compose',
320
				'wp-data',
321
				'wp-editor',
322
				'wp-element',
323
				'wp-rich-text',
324
			),
325
			$version,
326
			true
327
		);
328
329
		wp_localize_script(
330
			'wpcom-block-editor-default-editor-script',
331
			'wpcomGutenberg',
332
			array(
333
				'richTextToolbar' => array(
334
					'justify'   => __( 'Justify', 'jetpack' ),
335
					'underline' => __( 'Underline', 'jetpack' ),
336
				),
337
			)
338
		);
339
340
		if ( jetpack_is_atomic_site() ) {
341
			wp_enqueue_script(
342
				'wpcom-block-editor-wpcom-editor-script',
343
				$debug
344
					? '//widgets.wp.com/wpcom-block-editor/wpcom.editor.js?minify=false'
345
					: '//widgets.wp.com/wpcom-block-editor/wpcom.editor.min.js',
346
				array(
347
					'lodash',
348
					'wp-blocks',
349
					'wp-data',
350
					'wp-dom-ready',
351
					'wp-plugins',
352
				),
353
				$version,
354
				true
355
			);
356
		}
357
358
		if ( $this->is_iframed_block_editor() ) {
359
			wp_enqueue_script(
360
				'wpcom-block-editor-calypso-editor-script',
361
				$debug
362
					? '//widgets.wp.com/wpcom-block-editor/calypso.editor.js?minify=false'
363
					: '//widgets.wp.com/wpcom-block-editor/calypso.editor.min.js',
364
				array(
365
					'calypsoify_wpadminmods_js',
366
					'jquery',
367
					'lodash',
368
					'react',
369
					'wp-blocks',
370
					'wp-data',
371
					'wp-hooks',
372
					'wp-tinymce',
373
					'wp-url',
374
				),
375
				$version,
376
				true
377
			);
378
379
			wp_enqueue_style(
380
				'wpcom-block-editor-calypso-editor-styles',
381
				$debug
382
					? '//widgets.wp.com/wpcom-block-editor/calypso.editor.css?minify=false'
383
					: '//widgets.wp.com/wpcom-block-editor/calypso.editor.min.css',
384
				array(),
385
				$version
386
			);
387
		}
388
	}
389
390
	/**
391
	 * Enqueues the WordPress.com block editor integration assets for both editor and front-end.
392
	 */
393
	public function enqueue_block_assets() {
394
		// These styles are manually copied from //widgets.wp.com/wpcom-block-editor/default.view.css in order to
395
		// improve the performance by avoiding an extra network request to download the CSS file on every page.
396
		wp_add_inline_style( 'wp-block-library', '.has-text-align-justify{text-align:justify;}' );
397
	}
398
399
	/**
400
	 * Determines if the current $post contains a justified paragraph block.
401
	 *
402
	 * @return boolean true if justified paragraph is found, false otherwise.
403
	 */
404
	public function has_justified_block() {
405
		global $post;
406
		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...
407
			return false;
408
		};
409
410
		if ( ! has_blocks( $post ) ) {
411
			return false;
412
		}
413
414
		return false !== strpos( $post->post_content, '<!-- wp:paragraph {"align":"justify"' );
415
	}
416
417
	/**
418
	 * Register the Tiny MCE plugins for the WordPress.com block editor integration.
419
	 *
420
	 * @param array $plugin_array An array of external Tiny MCE plugins.
421
	 * @return array External TinyMCE plugins.
422
	 */
423
	public function add_tinymce_plugins( $plugin_array ) {
424
		if ( $this->is_iframed_block_editor() ) {
425
			$debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG;
426
427
			$plugin_array['gutenberg-wpcom-iframe-media-modal'] = add_query_arg(
428
				'v',
429
				gmdate( 'YW' ),
430
				$debug
431
					? '//widgets.wp.com/wpcom-block-editor/calypso.tinymce.js?minify=false'
432
					: '//widgets.wp.com/wpcom-block-editor/calypso.tinymce.min.js'
433
			);
434
		}
435
436
		return $plugin_array;
437
	}
438
439
	/**
440
	 * Ensures the authentication cookies are designated for cross-site access.
441
	 */
442
	private function enable_cross_site_auth_cookies() {
443
		/**
444
		 * Allow plugins to disable the cross-site auth cookies.
445
		 *
446
		 * @since 8.1.1
447
		 *
448
		 * @param false bool Whether auth cookies should be disabled for cross-site access. False by default.
449
		 */
450
		if ( apply_filters( 'jetpack_disable_cross_site_auth_cookies', false ) ) {
451
			return;
452
		}
453
454
		add_action( 'set_auth_cookie', array( $this, 'set_samesite_auth_cookies' ), 10, 5 );
455
		add_action( 'set_logged_in_cookie', array( $this, 'set_samesite_logged_in_cookies' ), 10, 4 );
456
		add_filter( 'send_auth_cookies', array( $this, 'maybe_send_cookies' ), 9999 );
457
	}
458
459
	/**
460
	 * Checks if we've stored any cookies to send and then sends them
461
	 * if the send_auth_cookies value is true.
462
	 *
463
	 * @param bool $send_cookies The filtered value that determines whether to send auth cookies.
464
	 */
465
	public function maybe_send_cookies( $send_cookies ) {
466
467
		if ( ! empty( $this->set_cookie_args ) && $send_cookies ) {
468
			array_map(
469
				function ( $cookie ) {
470
					call_user_func_array( 'jetpack_shim_setcookie', $cookie );
471
				},
472
				$this->set_cookie_args
473
			);
474
			$this->set_cookie_args = array();
475
			return false;
476
		}
477
478
		return $send_cookies;
479
	}
480
481
	/**
482
	 * Gets the SameSite attribute to use in auth cookies.
483
	 *
484
	 * @param  bool $secure Whether the connection is secure.
485
	 * @return string SameSite attribute to use on auth cookies.
486
	 */
487
	public function get_samesite_attr_for_auth_cookies( $secure ) {
488
		$samesite = $secure ? 'None' : 'Lax';
489
		/**
490
		 * Filters the SameSite attribute to use in auth cookies.
491
		 *
492
		 * @param string $samesite SameSite attribute to use in auth cookies.
493
		 *
494
		 * @since 8.1.1
495
		 */
496
		$samesite = apply_filters( 'jetpack_auth_cookie_samesite', $samesite );
497
498
		return $samesite;
499
	}
500
501
	/**
502
	 * Generates cross-site auth cookies so they can be accessed by WordPress.com.
503
	 *
504
	 * @param string $auth_cookie Authentication cookie value.
505
	 * @param int    $expire      The time the login grace period expires as a UNIX timestamp.
506
	 *                            Default is 12 hours past the cookie's expiration time.
507
	 * @param int    $expiration  The time when the authentication cookie expires as a UNIX timestamp.
508
	 *                            Default is 14 days from now.
509
	 * @param int    $user_id     User ID.
510
	 * @param string $scheme      Authentication scheme. Values include 'auth' or 'secure_auth'.
511
	 */
512
	public function set_samesite_auth_cookies( $auth_cookie, $expire, $expiration, $user_id, $scheme ) {
513
		if ( wp_startswith( $scheme, 'secure_' ) ) {
514
			$secure           = true;
515
			$auth_cookie_name = SECURE_AUTH_COOKIE;
516
		} else {
517
			$secure           = false;
518
			$auth_cookie_name = AUTH_COOKIE;
519
		}
520
		$samesite = $this->get_samesite_attr_for_auth_cookies( $secure );
521
522
		$this->set_cookie_args[] = array(
523
			$auth_cookie_name,
524
			$auth_cookie,
525
			array(
526
				'expires'  => $expire,
527
				'path'     => PLUGINS_COOKIE_PATH,
528
				'domain'   => COOKIE_DOMAIN,
529
				'secure'   => $secure,
530
				'httponly' => true,
531
				'samesite' => $samesite,
532
			),
533
		);
534
535
		$this->set_cookie_args[] = array(
536
			$auth_cookie_name,
537
			$auth_cookie,
538
			array(
539
				'expires'  => $expire,
540
				'path'     => ADMIN_COOKIE_PATH,
541
				'domain'   => COOKIE_DOMAIN,
542
				'secure'   => $secure,
543
				'httponly' => true,
544
				'samesite' => $samesite,
545
			),
546
		);
547
	}
548
549
	/**
550
	 * Generates cross-site logged in cookies so they can be accessed by WordPress.com.
551
	 *
552
	 * @param string $logged_in_cookie The logged-in cookie value.
553
	 * @param int    $expire           The time the login grace period expires as a UNIX timestamp.
554
	 *                                 Default is 12 hours past the cookie's expiration time.
555
	 * @param int    $expiration       The time when the logged-in cookie expires as a UNIX timestamp.
556
	 *                                 Default is 14 days from now.
557
	 * @param int    $user_id          User ID.
558
	 */
559
	public function set_samesite_logged_in_cookies( $logged_in_cookie, $expire, $expiration, $user_id ) {
560
		$secure = is_ssl();
561
562
		// Front-end cookie is secure when the auth cookie is secure and the site's home URL is forced HTTPS.
563
		$secure_logged_in_cookie = $secure && 'https' === wp_parse_url( get_option( 'home' ), PHP_URL_SCHEME );
564
565
		/** This filter is documented in core/src/wp-includes/pluggable.php */
566
		$secure = apply_filters( 'secure_auth_cookie', $secure, $user_id );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $user_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...
567
568
		/** This filter is documented in core/src/wp-includes/pluggable.php */
569
		$secure_logged_in_cookie = apply_filters( 'secure_logged_in_cookie', $secure_logged_in_cookie, $user_id, $secure );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $user_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...
570
571
		$samesite = $this->get_samesite_attr_for_auth_cookies( $secure_logged_in_cookie );
572
573
		$this->set_cookie_args[] = array(
574
			LOGGED_IN_COOKIE,
575
			$logged_in_cookie,
576
			array(
577
				'expires'  => $expire,
578
				'path'     => COOKIEPATH,
579
				'domain'   => COOKIE_DOMAIN,
580
				'secure'   => $secure_logged_in_cookie,
581
				'httponly' => true,
582
				'samesite' => $samesite,
583
			),
584
		);
585
586
		if ( COOKIEPATH !== SITECOOKIEPATH ) {
587
			$this->set_cookie_args[] = array(
588
				LOGGED_IN_COOKIE,
589
				$logged_in_cookie,
590
				array(
591
					'expires'  => $expire,
592
					'path'     => SITECOOKIEPATH,
593
					'domain'   => COOKIE_DOMAIN,
594
					'secure'   => $secure_logged_in_cookie,
595
					'httponly' => true,
596
					'samesite' => $samesite,
597
				),
598
			);
599
		}
600
	}
601
}
602
603
Jetpack_WPCOM_Block_Editor::init();
604