This error presents itself as "The specified file /path/file.png could not be copied to path/file.png"

So, I inherited a complex migration that loads a d2d migration from the database and modifies it.

I have discovered that I am unable to set the $destination parameter to the copyFile() through the UI.

Ultimately what is happening is that in

protected function copyFile($destination)

This is getting called in file.inc:

copy($this->sourcePath, $destination)

But $this->sourcePath is just /images/file.png and $destination is sites/default/files/images/file.png. Which is weird because these are both relative, and if I understand correctly copy() requires a third parameter $context if it is to be called using relative paths. A bug? Maybe. Or maybe something not getting registered right in the code I inherited to generate absolute paths.

In the end, I fixed this with a horrible bad hack, placed above the copy() function.

if ($this->defaultFile->migrate['machineName'] == 'ModclientMediaFile') {
  if (!strpos($this->sourcePath, '/Users/myuser/www' === 0)) {
    $this->sourcePath = '/Users/myuser/www/clientd6.myuser/sites/default/files' . $this->sourcePath;
  }
  if (!strpos($this->sourcePath, '/Users/myuser/www' === 0)) {
    $destination = '/Users/myuser/www/clientd7.myuser/' . $destination;
  }
}

My files now import. I felt very guilty, but was able to read an extra book to my son as he was going to sleep and so my guilt was assuaged. Now, even with this commented out, it is fixed.

Previously, I found that the the $destination parameter was coming from somewhere not accessible in the ui and not defined in code, but myseriously present as a BLOB in the database, so I set it with a query. Now my files import.

 $sql = "select arguments from migrate_status where machine_name like '%ModclientMediaUserPictures%'";
$result = db_query($sql);
$new_arguments = array();
if ($result) {
  while ($row = $result->fetchAssoc()) {
    dpm($row,'row');
    $arguments = unserialize($row['arguments']);
    if (strpos($arguments['source_dir'], '/Users/OldDev/Documents/Work/Current/client/clientdrupal/uc_client/sites/default/files') !== FALSE) {
      $new_arguments = $arguments;
      $new_arguments['source_dir'] = '/Users/myuser/www/clientd6.myuser/sites/default/files';
    }
    dpm($arguments['source_dir']);
  
  }
}
if($new_arguments['source_dir']) {
  $new_arguments = serialize($new_arguments);
  $update_sql = "UPDATE migrate_status SET arguments=:newargs WHERE machine_name like '%ModclientMediaUserPictures%'";
  $result = db_query($update_sql, array(':newargs'=> $new_arguments));
  dpm($result, 'result');
}

After writing this query, I felt the guilt again, but then went for a bike ride. I will remove this code after the migrations is complete.

I am not sure this issue qualifies as a "bug," but I leave it here for posterity. So where/how does $destination get saved to the database if not in the UI? Or rather in my case, saving it in the UI had no effect on what was passed to copy().

Comments

glass.dimly’s picture

Issue summary: View changes
glass.dimly’s picture

Issue summary: View changes
mikeryan’s picture

Title: PHP copy not passed a context, relative paths therefore undefined » Problem with drupal-to-drupal file copy
Category: Bug report » Support request

I have no idea what $context might have to do with relative paths, but I'm quite certain we have no need of $context here. Also, I need to point out that /images/file.png is an absolute path, not a relative path, so if you don't have an images directory containing file.png at the root of your filesystem, it is going to fail.

You shouldn't need to do all this hackery to get files to import, it should be fully configurable through the field mappings. What exactly are your field mappings? For reference (paying particular attention to source_dir, destination_dir, and destination_file): https://www.drupal.org/node/1540106

mikeryan’s picture

Status: Active » Postponed (maintainer needs more info)
mikeryan’s picture

Status: Postponed (maintainer needs more info) » Closed (cannot reproduce)
glass.dimly’s picture

Fair enough.