function data_export_import_batch_import_dataset_lines in Data export import 7
Same name and namespace in other branches
- 6 includes/profiles/all_content_types.inc \data_export_import_batch_import_dataset_lines()
Batch function to process lines from a dataset.
This function will process one line at a time from a dataset file. To stop the function from processing the first line each time we will store the file pointer and then start the next file read from that point.
Parameters
string $file_path: File being processed.
Return value
bool TRUE if the address is in a valid format, and FALSE if it isn't.
2 string references to 'data_export_import_batch_import_dataset_lines'
- data_export_import_import_all_content_types_using_drush in includes/
profiles/ nodes.inc - Will import a dataset file.
- data_export_import_import_nodes in includes/
profiles/ nodes.inc - Import a dataset file and make current nodes match exactly.
File
- includes/
profiles/ nodes.inc, line 820 - Enables nodes to be exported and imported.
Code
function data_export_import_batch_import_dataset_lines($file_path, $fields_of_type_file, &$context) {
if (!isset($context['sandbox']['progress'])) {
$context['sandbox']['progress'] = 0;
// Get the number of lines we will be processing.
$line_count = 0;
$handle = fopen($file_path, "r");
if ($handle) {
while (($buffer = fgets($handle)) !== FALSE) {
$line_count++;
}
if (!feof($handle)) {
drupal_set_message(t("Error: unexpected fgets() fail\n"), 'error');
}
fclose($handle);
}
$context['sandbox']['max'] = $line_count;
}
// Open the file for reading.
$file_handle = fopen($file_path, 'r');
// Check if file pointer position exists in the sandbox, and jump to
// location in file.
if (isset($context['sandbox']['file_pointer_position'])) {
fseek($file_handle, $context['sandbox']['file_pointer_position']);
}
// Get file line from the file.
$line_from_file = fgets($file_handle);
// The first line in the dataset file is a the content type data -
// so we will ignore that line.
if ($context['sandbox']['progress'] != 0) {
$dataset_node = unserialize(base64_decode($line_from_file));
// Find if there is an existing node and see if it matches what is
// in the dataset. Note that node_load() returns FALSE if it can't
// find a node.
$existing_node = node_load($dataset_node->nid);
// If node_load returns FALSE then it was not able to find a node
// with the nid - therefore a new node needs to be created.
// Otherwise the existing node may need to be updated with the
// data from the dataset.
if ($existing_node == FALSE) {
// Saving data for a new node is relatively straight forward.
// We just call a modified version of the node_save() function.
// The difficult part is dealing with attached files and files
// uploaded via CCK fields. First we will loop through the
// fields looking for CCK fields which contain file data. We
// will then save these files. This means that we can then use
// the new file ID in the node data and when we save the node
// the link to the CCK file will be working correctly.
foreach ($fields_of_type_file as $file_field_key => $file_field_data) {
// Here we are going to loop through all of the files which
// may have been attached to this field.
if (isset($dataset_node->{$file_field_data}[LANGUAGE_NONE])) {
foreach ($dataset_node->{$file_field_data}[LANGUAGE_NONE] as $file_array_key => $file_array_data) {
$file_data = base64_decode($file_array_data['data_export_import_file_data']);
$dest = $file_array_data['uri'];
// Actually save the file to the file system.
$file_object = file_save_data($file_data, $dest, FILE_EXISTS_REPLACE);
// Set the node object to use the returned fid value as this
// may be from the original fid value.
$dataset_node->{$file_field_data}[LANGUAGE_NONE][$file_array_key]['fid'] = $file_object->fid;
}
}
}
// This is the important line where we actually save the node.
// The node should now have correct fid values to link to the
// CCK fields which have already been saved - and after saving
// this node we will be able to use the correct revision vid to
// link the node to the Upload module files which we will be
// saving next.
//
// Here will try to use the new node_save()
// function in D7 which may allow us to save the node with its
// current ID.
//
// One thing, we will set a field first to prevent
// the node being saved as a new file which would presumably be
// issued a new ID number.
unset($dataset_node->vid);
data_export_import_node_save_with_defined_id($dataset_node);
// Here we wll re-create all of the comments which were exported into the
// dataset. First we will delete all existing comments for the node -
// this should probably not be necessary but there may be excess comments/
// replies which are attached to the node which need to be removed.
// Remember that this module is designed to end up with identical data on
// the receiving site as the sending site.
if (module_exists('comment')) {
$comments_result = db_query("SELECT cid FROM {comment} WHERE nid = :comment_node ORDER BY cid ASC", array(
':comment_node' => $dataset_node->nid,
));
foreach ($comments_result as $comment_row) {
comment_delete($comment_row->cid);
}
if (property_exists($dataset_node, 'comments')) {
foreach ($dataset_node->comments as $attached_comment) {
$attached_comment->is_anonymous = 0;
// Before we save the record we are going to create a placeholder record
// with the defined id value. That way - when the comment_save function
// tries to save the comment with a specified cid value the underlying
// functions will be able to update an existing record and will not fail
// to carry out the SQL UPDATE statement.
db_merge('comment')
->key(array(
'cid' => $attached_comment->cid,
))
->fields(array(
'thread' => "",
))
->execute();
comment_submit($attached_comment);
comment_save($attached_comment);
}
}
}
}
else {
// If the nodes don't match then update the existing node with
// the data from the dataset. Certain fields can be unset
// because they would be expected to be different. We will store
// the existing dataset node because it will be needed when
// updating the node.
$existing_node_vid = $existing_node->vid;
// The node may have had new revisions created since the dataset
// was created so we'll unset all the data about revisions.
unset($dataset_node->vid);
unset($existing_node->vid);
unset($dataset_node->log);
unset($existing_node->log);
unset($dataset_node->revision_timestamp);
unset($existing_node->revision_timestamp);
// The changed date for the existing node could easily be
// different from the dataset node - even from a previous import
// of the dataset - or say a user saved the node without any
// changes.
unset($dataset_node->changed);
unset($existing_node->changed);
// There is an important tweak RE comments attached to the node. If there
// were any comments attached to the original node then these are attached
// to the node object as an array on the 'comments' attribute. As the
// existing_node will never have this attribute then the nodes will never
// match and so the node will be updated. This is fine as it saves us
// from having to check that the comments from the existing node are an
// exact match for the comments on the node being imported. As for import
// times - it is probably better to recreate the comments as checking
// existing comments would probably add more overhead than simply updating
// the node.
if ($dataset_node != $existing_node) {
// Create a new revision. The dataset node may be from several
// revisions back - and we don't want to reset back to a
// previous revision - and we don't want to overwrite the
// current revision - so creating a new revision is the best
// option. The only other option is to delete the node (which
// would delete all revisions) and then re-create it - but
// this would lose all the revision history.
$dataset_node->vid = $existing_node_vid;
$dataset_node->revision = 1;
$dataset_node->log = "Imported from dataset file: " . $file_path;
foreach ($fields_of_type_file as $file_field_key => $file_field_data) {
// Here we are going to loop through all of the files which
// may have been attached to this field and re-import them.
if (isset($dataset_node->{$file_field_data}[LANGUAGE_NONE])) {
foreach ($dataset_node->{$file_field_data}[LANGUAGE_NONE] as $file_array_key => $file_array_data) {
$file_data = base64_decode($file_array_data['data_export_import_file_data']);
$dest = $file_array_data['uri'];
// Actually save the file to the file system.
$file_object = file_save_data($file_data, $dest, FILE_EXISTS_REPLACE);
// Set the node object to use the returned fid value as
// this may be from the original fid value.
$dataset_node->{$file_field_data}[LANGUAGE_NONE][$file_array_key]['fid'] = $file_object->fid;
}
}
}
node_save($dataset_node);
// Here we wll re-create all of the comments which were
// exported into the dataset. First we will delete all
// existing comments for the node - this should probably not
// be necessary but there may be excess comments/replies which
// are attached to the node which need to be removed. Remember
// that this module is designed to end up with identical data
// on the receiving site as the sending site.
if (module_exists('comment')) {
$comments_result = db_query("SELECT cid FROM {comment} WHERE nid = :comment_node ORDER BY cid ASC", array(
':comment_node' => $dataset_node->nid,
));
foreach ($comments_result as $comment_row) {
comment_delete($comment_row->cid);
}
if (property_exists($dataset_node, 'comments')) {
foreach ($dataset_node->comments as $attached_comment) {
// This is needed to get the comment_save to work - not sure why.
$attached_comment->is_anonymous = 0;
// Before we save the record we are going to create a
// placeholder record with the defined id value. That way -
// when the comment_save function tries to save the comment
// with a specified cid value the underlying functions will
// be able to update an existing record and will not fail to
// carry out the SQL UPDATE statement.
db_merge('comment')
->key(array(
'cid' => $attached_comment->cid,
))
->fields(array(
'thread' => "",
))
->execute();
comment_submit($attached_comment);
comment_save($attached_comment);
}
}
}
}
}
}
$context['sandbox']['progress']++;
$context['results'][$file_path] = basename($file_path);
// Retain current file pointer position.
$context['sandbox']['file_pointer_position'] = ftell($file_handle);
// Inform the batch engine that we are not finished,
// and provide an estimation of the completion level we reached.
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}