What is the best way to move a plugin´s subdirectory+files to wp-content/uploads-directory?

I am developer of the plugin Leaflet Maps Marker (http://www.mapsmarker.com – “Pin, organize & show your favorite places through OpenStreetMap, OGD Vienna or any custom WMTS-map”)
and have one question: the plugin contains about 100 marker icons from Maps Icons Collection (mapicons.nicolasmollet.com) which can be used to mark your favorite places.

These icons are stored in wp-content\plugins\leaflet-mapsmarker\img\mapicons. Now users can upload other own icons from the collection (which consist of more than 700 icons). Problem is, that if the users upload the custom icons to the plugins-directory and I release an plugin update in the future, the uploaded icons get deleted and have to be uploaded again by the user.

So I started working on moving the mapsicons-directory to wp-content/uploads/leaflet-maps-marker-icons. Creating a directory works quite fine with the wordpress function wp_mkdir_p():

$target = ABSPATH . 'wp-content/uploads/leaflet-maps-marker-icons';
wp_mkdir_p( $target );

as a next step, I wanted to move the directory from plugins by also using the (undocumented) wordpress file api function copy_dir():

$source = WP_PLUGIN_DIR . "https://wordpress.stackexchange.com/" . end(explode("https://wordpress.stackexchange.com/", dirname(__FILE__))) . '/img/mapicons'; //allows plugin directory names other than leaflet-maps-marker
$target = ABSPATH . 'wp-content/uploads/leaflet-maps-marker-icons';
copy_dir($source, $target, $skip_list = array() );

Unfortunately this didnt work – I get the error:

Fatal error: Call to a member function dirlist() on a non-object in /wp-current/wp-admin/includes/file.php on line 756

Has anyone here used this function in one of his projects before and knows how to use it correctly? or: do you know any other safe ways to copy/move files using wordpress functions? I don´t want to use PHP command directly, as from my experience, there are too many possible configurations of webservers leading to increased support requests (safemode on/off, having to enter ftp credentials…).

Any help is really appreciated!

To be complete, here is the code for the function copy_dir() from file.php:

function copy_dir($from, $to, $skip_list = array() ) {
global $wp_filesystem;

$dirlist = $wp_filesystem->dirlist($from);

$from = trailingslashit($from);
$to = trailingslashit($to);

$skip_regex = '';
foreach ( (array)$skip_list as $key => $skip_file )
    $skip_regex .= preg_quote($skip_file, '!') . '|';

if ( !empty($skip_regex) )
    $skip_regex = '!(' . rtrim($skip_regex, '|') . ')$!i';

foreach ( (array) $dirlist as $filename => $fileinfo ) {
    if ( !empty($skip_regex) )
        if ( preg_match($skip_regex, $from . $filename) )
            continue;

    if ( 'f' == $fileinfo['type'] ) {
        if ( ! $wp_filesystem->copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) ) {
            // If copy failed, chmod file to 0644 and try again.
            $wp_filesystem->chmod($to . $filename, 0644);
            if ( ! $wp_filesystem->copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) )
                return new WP_Error('copy_failed', __('Could not copy file.'), $to . $filename);
        }
    } elseif ( 'd' == $fileinfo['type'] ) {
        if ( !$wp_filesystem->is_dir($to . $filename) ) {
            if ( !$wp_filesystem->mkdir($to . $filename, FS_CHMOD_DIR) )
                return new WP_Error('mkdir_failed', __('Could not create directory.'), $to . $filename);
        }
        $result = copy_dir($from . $filename, $to . $filename, $skip_list);
        if ( is_wp_error($result) )
            return $result;
    }
}
return true;
}

updated code (as within comments code was not formatted properly)

WP_Filesystem();
$target = ABSPATH . 'wp-content/uploads/leaflet-maps-marker-icons';
    if (!is_dir($target)) //check for multisite installations
    {
        wp_mkdir_p( $target );
        $source = WP_PLUGIN_DIR . "https://wordpress.stackexchange.com/" . end(explode("https://wordpress.stackexchange.com/", dirname(__FILE__))) . '/img/mapicons';
        copy_dir($source, $target, $skip_list = array() );
        $zipfile = ABSPATH . 'wp-content/uploads/leaflet-maps-marker-icons/mapicons.zip';
        unzip_file( $zipfile, $target );
    }

1 Answer
1

Line 756 is $dirlist = $wp_filesystem->dirlist($from);. The argument is ok. I think that the object $wp_filesystem is not globally available for your plugin.

Leave a Comment