Migrate module: file handling
UPDATE: In the latest version of the migrate module, the hook names have changed - the word 'destination' has been removed.
So you're migrating pages and users from another CMS to Drupal using the Migrate module, but how do you handle all those file attachments? This example will cover taking the input filename and adding it to an imagefield on a Drupal content type. However, this should work in exactly the same way for filefields too.
The first thing you need to do is to take all files to be migrated and place them in your site's files
directory. If you plan on using the migrate module's "clear imported records" feature, so as to do multiple test runs, you should retain a backup of these files as when the nodes are cleared / deleted, so are the files.
Create the CCK content type and add an imagefield to it to store the migrated image. Then add a content set to map the source content fields to their Drupal equivalents. When configuring the content set, you will see three fields for your image: "fid", "list" and "data". We're going to ignore these and instead set the field value using the hook_migrate_destination_prepare_node()
.
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #007700">function </span><span style="color: #0000BB">mymodule_migrate_destination_prepare_node</span><span style="color: #007700">(&</span><span style="color: #0000BB">$node</span><span style="color: #007700">, </span><span style="color: #0000BB">$tblinfo</span><span style="color: #007700">, </span><span style="color: #0000BB">$row</span><span style="color: #007700">) {<br> </span><span style="color: #0000BB">$extensions </span><span style="color: #007700">= </span><span style="color: #0000BB">variable_get</span><span style="color: #007700">(</span><span style="color: #DD0000">'upload_extensions_default'</span><span style="color: #007700">, </span><span style="color: #DD0000">'jpg jpeg gif png txt html doc xls pdf ppt pps odt ods odp'</span><span style="color: #007700">);<br> if (</span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">type </span><span style="color: #007700">== </span><span style="color: #DD0000">'news'</span><span style="color: #007700">) {<br> </span><span style="color: #0000BB">$filepath </span><span style="color: #007700">= </span><span style="color: #DD0000">'sites/all/files/images/'</span><span style="color: #007700">. </span><span style="color: #0000BB">$row</span><span style="color: #007700">-></span><span style="color: #0000BB">cms_news_table_image</span><span style="color: #007700">;<br><br> </span><span style="color: #FF8000">// Ensure the file exists.<br> </span><span style="color: #007700">if (</span><span style="color: #0000BB">file_exists</span><span style="color: #007700">(</span><span style="color: #0000BB">file_create_path</span><span style="color: #007700">(</span><span style="color: #0000BB">$filepath</span><span style="color: #007700">))) {<br> </span><span style="color: #FF8000">// Check if the file exists in the 'files' table already.<br> </span><span style="color: #0000BB">$file </span><span style="color: #007700">= </span><span style="color: #0000BB">db_fetch_object</span><span style="color: #007700">(</span><span style="color: #0000BB">db_query</span><span style="color: #007700">(</span><span style="color: #DD0000">"SELECT * FROM {files} WHERE filepath = '%s'"</span><span style="color: #007700">, </span><span style="color: #0000BB">$filepath</span><span style="color: #007700">));<br><br> </span><span style="color: #FF8000">// Create the file entry in the 'files' table if necessary.<br> </span><span style="color: #007700">if (!</span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">fid</span><span style="color: #007700">) {<br> </span><span style="color: #0000BB">$file </span><span style="color: #007700">= new </span><span style="color: #0000BB">stdClass</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">filepath </span><span style="color: #007700">= </span><span style="color: #0000BB">$filepath</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">filename </span><span style="color: #007700">= </span><span style="color: #0000BB">file_munge_filename</span><span style="color: #007700">(</span><span style="color: #0000BB">basename</span><span style="color: #007700">(</span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">filepath</span><span style="color: #007700">), </span><span style="color: #0000BB">$extensions</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">filemime </span><span style="color: #007700">= </span><span style="color: #0000BB">file_get_mimetype</span><span style="color: #007700">(</span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">filename</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">uid </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">status </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">timestamp </span><span style="color: #007700">= </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">created</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">filesize </span><span style="color: #007700">= </span><span style="color: #0000BB">filesize</span><span style="color: #007700">(</span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">filepath</span><span style="color: #007700">);<br> </span><span style="color: #0000BB">drupal_write_record</span><span style="color: #007700">(</span><span style="color: #DD0000">'files'</span><span style="color: #007700">, </span><span style="color: #0000BB">$file</span><span style="color: #007700">);<br> }<br><br> </span><span style="color: #FF8000">// Set up the image field.<br> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">field_news_image</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">] = array(<br> </span><span style="color: #DD0000">'fid' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">fid</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'list' </span><span style="color: #007700">=> </span><span style="color: #0000BB">1</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'data' </span><span style="color: #007700">=> array(</span><span style="color: #DD0000">'alt' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">title</span><span style="color: #007700">, </span><span style="color: #DD0000">'title' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">title</span><span style="color: #007700">, </span><span style="color: #DD0000">'description' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">title</span><span style="color: #007700">),<br> </span><span style="color: #DD0000">'uid' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">uid</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'filename' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">filename</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'filepath' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">filepath</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'filemime' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$file</span><span style="color: #007700">-></span><span style="color: #0000BB">filemime</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'status' </span><span style="color: #007700">=> </span><span style="color: #0000BB">1</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'timestamp' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">created</span><span style="color: #007700">,<br> );<br><br> }<br> </span><span style="color: #FF8000">// Print an error message if the file doesn't exist.<br> </span><span style="color: #007700">else {<br> </span><span style="color: #0000BB">drupal_set_message</span><span style="color: #007700">(</span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #DD0000">'Failed to find file: %file'</span><span style="color: #007700">, array(</span><span style="color: #DD0000">'%file' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$filepath</span><span style="color: #007700">)), </span><span style="color: #DD0000">'error'</span><span style="color: #007700">);<br> }<br> }<br>}<br></span><span style="color: #0000BB">?></span></span>
In our example, we used a content type called "news" with a field_news_image
imagefield, while the column containing the image filename in the source CMS is cms_news_table_image
.
The hook_migrate_destination_prepare_node()
hook is invoked just before each node record is migrated, allowing the module to manipulate the node data, one row at a time, immediately before it is stored to Drupal's database.
For each row, we check that the file we wish to migrate exists in the "files" directory and create a record for it in Drupal's files
table if one doesn't already exist. Finally we configure the field_news_image
field with all the required information.