type); foreach ($fields['fields'] as $field_name => $field) { if ($field['type'] == 'nodereference') { foreach (array_filter($field['referenceable_types']) as $related_type) { _backreference_insert($related_type, $field_name, $node); } } } break; } } function _backreference_insert($type, $key, $node) { $fields = content_types($type); foreach ($fields['fields'] as $field) { if ($field['type'] == 'nodereference' && $field['referenceable_types'][$node->type]) { $info = content_database_info($field); $table = $info['table']; $fieldname = $info['columns']['nid']['column']; $new_nids = array($node->nid); $placeholders = array(); foreach ($node->$key as $item) { if ($item['nid']) { $new_nids[] = $item['nid']; $placeholders[] = '%d'; } } $placeholders = $placeholders ? implode(', ', $placeholders) : '%d'; // We pick the nodes that no longer point to us. $sql = 'FROM {'. $table .'} WHERE '. $fieldname .' = %d AND nid NOT IN ('. $placeholders .')'; $result = db_query('SELECT nid, vid '. $sql, $new_nids); while ($existing_node = db_fetch_object($result)) { cache_clear_all('content:'. $existing_node->nid .':'. $existing_node->vid, 'cache_content'); } // We delete the references that no longer point to us. db_query('DELETE '. $sql, $new_nids); unset($new_nids[0]); foreach ($new_nids as $nid) { $vid = db_result(db_query('SELECT vid FROM {node} WHERE nid = %d', $nid)); // Skip existing references. if (!db_result(db_query('SELECT 1 FROM {'. $table .'} WHERE '. $fieldname .' = %d AND nid = %d AND vid = %d', $node->nid, $nid, $vid))) { // This is a new reference, so we need to insert it after other references. // This is race condition, yes, but I do not have anything better. Do we want one sequence per nid? // Remove any NULL values first. db_query('DELETE FROM {'. $table .'} WHERE ' . $fieldname .' IS NULL AND vid = %d', $vid); $delta = db_result(db_query('SELECT MAX(delta) + 1 FROM {'. $table .'} WHERE nid = %d', $nid)); db_query('INSERT INTO {'. $table .'} (vid, delta, nid, '. $fieldname .') VALUES (%d, %d, %d, %d)', $vid, $delta, $nid, $node->nid); cache_clear_all('content:'. $nid .':'. $vid, 'cache_content'); } } } } }