How to: Use the WordPress Filesystem API

When developing a plugin, you may need to make changes to existing files on the server—like customizing the wp-config.php constant definitions or writing a custom config file.

Filesystem changes can be a pain, but they don’t have to be

With native PHP functions, you can easily:

  • Set incorrect permissions (and break sites)
  • Create new files with the wrong user or wrong permissions
  • Run into errors when attempting to delete a file

Once you switch over your plugin to utilize WordPress’ filesystem API, you can avoid these general issues.

Here’s how it works:

Step 1: Request credentials from the user

First, you need to request credentials from the user.

If your plugin needs to write or modify files, WordPress may not have access to do so.

Luckily, WordPress already handles the heavy lifting here because it has the request_filesystem_credentials function.

The function will check to see if credentials are required for making filesystem changes and if they are required, will output a form for collecting them.

Here’s how the codex recommends using it in your plugin:

$url = wp_nonce_url('themes.php?page=example','example-theme-options');

if (false === ($creds = request_filesystem_credentials($url, '', false, false, null) ) ) {
    return; // stop processing here
}  

If no credentials are required, then no form will be displayed and you can continue making file changes as needed.

Step 2: Load the correct classes within your plugin

Before you’re able to utilize the API, you will need to include the necessary files so that your plugin code is able to access them during the request.

if ( ! class_exists( 'WP_Filesystem_Direct' ) ) {
    require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
    require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
}

WordPress doesn’t include these classes automatically, so you’ll need to require them within your plugin.

First, you need to require the class-wp-filesystem-base.php class that provides the structure for specific implementations to extend.

Next, you’ll want to include one of the specific implementations depending on what you need to do in the filesystem:

  • WP_Filesystem_Direct – probably what you’ll use for most cases
  • WP_Filesystem_FTPext
  • WP_Filesystem_ftpsockets
  • WP_Filesystem_SSH2

Depending on your needs, choose the right implementation for your use case.

Step 3: Get the current file permissions for files & directories

WordPress includes constants that store the file permissions for a site, but they may not be utilized by the host your plugin is running on (most do, but it’s always good to assume they don’t).

You’ll want to check to make sure they’re defined before using any filesystem methods because they are necessary when adding, or moving files & directories.

Here are two small functions that detect the current file mode for files and directories that you can use to define FS_CHMOD_FILE and FS_CHMOD_DIR if they’re not already set. Otherwise, they’ll just return the set value:

/**
  * Get the file mode as an octal integer.
  */
function swpd_get_file_mode() {
    if ( defined( 'FS_CHMOD_FILE' ) ) {
        return FS_CHMOD_FILE;
    }

    return ( fileperms( ABSPATH . 'index.php' ) & 0777 | 0644 );
}


/**
  * Get the directory mode as an octal integer.
  */
function swpd_get_dir_mode() {
    if ( defined( 'FS_CHMOD_DIR' ) ) {
        return FS_CHMOD_DIR;
    }

    return ( fileperms( ABSPATH ) & 0777 | 0755 );
}

Once you have these two helper methods, you can then start utilizing the WordPress filesystem as you need to.

Any file or directory manipulation that you do, instead of the native PHP functions, use the WordPress API equivalents.

In Conclusion

Now that you have a functional implementation of the WordPress Filesystem API, you can use those methods in place of PHP’s.

Most of the API is just a proxy referring to the native PHP functions, but in certain situations WordPress will handle more complex compatibility across different server environments.

I hope this was insightful, I know it was for me when I found it and the complexity it removed from the plugins I’ve been working on lately.

If you’re working with the filesystem in your plugin, I hope this is helpful!