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 . '/' . end(explode('/', 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) )

    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)

$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 . '/' . end(explode('/', 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.

  • thanks - that was the problem. Here is the code I use now - I added a switch for multisite installation so that the directory only gets copied once - I added the code above.
    – robertharm
    Dec 20, 2011 at 19:54
  • I have two further suggestions which may improve your code. I've done a lot of research about the path constants used in WP and which constants and functions are backwards compatibel and still work. Since WP 2.6 the location of the wp-content directory can be customized. Thus ABSPATH . 'wp-content/...' will fail for such customisations. Using WP_CONTENT_DIR will solve this. Another problem is the explode('/', ... with only a slash. This will break on Windows. Today I've found a nice alternative on stackexchange. You may use the Wordpress function plugin_basename() instead.
    – jot
    Dec 20, 2011 at 23:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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