View source
<?php
function corresponding_node_references_menu() {
$items = array();
$items['admin/settings/corresponding_node_references'] = array(
'title' => t('Corresponding node references'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'corresponding_node_references_settings_form',
),
'access arguments' => array(
'administer corresponding node references settings',
),
'type' => MENU_NORMAL_ITEM,
);
$items['admin/settings/corresponding_node_references/references'] = array(
'title' => t('Corresponding node references'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'corresponding_node_references_settings_form',
),
'access arguments' => array(
'administer corresponding node references settings',
),
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/settings/corresponding_node_references/update'] = array(
'title' => t('Update existing nodes'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'corresponding_node_references_update_form',
),
'access arguments' => array(
'administer corresponding node references settings',
),
'type' => MENU_LOCAL_TASK,
);
return $items;
}
function corresponding_node_references_perm() {
return array(
'administer corresponding node references settings',
);
}
function corresponding_node_references_settings_form() {
$form['intro'] = array(
'#value' => t('Check which node references should listen to each other.
When checking a check box a reference on node type A to node B will automatically update the node reference field on node B
adding an entrie which points to node A.'),
);
$result = db_query("SELECT cnf.field_name, cnf.global_settings FROM {content_node_field} cnf WHERE cnf.type = '%s'", 'nodereference');
while ($row = db_fetch_object($result)) {
$data = unserialize($row->global_settings);
foreach ($data['referenceable_types'] as $reference) {
if ($reference != '0') {
$references[$row->field_name][] = $reference;
}
}
}
$result = db_query("SELECT cnfi.field_name, cnfi.type_name FROM {content_node_field_instance} cnfi INNER JOIN {content_node_field} cnf ON cnf.field_name = cnfi.field_name WHERE cnf.type = '%s'", 'nodereference');
while ($row = db_fetch_object($result)) {
if (!empty($references[$row->field_name])) {
foreach ($references[$row->field_name] as $reference) {
$fields_to_compare[] = array(
'field_type' => $row->field_name,
'node_type' => $row->type_name,
'reference' => $reference,
);
}
}
}
if (!empty($fields_to_compare)) {
$corr_noderefs = array();
foreach ($fields_to_compare as $field) {
foreach ($fields_to_compare as $second_field) {
if ($field['node_type'] == $second_field['reference'] && $second_field['node_type'] == $field['reference']) {
if (!array_key_exists($field['node_type'] . ' ' . $field['field_type'] . ' ' . $second_field['node_type'] . ' ' . $second_field['field_type'], $corr_noderefs) && !array_key_exists($second_field['node_type'] . ' ' . $second_field['field_type'] . ' ' . $field['node_type'] . ' ' . $field['field_type'], $corr_noderefs)) {
$corr_noderefs[$field['node_type'] . ' ' . $field['field_type'] . ' ' . $second_field['node_type'] . ' ' . $second_field['field_type']] = array(
'node_type_1' => $field['node_type'],
'field_1' => $field['field_type'],
'node_type_2' => $second_field['node_type'],
'field_2' => $second_field['field_type'],
);
}
}
}
}
if (!empty($corr_noderefs)) {
$count = 0;
foreach ($corr_noderefs as $key => $corr_noderef) {
$formated_label = corresponding_node_references_format_label($key);
$formated_key = str_replace(' ', '*', $key);
$mapping[] = $formated_key;
$form['values'][$count] = array(
'#type' => 'fieldset',
);
$form['values'][$count]['enabled_' . $count] = array(
'#type' => 'checkbox',
'#default_value' => db_result(db_query("SELECT enabled FROM {corresponding_node_references} WHERE node_types_content_fields = '%s'", $formated_key)),
'#title' => $formated_label,
);
$count++;
}
$form['mapping'] = array(
'#type' => 'hidden',
'#value' => serialize($mapping),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
}
else {
$form['text'] = array(
'#value' => '<div>' . t('There are no node types which have a corresponding node reference') . '</div>',
);
}
}
return $form;
}
function corresponding_node_references_settings_form_submit($form, $form_values) {
db_query("UPDATE {corresponding_node_references} SET enabled = %d", 0);
$query_values = array();
$mapping = unserialize($form_values['values']['mapping']);
foreach ($form_values['values'] as $key => $value) {
$keys = explode('_', $key);
if ($keys[0] == 'enabled') {
$query_values[$mapping[$keys[1]]] = $value;
}
}
foreach ($query_values as $key => $value) {
db_query("DELETE FROM {corresponding_node_references} WHERE node_types_content_fields='%s'", $key);
db_query("INSERT INTO {corresponding_node_references} (node_types_content_fields, enabled) VALUES ('%s', %d)", $key, $value);
}
drupal_set_message(t('The configuration has been saved'));
}
function corresponding_node_references_format_label($key) {
$key = explode(' ', $key);
return t('Field instance:"!field1" on Node type:"!type1" <b>Corresponds with</b> Field instance:"!field2" on Node type:"!type2"', array(
'!type1' => $key[0],
'!field1' => $key[1],
'!type2' => $key[2],
'!field2' => $key[3],
));
}
function corresponding_node_references_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
switch ($op) {
case 'insert':
case 'update':
case 'delete':
corresponding_node_references_process_node($op, $node);
break;
}
}
function corresponding_node_references_process_node($op, $node, $process_unchanged = FALSE) {
module_load_include('inc', 'corresponding_node_references', 'corresponding_node_references.crud');
$result = db_query("SELECT node_types_content_fields FROM {corresponding_node_references} WHERE enabled = %d", 1);
while ($row = db_fetch_object($result)) {
$key = explode('*', $row->node_types_content_fields);
switch ($node->type) {
case $key[0]:
$args = array(
$node,
$key[1],
$key[2],
$key[3],
$process_unchanged,
);
$function = 'corresponding_node_references_' . $op;
call_user_func_array($function, $args);
if ($key[0] != $key[2]) {
break;
}
case $key[2]:
$args = array(
$node,
$key[3],
$key[0],
$key[1],
$process_unchanged,
);
$function = 'corresponding_node_references_' . $op;
call_user_func_array($function, $args);
break;
}
}
}
function corresponding_node_references_update_form() {
$form = array();
$form['intro'] = array(
'#value' => t('This will update all the existing nodes for the selected content types so that their node reference fields are in sync.') . '<br />' . t('This process may take a long time depending on the number of nodes you are updating.') . '<br />' . t('When the process is finished you will see a count of the number of nodes that were updated.'),
);
$form['types'] = array(
'#type' => 'checkboxes',
'#title' => t('Node types'),
'#options' => node_get_types('names'),
'#description' => t('Select the node types that you want to update.'),
);
$form['limit'] = array(
'#type' => 'select',
'#title' => t('Number of nodes to process at once'),
'#options' => array(
10 => t('10'),
20 => t('20'),
30 => t('30'),
50 => t('50'),
75 => t('75'),
100 => t('100'),
125 => t('125'),
150 => t('150'),
200 => t('200'),
250 => t('250'),
300 => t('300'),
350 => t('350'),
400 => t('400'),
450 => t('450'),
500 => t('500'),
),
'#default_value' => 50,
'#description' => t('This process is done in batches. This is the number of nodes processed in each batch. If necessary, reduce the number of nodes to prevent timeouts and memory errors while processing.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'submit',
);
return $form;
}
function corresponding_node_references_update_form_validate($form, &$form_state) {
$types = array_filter($form_state['values']['types']);
if (empty($types)) {
form_set_error('types', t('You must select at least one node type.'));
}
}
function corresponding_node_references_update_form_submit($form, &$form_state) {
$types = array_filter($form_state['values']['types']);
$types = array_keys($types);
corresponding_node_references_batch_index_remaining($types, $form_state['values']['limit']);
}
function corresponding_node_references_batch_index_remaining($types, $limit) {
$batch = array(
'operations' => array(
array(
'corresponding_node_references_batch_update_existing_nodes',
array(
$types,
$limit,
),
),
),
'finished' => 'corresponding_node_references_batch_update_existing_finished',
'title' => t('Processing'),
'init_message' => t('Preparing to update corresponding node references for existing nodes...'),
'progress_message' => t('Processing nodes...'),
'error_message' => t('Corresponding node references existing node update has encountered an error.'),
);
batch_set($batch);
}
function corresponding_node_references_batch_update_existing_nodes($types, $limit, &$context) {
if (!isset($context['sandbox']['progress'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['current_node'] = 0;
$context['sandbox']['max'] = db_result(db_query("SELECT COUNT(DISTINCT nid) FROM {node} WHERE type IN (" . db_placeholders($types, 'varchar') . ")", $types));
}
$nids = array();
$args = $types;
$args[] = $context['sandbox']['current_node'];
$result = db_query_range("SELECT nid\n FROM {node}\n WHERE type IN (" . db_placeholders($types, 'varchar') . ")\n AND nid > %d\n ORDER BY nid", $args, 0, $limit);
while ($row = db_fetch_object($result)) {
$node = node_load($row->nid);
corresponding_node_references_process_node('update', $node, TRUE);
$context['sandbox']['progress']++;
$context['sandbox']['current_node'] = $node->nid;
$context['message'] = t('Processed @current of @total nodes', array(
'@current' => $context['sandbox']['progress'],
'@total' => $context['sandbox']['max'],
));
}
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
if ($context['finished']) {
$context['results']['count'] = $context['sandbox']['progress'];
}
}
function corresponding_node_references_batch_update_existing_finished($success, $results, $operations) {
if ($success) {
$type = 'status';
$message = format_plural($results['count'], '1 node processed successfully.', '@count nodes processed successfully.');
}
else {
$type = 'error';
$error_operation = reset($operations);
$message = 'An error occurred while processing ' . $error_operation[0] . ' with arguments:' . print_r($error_operation[0], TRUE);
}
drupal_set_message($message, $type);
}