wp/wp-admin/includes/misc.php
changeset 9 177826044cd9
parent 7 cf61fcea0001
child 16 a86126ab1dd4
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
    12  * @since 2.0.0
    12  * @since 2.0.0
    13  *
    13  *
    14  * @return bool
    14  * @return bool
    15  */
    15  */
    16 function got_mod_rewrite() {
    16 function got_mod_rewrite() {
    17 	$got_rewrite = apache_mod_loaded('mod_rewrite', true);
    17 	$got_rewrite = apache_mod_loaded( 'mod_rewrite', true );
    18 
    18 
    19 	/**
    19 	/**
    20 	 * Filters whether Apache and mod_rewrite are present.
    20 	 * Filters whether Apache and mod_rewrite are present.
    21 	 *
    21 	 *
    22 	 * This filter was previously used to force URL rewriting for other servers,
    22 	 * This filter was previously used to force URL rewriting for other servers,
    63  * @param string $filename
    63  * @param string $filename
    64  * @param string $marker
    64  * @param string $marker
    65  * @return array An array of strings from a file (.htaccess ) from between BEGIN and END markers.
    65  * @return array An array of strings from a file (.htaccess ) from between BEGIN and END markers.
    66  */
    66  */
    67 function extract_from_markers( $filename, $marker ) {
    67 function extract_from_markers( $filename, $marker ) {
    68 	$result = array ();
    68 	$result = array();
    69 
    69 
    70 	if ( ! file_exists( $filename ) ) {
    70 	if ( ! file_exists( $filename ) ) {
    71 		return $result;
    71 		return $result;
    72 	}
    72 	}
    73 
    73 
   134 	while ( ! feof( $fp ) ) {
   134 	while ( ! feof( $fp ) ) {
   135 		$lines[] = rtrim( fgets( $fp ), "\r\n" );
   135 		$lines[] = rtrim( fgets( $fp ), "\r\n" );
   136 	}
   136 	}
   137 
   137 
   138 	// Split out the existing file into the preceding lines, and those that appear after the marker
   138 	// Split out the existing file into the preceding lines, and those that appear after the marker
   139 	$pre_lines = $post_lines = $existing_lines = array();
   139 	$pre_lines    = $post_lines = $existing_lines = array();
   140 	$found_marker = $found_end_marker = false;
   140 	$found_marker = $found_end_marker = false;
   141 	foreach ( $lines as $line ) {
   141 	foreach ( $lines as $line ) {
   142 		if ( ! $found_marker && false !== strpos( $line, $start_marker ) ) {
   142 		if ( ! $found_marker && false !== strpos( $line, $start_marker ) ) {
   143 			$found_marker = true;
   143 			$found_marker = true;
   144 			continue;
   144 			continue;
   162 
   162 
   163 		return true;
   163 		return true;
   164 	}
   164 	}
   165 
   165 
   166 	// Generate the new file data
   166 	// Generate the new file data
   167 	$new_file_data = implode( "\n", array_merge(
   167 	$new_file_data = implode(
   168 		$pre_lines,
   168 		"\n",
   169 		array( $start_marker ),
   169 		array_merge(
   170 		$insertion,
   170 			$pre_lines,
   171 		array( $end_marker ),
   171 			array( $start_marker ),
   172 		$post_lines
   172 			$insertion,
   173 	) );
   173 			array( $end_marker ),
       
   174 			$post_lines
       
   175 		)
       
   176 	);
   174 
   177 
   175 	// Write to the start of the file, and truncate it to that length
   178 	// Write to the start of the file, and truncate it to that length
   176 	fseek( $fp, 0 );
   179 	fseek( $fp, 0 );
   177 	$bytes = fwrite( $fp, $new_file_data );
   180 	$bytes = fwrite( $fp, $new_file_data );
   178 	if ( $bytes ) {
   181 	if ( $bytes ) {
   196  * @global WP_Rewrite $wp_rewrite
   199  * @global WP_Rewrite $wp_rewrite
   197  *
   200  *
   198  * @return bool|null True on write success, false on failure. Null in multisite.
   201  * @return bool|null True on write success, false on failure. Null in multisite.
   199  */
   202  */
   200 function save_mod_rewrite_rules() {
   203 function save_mod_rewrite_rules() {
   201 	if ( is_multisite() )
   204 	if ( is_multisite() ) {
   202 		return;
   205 		return;
       
   206 	}
   203 
   207 
   204 	global $wp_rewrite;
   208 	global $wp_rewrite;
   205 
   209 
   206 	// Ensure get_home_path() is declared.
   210 	// Ensure get_home_path() is declared.
   207 	require_once( ABSPATH . 'wp-admin/includes/file.php' );
   211 	require_once( ABSPATH . 'wp-admin/includes/file.php' );
   211 
   215 
   212 	/*
   216 	/*
   213 	 * If the file doesn't already exist check for write access to the directory
   217 	 * If the file doesn't already exist check for write access to the directory
   214 	 * and whether we have some rules. Else check for write access to the file.
   218 	 * and whether we have some rules. Else check for write access to the file.
   215 	 */
   219 	 */
   216 	if ((!file_exists($htaccess_file) && is_writable($home_path) && $wp_rewrite->using_mod_rewrite_permalinks()) || is_writable($htaccess_file)) {
   220 	if ( ( ! file_exists( $htaccess_file ) && is_writable( $home_path ) && $wp_rewrite->using_mod_rewrite_permalinks() ) || is_writable( $htaccess_file ) ) {
   217 		if ( got_mod_rewrite() ) {
   221 		if ( got_mod_rewrite() ) {
   218 			$rules = explode( "\n", $wp_rewrite->mod_rewrite_rules() );
   222 			$rules = explode( "\n", $wp_rewrite->mod_rewrite_rules() );
   219 			return insert_with_markers( $htaccess_file, 'WordPress', $rules );
   223 			return insert_with_markers( $htaccess_file, 'WordPress', $rules );
   220 		}
   224 		}
   221 	}
   225 	}
   231  *
   235  *
   232  * @global WP_Rewrite $wp_rewrite
   236  * @global WP_Rewrite $wp_rewrite
   233  *
   237  *
   234  * @return bool|null True on write success, false on failure. Null in multisite.
   238  * @return bool|null True on write success, false on failure. Null in multisite.
   235  */
   239  */
   236 function iis7_save_url_rewrite_rules(){
   240 function iis7_save_url_rewrite_rules() {
   237 	if ( is_multisite() )
   241 	if ( is_multisite() ) {
   238 		return;
   242 		return;
       
   243 	}
   239 
   244 
   240 	global $wp_rewrite;
   245 	global $wp_rewrite;
   241 
   246 
   242 	// Ensure get_home_path() is declared.
   247 	// Ensure get_home_path() is declared.
   243 	require_once( ABSPATH . 'wp-admin/includes/file.php' );
   248 	require_once( ABSPATH . 'wp-admin/includes/file.php' );
   244 
   249 
   245 	$home_path       = get_home_path();
   250 	$home_path       = get_home_path();
   246 	$web_config_file = $home_path . 'web.config';
   251 	$web_config_file = $home_path . 'web.config';
   247 
   252 
   248 	// Using win_is_writable() instead of is_writable() because of a bug in Windows PHP
   253 	// Using win_is_writable() instead of is_writable() because of a bug in Windows PHP
   249 	if ( iis7_supports_permalinks() && ( ( ! file_exists($web_config_file) && win_is_writable($home_path) && $wp_rewrite->using_mod_rewrite_permalinks() ) || win_is_writable($web_config_file) ) ) {
   254 	if ( iis7_supports_permalinks() && ( ( ! file_exists( $web_config_file ) && win_is_writable( $home_path ) && $wp_rewrite->using_mod_rewrite_permalinks() ) || win_is_writable( $web_config_file ) ) ) {
   250 		$rule = $wp_rewrite->iis7_url_rewrite_rules(false, '', '');
   255 		$rule = $wp_rewrite->iis7_url_rewrite_rules( false );
   251 		if ( ! empty($rule) ) {
   256 		if ( ! empty( $rule ) ) {
   252 			return iis7_add_rewrite_rule($web_config_file, $rule);
   257 			return iis7_add_rewrite_rule( $web_config_file, $rule );
   253 		} else {
   258 		} else {
   254 			return iis7_delete_rewrite_rule($web_config_file);
   259 			return iis7_delete_rewrite_rule( $web_config_file );
   255 		}
   260 		}
   256 	}
   261 	}
   257 	return false;
   262 	return false;
   258 }
   263 }
   259 
   264 
   263  * @since 1.5.0
   268  * @since 1.5.0
   264  *
   269  *
   265  * @param string $file
   270  * @param string $file
   266  */
   271  */
   267 function update_recently_edited( $file ) {
   272 function update_recently_edited( $file ) {
   268 	$oldfiles = (array ) get_option( 'recently_edited' );
   273 	$oldfiles = (array) get_option( 'recently_edited' );
   269 	if ( $oldfiles ) {
   274 	if ( $oldfiles ) {
   270 		$oldfiles = array_reverse( $oldfiles );
   275 		$oldfiles   = array_reverse( $oldfiles );
   271 		$oldfiles[] = $file;
   276 		$oldfiles[] = $file;
   272 		$oldfiles = array_reverse( $oldfiles );
   277 		$oldfiles   = array_reverse( $oldfiles );
   273 		$oldfiles = array_unique( $oldfiles );
   278 		$oldfiles   = array_unique( $oldfiles );
   274 		if ( 5 < count( $oldfiles ))
   279 		if ( 5 < count( $oldfiles ) ) {
   275 			array_pop( $oldfiles );
   280 			array_pop( $oldfiles );
       
   281 		}
   276 	} else {
   282 	} else {
   277 		$oldfiles[] = $file;
   283 		$oldfiles[] = $file;
   278 	}
   284 	}
   279 	update_option( 'recently_edited', $oldfiles );
   285 	update_option( 'recently_edited', $oldfiles );
   280 }
   286 }
   281 
   287 
   282 /**
   288 /**
   283  * Makes a tree structure for the Theme Editor's file list.
   289  * Makes a tree structure for the theme editor's file list.
   284  *
   290  *
   285  * @since 4.9.0
   291  * @since 4.9.0
   286  * @access private
   292  * @access private
   287  *
   293  *
   288  * @param array $allowed_files List of theme file paths.
   294  * @param array $allowed_files List of theme file paths.
   289  * @return array Tree structure for listing theme files.
   295  * @return array Tree structure for listing theme files.
   290  */
   296  */
   291 function wp_make_theme_file_tree( $allowed_files ) {
   297 function wp_make_theme_file_tree( $allowed_files ) {
   292 	$tree_list = array();
   298 	$tree_list = array();
   293 	foreach ( $allowed_files as $file_name => $absolute_filename ) {
   299 	foreach ( $allowed_files as $file_name => $absolute_filename ) {
   294 		$list = explode( '/', $file_name );
   300 		$list     = explode( '/', $file_name );
   295 		$last_dir = &$tree_list;
   301 		$last_dir = &$tree_list;
   296 		foreach ( $list as $dir ) {
   302 		foreach ( $list as $dir ) {
   297 			$last_dir =& $last_dir[ $dir ];
   303 			$last_dir =& $last_dir[ $dir ];
   298 		}
   304 		}
   299 		$last_dir = $file_name;
   305 		$last_dir = $file_name;
   300 	}
   306 	}
   301 	return $tree_list;
   307 	return $tree_list;
   302 }
   308 }
   303 
   309 
   304 /**
   310 /**
   305  * Outputs the formatted file list for the Theme Editor.
   311  * Outputs the formatted file list for the theme editor.
   306  *
   312  *
   307  * @since 4.9.0
   313  * @since 4.9.0
   308  * @access private
   314  * @access private
       
   315  *
       
   316  * @global string $relative_file Name of the file being edited relative to the
       
   317  *                               theme directory.
       
   318  * @global string $stylesheet    The stylesheet name of the theme being edited.
   309  *
   319  *
   310  * @param array|string $tree  List of file/folder paths, or filename.
   320  * @param array|string $tree  List of file/folder paths, or filename.
   311  * @param int          $level The aria-level for the current iteration.
   321  * @param int          $level The aria-level for the current iteration.
   312  * @param int          $size  The aria-setsize for the current iteration.
   322  * @param int          $size  The aria-setsize for the current iteration.
   313  * @param int          $index The aria-posinset for the current iteration.
   323  * @param int          $index The aria-posinset for the current iteration.
   315 function wp_print_theme_file_tree( $tree, $level = 2, $size = 1, $index = 1 ) {
   325 function wp_print_theme_file_tree( $tree, $level = 2, $size = 1, $index = 1 ) {
   316 	global $relative_file, $stylesheet;
   326 	global $relative_file, $stylesheet;
   317 
   327 
   318 	if ( is_array( $tree ) ) {
   328 	if ( is_array( $tree ) ) {
   319 		$index = 0;
   329 		$index = 0;
   320 		$size = count( $tree );
   330 		$size  = count( $tree );
   321 		foreach ( $tree as $label => $theme_file ) :
   331 		foreach ( $tree as $label => $theme_file ) :
   322 			$index++;
   332 			$index++;
   323 			if ( ! is_array( $theme_file ) ) {
   333 			if ( ! is_array( $theme_file ) ) {
   324 				wp_print_theme_file_tree( $theme_file, $level, $index, $size );
   334 				wp_print_theme_file_tree( $theme_file, $level, $index, $size );
   325 				continue;
   335 				continue;
   334 			</li>
   344 			</li>
   335 			<?php
   345 			<?php
   336 		endforeach;
   346 		endforeach;
   337 	} else {
   347 	} else {
   338 		$filename = $tree;
   348 		$filename = $tree;
   339 		$url = add_query_arg(
   349 		$url      = add_query_arg(
   340 			array(
   350 			array(
   341 				'file' => rawurlencode( $tree ),
   351 				'file'  => rawurlencode( $tree ),
   342 				'theme' => rawurlencode( $stylesheet ),
   352 				'theme' => rawurlencode( $stylesheet ),
   343 			),
   353 			),
   344 			self_admin_url( 'theme-editor.php' )
   354 			self_admin_url( 'theme-editor.php' )
   345 		);
   355 		);
   346 		?>
   356 		?>
   350 				aria-level="<?php echo esc_attr( $level ); ?>"
   360 				aria-level="<?php echo esc_attr( $level ); ?>"
   351 				aria-setsize="<?php echo esc_attr( $size ); ?>"
   361 				aria-setsize="<?php echo esc_attr( $size ); ?>"
   352 				aria-posinset="<?php echo esc_attr( $index ); ?>">
   362 				aria-posinset="<?php echo esc_attr( $index ); ?>">
   353 				<?php
   363 				<?php
   354 				$file_description = esc_html( get_file_description( $filename ) );
   364 				$file_description = esc_html( get_file_description( $filename ) );
   355 				if ( $file_description !== $filename && basename( $filename ) !== $file_description ) {
   365 				if ( $file_description !== $filename && wp_basename( $filename ) !== $file_description ) {
   356 					$file_description .= '<br /><span class="nonessential">(' . esc_html( $filename ) . ')</span>';
   366 					$file_description .= '<br /><span class="nonessential">(' . esc_html( $filename ) . ')</span>';
   357 				}
   367 				}
   358 
   368 
   359 				if ( $relative_file === $filename ) {
   369 				if ( $relative_file === $filename ) {
   360 					echo '<span class="notice notice-info">' . $file_description . '</span>';
   370 					echo '<span class="notice notice-info">' . $file_description . '</span>';
   367 		<?php
   377 		<?php
   368 	}
   378 	}
   369 }
   379 }
   370 
   380 
   371 /**
   381 /**
   372  * Makes a tree structure for the Plugin Editor's file list.
   382  * Makes a tree structure for the plugin editor's file list.
   373  *
   383  *
   374  * @since 4.9.0
   384  * @since 4.9.0
   375  * @access private
   385  * @access private
   376  *
   386  *
   377  * @param string $plugin_editable_files List of plugin file paths.
   387  * @param array $plugin_editable_files List of plugin file paths.
   378  * @return array Tree structure for listing plugin files.
   388  * @return array Tree structure for listing plugin files.
   379  */
   389  */
   380 function wp_make_plugin_file_tree( $plugin_editable_files ) {
   390 function wp_make_plugin_file_tree( $plugin_editable_files ) {
   381 	$tree_list = array();
   391 	$tree_list = array();
   382 	foreach ( $plugin_editable_files as $plugin_file ) {
   392 	foreach ( $plugin_editable_files as $plugin_file ) {
   383 		$list = explode( '/', preg_replace( '#^.+?/#', '', $plugin_file ) );
   393 		$list     = explode( '/', preg_replace( '#^.+?/#', '', $plugin_file ) );
   384 		$last_dir = &$tree_list;
   394 		$last_dir = &$tree_list;
   385 		foreach ( $list as $dir ) {
   395 		foreach ( $list as $dir ) {
   386 			$last_dir =& $last_dir[ $dir ];
   396 			$last_dir =& $last_dir[ $dir ];
   387 		}
   397 		}
   388 		$last_dir = $plugin_file;
   398 		$last_dir = $plugin_file;
   389 	}
   399 	}
   390 	return $tree_list;
   400 	return $tree_list;
   391 }
   401 }
   392 
   402 
   393 /**
   403 /**
   394  * Outputs the formatted file list for the Plugin Editor.
   404  * Outputs the formatted file list for the plugin editor.
   395  *
   405  *
   396  * @since 4.9.0
   406  * @since 4.9.0
   397  * @access private
   407  * @access private
   398  *
   408  *
   399  * @param array|string $tree  List of file/folder paths, or filename.
   409  * @param array|string $tree  List of file/folder paths, or filename.
   404  */
   414  */
   405 function wp_print_plugin_file_tree( $tree, $label = '', $level = 2, $size = 1, $index = 1 ) {
   415 function wp_print_plugin_file_tree( $tree, $label = '', $level = 2, $size = 1, $index = 1 ) {
   406 	global $file, $plugin;
   416 	global $file, $plugin;
   407 	if ( is_array( $tree ) ) {
   417 	if ( is_array( $tree ) ) {
   408 		$index = 0;
   418 		$index = 0;
   409 		$size = count( $tree );
   419 		$size  = count( $tree );
   410 		foreach ( $tree as $label => $plugin_file ) :
   420 		foreach ( $tree as $label => $plugin_file ) :
   411 			$index++;
   421 			$index++;
   412 			if ( ! is_array( $plugin_file ) ) {
   422 			if ( ! is_array( $plugin_file ) ) {
   413 				wp_print_plugin_file_tree( $plugin_file, $label, $level, $index, $size );
   423 				wp_print_plugin_file_tree( $plugin_file, $label, $level, $index, $size );
   414 				continue;
   424 				continue;
   424 			<?php
   434 			<?php
   425 		endforeach;
   435 		endforeach;
   426 	} else {
   436 	} else {
   427 		$url = add_query_arg(
   437 		$url = add_query_arg(
   428 			array(
   438 			array(
   429 				'file' => rawurlencode( $tree ),
   439 				'file'   => rawurlencode( $tree ),
   430 				'plugin' => rawurlencode( $plugin ),
   440 				'plugin' => rawurlencode( $plugin ),
   431 			),
   441 			),
   432 			self_admin_url( 'plugin-editor.php' )
   442 			self_admin_url( 'plugin-editor.php' )
   433 		);
   443 		);
   434 		?>
   444 		?>
   458  *
   468  *
   459  * @param string $old_value
   469  * @param string $old_value
   460  * @param string $value
   470  * @param string $value
   461  */
   471  */
   462 function update_home_siteurl( $old_value, $value ) {
   472 function update_home_siteurl( $old_value, $value ) {
   463 	if ( wp_installing() )
   473 	if ( wp_installing() ) {
   464 		return;
   474 		return;
       
   475 	}
   465 
   476 
   466 	if ( is_multisite() && ms_is_switched() ) {
   477 	if ( is_multisite() && ms_is_switched() ) {
   467 		delete_option( 'rewrite_rules' );
   478 		delete_option( 'rewrite_rules' );
   468 	} else {
   479 	} else {
   469 		flush_rewrite_rules();
   480 		flush_rewrite_rules();
   501  *
   512  *
   502  * @since 2.1.0
   513  * @since 2.1.0
   503  *
   514  *
   504  * @param string|WP_Error $message
   515  * @param string|WP_Error $message
   505  */
   516  */
   506 function show_message($message) {
   517 function show_message( $message ) {
   507 	if ( is_wp_error($message) ){
   518 	if ( is_wp_error( $message ) ) {
   508 		if ( $message->get_error_data() && is_string( $message->get_error_data() ) )
   519 		if ( $message->get_error_data() && is_string( $message->get_error_data() ) ) {
   509 			$message = $message->get_error_message() . ': ' . $message->get_error_data();
   520 			$message = $message->get_error_message() . ': ' . $message->get_error_data();
   510 		else
   521 		} else {
   511 			$message = $message->get_error_message();
   522 			$message = $message->get_error_message();
       
   523 		}
   512 	}
   524 	}
   513 	echo "<p>$message</p>\n";
   525 	echo "<p>$message</p>\n";
   514 	wp_ob_end_flush_all();
   526 	wp_ob_end_flush_all();
   515 	flush();
   527 	flush();
   516 }
   528 }
   520  *
   532  *
   521  * @param string $content
   533  * @param string $content
   522  * @return array
   534  * @return array
   523  */
   535  */
   524 function wp_doc_link_parse( $content ) {
   536 function wp_doc_link_parse( $content ) {
   525 	if ( !is_string( $content ) || empty( $content ) )
   537 	if ( ! is_string( $content ) || empty( $content ) ) {
   526 		return array();
   538 		return array();
   527 
   539 	}
   528 	if ( !function_exists('token_get_all') )
   540 
       
   541 	if ( ! function_exists( 'token_get_all' ) ) {
   529 		return array();
   542 		return array();
   530 
   543 	}
   531 	$tokens = token_get_all( $content );
   544 
   532 	$count = count( $tokens );
   545 	$tokens           = token_get_all( $content );
   533 	$functions = array();
   546 	$count            = count( $tokens );
       
   547 	$functions        = array();
   534 	$ignore_functions = array();
   548 	$ignore_functions = array();
   535 	for ( $t = 0; $t < $count - 2; $t++ ) {
   549 	for ( $t = 0; $t < $count - 2; $t++ ) {
   536 		if ( ! is_array( $tokens[ $t ] ) ) {
   550 		if ( ! is_array( $tokens[ $t ] ) ) {
   537 			continue;
   551 			continue;
   538 		}
   552 		}
   539 
   553 
   540 		if ( T_STRING == $tokens[ $t ][0] && ( '(' == $tokens[ $t + 1 ] || '(' == $tokens[ $t + 2 ] ) ) {
   554 		if ( T_STRING == $tokens[ $t ][0] && ( '(' == $tokens[ $t + 1 ] || '(' == $tokens[ $t + 2 ] ) ) {
   541 			// If it's a function or class defined locally, there's not going to be any docs available
   555 			// If it's a function or class defined locally, there's not going to be any docs available
   542 			if ( ( isset( $tokens[ $t - 2 ][1] ) && in_array( $tokens[ $t - 2 ][1], array( 'function', 'class' ) ) ) || ( isset( $tokens[ $t - 2 ][0] ) && T_OBJECT_OPERATOR == $tokens[ $t - 1 ][0] ) ) {
   556 			if ( ( isset( $tokens[ $t - 2 ][1] ) && in_array( $tokens[ $t - 2 ][1], array( 'function', 'class' ) ) ) || ( isset( $tokens[ $t - 2 ][0] ) && T_OBJECT_OPERATOR == $tokens[ $t - 1 ][0] ) ) {
   543 				$ignore_functions[] = $tokens[$t][1];
   557 				$ignore_functions[] = $tokens[ $t ][1];
   544 			}
   558 			}
   545 			// Add this to our stack of unique references
   559 			// Add this to our stack of unique references
   546 			$functions[] = $tokens[$t][1];
   560 			$functions[] = $tokens[ $t ][1];
   547 		}
   561 		}
   548 	}
   562 	}
   549 
   563 
   550 	$functions = array_unique( $functions );
   564 	$functions = array_unique( $functions );
   551 	sort( $functions );
   565 	sort( $functions );
   553 	/**
   567 	/**
   554 	 * Filters the list of functions and classes to be ignored from the documentation lookup.
   568 	 * Filters the list of functions and classes to be ignored from the documentation lookup.
   555 	 *
   569 	 *
   556 	 * @since 2.8.0
   570 	 * @since 2.8.0
   557 	 *
   571 	 *
   558 	 * @param array $ignore_functions Functions and classes to be ignored.
   572 	 * @param string[] $ignore_functions Array of names of functions and classes to be ignored.
   559 	 */
   573 	 */
   560 	$ignore_functions = apply_filters( 'documentation_ignore_functions', $ignore_functions );
   574 	$ignore_functions = apply_filters( 'documentation_ignore_functions', $ignore_functions );
   561 
   575 
   562 	$ignore_functions = array_unique( $ignore_functions );
   576 	$ignore_functions = array_unique( $ignore_functions );
   563 
   577 
   564 	$out = array();
   578 	$out = array();
   565 	foreach ( $functions as $function ) {
   579 	foreach ( $functions as $function ) {
   566 		if ( in_array( $function, $ignore_functions ) )
   580 		if ( in_array( $function, $ignore_functions ) ) {
   567 			continue;
   581 			continue;
       
   582 		}
   568 		$out[] = $function;
   583 		$out[] = $function;
   569 	}
   584 	}
   570 
   585 
   571 	return $out;
   586 	return $out;
   572 }
   587 }
   576  *
   591  *
   577  * @since 2.8.0
   592  * @since 2.8.0
   578  */
   593  */
   579 function set_screen_options() {
   594 function set_screen_options() {
   580 
   595 
   581 	if ( isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options']) ) {
   596 	if ( isset( $_POST['wp_screen_options'] ) && is_array( $_POST['wp_screen_options'] ) ) {
   582 		check_admin_referer( 'screen-options-nonce', 'screenoptionnonce' );
   597 		check_admin_referer( 'screen-options-nonce', 'screenoptionnonce' );
   583 
   598 
   584 		if ( !$user = wp_get_current_user() )
   599 		if ( ! $user = wp_get_current_user() ) {
   585 			return;
   600 			return;
       
   601 		}
   586 		$option = $_POST['wp_screen_options']['option'];
   602 		$option = $_POST['wp_screen_options']['option'];
   587 		$value = $_POST['wp_screen_options']['value'];
   603 		$value  = $_POST['wp_screen_options']['value'];
   588 
   604 
   589 		if ( $option != sanitize_key( $option ) )
   605 		if ( $option != sanitize_key( $option ) ) {
   590 			return;
   606 			return;
       
   607 		}
   591 
   608 
   592 		$map_option = $option;
   609 		$map_option = $option;
   593 		$type = str_replace('edit_', '', $map_option);
   610 		$type       = str_replace( 'edit_', '', $map_option );
   594 		$type = str_replace('_per_page', '', $type);
   611 		$type       = str_replace( '_per_page', '', $type );
   595 		if ( in_array( $type, get_taxonomies() ) )
   612 		if ( in_array( $type, get_taxonomies() ) ) {
   596 			$map_option = 'edit_tags_per_page';
   613 			$map_option = 'edit_tags_per_page';
   597 		elseif ( in_array( $type, get_post_types() ) )
   614 		} elseif ( in_array( $type, get_post_types() ) ) {
   598 			$map_option = 'edit_per_page';
   615 			$map_option = 'edit_per_page';
   599 		else
   616 		} else {
   600 			$option = str_replace('-', '_', $option);
   617 			$option = str_replace( '-', '_', $option );
       
   618 		}
   601 
   619 
   602 		switch ( $map_option ) {
   620 		switch ( $map_option ) {
   603 			case 'edit_per_page':
   621 			case 'edit_per_page':
   604 			case 'users_per_page':
   622 			case 'users_per_page':
   605 			case 'edit_comments_per_page':
   623 			case 'edit_comments_per_page':
   606 			case 'upload_per_page':
   624 			case 'upload_per_page':
   607 			case 'edit_tags_per_page':
   625 			case 'edit_tags_per_page':
   608 			case 'plugins_per_page':
   626 			case 'plugins_per_page':
   609 			case 'export_personal_data_requests_per_page':
   627 			case 'export_personal_data_requests_per_page':
   610 			case 'remove_personal_data_requests_per_page':
   628 			case 'remove_personal_data_requests_per_page':
   611 			// Network admin
   629 				// Network admin
   612 			case 'sites_network_per_page':
   630 			case 'sites_network_per_page':
   613 			case 'users_network_per_page':
   631 			case 'users_network_per_page':
   614 			case 'site_users_network_per_page':
   632 			case 'site_users_network_per_page':
   615 			case 'plugins_network_per_page':
   633 			case 'plugins_network_per_page':
   616 			case 'themes_network_per_page':
   634 			case 'themes_network_per_page':
   617 			case 'site_themes_network_per_page':
   635 			case 'site_themes_network_per_page':
   618 				$value = (int) $value;
   636 				$value = (int) $value;
   619 				if ( $value < 1 || $value > 999 )
   637 				if ( $value < 1 || $value > 999 ) {
   620 					return;
   638 					return;
       
   639 				}
   621 				break;
   640 				break;
   622 			default:
   641 			default:
   623 
       
   624 				/**
   642 				/**
   625 				 * Filters a screen option value before it is set.
   643 				 * Filters a screen option value before it is set.
   626 				 *
   644 				 *
   627 				 * The filter can also be used to modify non-standard [items]_per_page
   645 				 * The filter can also be used to modify non-standard [items]_per_page
   628 				 * settings. See the parent function for a full list of standard options.
   646 				 * settings. See the parent function for a full list of standard options.
   631 				 *
   649 				 *
   632 				 * @since 2.8.0
   650 				 * @since 2.8.0
   633 				 *
   651 				 *
   634 				 * @see set_screen_options()
   652 				 * @see set_screen_options()
   635 				 *
   653 				 *
   636 				 * @param bool|int $value  Screen option value. Default false to skip.
   654 				 * @param bool     $keep   Whether to save or skip saving the screen option value. Default false.
   637 				 * @param string   $option The option name.
   655 				 * @param string   $option The option name.
   638 				 * @param int      $value  The number of rows to use.
   656 				 * @param int      $value  The number of rows to use.
   639 				 */
   657 				 */
   640 				$value = apply_filters( 'set-screen-option', false, $option, $value );
   658 				$value = apply_filters( 'set-screen-option', false, $option, $value );
   641 
   659 
   642 				if ( false === $value )
   660 				if ( false === $value ) {
   643 					return;
   661 					return;
       
   662 				}
   644 				break;
   663 				break;
   645 		}
   664 		}
   646 
   665 
   647 		update_user_meta($user->ID, $option, $value);
   666 		update_user_meta( $user->ID, $option, $value );
   648 
   667 
   649 		$url = remove_query_arg( array( 'pagenum', 'apage', 'paged' ), wp_get_referer() );
   668 		$url = remove_query_arg( array( 'pagenum', 'apage', 'paged' ), wp_get_referer() );
   650 		if ( isset( $_POST['mode'] ) ) {
   669 		if ( isset( $_POST['mode'] ) ) {
   651 			$url = add_query_arg( array( 'mode' => $_POST['mode'] ), $url );
   670 			$url = add_query_arg( array( 'mode' => $_POST['mode'] ), $url );
   652 		}
   671 		}
   662  * @since 2.8.0
   681  * @since 2.8.0
   663  *
   682  *
   664  * @return bool
   683  * @return bool
   665  * @param string $filename The file path to the configuration file
   684  * @param string $filename The file path to the configuration file
   666  */
   685  */
   667 function iis7_rewrite_rule_exists($filename) {
   686 function iis7_rewrite_rule_exists( $filename ) {
   668 	if ( ! file_exists($filename) )
   687 	if ( ! file_exists( $filename ) ) {
   669 		return false;
   688 		return false;
       
   689 	}
   670 	if ( ! class_exists( 'DOMDocument', false ) ) {
   690 	if ( ! class_exists( 'DOMDocument', false ) ) {
   671 		return false;
   691 		return false;
   672 	}
   692 	}
   673 
   693 
   674 	$doc = new DOMDocument();
   694 	$doc = new DOMDocument();
   675 	if ( $doc->load($filename) === false )
   695 	if ( $doc->load( $filename ) === false ) {
   676 		return false;
   696 		return false;
   677 	$xpath = new DOMXPath($doc);
   697 	}
   678 	$rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]');
   698 	$xpath = new DOMXPath( $doc );
   679 	if ( $rules->length == 0 )
   699 	$rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' );
       
   700 	if ( $rules->length == 0 ) {
   680 		return false;
   701 		return false;
   681 	else
   702 	} else {
   682 		return true;
   703 		return true;
       
   704 	}
   683 }
   705 }
   684 
   706 
   685 /**
   707 /**
   686  * Delete WordPress rewrite rule from web.config file if it exists there
   708  * Delete WordPress rewrite rule from web.config file if it exists there
   687  *
   709  *
   688  * @since 2.8.0
   710  * @since 2.8.0
   689  *
   711  *
   690  * @param string $filename Name of the configuration file
   712  * @param string $filename Name of the configuration file
   691  * @return bool
   713  * @return bool
   692  */
   714  */
   693 function iis7_delete_rewrite_rule($filename) {
   715 function iis7_delete_rewrite_rule( $filename ) {
   694 	// If configuration file does not exist then rules also do not exist so there is nothing to delete
   716 	// If configuration file does not exist then rules also do not exist so there is nothing to delete
   695 	if ( ! file_exists($filename) )
   717 	if ( ! file_exists( $filename ) ) {
   696 		return true;
   718 		return true;
       
   719 	}
   697 
   720 
   698 	if ( ! class_exists( 'DOMDocument', false ) ) {
   721 	if ( ! class_exists( 'DOMDocument', false ) ) {
   699 		return false;
   722 		return false;
   700 	}
   723 	}
   701 
   724 
   702 	$doc = new DOMDocument();
   725 	$doc                     = new DOMDocument();
   703 	$doc->preserveWhiteSpace = false;
   726 	$doc->preserveWhiteSpace = false;
   704 
   727 
   705 	if ( $doc -> load($filename) === false )
   728 	if ( $doc->load( $filename ) === false ) {
   706 		return false;
   729 		return false;
   707 	$xpath = new DOMXPath($doc);
   730 	}
   708 	$rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]');
   731 	$xpath = new DOMXPath( $doc );
       
   732 	$rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' );
   709 	if ( $rules->length > 0 ) {
   733 	if ( $rules->length > 0 ) {
   710 		$child = $rules->item(0);
   734 		$child  = $rules->item( 0 );
   711 		$parent = $child->parentNode;
   735 		$parent = $child->parentNode;
   712 		$parent->removeChild($child);
   736 		$parent->removeChild( $child );
   713 		$doc->formatOutput = true;
   737 		$doc->formatOutput = true;
   714 		saveDomDocument($doc, $filename);
   738 		saveDomDocument( $doc, $filename );
   715 	}
   739 	}
   716 	return true;
   740 	return true;
   717 }
   741 }
   718 
   742 
   719 /**
   743 /**
   723  *
   747  *
   724  * @param string $filename The file path to the configuration file
   748  * @param string $filename The file path to the configuration file
   725  * @param string $rewrite_rule The XML fragment with URL Rewrite rule
   749  * @param string $rewrite_rule The XML fragment with URL Rewrite rule
   726  * @return bool
   750  * @return bool
   727  */
   751  */
   728 function iis7_add_rewrite_rule($filename, $rewrite_rule) {
   752 function iis7_add_rewrite_rule( $filename, $rewrite_rule ) {
   729 	if ( ! class_exists( 'DOMDocument', false ) ) {
   753 	if ( ! class_exists( 'DOMDocument', false ) ) {
   730 		return false;
   754 		return false;
   731 	}
   755 	}
   732 
   756 
   733 	// If configuration file does not exist then we create one.
   757 	// If configuration file does not exist then we create one.
   734 	if ( ! file_exists($filename) ) {
   758 	if ( ! file_exists( $filename ) ) {
   735 		$fp = fopen( $filename, 'w');
   759 		$fp = fopen( $filename, 'w' );
   736 		fwrite($fp, '<configuration/>');
   760 		fwrite( $fp, '<configuration/>' );
   737 		fclose($fp);
   761 		fclose( $fp );
   738 	}
   762 	}
   739 
   763 
   740 	$doc = new DOMDocument();
   764 	$doc                     = new DOMDocument();
   741 	$doc->preserveWhiteSpace = false;
   765 	$doc->preserveWhiteSpace = false;
   742 
   766 
   743 	if ( $doc->load($filename) === false )
   767 	if ( $doc->load( $filename ) === false ) {
   744 		return false;
   768 		return false;
   745 
   769 	}
   746 	$xpath = new DOMXPath($doc);
   770 
       
   771 	$xpath = new DOMXPath( $doc );
   747 
   772 
   748 	// First check if the rule already exists as in that case there is no need to re-add it
   773 	// First check if the rule already exists as in that case there is no need to re-add it
   749 	$wordpress_rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]');
   774 	$wordpress_rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' );
   750 	if ( $wordpress_rules->length > 0 )
   775 	if ( $wordpress_rules->length > 0 ) {
   751 		return true;
   776 		return true;
       
   777 	}
   752 
   778 
   753 	// Check the XPath to the rewrite rule and create XML nodes if they do not exist
   779 	// Check the XPath to the rewrite rule and create XML nodes if they do not exist
   754 	$xmlnodes = $xpath->query('/configuration/system.webServer/rewrite/rules');
   780 	$xmlnodes = $xpath->query( '/configuration/system.webServer/rewrite/rules' );
   755 	if ( $xmlnodes->length > 0 ) {
   781 	if ( $xmlnodes->length > 0 ) {
   756 		$rules_node = $xmlnodes->item(0);
   782 		$rules_node = $xmlnodes->item( 0 );
   757 	} else {
   783 	} else {
   758 		$rules_node = $doc->createElement('rules');
   784 		$rules_node = $doc->createElement( 'rules' );
   759 
   785 
   760 		$xmlnodes = $xpath->query('/configuration/system.webServer/rewrite');
   786 		$xmlnodes = $xpath->query( '/configuration/system.webServer/rewrite' );
   761 		if ( $xmlnodes->length > 0 ) {
   787 		if ( $xmlnodes->length > 0 ) {
   762 			$rewrite_node = $xmlnodes->item(0);
   788 			$rewrite_node = $xmlnodes->item( 0 );
   763 			$rewrite_node->appendChild($rules_node);
   789 			$rewrite_node->appendChild( $rules_node );
   764 		} else {
   790 		} else {
   765 			$rewrite_node = $doc->createElement('rewrite');
   791 			$rewrite_node = $doc->createElement( 'rewrite' );
   766 			$rewrite_node->appendChild($rules_node);
   792 			$rewrite_node->appendChild( $rules_node );
   767 
   793 
   768 			$xmlnodes = $xpath->query('/configuration/system.webServer');
   794 			$xmlnodes = $xpath->query( '/configuration/system.webServer' );
   769 			if ( $xmlnodes->length > 0 ) {
   795 			if ( $xmlnodes->length > 0 ) {
   770 				$system_webServer_node = $xmlnodes->item(0);
   796 				$system_webServer_node = $xmlnodes->item( 0 );
   771 				$system_webServer_node->appendChild($rewrite_node);
   797 				$system_webServer_node->appendChild( $rewrite_node );
   772 			} else {
   798 			} else {
   773 				$system_webServer_node = $doc->createElement('system.webServer');
   799 				$system_webServer_node = $doc->createElement( 'system.webServer' );
   774 				$system_webServer_node->appendChild($rewrite_node);
   800 				$system_webServer_node->appendChild( $rewrite_node );
   775 
   801 
   776 				$xmlnodes = $xpath->query('/configuration');
   802 				$xmlnodes = $xpath->query( '/configuration' );
   777 				if ( $xmlnodes->length > 0 ) {
   803 				if ( $xmlnodes->length > 0 ) {
   778 					$config_node = $xmlnodes->item(0);
   804 					$config_node = $xmlnodes->item( 0 );
   779 					$config_node->appendChild($system_webServer_node);
   805 					$config_node->appendChild( $system_webServer_node );
   780 				} else {
   806 				} else {
   781 					$config_node = $doc->createElement('configuration');
   807 					$config_node = $doc->createElement( 'configuration' );
   782 					$doc->appendChild($config_node);
   808 					$doc->appendChild( $config_node );
   783 					$config_node->appendChild($system_webServer_node);
   809 					$config_node->appendChild( $system_webServer_node );
   784 				}
   810 				}
   785 			}
   811 			}
   786 		}
   812 		}
   787 	}
   813 	}
   788 
   814 
   789 	$rule_fragment = $doc->createDocumentFragment();
   815 	$rule_fragment = $doc->createDocumentFragment();
   790 	$rule_fragment->appendXML($rewrite_rule);
   816 	$rule_fragment->appendXML( $rewrite_rule );
   791 	$rules_node->appendChild($rule_fragment);
   817 	$rules_node->appendChild( $rule_fragment );
   792 
   818 
   793 	$doc->encoding = "UTF-8";
   819 	$doc->encoding     = 'UTF-8';
   794 	$doc->formatOutput = true;
   820 	$doc->formatOutput = true;
   795 	saveDomDocument($doc, $filename);
   821 	saveDomDocument( $doc, $filename );
   796 
   822 
   797 	return true;
   823 	return true;
   798 }
   824 }
   799 
   825 
   800 /**
   826 /**
   803  * @since 2.8.0
   829  * @since 2.8.0
   804  *
   830  *
   805  * @param DOMDocument $doc
   831  * @param DOMDocument $doc
   806  * @param string $filename
   832  * @param string $filename
   807  */
   833  */
   808 function saveDomDocument($doc, $filename) {
   834 function saveDomDocument( $doc, $filename ) {
   809 	$config = $doc->saveXML();
   835 	$config = $doc->saveXML();
   810 	$config = preg_replace("/([^\r])\n/", "$1\r\n", $config);
   836 	$config = preg_replace( "/([^\r])\n/", "$1\r\n", $config );
   811 	$fp = fopen($filename, 'w');
   837 	$fp     = fopen( $filename, 'w' );
   812 	fwrite($fp, $config);
   838 	fwrite( $fp, $config );
   813 	fclose($fp);
   839 	fclose( $fp );
   814 }
   840 }
   815 
   841 
   816 /**
   842 /**
   817  * Display the default admin color scheme picker (Used in user-edit.php)
   843  * Display the default admin color scheme picker (Used in user-edit.php)
   818  *
   844  *
   827 
   853 
   828 	ksort( $_wp_admin_css_colors );
   854 	ksort( $_wp_admin_css_colors );
   829 
   855 
   830 	if ( isset( $_wp_admin_css_colors['fresh'] ) ) {
   856 	if ( isset( $_wp_admin_css_colors['fresh'] ) ) {
   831 		// Set Default ('fresh') and Light should go first.
   857 		// Set Default ('fresh') and Light should go first.
   832 		$_wp_admin_css_colors = array_filter( array_merge( array( 'fresh' => '', 'light' => '' ), $_wp_admin_css_colors ) );
   858 		$_wp_admin_css_colors = array_filter(
       
   859 			array_merge(
       
   860 				array(
       
   861 					'fresh' => '',
       
   862 					'light' => '',
       
   863 				),
       
   864 				$_wp_admin_css_colors
       
   865 			)
       
   866 		);
   833 	}
   867 	}
   834 
   868 
   835 	$current_color = get_user_option( 'admin_color', $user_id );
   869 	$current_color = get_user_option( 'admin_color', $user_id );
   836 
   870 
   837 	if ( empty( $current_color ) || ! isset( $_wp_admin_css_colors[ $current_color ] ) ) {
   871 	if ( empty( $current_color ) || ! isset( $_wp_admin_css_colors[ $current_color ] ) ) {
   867 			</div>
   901 			</div>
   868 			<?php
   902 			<?php
   869 
   903 
   870 		endforeach;
   904 		endforeach;
   871 
   905 
   872 	?>
   906 		?>
   873 	</fieldset>
   907 	</fieldset>
   874 	<?php
   908 	<?php
   875 }
   909 }
   876 
   910 
   877 /**
   911 /**
   892 		$icon_colors = $_wp_admin_css_colors[ $color_scheme ]->icon_colors;
   926 		$icon_colors = $_wp_admin_css_colors[ $color_scheme ]->icon_colors;
   893 	} elseif ( ! empty( $_wp_admin_css_colors['fresh']->icon_colors ) ) {
   927 	} elseif ( ! empty( $_wp_admin_css_colors['fresh']->icon_colors ) ) {
   894 		$icon_colors = $_wp_admin_css_colors['fresh']->icon_colors;
   928 		$icon_colors = $_wp_admin_css_colors['fresh']->icon_colors;
   895 	} else {
   929 	} else {
   896 		// Fall back to the default set of icon colors if the default scheme is missing.
   930 		// Fall back to the default set of icon colors if the default scheme is missing.
   897 		$icon_colors = array( 'base' => '#82878c', 'focus' => '#00a0d2', 'current' => '#fff' );
   931 		$icon_colors = array(
       
   932 			'base'    => '#a0a5aa',
       
   933 			'focus'   => '#00a0d2',
       
   934 			'current' => '#fff',
       
   935 		);
   898 	}
   936 	}
   899 
   937 
   900 	echo '<script type="text/javascript">var _wpColorScheme = ' . wp_json_encode( array( 'icons' => $icon_colors ) ) . ";</script>\n";
   938 	echo '<script type="text/javascript">var _wpColorScheme = ' . wp_json_encode( array( 'icons' => $icon_colors ) ) . ";</script>\n";
   901 }
   939 }
   902 
   940 
   924 function wp_check_locked_posts( $response, $data, $screen_id ) {
   962 function wp_check_locked_posts( $response, $data, $screen_id ) {
   925 	$checked = array();
   963 	$checked = array();
   926 
   964 
   927 	if ( array_key_exists( 'wp-check-locked-posts', $data ) && is_array( $data['wp-check-locked-posts'] ) ) {
   965 	if ( array_key_exists( 'wp-check-locked-posts', $data ) && is_array( $data['wp-check-locked-posts'] ) ) {
   928 		foreach ( $data['wp-check-locked-posts'] as $key ) {
   966 		foreach ( $data['wp-check-locked-posts'] as $key ) {
   929 			if ( ! $post_id = absint( substr( $key, 5 ) ) )
   967 			if ( ! $post_id = absint( substr( $key, 5 ) ) ) {
   930 				continue;
   968 				continue;
       
   969 			}
   931 
   970 
   932 			if ( ( $user_id = wp_check_post_lock( $post_id ) ) && ( $user = get_userdata( $user_id ) ) && current_user_can( 'edit_post', $post_id ) ) {
   971 			if ( ( $user_id = wp_check_post_lock( $post_id ) ) && ( $user = get_userdata( $user_id ) ) && current_user_can( 'edit_post', $post_id ) ) {
   933 				$send = array( 'text' => sprintf( __( '%s is currently editing' ), $user->display_name ) );
   972 				$send = array( 'text' => sprintf( __( '%s is currently editing' ), $user->display_name ) );
   934 
   973 
   935 				if ( ( $avatar = get_avatar( $user->ID, 18 ) ) && preg_match( "|src='([^']+)'|", $avatar, $matches ) )
   974 				if ( ( $avatar = get_avatar( $user->ID, 18 ) ) && preg_match( "|src='([^']+)'|", $avatar, $matches ) ) {
   936 					$send['avatar_src'] = $matches[1];
   975 					$send['avatar_src'] = $matches[1];
   937 
   976 				}
   938 				$checked[$key] = $send;
   977 
       
   978 				$checked[ $key ] = $send;
   939 			}
   979 			}
   940 		}
   980 		}
   941 	}
   981 	}
   942 
   982 
   943 	if ( ! empty( $checked ) )
   983 	if ( ! empty( $checked ) ) {
   944 		$response['wp-check-locked-posts'] = $checked;
   984 		$response['wp-check-locked-posts'] = $checked;
       
   985 	}
   945 
   986 
   946 	return $response;
   987 	return $response;
   947 }
   988 }
   948 
   989 
   949 /**
   990 /**
   957  * @return array The Heartbeat response.
   998  * @return array The Heartbeat response.
   958  */
   999  */
   959 function wp_refresh_post_lock( $response, $data, $screen_id ) {
  1000 function wp_refresh_post_lock( $response, $data, $screen_id ) {
   960 	if ( array_key_exists( 'wp-refresh-post-lock', $data ) ) {
  1001 	if ( array_key_exists( 'wp-refresh-post-lock', $data ) ) {
   961 		$received = $data['wp-refresh-post-lock'];
  1002 		$received = $data['wp-refresh-post-lock'];
   962 		$send = array();
  1003 		$send     = array();
   963 
  1004 
   964 		if ( ! $post_id = absint( $received['post_id'] ) )
  1005 		if ( ! $post_id = absint( $received['post_id'] ) ) {
   965 			return $response;
  1006 			return $response;
   966 
  1007 		}
   967 		if ( ! current_user_can('edit_post', $post_id) )
  1008 
       
  1009 		if ( ! current_user_can( 'edit_post', $post_id ) ) {
   968 			return $response;
  1010 			return $response;
       
  1011 		}
   969 
  1012 
   970 		if ( ( $user_id = wp_check_post_lock( $post_id ) ) && ( $user = get_userdata( $user_id ) ) ) {
  1013 		if ( ( $user_id = wp_check_post_lock( $post_id ) ) && ( $user = get_userdata( $user_id ) ) ) {
   971 			$error = array(
  1014 			$error = array(
   972 				'text' => sprintf( __( '%s has taken over and is currently editing.' ), $user->display_name )
  1015 				'text' => sprintf( __( '%s has taken over and is currently editing.' ), $user->display_name ),
   973 			);
  1016 			);
   974 
  1017 
   975 			if ( $avatar = get_avatar( $user->ID, 64 ) ) {
  1018 			if ( $avatar = get_avatar( $user->ID, 64 ) ) {
   976 				if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) )
  1019 				if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) {
   977 					$error['avatar_src'] = $matches[1];
  1020 					$error['avatar_src'] = $matches[1];
       
  1021 				}
   978 			}
  1022 			}
   979 
  1023 
   980 			$send['lock_error'] = $error;
  1024 			$send['lock_error'] = $error;
   981 		} else {
  1025 		} else {
   982 			if ( $new_lock = wp_set_post_lock( $post_id ) )
  1026 			if ( $new_lock = wp_set_post_lock( $post_id ) ) {
   983 				$send['new_lock'] = implode( ':', $new_lock );
  1027 				$send['new_lock'] = implode( ':', $new_lock );
       
  1028 			}
   984 		}
  1029 		}
   985 
  1030 
   986 		$response['wp-refresh-post-lock'] = $send;
  1031 		$response['wp-refresh-post-lock'] = $send;
   987 	}
  1032 	}
   988 
  1033 
   999  * @param string $screen_id The screen id.
  1044  * @param string $screen_id The screen id.
  1000  * @return array The Heartbeat response.
  1045  * @return array The Heartbeat response.
  1001  */
  1046  */
  1002 function wp_refresh_post_nonces( $response, $data, $screen_id ) {
  1047 function wp_refresh_post_nonces( $response, $data, $screen_id ) {
  1003 	if ( array_key_exists( 'wp-refresh-post-nonces', $data ) ) {
  1048 	if ( array_key_exists( 'wp-refresh-post-nonces', $data ) ) {
  1004 		$received = $data['wp-refresh-post-nonces'];
  1049 		$received                           = $data['wp-refresh-post-nonces'];
  1005 		$response['wp-refresh-post-nonces'] = array( 'check' => 1 );
  1050 		$response['wp-refresh-post-nonces'] = array( 'check' => 1 );
  1006 
  1051 
  1007 		if ( ! $post_id = absint( $received['post_id'] ) ) {
  1052 		if ( ! $post_id = absint( $received['post_id'] ) ) {
  1008 			return $response;
  1053 			return $response;
  1009 		}
  1054 		}
  1012 			return $response;
  1057 			return $response;
  1013 		}
  1058 		}
  1014 
  1059 
  1015 		$response['wp-refresh-post-nonces'] = array(
  1060 		$response['wp-refresh-post-nonces'] = array(
  1016 			'replace' => array(
  1061 			'replace' => array(
  1017 				'getpermalinknonce' => wp_create_nonce('getpermalink'),
  1062 				'getpermalinknonce'    => wp_create_nonce( 'getpermalink' ),
  1018 				'samplepermalinknonce' => wp_create_nonce('samplepermalink'),
  1063 				'samplepermalinknonce' => wp_create_nonce( 'samplepermalink' ),
  1019 				'closedpostboxesnonce' => wp_create_nonce('closedpostboxes'),
  1064 				'closedpostboxesnonce' => wp_create_nonce( 'closedpostboxes' ),
  1020 				'_ajax_linking_nonce' => wp_create_nonce( 'internal-linking' ),
  1065 				'_ajax_linking_nonce'  => wp_create_nonce( 'internal-linking' ),
  1021 				'_wpnonce' => wp_create_nonce( 'update-post_' . $post_id ),
  1066 				'_wpnonce'             => wp_create_nonce( 'update-post_' . $post_id ),
  1022 			),
  1067 			),
  1023 			'heartbeatNonce' => wp_create_nonce( 'heartbeat-nonce' ),
       
  1024 		);
  1068 		);
  1025 	}
  1069 	}
  1026 
  1070 
       
  1071 	return $response;
       
  1072 }
       
  1073 
       
  1074 /**
       
  1075  * Add the latest Heartbeat and REST-API nonce to the Heartbeat response.
       
  1076  *
       
  1077  * @since 5.0.0
       
  1078  *
       
  1079  * @param array  $response  The Heartbeat response.
       
  1080  * @return array The Heartbeat response.
       
  1081  */
       
  1082 function wp_refresh_heartbeat_nonces( $response ) {
       
  1083 	// Refresh the Rest API nonce.
       
  1084 	$response['rest_nonce'] = wp_create_nonce( 'wp_rest' );
       
  1085 
       
  1086 	// Refresh the Heartbeat nonce.
       
  1087 	$response['heartbeat_nonce'] = wp_create_nonce( 'heartbeat-nonce' );
  1027 	return $response;
  1088 	return $response;
  1028 }
  1089 }
  1029 
  1090 
  1030 /**
  1091 /**
  1031  * Disable suspension of Heartbeat on the Add/Edit Post screens.
  1092  * Disable suspension of Heartbeat on the Add/Edit Post screens.
  1059 function heartbeat_autosave( $response, $data ) {
  1120 function heartbeat_autosave( $response, $data ) {
  1060 	if ( ! empty( $data['wp_autosave'] ) ) {
  1121 	if ( ! empty( $data['wp_autosave'] ) ) {
  1061 		$saved = wp_autosave( $data['wp_autosave'] );
  1122 		$saved = wp_autosave( $data['wp_autosave'] );
  1062 
  1123 
  1063 		if ( is_wp_error( $saved ) ) {
  1124 		if ( is_wp_error( $saved ) ) {
  1064 			$response['wp_autosave'] = array( 'success' => false, 'message' => $saved->get_error_message() );
  1125 			$response['wp_autosave'] = array(
       
  1126 				'success' => false,
       
  1127 				'message' => $saved->get_error_message(),
       
  1128 			);
  1065 		} elseif ( empty( $saved ) ) {
  1129 		} elseif ( empty( $saved ) ) {
  1066 			$response['wp_autosave'] = array( 'success' => false, 'message' => __( 'Error while saving.' ) );
  1130 			$response['wp_autosave'] = array(
       
  1131 				'success' => false,
       
  1132 				'message' => __( 'Error while saving.' ),
       
  1133 			);
  1067 		} else {
  1134 		} else {
  1068 			/* translators: draft saved date format, see https://secure.php.net/date */
  1135 			/* translators: draft saved date format, see https://secure.php.net/date */
  1069 			$draft_saved_date_format = __( 'g:i:s a' );
  1136 			$draft_saved_date_format = __( 'g:i:s a' );
  1070 			/* translators: %s: date and time */
  1137 			/* translators: %s: date and time */
  1071 			$response['wp_autosave'] = array( 'success' => true, 'message' => sprintf( __( 'Draft saved at %s.' ), date_i18n( $draft_saved_date_format ) ) );
  1138 			$response['wp_autosave'] = array(
       
  1139 				'success' => true,
       
  1140 				'message' => sprintf( __( 'Draft saved at %s.' ), date_i18n( $draft_saved_date_format ) ),
       
  1141 			);
  1072 		}
  1142 		}
  1073 	}
  1143 	}
  1074 
  1144 
  1075 	return $response;
  1145 	return $response;
  1076 }
  1146 }
  1098 	<script>
  1168 	<script>
  1099 		if ( window.history.replaceState ) {
  1169 		if ( window.history.replaceState ) {
  1100 			window.history.replaceState( null, null, document.getElementById( 'wp-admin-canonical' ).href + window.location.hash );
  1170 			window.history.replaceState( null, null, document.getElementById( 'wp-admin-canonical' ).href + window.location.hash );
  1101 		}
  1171 		}
  1102 	</script>
  1172 	</script>
  1103 <?php
  1173 	<?php
  1104 }
  1174 }
  1105 
  1175 
  1106 /**
  1176 /**
  1107  * Send a referrer policy header so referrers are not sent externally from administration screens.
  1177  * Send a referrer policy header so referrers are not sent externally from administration screens.
  1108  *
  1178  *
  1158 function update_option_new_admin_email( $old_value, $value ) {
  1228 function update_option_new_admin_email( $old_value, $value ) {
  1159 	if ( $value == get_option( 'admin_email' ) || ! is_email( $value ) ) {
  1229 	if ( $value == get_option( 'admin_email' ) || ! is_email( $value ) ) {
  1160 		return;
  1230 		return;
  1161 	}
  1231 	}
  1162 
  1232 
  1163 	$hash = md5( $value . time() . wp_rand() );
  1233 	$hash            = md5( $value . time() . wp_rand() );
  1164 	$new_admin_email = array(
  1234 	$new_admin_email = array(
  1165 		'hash'     => $hash,
  1235 		'hash'     => $hash,
  1166 		'newemail' => $value,
  1236 		'newemail' => $value,
  1167 	);
  1237 	);
  1168 	update_option( 'adminhash', $new_admin_email );
  1238 	update_option( 'adminhash', $new_admin_email );
  1169 
  1239 
  1170 	$switched_locale = switch_to_locale( get_user_locale() );
  1240 	$switched_locale = switch_to_locale( get_user_locale() );
  1171 
  1241 
  1172 	/* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */
  1242 	/* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */
  1173 	$email_text = __( 'Howdy ###USERNAME###,
  1243 	$email_text = __(
       
  1244 		'Howdy ###USERNAME###,
  1174 
  1245 
  1175 You recently requested to have the administration email address on
  1246 You recently requested to have the administration email address on
  1176 your site changed.
  1247 your site changed.
  1177 
  1248 
  1178 If this is correct, please click on the following link to change it:
  1249 If this is correct, please click on the following link to change it:
  1183 
  1254 
  1184 This email has been sent to ###EMAIL###
  1255 This email has been sent to ###EMAIL###
  1185 
  1256 
  1186 Regards,
  1257 Regards,
  1187 All at ###SITENAME###
  1258 All at ###SITENAME###
  1188 ###SITEURL###' );
  1259 ###SITEURL###'
       
  1260 	);
  1189 
  1261 
  1190 	/**
  1262 	/**
  1191 	 * Filters the text of the email sent when a change of site admin email address is attempted.
  1263 	 * Filters the text of the email sent when a change of site admin email address is attempted.
  1192 	 *
  1264 	 *
  1193 	 * The following strings have a special meaning and will get replaced dynamically:
  1265 	 * The following strings have a special meaning and will get replaced dynamically:
  1209 	 * }
  1281 	 * }
  1210 	 */
  1282 	 */
  1211 	$content = apply_filters( 'new_admin_email_content', $email_text, $new_admin_email );
  1283 	$content = apply_filters( 'new_admin_email_content', $email_text, $new_admin_email );
  1212 
  1284 
  1213 	$current_user = wp_get_current_user();
  1285 	$current_user = wp_get_current_user();
  1214 	$content = str_replace( '###USERNAME###', $current_user->user_login, $content );
  1286 	$content      = str_replace( '###USERNAME###', $current_user->user_login, $content );
  1215 	$content = str_replace( '###ADMIN_URL###', esc_url( self_admin_url( 'options.php?adminhash=' . $hash ) ), $content );
  1287 	$content      = str_replace( '###ADMIN_URL###', esc_url( self_admin_url( 'options.php?adminhash=' . $hash ) ), $content );
  1216 	$content = str_replace( '###EMAIL###', $value, $content );
  1288 	$content      = str_replace( '###EMAIL###', $value, $content );
  1217 	$content = str_replace( '###SITENAME###', wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), $content );
  1289 	$content      = str_replace( '###SITENAME###', wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), $content );
  1218 	$content = str_replace( '###SITEURL###', home_url(), $content );
  1290 	$content      = str_replace( '###SITEURL###', home_url(), $content );
  1219 
  1291 
       
  1292 	/* translators: New admin email address notification email subject. %s: Site title */
  1220 	wp_mail( $value, sprintf( __( '[%s] New Admin Email Address' ), wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) ), $content );
  1293 	wp_mail( $value, sprintf( __( '[%s] New Admin Email Address' ), wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) ), $content );
  1221 
  1294 
  1222 	if ( $switched_locale ) {
  1295 	if ( $switched_locale ) {
  1223 		restore_previous_locale();
  1296 		restore_previous_locale();
  1224 	}
  1297 	}
  1269 	 * The suggested text should contain information about any functionality that affects user privacy,
  1342 	 * The suggested text should contain information about any functionality that affects user privacy,
  1270 	 * and will be shown in the Suggested Privacy Policy Content postbox.
  1343 	 * and will be shown in the Suggested Privacy Policy Content postbox.
  1271 	 *
  1344 	 *
  1272 	 * Intended for use from `wp_add_privacy_policy_content()`.
  1345 	 * Intended for use from `wp_add_privacy_policy_content()`.
  1273 	 *
  1346 	 *
  1274 	 * $since 4.9.6
  1347 	 * @since 4.9.6
  1275 	 *
  1348 	 *
  1276 	 * @param string $plugin_name The name of the plugin or theme that is suggesting content for the site's privacy policy.
  1349 	 * @param string $plugin_name The name of the plugin or theme that is suggesting content for the site's privacy policy.
  1277 	 * @param string $policy_text The suggested content for inclusion in the policy.
  1350 	 * @param string $policy_text The suggested content for inclusion in the policy.
  1278 	 */
  1351 	 */
  1279 	public static function add( $plugin_name, $policy_text ) {
  1352 	public static function add( $plugin_name, $policy_text ) {
  1379 			return;
  1452 			return;
  1380 		}
  1453 		}
  1381 
  1454 
  1382 		?>
  1455 		?>
  1383 		<div class="policy-text-updated notice notice-warning is-dismissible">
  1456 		<div class="policy-text-updated notice notice-warning is-dismissible">
  1384 			<p><?php
  1457 			<p>
       
  1458 			<?php
  1385 				printf(
  1459 				printf(
  1386 					/* translators: %s: Privacy Policy Guide URL */
  1460 					/* translators: %s: Privacy Policy Guide URL */
  1387 					__( 'The suggested privacy policy text has changed. Please <a href="%s">review the guide</a> and update your privacy policy.' ),
  1461 					__( 'The suggested privacy policy text has changed. Please <a href="%s">review the guide</a> and update your privacy policy.' ),
  1388 					esc_url( admin_url( 'tools.php?wp-privacy-policy-guide=1' ) )
  1462 					esc_url( admin_url( 'tools.php?wp-privacy-policy-guide=1' ) )
  1389 				);
  1463 				);
  1390 			?></p>
  1464 			?>
       
  1465 			</p>
  1391 		</div>
  1466 		</div>
  1392 		<?php
  1467 		<?php
  1393 	}
  1468 	}
  1394 
  1469 
  1395 	/**
  1470 	/**
  1404 		if ( ! $policy_page_id || $policy_page_id !== (int) $post_id ) {
  1479 		if ( ! $policy_page_id || $policy_page_id !== (int) $post_id ) {
  1405 			return;
  1480 			return;
  1406 		}
  1481 		}
  1407 
  1482 
  1408 		// Remove updated|removed status.
  1483 		// Remove updated|removed status.
  1409 		$old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
  1484 		$old          = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
  1410 		$done = array();
  1485 		$done         = array();
  1411 		$update_cache = false;
  1486 		$update_cache = false;
  1412 
  1487 
  1413 		foreach ( $old as $old_key => $old_data ) {
  1488 		foreach ( $old as $old_key => $old_data ) {
  1414 			if ( ! empty( $old_data['removed'] ) ) {
  1489 			if ( ! empty( $old_data['removed'] ) ) {
  1415 				// Remove the old policy text.
  1490 				// Remove the old policy text.
  1417 				continue;
  1492 				continue;
  1418 			}
  1493 			}
  1419 
  1494 
  1420 			if ( ! empty( $old_data['updated'] ) ) {
  1495 			if ( ! empty( $old_data['updated'] ) ) {
  1421 				// 'updated' is now 'added'.
  1496 				// 'updated' is now 'added'.
  1422 				$done[] = array(
  1497 				$done[]       = array(
  1423 					'plugin_name' => $old_data['plugin_name'],
  1498 					'plugin_name' => $old_data['plugin_name'],
  1424 					'policy_text' => $old_data['policy_text'],
  1499 					'policy_text' => $old_data['policy_text'],
  1425 					'added'       => $old_data['updated'],
  1500 					'added'       => $old_data['updated'],
  1426 				);
  1501 				);
  1427 				$update_cache = true;
  1502 				$update_cache = true;
  1448 	 *
  1523 	 *
  1449 	 * @return array The privacy policy text/informtion added by core and plugins.
  1524 	 * @return array The privacy policy text/informtion added by core and plugins.
  1450 	 */
  1525 	 */
  1451 	public static function get_suggested_policy_text() {
  1526 	public static function get_suggested_policy_text() {
  1452 		$policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
  1527 		$policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
  1453 		$checked = array();
  1528 		$checked        = array();
  1454 		$time = time();
  1529 		$time           = time();
  1455 		$update_cache = false;
  1530 		$update_cache   = false;
  1456 		$new = self::$policy_content;
  1531 		$new            = self::$policy_content;
  1457 		$old = array();
  1532 		$old            = array();
  1458 
  1533 
  1459 		if ( $policy_page_id ) {
  1534 		if ( $policy_page_id ) {
  1460 			$old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
  1535 			$old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
  1461 		}
  1536 		}
  1462 
  1537 
  1467 
  1542 
  1468 				if ( $new_data['policy_text'] === $old_data['policy_text'] ) {
  1543 				if ( $new_data['policy_text'] === $old_data['policy_text'] ) {
  1469 					// Use the new plugin name in case it was changed, translated, etc.
  1544 					// Use the new plugin name in case it was changed, translated, etc.
  1470 					if ( $old_data['plugin_name'] !== $new_data['plugin_name'] ) {
  1545 					if ( $old_data['plugin_name'] !== $new_data['plugin_name'] ) {
  1471 						$old_data['plugin_name'] = $new_data['plugin_name'];
  1546 						$old_data['plugin_name'] = $new_data['plugin_name'];
  1472 						$update_cache = true;
  1547 						$update_cache            = true;
  1473 					}
  1548 					}
  1474 
  1549 
  1475 					// A plugin was re-activated.
  1550 					// A plugin was re-activated.
  1476 					if ( ! empty( $old_data['removed'] ) ) {
  1551 					if ( ! empty( $old_data['removed'] ) ) {
  1477 						unset( $old_data['removed'] );
  1552 						unset( $old_data['removed'] );
  1478 						$old_data['added'] = $time;
  1553 						$old_data['added'] = $time;
  1479 						$update_cache = true;
  1554 						$update_cache      = true;
  1480 					}
  1555 					}
  1481 
  1556 
  1482 					$checked[] = $old_data;
  1557 					$checked[] = $old_data;
  1483 					$found = true;
  1558 					$found     = true;
  1484 				} elseif ( $new_data['plugin_name'] === $old_data['plugin_name'] ) {
  1559 				} elseif ( $new_data['plugin_name'] === $old_data['plugin_name'] ) {
  1485 					// The info for the policy was updated.
  1560 					// The info for the policy was updated.
  1486 					$checked[] = array(
  1561 					$checked[] = array(
  1487 						'plugin_name' => $new_data['plugin_name'],
  1562 						'plugin_name' => $new_data['plugin_name'],
  1488 						'policy_text' => $new_data['policy_text'],
  1563 						'policy_text' => $new_data['policy_text'],
  1489 						'updated'     => $time,
  1564 						'updated'     => $time,
  1490 					);
  1565 					);
  1491 					$found = $update_cache = true;
  1566 					$found     = $update_cache = true;
  1492 				}
  1567 				}
  1493 
  1568 
  1494 				if ( $found ) {
  1569 				if ( $found ) {
  1495 					unset( $new[ $new_key ], $old[ $old_key ] );
  1570 					unset( $new[ $new_key ], $old[ $old_key ] );
  1496 					continue 2;
  1571 					continue 2;
  1538 
  1613 
  1539 	/**
  1614 	/**
  1540 	 * Add a notice with a link to the guide when editing the privacy policy page.
  1615 	 * Add a notice with a link to the guide when editing the privacy policy page.
  1541 	 *
  1616 	 *
  1542 	 * @since 4.9.6
  1617 	 * @since 4.9.6
  1543 	 *
  1618 	 * @since 5.0.0 The $post parameter is now optional.
  1544 	 * @param $post WP_Post The currently edited post.
  1619 	 *
       
  1620 	 * @param WP_Post|null $post The currently edited post. Default null.
  1545 	 */
  1621 	 */
  1546 	public static function notice( $post ) {
  1622 	public static function notice( $post = null ) {
       
  1623 		if ( is_null( $post ) ) {
       
  1624 			global $post;
       
  1625 		} else {
       
  1626 			$post = get_post( $post );
       
  1627 		}
       
  1628 
  1547 		if ( ! ( $post instanceof WP_Post ) ) {
  1629 		if ( ! ( $post instanceof WP_Post ) ) {
  1548 			return;
  1630 			return;
  1549 		}
  1631 		}
  1550 
  1632 
  1551 		if ( ! current_user_can( 'manage_privacy_options' ) ) {
  1633 		if ( ! current_user_can( 'manage_privacy_options' ) ) {
  1552 			return;
  1634 			return;
  1553 		}
  1635 		}
  1554 
  1636 
  1555 		$policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
  1637 		$policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
  1556 
  1638 
  1557 		if ( ! $policy_page_id || $policy_page_id != $post->ID ) {
  1639 		if ( ! $policy_page_id || $policy_page_id !== $post->ID ) {
  1558 			return;
  1640 			return;
  1559 		}
  1641 		}
  1560 
  1642 
  1561 		?>
  1643 		$message = __( 'Need help putting together your new Privacy Policy page? Check out our guide for recommendations on what content to include, along with policies suggested by your plugins and theme.' );
  1562 		<div class="notice notice-warning inline wp-pp-notice">
  1644 		$url     = esc_url( admin_url( 'tools.php?wp-privacy-policy-guide=1' ) );
  1563 			<p>
  1645 		$label   = __( 'View Privacy Policy Guide.' );
  1564 			<?php
  1646 
  1565 			/* translators: 1: Privacy Policy guide URL, 2: additional link attributes, 3: accessibility text */
  1647 		if ( get_current_screen()->is_block_editor() ) {
  1566 			printf(
  1648 			wp_enqueue_script( 'wp-notices' );
  1567 				__( 'Need help putting together your new Privacy Policy page? <a href="%1$s" %2$s>Check out our guide%3$s</a> for recommendations on what content to include, along with policies suggested by your plugins and theme.' ),
  1649 			$action = array(
  1568 				admin_url( 'tools.php?wp-privacy-policy-guide=1' ),
  1650 				'url'   => $url,
  1569 				'target="_blank"',
  1651 				'label' => $label,
       
  1652 			);
       
  1653 			wp_add_inline_script(
       
  1654 				'wp-notices',
  1570 				sprintf(
  1655 				sprintf(
  1571 					'<span class="screen-reader-text"> %s</span>',
  1656 					'wp.data.dispatch( "core/notices" ).createWarningNotice( "%s", { actions: [ %s ], isDismissible: false } )',
       
  1657 					$message,
       
  1658 					wp_json_encode( $action )
       
  1659 				),
       
  1660 				'after'
       
  1661 			);
       
  1662 		} else {
       
  1663 			?>
       
  1664 			<div class="notice notice-warning inline wp-pp-notice">
       
  1665 				<p>
       
  1666 				<?php
       
  1667 				echo $message;
       
  1668 				printf(
       
  1669 					' <a href="%s" target="_blank">%s <span class="screen-reader-text">%s</span></a>',
       
  1670 					$url,
       
  1671 					$label,
  1572 					/* translators: accessibility text */
  1672 					/* translators: accessibility text */
  1573 					__( '(opens in a new tab)' )
  1673 					__( '(opens in a new tab)' )
  1574 				)
  1674 				);
  1575 			);
  1675 				?>
  1576 			?>
  1676 				</p>
  1577 			</p>
  1677 			</div>
  1578 		</div>
  1678 			<?php
  1579 		<?php
  1679 		}
  1580 
       
  1581 	}
  1680 	}
  1582 
  1681 
  1583 	/**
  1682 	/**
  1584 	 * Output the privacy policy guide together with content from the theme and plugins.
  1683 	 * Output the privacy policy guide together with content from the theme and plugins.
  1585 	 *
  1684 	 *
  1587 	 */
  1686 	 */
  1588 	public static function privacy_policy_guide() {
  1687 	public static function privacy_policy_guide() {
  1589 
  1688 
  1590 		$content_array = self::get_suggested_policy_text();
  1689 		$content_array = self::get_suggested_policy_text();
  1591 
  1690 
  1592 		$content = '';
  1691 		$content       = '';
  1593 		$toc = array( '<li><a href="#wp-privacy-policy-guide-introduction">' . __( 'Introduction' ) . '</a></li>' );
  1692 		$toc           = array( '<li><a href="#wp-privacy-policy-guide-introduction">' . __( 'Introduction' ) . '</a></li>' );
  1594 		$date_format = __( 'F j, Y' );
  1693 		$date_format   = __( 'F j, Y' );
  1595 		$copy = __( 'Copy' );
  1694 		$copy          = __( 'Copy this section to clipboard' );
  1596 		$return_to_top = '<a href="#" class="return-to-top">' . __( '&uarr; Return to Top' ) . '</a>';
  1695 		$return_to_top = '<a href="#" class="return-to-top">' . __( '&uarr; Return to Top' ) . '</a>';
  1597 
  1696 
  1598 		foreach ( $content_array as $section ) {
  1697 		foreach ( $content_array as $section ) {
  1599 			$class = $meta = $removed = '';
  1698 			$class = $meta = $removed = '';
  1600 
  1699 
  1601 			if ( ! empty( $section['removed'] ) ) {
  1700 			if ( ! empty( $section['removed'] ) ) {
  1602 				$class = ' text-removed';
  1701 				$class = ' text-removed';
  1603 				$date = date_i18n( $date_format, $section['removed'] );
  1702 				$date  = date_i18n( $date_format, $section['removed'] );
  1604 				$meta  = sprintf( __( 'Removed %s.' ), $date );
  1703 				$meta  = sprintf( __( 'Removed %s.' ), $date );
  1605 
  1704 
  1606 				$removed = __( 'You deactivated this plugin on %s and may no longer need this policy.' );
  1705 				$removed = __( 'You deactivated this plugin on %s and may no longer need this policy.' );
  1607 				$removed = '<div class="error inline"><p>' . sprintf( $removed, $date ) . '</p></div>';
  1706 				$removed = '<div class="error inline"><p>' . sprintf( $removed, $date ) . '</p></div>';
  1608 			} elseif ( ! empty( $section['updated'] ) ) {
  1707 			} elseif ( ! empty( $section['updated'] ) ) {
  1609 				$class = ' text-updated';
  1708 				$class = ' text-updated';
  1610 				$date = date_i18n( $date_format, $section['updated'] );
  1709 				$date  = date_i18n( $date_format, $section['updated'] );
  1611 				$meta  = sprintf( __( 'Updated %s.' ), $date );
  1710 				$meta  = sprintf( __( 'Updated %s.' ), $date );
  1612 			}
  1711 			}
  1613 
  1712 
  1614 			if ( $meta ) {
  1713 			if ( $meta ) {
  1615 				$meta = '<br><span class="privacy-text-meta">' . $meta . '</span>';
  1714 				$meta = '<br><span class="privacy-text-meta">' . $meta . '</span>';
  1616 			}
  1715 			}
  1617 
  1716 
  1618 			$plugin_name = esc_html( $section['plugin_name'] );
  1717 			$plugin_name = esc_html( $section['plugin_name'] );
  1619 			$toc_id = 'wp-privacy-policy-guide-' . sanitize_title( $plugin_name );
  1718 			$toc_id      = 'wp-privacy-policy-guide-' . sanitize_title( $plugin_name );
  1620 			$toc[] = sprintf( '<li><a href="#%1$s">%2$s</a>' . $meta . '</li>', $toc_id, $plugin_name );
  1719 			$toc[]       = sprintf( '<li><a href="#%1$s">%2$s</a>' . $meta . '</li>', $toc_id, $plugin_name );
  1621 
  1720 
  1622 			$content .= '<div class="privacy-text-section' . $class . '">';
  1721 			$content .= '<div class="privacy-text-section' . $class . '">';
  1623 			$content .= '<a id="' . $toc_id . '">&nbsp;</a>';
  1722 			$content .= '<a id="' . $toc_id . '">&nbsp;</a>';
  1624 			/* translators: %s: plugin name */
  1723 			/* translators: %s: plugin name */
  1625 			$content .= '<h2>' . sprintf( __( 'Source: %s' ), $plugin_name ) . '</h2>';
  1724 			$content .= '<h2>' . sprintf( __( 'Source: %s' ), $plugin_name ) . '</h2>';
  1627 
  1726 
  1628 			$content .= '<div class="policy-text">' . $section['policy_text'] . '</div>';
  1727 			$content .= '<div class="policy-text">' . $section['policy_text'] . '</div>';
  1629 			$content .= $return_to_top;
  1728 			$content .= $return_to_top;
  1630 
  1729 
  1631 			if ( empty( $section['removed'] ) ) {
  1730 			if ( empty( $section['removed'] ) ) {
  1632 				$content .= '<div class="privacy-text-actions">';
  1731 				$content         .= '<div class="privacy-text-actions">';
  1633 					$content .= '<button type="button" class="privacy-text-copy button">';
  1732 					$content     .= '<button type="button" class="privacy-text-copy button">';
  1634 						$content .= $copy;
  1733 						$content .= $copy;
  1635 						$content .= '<span class="screen-reader-text">' . sprintf( __( 'Copy suggested policy text from %s.' ), $plugin_name ) . '</span>';
  1734 						$content .= '<span class="screen-reader-text">' . sprintf( __( 'Copy suggested policy text from %s.' ), $plugin_name ) . '</span>';
  1636 					$content .= '</button>';
  1735 					$content     .= '</button>';
  1637 				$content .= '</div>';
  1736 				$content         .= '</div>';
  1638 			}
  1737 			}
  1639 
  1738 
  1640 			$content .= "</div>\n"; // End of .privacy-text-section.
  1739 			$content .= "</div>\n"; // End of .privacy-text-section.
  1641 		}
  1740 		}
  1642 
  1741 
  1672 
  1771 
  1673 	/**
  1772 	/**
  1674 	 * Return the default suggested privacy policy content.
  1773 	 * Return the default suggested privacy policy content.
  1675 	 *
  1774 	 *
  1676 	 * @since 4.9.6
  1775 	 * @since 4.9.6
  1677 	 *
  1776 	 * @since 5.0.0 Added the `$blocks` parameter.
  1678 	 * @param bool $descr Whether to include the descriptions under the section headings. Default false.
  1777 	 *
       
  1778 	 * @param bool $description Whether to include the descriptions under the section headings. Default false.
       
  1779 	 * @param bool $blocks      Whether to format the content for the block editor. Default true.
  1679 	 * @return string The default policy content.
  1780 	 * @return string The default policy content.
  1680 	 */
  1781 	 */
  1681 	public static function get_default_content( $descr = false ) {
  1782 	public static function get_default_content( $description = false, $blocks = true ) {
  1682 		$suggested_text = $descr ? '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:' ) . ' </strong>' : '';
  1783 		$suggested_text = $description ? '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:' ) . ' </strong>' : '';
  1683 		$content = '';
  1784 		$content        = '';
       
  1785 		$strings        = array();
  1684 
  1786 
  1685 		// Start of the suggested privacy policy text.
  1787 		// Start of the suggested privacy policy text.
  1686 		$descr && $content .=
  1788 		if ( $description ) {
  1687 			'<div class="wp-suggested-text">';
  1789 			$strings[] = '<div class="wp-suggested-text">';
  1688 		$content .=
  1790 		}
  1689 			'<h2>' . __( 'Who we are' ) . '</h2>';
  1791 
  1690 		$descr && $content .=
  1792 		/* translators: default privacy policy heading. */
  1691 			'<p class="privacy-policy-tutorial">' . __( 'In this section you should note your site URL, as well as the name of the company, organization, or individual behind it, and some accurate contact information.' ) . '</p>' .
  1793 		$strings[] = '<h2>' . __( 'Who we are' ) . '</h2>';
  1692 			'<p class="privacy-policy-tutorial">' . __( 'The amount of information you may be required to show will vary depending on your local or national business regulations. You may, for example, be required to display a physical address, a registered address, or your company registration number.' ) . '</p>';
  1794 
  1693 		$content .=
  1795 		if ( $description ) {
  1694 			/* translators: %s Site URL */
  1796 			/* translators: privacy policy tutorial. */
  1695 			'<p>' . $suggested_text . sprintf( __( 'Our website address is: %s.' ), get_bloginfo( 'url', 'display' ) ) . '</p>' .
  1797 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should note your site URL, as well as the name of the company, organization, or individual behind it, and some accurate contact information.' ) . '</p>';
  1696 
  1798 			/* translators: privacy policy tutorial. */
  1697 			'<h2>' . __( 'What personal data we collect and why we collect it' ) . '</h2>';
  1799 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'The amount of information you may be required to show will vary depending on your local or national business regulations. You may, for example, be required to display a physical address, a registered address, or your company registration number.' ) . '</p>';
  1698 		$descr && $content .=
  1800 		}
  1699 			'<p class="privacy-policy-tutorial">' . __( 'In this section you should note what personal data you collect from users and site visitors. This may include personal data, such as name, email address, personal account preferences; transactional data, such as purchase information; and technical data, such as information about cookies.' ) . '</p>' .
  1801 
  1700 			'<p class="privacy-policy-tutorial">' . __( 'You should also note any collection and retention of sensitive personal data, such as data concerning health.' ) . '</p>' .
  1802 		/* translators: default privacy policy text, %s Site URL. */
  1701 			'<p class="privacy-policy-tutorial">' . __( 'In addition to listing what personal data you collect, you need to note why you collect it. These explanations must note either the legal basis for your data collection and retention or the active consent the user has given.' ) . '</p>' .
  1803 		$strings[] = '<p>' . $suggested_text . sprintf( __( 'Our website address is: %s.' ), get_bloginfo( 'url', 'display' ) ) . '</p>';
  1702 			'<p class="privacy-policy-tutorial">' . __( 'Personal data is not just created by a user&#8217;s interactions with your site. Personal data is also generated from technical processes such as contact forms, comments, cookies, analytics, and third party embeds.' ) . '</p>' .
  1804 
  1703 			'<p class="privacy-policy-tutorial">' . __( 'By default WordPress does not collect any personal data about visitors, and only collects the data shown on the User Profile screen from registered users. However some of your plugins may collect personal data. You should add the relevant information below.' ) . '</p>';
  1805 		/* translators: default privacy policy heading. */
  1704 
  1806 		$strings[] = '<h2>' . __( 'What personal data we collect and why we collect it' ) . '</h2>';
  1705 		$content .=
  1807 
  1706 			'<h3>' . __( 'Comments' ) . '</h3>';
  1808 		if ( $description ) {
  1707 		$descr && $content .=
  1809 			/* translators: privacy policy tutorial. */
  1708 			'<p class="privacy-policy-tutorial">' . __( 'In this subsection you should note what information is captured through comments. We have noted the data which WordPress collects by default.' ) . '</p>';
  1810 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should note what personal data you collect from users and site visitors. This may include personal data, such as name, email address, personal account preferences; transactional data, such as purchase information; and technical data, such as information about cookies.' ) . '</p>';
  1709 		$content .=
  1811 			/* translators: privacy policy tutorial. */
  1710 			'<p>' . $suggested_text . __( 'When visitors leave comments on the site we collect the data shown in the comments form, and also the visitor&#8217;s IP address and browser user agent string to help spam detection.' ) . '</p>' .
  1812 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'You should also note any collection and retention of sensitive personal data, such as data concerning health.' ) . '</p>';
  1711 			'<p>' . __( 'An anonymized string created from your email address (also called a hash) may be provided to the Gravatar service to see if you are using it. The Gravatar service privacy policy is available here: https://automattic.com/privacy/. After approval of your comment, your profile picture is visible to the public in the context of your comment.' ) . '</p>' .
  1813 			/* translators: privacy policy tutorial. */
  1712 
  1814 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In addition to listing what personal data you collect, you need to note why you collect it. These explanations must note either the legal basis for your data collection and retention or the active consent the user has given.' ) . '</p>';
  1713 			'<h3>' . __( 'Media' ) . '</h3>';
  1815 			/* translators: privacy policy tutorial. */
  1714 		$descr && $content .=
  1816 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'Personal data is not just created by a user&#8217;s interactions with your site. Personal data is also generated from technical processes such as contact forms, comments, cookies, analytics, and third party embeds.' ) . '</p>';
  1715 			'<p class="privacy-policy-tutorial">' . __( 'In this subsection you should note what information may be disclosed by users who can upload media files. All uploaded files are usually publicly accessible.' ) . '</p>';
  1817 			/* translators: privacy policy tutorial. */
  1716 		$content .=
  1818 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'By default WordPress does not collect any personal data about visitors, and only collects the data shown on the User Profile screen from registered users. However some of your plugins may collect personal data. You should add the relevant information below.' ) . '</p>';
  1717 			'<p>' . $suggested_text . __( 'If you upload images to the website, you should avoid uploading images with embedded location data (EXIF GPS) included. Visitors to the website can download and extract any location data from images on the website.' ) . '</p>' .
  1819 		}
  1718 
  1820 
  1719 			'<h3>' . __( 'Contact forms' ) . '</h3>';
  1821 		/* translators: default privacy policy heading. */
  1720 		$descr && $content .=
  1822 		$strings[] = '<h3>' . __( 'Comments' ) . '</h3>';
  1721 			'<p class="privacy-policy-tutorial">' . __( 'By default, WordPress does not include a contact form. If you use a contact form plugin, use this subsection to note what personal data is captured when someone submits a contact form, and how long you keep it. For example, you may note that you keep contact form submissions for a certain period for customer service purposes, but you do not use the information submitted through them for marketing purposes.' ) . '</p>';
  1823 
  1722 
  1824 		if ( $description ) {
  1723 		$content .=
  1825 			/* translators: privacy policy tutorial. */
  1724 			'<h3>' . __( 'Cookies' ) . '</h3>';
  1826 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this subsection you should note what information is captured through comments. We have noted the data which WordPress collects by default.' ) . '</p>';
  1725 		$descr && $content .=
  1827 		}
  1726 			'<p class="privacy-policy-tutorial">' . __( 'In this subsection you should list the cookies your web site uses, including those set by your plugins, social media, and analytics. We have provided the cookies which WordPress installs by default.' ) . '</p>';
  1828 
  1727 		$content .=
  1829 		/* translators: default privacy policy text. */
  1728 			'<p>' . $suggested_text . __( 'If you leave a comment on our site you may opt-in to saving your name, email address and website in cookies. These are for your convenience so that you do not have to fill in your details again when you leave another comment. These cookies will last for one year.' ) . '</p>' .
  1830 		$strings[] = '<p>' . $suggested_text . __( 'When visitors leave comments on the site we collect the data shown in the comments form, and also the visitor&#8217;s IP address and browser user agent string to help spam detection.' ) . '</p>';
  1729 			'<p>' . __( 'If you have an account and you log in to this site, we will set a temporary cookie to determine if your browser accepts cookies. This cookie contains no personal data and is discarded when you close your browser.' ) . '</p>' .
  1831 		/* translators: default privacy policy text. */
  1730 			'<p>' . __( 'When you log in, we will also set up several cookies to save your login information and your screen display choices. Login cookies last for two days, and screen options cookies last for a year. If you select &quot;Remember Me&quot;, your login will persist for two weeks. If you log out of your account, the login cookies will be removed.' ) . '</p>' .
  1832 		$strings[] = '<p>' . __( 'An anonymized string created from your email address (also called a hash) may be provided to the Gravatar service to see if you are using it. The Gravatar service privacy policy is available here: https://automattic.com/privacy/. After approval of your comment, your profile picture is visible to the public in the context of your comment.' ) . '</p>';
  1731 			'<p>' . __( 'If you edit or publish an article, an additional cookie will be saved in your browser. This cookie includes no personal data and simply indicates the post ID of the article you just edited. It expires after 1 day.' ) . '</p>' .
  1833 
  1732 
  1834 		/* translators: default privacy policy heading. */
  1733 			'<h3>' . __( 'Embedded content from other websites' ) . '</h3>' .
  1835 		$strings[] = '<h3>' . __( 'Media' ) . '</h3>';
  1734 			'<p>' . $suggested_text . __( 'Articles on this site may include embedded content (e.g. videos, images, articles, etc.). Embedded content from other websites behaves in the exact same way as if the visitor has visited the other website.' ) . '</p>' .
  1836 
  1735 			'<p>' . __( 'These websites may collect data about you, use cookies, embed additional third-party tracking, and monitor your interaction with that embedded content, including tracking your interaction with the embedded content if you have an account and are logged in to that website.' ) . '</p>' .
  1837 		if ( $description ) {
  1736 
  1838 			/* translators: privacy policy tutorial. */
  1737 			'<h3>' . __( 'Analytics' ) . '</h3>';
  1839 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this subsection you should note what information may be disclosed by users who can upload media files. All uploaded files are usually publicly accessible.' ) . '</p>';
  1738 		$descr && $content .=
  1840 		}
  1739 			'<p class="privacy-policy-tutorial">' . __( 'In this subsection you should note what analytics package you use, how users can opt out of analytics tracking, and a link to your analytics provider&#8217;s privacy policy, if any.' ) . '</p>' .
  1841 
  1740 			'<p class="privacy-policy-tutorial">' . __( 'By default WordPress does not collect any analytics data. However, many web hosting accounts collect some anonymous analytics data. You may also have installed a WordPress plugin that provides analytics services. In that case, add information from that plugin here.' ) . '</p>';
  1842 		/* translators: default privacy policy text. */
  1741 
  1843 		$strings[] = '<p>' . $suggested_text . __( 'If you upload images to the website, you should avoid uploading images with embedded location data (EXIF GPS) included. Visitors to the website can download and extract any location data from images on the website.' ) . '</p>';
  1742 		$content .=
  1844 
  1743 			'<h2>' . __( 'Who we share your data with' ) . '</h2>';
  1845 		/* translators: default privacy policy heading. */
  1744 		$descr && $content .=
  1846 		$strings[] = '<h3>' . __( 'Contact forms' ) . '</h3>';
  1745 			'<p class="privacy-policy-tutorial">' . __( 'In this section you should name and list all third party providers with whom you share site data, including partners, cloud-based services, payment processors, and third party service providers, and note what data you share with them and why. Link to their own privacy policies if possible.' ) . '</p>' .
  1847 
  1746 			'<p class="privacy-policy-tutorial">' . __( 'By default WordPress does not share any personal data with anyone.' ) . '</p>';
  1848 		if ( $description ) {
  1747 
  1849 			/* translators: privacy policy tutorial. */
  1748 		$content .=
  1850 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'By default, WordPress does not include a contact form. If you use a contact form plugin, use this subsection to note what personal data is captured when someone submits a contact form, and how long you keep it. For example, you may note that you keep contact form submissions for a certain period for customer service purposes, but you do not use the information submitted through them for marketing purposes.' ) . '</p>';
  1749 			'<h2>' . __( 'How long we retain your data' ) . '</h2>';
  1851 		}
  1750 		$descr && $content .=
  1852 
  1751 			'<p class="privacy-policy-tutorial">' . __( 'In this section you should explain how long you retain personal data collected or processed by the web site. While it is your responsibility to come up with the schedule of how long you keep each dataset for and why you keep it, that information does need to be listed here. For example, you may want to say that you keep contact form entries for six months, analytics records for a year, and customer purchase records for ten years.' ) . '</p>';
  1853 		/* translators: default privacy policy heading. */
  1752 		$content .=
  1854 		$strings[] = '<h3>' . __( 'Cookies' ) . '</h3>';
  1753 			'<p>' . $suggested_text . __( 'If you leave a comment, the comment and its metadata are retained indefinitely. This is so we can recognize and approve any follow-up comments automatically instead of holding them in a moderation queue.' ) . '</p>' .
  1855 
  1754 			'<p>' . __( 'For users that register on our website (if any), we also store the personal information they provide in their user profile. All users can see, edit, or delete their personal information at any time (except they cannot change their username). Website administrators can also see and edit that information.' ) . '</p>' .
  1856 		if ( $description ) {
  1755 
  1857 			/* translators: privacy policy tutorial. */
  1756 			'<h2>' . __( 'What rights you have over your data' ) . '</h2>';
  1858 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this subsection you should list the cookies your web site uses, including those set by your plugins, social media, and analytics. We have provided the cookies which WordPress installs by default.' ) . '</p>';
  1757 		$descr && $content .=
  1859 		}
  1758 			'<p class="privacy-policy-tutorial">' . __( 'In this section you should explain what rights your users have over their data and how they can invoke those rights.' ) . '</p>';
  1860 
  1759 		$content .=
  1861 		/* translators: default privacy policy text. */
  1760 			'<p>' . $suggested_text . __( 'If you have an account on this site, or have left comments, you can request to receive an exported file of the personal data we hold about you, including any data you have provided to us. You can also request that we erase any personal data we hold about you. This does not include any data we are obliged to keep for administrative, legal, or security purposes.' ) . '</p>' .
  1862 		$strings[] = '<p>' . $suggested_text . __( 'If you leave a comment on our site you may opt-in to saving your name, email address and website in cookies. These are for your convenience so that you do not have to fill in your details again when you leave another comment. These cookies will last for one year.' ) . '</p>';
  1761 
  1863 		/* translators: default privacy policy text. */
  1762 			'<h2>' . __( 'Where we send your data' ) . '</h2>';
  1864 		$strings[] = '<p>' . __( 'If you visit our login page, we will set a temporary cookie to determine if your browser accepts cookies. This cookie contains no personal data and is discarded when you close your browser.' ) . '</p>';
  1763 		$descr && $content .=
  1865 		/* translators: default privacy policy text. */
  1764 			'<p class="privacy-policy-tutorial">' . __( 'In this section you should list all transfers of your site data outside the European Union and describe the means by which that data is safeguarded to European data protection standards. This could include your web hosting, cloud storage, or other third party services.' ) . '</p>' .
  1866 		$strings[] = '<p>' . __( 'When you log in, we will also set up several cookies to save your login information and your screen display choices. Login cookies last for two days, and screen options cookies last for a year. If you select &quot;Remember Me&quot;, your login will persist for two weeks. If you log out of your account, the login cookies will be removed.' ) . '</p>';
  1765 			'<p class="privacy-policy-tutorial">' . __( 'European data protection law requires data about European residents which is transferred outside the European Union to be safeguarded to the same standards as if the data was in Europe. So in addition to listing where data goes, you should describe how you ensure that these standards are met either by yourself or by your third party providers, whether that is through an agreement such as Privacy Shield, model clauses in your contracts, or binding corporate rules.' ) . '</p>';
  1867 		/* translators: default privacy policy text. */
  1766 		$content .=
  1868 		$strings[] = '<p>' . __( 'If you edit or publish an article, an additional cookie will be saved in your browser. This cookie includes no personal data and simply indicates the post ID of the article you just edited. It expires after 1 day.' ) . '</p>';
  1767 			'<p>' . $suggested_text . __( 'Visitor comments may be checked through an automated spam detection service.' ) . '</p>' .
  1869 
  1768 
  1870 		/* translators: default privacy policy heading. */
  1769 			'<h2>' . __( 'Your contact information' ) . '</h2>';
  1871 		$strings[] = '<h3>' . __( 'Embedded content from other websites' ) . '</h3>';
  1770 		$descr && $content .=
  1872 		/* translators: default privacy policy text. */
  1771 			'<p class="privacy-policy-tutorial">' . __( 'In this section you should provide a contact method for privacy-specific concerns. If you are required to have a Data Protection Officer, list their name and full contact details here as well.' ) . '</p>';
  1873 		$strings[] = '<p>' . $suggested_text . __( 'Articles on this site may include embedded content (e.g. videos, images, articles, etc.). Embedded content from other websites behaves in the exact same way as if the visitor has visited the other website.' ) . '</p>';
  1772 
  1874 		/* translators: default privacy policy text. */
  1773 		$content .=
  1875 		$strings[] = '<p>' . __( 'These websites may collect data about you, use cookies, embed additional third-party tracking, and monitor your interaction with that embedded content, including tracking your interaction with the embedded content if you have an account and are logged in to that website.' ) . '</p>';
  1774 			'<h2>' . __( 'Additional information' ) . '</h2>';
  1876 
  1775 		$descr && $content .=
  1877 		/* translators: default privacy policy heading. */
  1776 			'<p class="privacy-policy-tutorial">' . __( 'If you use your site for commercial purposes and you engage in more complex collection or processing of personal data, you should note the following information in your privacy policy in addition to the information we have already discussed.' ) . '</p>';
  1878 		$strings[] = '<h3>' . __( 'Analytics' ) . '</h3>';
  1777 
  1879 
  1778 		$content .=
  1880 		if ( $description ) {
  1779 			'<h3>' . __( 'How we protect your data' ) . '</h3>';
  1881 			/* translators: privacy policy tutorial. */
  1780 		$descr && $content .=
  1882 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this subsection you should note what analytics package you use, how users can opt out of analytics tracking, and a link to your analytics provider&#8217;s privacy policy, if any.' ) . '</p>';
  1781 			'<p class="privacy-policy-tutorial">' . __( 'In this section you should explain what measures you have taken to protect your users&#8217; data. This could include technical measures such as encryption; security measures such as two factor authentication; and measures such as staff training in data protection. If you have carried out a Privacy Impact Assessment, you can mention it here too.' ) . '</p>';
  1883 			/* translators: privacy policy tutorial. */
  1782 
  1884 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'By default WordPress does not collect any analytics data. However, many web hosting accounts collect some anonymous analytics data. You may also have installed a WordPress plugin that provides analytics services. In that case, add information from that plugin here.' ) . '</p>';
  1783 		$content .=
  1885 		}
  1784 			'<h3>' . __( 'What data breach procedures we have in place' ) . '</h3>';
  1886 
  1785 		$descr && $content .=
  1887 		/* translators: default privacy policy heading. */
  1786 			'<p class="privacy-policy-tutorial">' . __( 'In this section you should explain what procedures you have in place to deal with data breaches, either potential or real, such as internal reporting systems, contact mechanisms, or bug bounties.' ) . '</p>';
  1888 		$strings[] = '<h2>' . __( 'Who we share your data with' ) . '</h2>';
  1787 
  1889 
  1788 		$content .=
  1890 		if ( $description ) {
  1789 			'<h3>' . __( 'What third parties we receive data from' ) . '</h3>';
  1891 			/* translators: privacy policy tutorial. */
  1790 		$descr && $content .=
  1892 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should name and list all third party providers with whom you share site data, including partners, cloud-based services, payment processors, and third party service providers, and note what data you share with them and why. Link to their own privacy policies if possible.' ) . '</p>';
  1791 			'<p class="privacy-policy-tutorial">' . __( 'If your web site receives data about users from third parties, including advertisers, this information must be included within the section of your privacy policy dealing with third party data.' ) . '</p>';
  1893 			/* translators: privacy policy tutorial. */
  1792 
  1894 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'By default WordPress does not share any personal data with anyone.' ) . '</p>';
  1793 		$content .=
  1895 		}
  1794 			'<h3>' . __( 'What automated decision making and/or profiling we do with user data' ) . '</h3>';
  1896 
  1795 		$descr && $content .=
  1897 		/* translators: default privacy policy heading. */
  1796 			'<p class="privacy-policy-tutorial">' . __( 'If your web site provides a service which includes automated decision making - for example, allowing customers to apply for credit, or aggregating their data into an advertising profile - you must note that this is taking place, and include information about how that information is used, what decisions are made with that aggregated data, and what rights users have over decisions made without human intervention.' ) . '</p>';
  1898 		$strings[] = '<h2>' . __( 'How long we retain your data' ) . '</h2>';
  1797 
  1899 
  1798 		$content .=
  1900 		if ( $description ) {
  1799 			'<h3>' . __( 'Industry regulatory disclosure requirements' ) . '</h3>';
  1901 			/* translators: privacy policy tutorial. */
  1800 		$descr && $content .=
  1902 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should explain how long you retain personal data collected or processed by the web site. While it is your responsibility to come up with the schedule of how long you keep each dataset for and why you keep it, that information does need to be listed here. For example, you may want to say that you keep contact form entries for six months, analytics records for a year, and customer purchase records for ten years.' ) . '</p>';
  1801 			'<p class="privacy-policy-tutorial">' . __( 'If you are a member of a regulated industry, or if you are subject to additional privacy laws, you may be required to disclose that information here.' ) . '</p>' .
  1903 		}
  1802 			'</div>';
  1904 
       
  1905 		/* translators: default privacy policy text. */
       
  1906 		$strings[] = '<p>' . $suggested_text . __( 'If you leave a comment, the comment and its metadata are retained indefinitely. This is so we can recognize and approve any follow-up comments automatically instead of holding them in a moderation queue.' ) . '</p>';
       
  1907 		/* translators: default privacy policy text. */
       
  1908 		$strings[] = '<p>' . __( 'For users that register on our website (if any), we also store the personal information they provide in their user profile. All users can see, edit, or delete their personal information at any time (except they cannot change their username). Website administrators can also see and edit that information.' ) . '</p>';
       
  1909 
       
  1910 		/* translators: default privacy policy heading. */
       
  1911 		$strings[] = '<h2>' . __( 'What rights you have over your data' ) . '</h2>';
       
  1912 
       
  1913 		if ( $description ) {
       
  1914 			/* translators: privacy policy tutorial. */
       
  1915 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should explain what rights your users have over their data and how they can invoke those rights.' ) . '</p>';
       
  1916 		}
       
  1917 
       
  1918 		/* translators: default privacy policy text. */
       
  1919 		$strings[] = '<p>' . $suggested_text . __( 'If you have an account on this site, or have left comments, you can request to receive an exported file of the personal data we hold about you, including any data you have provided to us. You can also request that we erase any personal data we hold about you. This does not include any data we are obliged to keep for administrative, legal, or security purposes.' ) . '</p>';
       
  1920 
       
  1921 		/* translators: default privacy policy heading. */
       
  1922 		$strings[] = '<h2>' . __( 'Where we send your data' ) . '</h2>';
       
  1923 
       
  1924 		if ( $description ) {
       
  1925 			/* translators: privacy policy tutorial. */
       
  1926 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should list all transfers of your site data outside the European Union and describe the means by which that data is safeguarded to European data protection standards. This could include your web hosting, cloud storage, or other third party services.' ) . '</p>';
       
  1927 			/* translators: privacy policy tutorial. */
       
  1928 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'European data protection law requires data about European residents which is transferred outside the European Union to be safeguarded to the same standards as if the data was in Europe. So in addition to listing where data goes, you should describe how you ensure that these standards are met either by yourself or by your third party providers, whether that is through an agreement such as Privacy Shield, model clauses in your contracts, or binding corporate rules.' ) . '</p>';
       
  1929 		}
       
  1930 
       
  1931 		/* translators: default privacy policy text. */
       
  1932 		$strings[] = '<p>' . $suggested_text . __( 'Visitor comments may be checked through an automated spam detection service.' ) . '</p>';
       
  1933 
       
  1934 		/* translators: default privacy policy heading. */
       
  1935 		$strings[] = '<h2>' . __( 'Your contact information' ) . '</h2>';
       
  1936 
       
  1937 		if ( $description ) {
       
  1938 			/* translators: privacy policy tutorial. */
       
  1939 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should provide a contact method for privacy-specific concerns. If you are required to have a Data Protection Officer, list their name and full contact details here as well.' ) . '</p>';
       
  1940 		}
       
  1941 
       
  1942 		/* translators: default privacy policy heading. */
       
  1943 		$strings[] = '<h2>' . __( 'Additional information' ) . '</h2>';
       
  1944 
       
  1945 		if ( $description ) {
       
  1946 			/* translators: privacy policy tutorial. */
       
  1947 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'If you use your site for commercial purposes and you engage in more complex collection or processing of personal data, you should note the following information in your privacy policy in addition to the information we have already discussed.' ) . '</p>';
       
  1948 		}
       
  1949 
       
  1950 		/* translators: default privacy policy heading. */
       
  1951 		$strings[] = '<h3>' . __( 'How we protect your data' ) . '</h3>';
       
  1952 
       
  1953 		if ( $description ) {
       
  1954 			/* translators: privacy policy tutorial. */
       
  1955 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should explain what measures you have taken to protect your users&#8217; data. This could include technical measures such as encryption; security measures such as two factor authentication; and measures such as staff training in data protection. If you have carried out a Privacy Impact Assessment, you can mention it here too.' ) . '</p>';
       
  1956 		}
       
  1957 
       
  1958 		/* translators: default privacy policy heading. */
       
  1959 		$strings[] = '<h3>' . __( 'What data breach procedures we have in place' ) . '</h3>';
       
  1960 
       
  1961 		if ( $description ) {
       
  1962 			/* translators: privacy policy tutorial. */
       
  1963 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should explain what procedures you have in place to deal with data breaches, either potential or real, such as internal reporting systems, contact mechanisms, or bug bounties.' ) . '</p>';
       
  1964 		}
       
  1965 
       
  1966 		/* translators: default privacy policy heading. */
       
  1967 		$strings[] = '<h3>' . __( 'What third parties we receive data from' ) . '</h3>';
       
  1968 
       
  1969 		if ( $description ) {
       
  1970 			/* translators: privacy policy tutorial. */
       
  1971 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'If your web site receives data about users from third parties, including advertisers, this information must be included within the section of your privacy policy dealing with third party data.' ) . '</p>';
       
  1972 		}
       
  1973 
       
  1974 		/* translators: default privacy policy heading. */
       
  1975 		$strings[] = '<h3>' . __( 'What automated decision making and/or profiling we do with user data' ) . '</h3>';
       
  1976 
       
  1977 		if ( $description ) {
       
  1978 			/* translators: privacy policy tutorial. */
       
  1979 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'If your web site provides a service which includes automated decision making - for example, allowing customers to apply for credit, or aggregating their data into an advertising profile - you must note that this is taking place, and include information about how that information is used, what decisions are made with that aggregated data, and what rights users have over decisions made without human intervention.' ) . '</p>';
       
  1980 		}
       
  1981 
       
  1982 		/* translators: default privacy policy heading. */
       
  1983 		$strings[] = '<h3>' . __( 'Industry regulatory disclosure requirements' ) . '</h3>';
       
  1984 
       
  1985 		if ( $description ) {
       
  1986 			/* translators: privacy policy tutorial. */
       
  1987 			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'If you are a member of a regulated industry, or if you are subject to additional privacy laws, you may be required to disclose that information here.' ) . '</p>';
       
  1988 			$strings[] = '</div>';
       
  1989 		}
       
  1990 
       
  1991 		if ( $blocks ) {
       
  1992 			foreach ( $strings as $key => $string ) {
       
  1993 				if ( 0 === strpos( $string, '<p>' ) ) {
       
  1994 					$strings[ $key ] = '<!-- wp:paragraph -->' . $string . '<!-- /wp:paragraph -->';
       
  1995 				}
       
  1996 
       
  1997 				if ( 0 === strpos( $string, '<h2>' ) ) {
       
  1998 					$strings[ $key ] = '<!-- wp:heading -->' . $string . '<!-- /wp:heading -->';
       
  1999 				}
       
  2000 
       
  2001 				if ( 0 === strpos( $string, '<h3>' ) ) {
       
  2002 					$strings[ $key ] = '<!-- wp:heading {"level":3} -->' . $string . '<!-- /wp:heading -->';
       
  2003 				}
       
  2004 			}
       
  2005 		}
       
  2006 
       
  2007 		$content = implode( '', $strings );
  1803 		// End of the suggested privacy policy text.
  2008 		// End of the suggested privacy policy text.
  1804 
  2009 
  1805 		/**
  2010 		/**
  1806 		 * Filters the default content suggested for inclusion in a privacy policy.
  2011 		 * Filters the default content suggested for inclusion in a privacy policy.
  1807 		 *
  2012 		 *
  1808 		 * @since 4.9.6
  2013 		 * @since 4.9.6
       
  2014 		 * @since 5.0.0 Added the `$strings`, `$description`, and `$blocks` parameters.
  1809 		 *
  2015 		 *
  1810 		 * @param $content string The default policy content.
  2016 		 * @param string $content     The default policy content.
       
  2017 		 * @param array  $strings     An array of privacy policy content strings.
       
  2018 		 * @param bool   $description Whether policy descriptions should be included.
       
  2019 		 * @param bool   $blocks      Whether the content should be formatted for the block editor.
  1811 		 */
  2020 		 */
  1812 		return apply_filters( 'wp_get_default_privacy_policy_content', $content );
  2021 		return apply_filters( 'wp_get_default_privacy_policy_content', $content, $strings, $description, $blocks );
  1813 	}
  2022 	}
  1814 
  2023 
  1815 	/**
  2024 	/**
  1816 	 * Add the suggested privacy policy text to the policy postbox.
  2025 	 * Add the suggested privacy policy text to the policy postbox.
  1817 	 *
  2026 	 *
  1818 	 * @since 4.9.6
  2027 	 * @since 4.9.6
  1819 	 */
  2028 	 */
  1820 	public static function add_suggested_content() {
  2029 	public static function add_suggested_content() {
  1821 		$content = self::get_default_content( true );
  2030 		$content = self::get_default_content( true, false );
  1822 		wp_add_privacy_policy_content( __( 'WordPress' ), $content );
  2031 		wp_add_privacy_policy_content( __( 'WordPress' ), $content );
  1823 	}
  2032 	}
  1824 }
  2033 }
       
  2034 
       
  2035 /**
       
  2036  * Checks if the user needs to update PHP.
       
  2037  *
       
  2038  * @since 5.1.0
       
  2039  * @since 5.1.1 Added the {@see 'wp_is_php_version_acceptable'} filter.
       
  2040  *
       
  2041  * @return array|false $response Array of PHP version data. False on failure.
       
  2042  */
       
  2043 function wp_check_php_version() {
       
  2044 	$version = phpversion();
       
  2045 	$key     = md5( $version );
       
  2046 
       
  2047 	$response = get_site_transient( 'php_check_' . $key );
       
  2048 	if ( false === $response ) {
       
  2049 		$url = 'http://api.wordpress.org/core/serve-happy/1.0/';
       
  2050 		if ( wp_http_supports( array( 'ssl' ) ) ) {
       
  2051 			$url = set_url_scheme( $url, 'https' );
       
  2052 		}
       
  2053 
       
  2054 		$url = add_query_arg( 'php_version', $version, $url );
       
  2055 
       
  2056 		$response = wp_remote_get( $url );
       
  2057 
       
  2058 		if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
       
  2059 			return false;
       
  2060 		}
       
  2061 
       
  2062 		/**
       
  2063 		 * Response should be an array with:
       
  2064 		 *  'recommended_version' - string - The PHP version recommended by WordPress.
       
  2065 		 *  'is_supported' - boolean - Whether the PHP version is actively supported.
       
  2066 		 *  'is_secure' - boolean - Whether the PHP version receives security updates.
       
  2067 		 *  'is_acceptable' - boolean - Whether the PHP version is still acceptable for WordPress.
       
  2068 		 */
       
  2069 		$response = json_decode( wp_remote_retrieve_body( $response ), true );
       
  2070 
       
  2071 		if ( ! is_array( $response ) ) {
       
  2072 			return false;
       
  2073 		}
       
  2074 
       
  2075 		set_site_transient( 'php_check_' . $key, $response, WEEK_IN_SECONDS );
       
  2076 	}
       
  2077 
       
  2078 	if ( isset( $response['is_acceptable'] ) && $response['is_acceptable'] ) {
       
  2079 		/**
       
  2080 		 * Filters whether the active PHP version is considered acceptable by WordPress.
       
  2081 		 *
       
  2082 		 * Returning false will trigger a PHP version warning to show up in the admin dashboard to administrators.
       
  2083 		 *
       
  2084 		 * This filter is only run if the wordpress.org Serve Happy API considers the PHP version acceptable, ensuring
       
  2085 		 * that this filter can only make this check stricter, but not loosen it.
       
  2086 		 *
       
  2087 		 * @since 5.1.1
       
  2088 		 *
       
  2089 		 * @param bool   $is_acceptable Whether the PHP version is considered acceptable. Default true.
       
  2090 		 * @param string $version       PHP version checked.
       
  2091 		 */
       
  2092 		$response['is_acceptable'] = (bool) apply_filters( 'wp_is_php_version_acceptable', true, $version );
       
  2093 	}
       
  2094 
       
  2095 	return $response;
       
  2096 }