Backing up a File Before Overwriting It (in Drupal 7)
I’m communicating with a 3rd party SOAP API to pull some data into a CSV file. The CSV file will be used by Feeds and/or Migrate so it’s important to have the file named exactly the same for each run. I want the generated CSV to always be named “mdb_interests.csv” but I want to “backup” the existing “mdb_interests.csv” to “mdb_interests_N.csv” if one already exists. This will ensure that we always have the latest data in “mdb_interests.csv” but will have backups from all previous API pulls. Using some built-in Drupal functions it’s pretty simple:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
function mymodule_writecsv_interests($client) { $filename_prefix = 'mdb_interests'; $filename = $filename_prefix . '.csv'; $filepath_temp = file_directory_temp() . '/' . $filename; $target_dir = 'public://csv_files/'; // Open a CSV file and write the data to it $handle = fopen($filepath_temp, 'w'); $field_labels = array('mdb_id', 'mdb_title', 'mdb_regions', 'dru_uni_tids'); fputcsv($handle, $field_labels); $mdb_interests = mymodule_mdb_interests($client); foreach ($mdb_interests as $interest) { fputcsv($handle, $interest); } fclose($handle); // Make sure our directory exists file_prepare_directory($target_dir, FILE_CREATE_DIRECTORY); // If new filename results in incremented filename, move existing mdb_interests.csv // file to mdb_interests_N.csv. (strpos should perform better than preg_match) $incremented = file_create_filename($filename, $target_dir); if (strpos($incremented, $filename_prefix . '_') !== FALSE) { file_unmanaged_move($target_dir . $filename, $incremented); } // Move the temporary file to the permanent directory file_unmanaged_move($filepath_temp, $target_dir. $filename); } |
NOTE: If the first file_unmanaged_move() does move an existing file for you, the date of the new “incremented” file will change to the current date. There are ways to fix this but I don’t need to for this project, so…
You can also make a function that is a bit more “reusable”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
/** * Write a CSV file (backing up and replacing existing one) * * @param string $target_dir * Directory where the new file will be saved * @param string $filename_prefix * Prefix of filename (filename without .csv) * @param array $headers * Header values * @param array $rows * Row values * * @return * The URI of the moved file, or FALSE in the event of an error. */ function mymodule_writecsv($target_dir, $filename_prefix, $headers, $rows) { $filename = $filename_prefix . '.csv'; $filepath_temp = file_directory_temp() . '/' . $filename; $handle = fopen($filepath_temp, 'w'); fputcsv($handle, $headers); foreach ($rows as $item) { fputcsv($handle, $item); } fclose($handle); file_prepare_directory($target_dir, FILE_CREATE_DIRECTORY); // If new filename results in incremented filename, move existing PREFIX.csv // file to PREFIX_N.csv. (strpos with _ should perform better than preg_match) $incremented = file_create_filename($filename, $target_dir); if (strpos($incremented, $filename_prefix . '_') !== FALSE) { file_unmanaged_move($target_dir . $filename, $incremented); } return file_unmanaged_move($filepath_temp, $target_dir. $filename); } |
One Comment
Hosting
The cp command has a feature not well-known to everybody that it can backup before overwriting the target file.