Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm using an external CSV reading library that takes a filehandle (resource) as an argument. I'm using wp_handle_upload() to actually process and store the file in the Uploads directory, but that returns the file path, not a resource.

Is $filehandle = fopen( $file['file'], 'r' ) acceptable here, or is there a better WP alternative? I don't see anything that fits the bill in file.php, or anywhere else I've looked.

share|improve this question

2 Answers 2

WordPress do not use fopen(). The WordPress filesystem uses four methods to access a file:

  • file_get_contents() (method direct)
  • sockets via a ftp class (method ftpsockets)
  • ftp via ftp_connect() / ftp_ssl_connect() (method ftpext)
  • ssh2 via ssh2_connect() (method ssh2)

You have to create the filehandle on your own with fopen(). When you use wp_handle_upload(), than WordPress should have sanitized and verified the file. $file['file'] should be clean and usable.

share|improve this answer

What follows is kind of complicated. You can probably just use fopen or file_get_contents without any issues.

There's the filesystem api. Which deals with determining ownership of a file and returning the correct way of accessing it -- most of the time that just means normal PHP functions (or the direct filesystem class).

Otto has a nice tutorial on this which I'm copied/altered to figure out how it works for this answer.

Essentially you use request_filesystem_credentials to get the appropriate information to interact with the file system. This might be nothing (eg. direct, see the link above) or it may show a form to the user so they can enter the username/password for FTP or SSH. Depends on your server setup.

Some quick examples. Let's add an admin page, with a simple form.

<?php
add_action('admin_menu', 'wpse74395_add_menu_page');
function wpse74395_add_menu_page()
{
    add_options_page(
        __('Filesystem', 'wpse'),
        __('Filesystem', 'wpse'),
        'manage_options',
        'wpse-filesystem',
        'wpse74395_page_cb'
    );
}

function wpse74395_page_cb()
{
    if(wpse74395_use_filesystem())
        return;

    ?>
    <div class="wrap">
        <?php screen_icon(); ?>
        <h2><?php _e('Filesystem Practice', 'wpse'); ?></h2>
        <form method="post" action="">
            <?php wp_nonce_field('wpse74395-nonce'); ?>
            <p><input name="save" type="submit" value="<?php esc_attr_e('Go!', 'wpse'); ?>" class="button-primary" /></p>
        </form>
    </div>
    <?php
}

The wpse74395_use_filesystem function:

<?php
function wpse74395_use_filesystem()
{
    if(empty($_POST['save']))
        return false;

    // can we do this?
    check_admin_referer('wpse74395-nonce');

    // try to get the filesystem credentials.
    $url = wp_nonce_url(admin_url('options-general.php?page=wpse-filesystem'), 'wpse74395-nonce');
    if(false === ($creds = request_filesystem_credentials($url)))
    {
        // we didn't get creds...
        // The user will see a form at this point, so stop the
        // rest of the page.
        return true; 
    }

    // use WP_Filesystem to check initialize the global $wp_filesystem
    if(!WP_Filesystem($creds))
    {
        // didn't work, try again!
        request_filesystem_credentials($url);
        return true;
    }

    global $wp_filesystem;

    // get your file path
    $fp = WP_CONTENT_DIR . '/test.txt';

    // do your thing.
    if($wp_filesystem->exists($fp))
    {
        $res = $wp_filesystem->get_contents($fp);
        var_dump($res);
        return true;
    }

    // nothing worked, try again.
    return false;
}

The comments should help explain what's going on. Essentially: make sure we're in a POST request (form submission), and the request checks out (nonce validation). From there, we'll try to get filesystem credentials. If we don't get any, a form will show to collect them, so stop the rest of the page from showing.

By only giving request_filesystem_credentials the first argument, we're letting WP decide what method we need to use. Most of the time this is direct and the user won't see anything. Please note that request_filesystem_credentials will do everything it can to get the stuff without asking the user -- database options, config options, etc.

Once we have the creds, try to initialize the global $wp_filesystem object with WP_Filesystem. If it works, awesome! If not, try to get the credentials again.

If everything checks out, use the $wp_filesystem as you need to. They all have a consistent interface. Here's the above code in a plugin.

share|improve this answer
1  
If he just wants to read the file, that stuff is kinda overkill. fopen is probably fine. –  Otto Nov 30 '12 at 0:19
    
Very much agreed. –  chrisguitarguy Nov 30 '12 at 0:31
    
Haha, thanks Chris - this is a great writeup for people interested in learning about WP_Filesystem usage! But I'm not sure you have addressed my concern about getting the resource handle to the file. From what I can see, get_contents() returns the file as a string, not the filehandle resources that I need for my external library. If we look at, for example, the Direct implementation simply uses PHP's file_get_contents( $file ), which returns the entire file's contents as a string, but does not give you the filehandle resource. Unless I'm mistaken. –  Tom Auger Nov 30 '12 at 15:02
    
You're not going to find anything like that in WP_Filesystem -- sometimes it falls back to FTP or SSH, which wouldn't support file handles in the same way. The filesystem API is meant to be portable. If you need the file handle itself, just use fopen it will probably work file -- as I mentioned in the first line. –  chrisguitarguy Nov 30 '12 at 15:36

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.