0

I am working on a module that is transferring files from my old site (hosted on the same server) to a new drupal based site. The files will be associated with a single content type (the content type has multipel file fields associated with it). I've written code to read a directory and then loop through the files, associating the files with the appropriate file file. So far the files are getting transferred correctly, but they aren't being associated with the new node. What am I missing

$result = new stdClass;
$result->type = "results";
node_object_prepare($result);

//add values to text fields here
...

//open the source directory
$d = dir($seasonDir);
while(false !== ($entry = $d->read())) {
      if($entry != "." && $entry != "..") {
        //set the file location
        $fileLocation = $seasonDir . "/" . $entry;
        //get the file contents
        $fileContents = file_get_contents($fileLocation);
        //save the file
        $file = file_save_data($fileContents,'public://results/'.$entry,FILE_EXISTS_RENAME);
        //store the file for copying to a subdirectory later
        $result_files[] = $file;
        //create an array to assign to the various file fields
        $file_details = array(LANGUAGE_NONE => array('0' => (array)$file));
        switch($entry) {
          case "results.inc.html":
            $result->field_results_html = $file_details;
            break;
          case"clubs.inc.html":
            $result->field_clubs_html = $file_details;
            break;
          case "events.inc.html":
            $result->field_events_html = $file_details;
            break;
          case "index.xml":
            $result->field_results_index = $file_details;
            break;
          case "events.xml":
            $result->field_results_events = $file_details;
            break;
          case "clubs.xml":
            $result->field_results_clubs = $file_details;
            break;
          case "results.xml":
            $result->field_results = $file_details;
            break;
          default:
            //because the resuls_files field allows multiple files, this
            //field has to use a different method of assigning the file
            $result->results_files[LANGUAGE_NONE][] = (array)$file;
            break;
        }
       }
    }
    $d->close();

    node_save($result);
    //now move the files to the folder using the node ID as the subfolder
    $newdir = 'public://results/' . $result->nid;
    if(file_prepare_directory($newdir, FILE_CREATE_DIRECTORY)) {
      //move the files into this directory
      foreach($result_files as $file) {
        file_move($file, $newdir . '/' . $file->filename, FILE_EXISTS_REPLACE);
      }
    }
    else {
      drupal_set_message("could not create $newdir");
    }

At the end, all the nodes have been created, the files have been moved to the correct sub directory, but the node doesn't show any attached files. What am I missing?

2
  • why use file_save_data then file_move ?
    – Aboodred1
    May 4, 2013 at 15:16
  • The files are going to be out in a subfolder using the node's id. When I upload the file to drupal, the node hasn't been saved yet so the node id doesn't exist. I move the files over after the node has been created. Looks like the answer below would remove the need for that step.
    – Robbert
    May 4, 2013 at 18:19

1 Answer 1

2

I think from what I understand; you are trying to add each file(s) to its node folder public://results/[nid]/filename.ext

As solution to your issue, first you need to save the node before you attach the file(s) to it. Then move/save file(s) to its desired location. Then attach the moved file(s) to the selected node again.

Change your code to look like the following:

$result = new stdClass;
$result->type = "results";
node_object_prepare($result);

//add values to text fields here

// save node
node_save($result);


//open the source directory

$d = dir($seasonDir);

while(false !== ($entry = $d->read())) {
  if($entry != "." && $entry != "..") {

    $dir = 'public://results/' . $result->nid;  
    // create folder str 
    if(file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) {

      //set the file location
      $fileLocation = $seasonDir . "/" . $entry;

      //get the file contents
      $fileContents = file_get_contents($fileLocation);

      //save the file - added nid as sub folder
      $file = file_save_data($fileContents, $dir . '/' . $entry, FILE_EXISTS_RENAME);

      // important if you are importing none image files
      $file->display = 1; 

      // you don't need to copy files to an array anymore

      // create entity object to store file(s) to the node 

      $entity = new stdClass();
      $entity->nid = $result->nid;
      $entity->vid = $result->vid;
      $entity->type  = $result->type;

      //create an array to assign to the various file fields
      $file_details = array(LANGUAGE_NONE => array('0' => (array)$file));

      switch($entry) {
        case "results.inc.html":
          $entity->field_results_html = $file_details;
          break;
        case"clubs.inc.html":
          $entity->field_clubs_html = $file_details;
          break;
        case "events.inc.html":
          $entity->field_events_html = $file_details;
          break;
        case "index.xml":
          $entity->field_results_index = $file_details;
          break;
        case "events.xml":
          $entity->field_results_events = $file_details;
          break;
        case "clubs.xml":
          $entity->field_results_clubs = $file_details;
          break;
        case "results.xml":
          $entity->field_results = $file_details;
          break;
        default:
          //because the resuls_files field allows multiple files, this
          //field has to use a different method of assigning the file
          $entity->results_files[LANGUAGE_NONE][] = (array)$file;
          break;
      }

      // save entity 
      field_attach_presave('node', $entity);
      field_attach_update('node', $entity);
    }
  }
}
$d->close();
5
  • don't forget to read the comments as well.
    – Aboodred1
    May 4, 2013 at 19:34
  • 1
    Yup, I saw them. Going to try this tonight when the kiddies are in bed.
    – Robbert
    May 4, 2013 at 19:53
  • We're getting close. When I browse to the newly created node, it recognizes that the files were created, but the filename doesn't appear, just a generic icon. I checked the database and the managed_files table has the filenames in it, and links to the file appear in the corresponding field's table. I am getting several Drupal errors on the page, like Notice: Undefined property: stdClass::$uri in theme_file_link() ... Notice: Undefined property: stdClass::$filemime in theme_file_icon() ...
    – Robbert
    May 5, 2013 at 15:29
  • Solved the problem. Instead of creating a new entity, I just used the original $result object. Thanks for steering me in the right direction.
    – Robbert
    May 5, 2013 at 15:36
  • @Robbert I was about to mention that you can use $result object as well. Glad it worked for you :)
    – Aboodred1
    May 5, 2013 at 16:29

Your Answer

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

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