: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( ! wp_installing() ) {
update_option( 'ftp_credentials', $stored_credentials );
$hostname = isset( $credentials['hostname'] ) ? $credentials['hostname'] : '';
$username = isset( $credentials['username'] ) ? $credentials['username'] : '';
$public_key = isset( $credentials['public_key'] ) ? $credentials['public_key'] : '';
$private_key = isset( $credentials['private_key'] ) ? $credentials['private_key'] : '';
$port = isset( $credentials['port'] ) ? $credentials['port'] : '';
$connection_type = isset( $credentials['connection_type'] ) ? $credentials['connection_type'] : '';
$error_string = __( '<strong>Error:</strong> Could not connect to the server. Please verify the settings are correct.' );
if ( is_wp_error( $error ) ) {
$error_string = esc_html( $error->get_error_message() );
'additional_classes' => array( 'error' ),
if ( extension_loaded( 'ftp' ) || extension_loaded( 'sockets' ) || function_exists( 'fsockopen' ) ) {
$types['ftp'] = __( 'FTP' );
if ( extension_loaded( 'ftp' ) ) { // Only this supports FTPS.
$types['ftps'] = __( 'FTPS (SSL)' );
if ( extension_loaded( 'ssh2' ) ) {
$types['ssh'] = __( 'SSH2' );
* Filters the connection types to output to the filesystem credentials form.
* @since 4.6.0 The `$context` parameter default changed from `false` to an empty string.
* @param string[] $types Types of connections.
* @param array $credentials Credentials to connect with.
* @param string $type Chosen filesystem method.
* @param bool|WP_Error $error Whether the current request has failed to connect,
* @param string $context Full path to the directory that is tested for being writable.
$types = apply_filters( 'fs_ftp_connection_types', $types, $credentials, $type, $error, $context );
<form action="<?php echo esc_url( $form_post ); ?>" method="post">
<div id="request-filesystem-credentials-form" class="request-filesystem-credentials-form">
// Print a H1 heading in the FTP credentials modal dialog, default is a H2.
if ( 'plugins.php' === $pagenow || 'plugin-install.php' === $pagenow ) {
echo "<$heading_tag id='request-filesystem-credentials-title'>" . __( 'Connection Information' ) . "</$heading_tag>";
<p id="request-filesystem-credentials-desc">
$label_user = __( 'Username' );
$label_pass = __( 'Password' );
_e( 'To perform the requested action, WordPress needs to access your web server.' );
if ( ( isset( $types['ftp'] ) || isset( $types['ftps'] ) ) ) {
if ( isset( $types['ssh'] ) ) {
_e( 'Please enter your FTP or SSH credentials to proceed.' );
$label_user = __( 'FTP/SSH Username' );
$label_pass = __( 'FTP/SSH Password' );
_e( 'Please enter your FTP credentials to proceed.' );
$label_user = __( 'FTP Username' );
$label_pass = __( 'FTP Password' );
_e( 'If you do not remember your credentials, you should contact your web host.' );
$hostname_value = esc_attr( $hostname );
if ( ! empty( $port ) ) {
$hostname_value .= ":$port";
if ( defined( 'FTP_PASS' ) ) {
$password_value = '*****';
<span class="field-title"><?php _e( 'Hostname' ); ?></span>
<input name="hostname" type="text" id="hostname" aria-describedby="request-filesystem-credentials-desc" class="code" placeholder="<?php esc_attr_e( 'example: www.wordpress.org' ); ?>" value="<?php echo $hostname_value; ?>"<?php disabled( defined( 'FTP_HOST' ) ); ?> />
<div class="ftp-username">
<span class="field-title"><?php echo $label_user; ?></span>
<input name="username" type="text" id="username" value="<?php echo esc_attr( $username ); ?>"<?php disabled( defined( 'FTP_USER' ) ); ?> />
<div class="ftp-password">
<span class="field-title"><?php echo $label_pass; ?></span>
<input name="password" type="password" id="password" value="<?php echo $password_value; ?>"<?php disabled( defined( 'FTP_PASS' ) ); ?> spellcheck="false" />
if ( ! defined( 'FTP_PASS' ) ) {
_e( 'This password will not be stored on the server.' );
<legend><?php _e( 'Connection Type' ); ?></legend>
$disabled = disabled( ( defined( 'FTP_SSL' ) && FTP_SSL ) || ( defined( 'FTP_SSH' ) && FTP_SSH ), true, false );
foreach ( $types as $name => $text ) :
<label for="<?php echo esc_attr( $name ); ?>">
<input type="radio" name="connection_type" id="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $name ); ?>" <?php checked( $name, $connection_type ); ?> <?php echo $disabled; ?> />
if ( isset( $types['ssh'] ) ) {
if ( 'ssh' !== $connection_type || empty( $connection_type ) ) {
$hidden_class = ' class="hidden"';
<fieldset id="ssh-keys"<?php echo $hidden_class; ?>>
<legend><?php _e( 'Authentication Keys' ); ?></legend>
<span class="field-title"><?php _e( 'Public Key:' ); ?></span>
<input name="public_key" type="text" id="public_key" aria-describedby="auth-keys-desc" value="<?php echo esc_attr( $public_key ); ?>"<?php disabled( defined( 'FTP_PUBKEY' ) ); ?> />
<label for="private_key">
<span class="field-title"><?php _e( 'Private Key:' ); ?></span>
<input name="private_key" type="text" id="private_key" value="<?php echo esc_attr( $private_key ); ?>"<?php disabled( defined( 'FTP_PRIKEY' ) ); ?> />
<p id="auth-keys-desc"><?php _e( 'Enter the location on the server where the public and private keys are located. If a passphrase is needed, enter that in the password field above.' ); ?></p>
foreach ( (array) $extra_fields as $field ) {
if ( isset( $submitted_form[ $field ] ) ) {
echo '<input type="hidden" name="' . esc_attr( $field ) . '" value="' . esc_attr( $submitted_form[ $field ] ) . '" />';
* Make sure the `submit_button()` function is available during the REST API call
* from WP_Site_Health_Auto_Updates::test_check_wp_filesystem_method().
if ( ! function_exists( 'submit_button' ) ) {
require_once ABSPATH . 'wp-admin/includes/template.php';
<p class="request-filesystem-credentials-action-buttons">
<?php wp_nonce_field( 'filesystem-credentials', '_fs_nonce', false, true ); ?>
<button class="button cancel-button" data-js-action="close" type="button"><?php _e( 'Cancel' ); ?></button>
<?php submit_button( __( 'Proceed' ), 'primary', 'upgrade', false ); ?>
* Prints the filesystem credentials modal when needed.
function wp_print_request_filesystem_credentials_modal() {
$filesystem_method = get_filesystem_method();
$filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() );
$request_filesystem_credentials = ( 'direct' !== $filesystem_method && ! $filesystem_credentials_are_stored );
if ( ! $request_filesystem_credentials ) {
<div id="request-filesystem-credentials-dialog" class="notification-dialog-wrap request-filesystem-credentials-dialog">
<div class="notification-dialog-background"></div>
<div class="notification-dialog" role="dialog" aria-labelledby="request-filesystem-credentials-title" tabindex="0">
<div class="request-filesystem-credentials-dialog-content">
<?php request_filesystem_credentials( site_url() ); ?>
* Attempts to clear the opcode cache for an individual PHP file.
* This function can be called safely without having to check the file extension
* or availability of the OPcache extension.
* Whether or not invalidation is possible is cached to improve performance.
* @link https://www.php.net/manual/en/function.opcache-invalidate.php
* @param string $filepath Path to the file, including extension, for which the opcode cache is to be cleared.
* @param bool $force Invalidate even if the modification time is not newer than the file in cache.
* @return bool True if opcache was invalidated for `$filepath`, or there was nothing to invalidate.
* False if opcache invalidation is not available, or is disabled via filter.
function wp_opcache_invalidate( $filepath, $force = false ) {
static $can_invalidate = null;
* Check to see if WordPress is able to run `opcache_invalidate()` or not, and cache the value.
* First, check to see if the function is available to call, then if the host has restricted
* the ability to run the function to avoid a PHP warning.
* `opcache.restrict_api` can specify the path for files allowed to call `opcache_invalidate()`.
* If the host has this set, check whether the path in `opcache.restrict_api` matches
* the beginning of the path of the origin file.
* `$_SERVER['SCRIPT_FILENAME']` approximates the origin file's path, but `realpath()`
* is necessary because `SCRIPT_FILENAME` can be a relative path when run from CLI.
* - https://www.php.net/manual/en/opcache.configuration.php
* - https://www.php.net/manual/en/reserved.variables.server.php
* - https://core.trac.wordpress.org/ticket/36455
if ( null === $can_invalidate
&& function_exists( 'opcache_invalidate' )
&& ( ! ini_get( 'opcache.restrict_api' )
|| stripos( realpath( $_SERVER['SCRIPT_FILENAME'] ), ini_get( 'opcache.restrict_api' ) ) === 0 )
// If invalidation is not available, return early.
if ( ! $can_invalidate ) {
// Verify that file to be invalidated has a PHP extension.
if ( '.php' !== strtolower( substr( $filepath, -4 ) ) ) {
* Filters whether to invalidate a file from the opcode cache.
* @param bool $will_invalidate Whether WordPress will invalidate `$filepath`. Default true.
* @param string $filepath The path to the PHP file to invalidate.
if ( apply_filters( 'wp_opcache_invalidate_file', true, $filepath ) ) {
return opcache_invalidate( $filepath, $force );
* Attempts to clear the opcode cache for a directory of files.
* @see wp_opcache_invalidate()
* @link https://www.php.net/manual/en/function.opcache-invalidate.php
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
* @param string $dir The path to the directory for which the opcode cache is to be cleared.
function wp_opcache_invalidate_directory( $dir ) {
if ( ! is_string( $dir ) || '' === trim( $dir ) ) {
$error_message = sprintf(
/* translators: %s: The function name. */
__( '%s expects a non-empty string.' ),
'<code>wp_opcache_invalidate_directory()</code>'
wp_trigger_error( '', $error_message );
$dirlist = $wp_filesystem->dirlist( $dir, false, true );
if ( empty( $dirlist ) ) {
* Recursively invalidate opcache of files in a directory.
* WP_Filesystem_*::dirlist() returns an array of file and directory information.
* This does not include a path to the file or directory.
* To invalidate files within sub-directories, recursion is needed
* to prepend an absolute path containing the sub-directory's name.
* @param array $dirlist Array of file/directory information from WP_Filesystem_Base::dirlist(),
* with sub-directories represented as nested arrays.
* @param string $path Absolute path to the directory.
$invalidate_directory = static function ( $dirlist, $path ) use ( &$invalidate_directory ) {
$path = trailingslashit( $path );
foreach ( $dirlist as $name => $details ) {
if ( 'f' === $details['type'] ) {
wp_opcache_invalidate( $path . $name, true );
} elseif ( is_array( $details['files'] ) && ! empty( $details['files'] ) ) {
$invalidate_directory( $details['files'], $path . $name );
$invalidate_directory( $dirlist, $dir );