Index: nodereference.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/cck/nodereference.module,v retrieving revision 1.25.2.7 diff -u -r1.25.2.7 nodereference.module --- nodereference.module 10 Aug 2006 02:28:14 -0000 1.25.2.7 +++ nodereference.module 10 Aug 2006 07:15:23 -0000 @@ -23,8 +23,13 @@ $items = array(); if ($may_cache) { - $items[] = array('path' => 'nodereference/autocomplete', 'title' => t('node reference autocomplete'), - 'callback' => 'nodereference_autocomplete', 'access' => user_access('access content'), 'type' => MENU_CALLBACK); + $items[] = array( + 'path' => 'nodereference/autocomplete', + 'title' => t('node reference autocomplete'), + 'callback' => 'nodereference_autocomplete', + 'access' => user_access('access content'), + 'type' => MENU_CALLBACK, + ); } return $items; @@ -35,7 +40,8 @@ */ function nodereference_field_info() { return array( - 'nodereference' => array('label' => 'Node Reference'), + 'nodereference' => array('label' => t('Node Reference')), + 'nodereferrers' => array('label' => t('Node Referrers')), ); } @@ -43,8 +49,8 @@ * Implementation of hook_field_settings(). */ function nodereference_field_settings($op, $field) { - switch ($op) { - case 'form': + switch ($field['type'] .'/'. $op) { + case 'nodereference/form': $form = array(); $form['referenceable_types'] = array( '#type' => 'checkboxes', @@ -55,14 +61,30 @@ ); return $form; - case 'save': + case 'nodereference/save': return array('referenceable_types'); - case 'database columns': + case 'nodereferrers/form': + $form = array(); + $form['referrer_types'] = array( + '#type' => 'checkboxes', + '#title' => t('Referrer types to be displayed in list.'), + '#multiple' => TRUE, + '#default_value' => isset($field['referrer_types']) ? $field['referrer_types'] : array(), + '#options' => node_get_types(), + ); + return $form; + + case 'nodereferrers/save': + return array('referrer_types'); + + case 'nodereference/database columns': + case 'nodereferrers/database columns': $columns = array( 'nid' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'), ); return $columns; + } } @@ -70,25 +92,62 @@ * Implementation of hook_field(). */ function nodereference_field($op, &$node, $field, &$node_field, $teaser, $page) { - switch ($op) { - case 'view': + drupal_set_message('
'. print_r($field, true) .''); + switch ($field['type'] .'/'. $op) { + case 'nodereference/view': foreach ($node_field as $delta => $item) { - $node_field[$delta]['view'] = nodereference_field_view_item($field, $item, $node); + $node_field[$delta]['view'] = nodereference_field_view_item($field, $item); } return theme('field', $node, $field, $node_field, $teaser, $page); + + case 'nodereferrers/view': + foreach ($node_field as $delta => $item) { + $output[$delta]['view'] = theme('nodereference', $field, $item); + } + return theme('field', $node, $field, $output, $teaser, $page); + + case 'nodereferrers/insert': + // Assign the node's nid to the referrers data. This helps retrieving the node's referrers. + // @question: wouldn't we have the node or nid in most cases anyway? Wouldn't it be better to not store any + // data here? and just query a list of referring nodes on op==load? --dopry + $node_field[0]['nid'] = $node->nid; + return; + + case 'nodereferrers/load': + $types = array_values($field['referrer_types']); + drupal_set_message('referrer_types:
'.print_r($types, true) .''); + $values = nodereference_get_referrers($node->nid, $types); + + //reset node_field value... we're going to make it the list of referrers... + $node_field = array(); + foreach ($values as $nid => $rnode) { + $node_field[] = $rnode; + } + return array($field['field_name'] => $values); } } /** * Implementation of hook_field_view_item(). */ -function nodereference_field_view_item($field, $node_field_item) { - if (!isset($node_field_item['nid'])) { +function nodereference_field_view_item($field, $item) { + if (!isset($item['nid'])) { return ''; } - $referenced_node = node_load($node_field_item['nid']); - if ($referenced_node) { - return l($referenced_node->title, 'node/'. $referenced_node->nid); + switch($field['type']) { + case 'nodereference': + $referenced_node = node_load($item['nid']); + if ($referenced_node) { + return theme('nodereference', $field, $referenced_node); + } + break; + + case 'nodereferrers': + $referrers = nodereference_get_referrers($item['nid']); // Should/could these be retrieved on hook_field($op='load')? + foreach($referrers as $referrer) { + $output .= theme('nodereference', $field, $referrer); + } + return $output; } } @@ -99,13 +158,17 @@ function nodereference_widget_info() { return array( 'nodereference_select' => array( - 'label' => 'Select List', + 'label' => t('Select List'), 'field types' => array('nodereference'), ), 'nodereference_autocomplete' => array( - 'label' => 'Autocomplete Text Field', + 'label' => t('Autocomplete Text Field'), 'field types' => array('nodereference'), ), + 'nodereferrers_list' => array( + 'label' => t('Read-Only List'), + 'field types' => array('nodereferrers'), + ), ); } @@ -113,120 +176,125 @@ * Implementation of hook_widget(). */ function nodereference_widget($op, &$node, $field, &$node_field) { - if ($field['widget']['type'] == 'nodereference_select') { - switch ($op) { - case 'prepare form values': - $node_field_transposed = content_transpose_array_rows_cols($node_field); - $node_field['default nids'] = $node_field_transposed['nid']; - break; - - case 'form': - $form = array(); - - $form[$field['field_name']] = array('#tree' => TRUE); - $form[$field['field_name']]['nids'] = array( - '#type' => 'select', - '#title' => t($field['widget']['label']), - '#default_value' => $node_field['default nids'], - '#multiple' => $field['multiple'], - '#options' => _nodereference_potential_references($field), - '#required' => $field['required'], - '#description' => $field['widget']['description'], - ); + switch($field['widget']['type'] .'/'. $op) { + case 'nodereference_select/prepare form values': + $node_field_transposed = content_transpose_array_rows_cols($node_field); + $node_field['default nids'] = $node_field_transposed['nid']; + break; - return $form; + case 'nodereference_select/form': + $form = array(); + $form[$field['field_name']] = array('#tree' => TRUE); + $form[$field['field_name']]['nids'] = array( + '#type' => 'select', + '#title' => t($field['widget']['label']), + '#default_value' => $node_field['default nids'], + '#multiple' => $field['multiple'], + '#options' => _nodereference_potential_references($field), + '#required' => $field['required'], + '#description' => $field['widget']['description'], + ); + return $form; - case 'process form values': - if ($field['multiple']) { - $node_field = content_transpose_array_rows_cols(array('nid' => $node_field['nids'])); - } - else { - $node_field[0]['nid'] = $node_field['nids']; - } - // Remove the widget's data representation so it isn't saved. - unset($node_field['nids']); - } - } - else { - switch ($op) { - case 'prepare form values': - foreach ($node_field as $delta => $item) { - $node_field[$delta]['default node_name'] = db_result(db_query(db_rewrite_sql('SELECT n.title FROM {node} n WHERE n.nid = %d'), $node_field[$delta]['nid'])); - } - break; + case 'nodereference_select/process form values': + if ($field['multiple']) { + $node_field = content_transpose_array_rows_cols(array('nid' => $node_field['nids'])); + } + else { + $node_field[0]['nid'] = $node_field['nids']; + } + // Remove the widget's data representation so it isn't saved. + unset($node_field['nids']); + break; - case 'form': - $form = array(); - $form[$field['field_name']] = array('#tree' => TRUE); - - if ($field['multiple']) { - $form[$field['field_name']]['#type'] = 'fieldset'; - $form[$field['field_name']]['#title'] = t($field['widget']['label']); - $form[$field['field_name']]['#description'] = $field['widget']['description']; - $delta = 0; - foreach ($node_field as $item) { - if ($item['nid']) { - $form[$field['field_name']][$delta]['node_name'] = array( - '#type' => 'textfield', - '#title' => '', - '#autocomplete_path' => 'nodereference/autocomplete/'. $field['field_name'], - '#default_value' => $item['default node_name'], - '#required' => ($delta == 0) ? $field['required'] : FALSE, - ); - $delta++; - } - } - foreach (range($delta, $delta + 2) as $delta) { + case 'nodereference_autocomplete/prepare form values': + foreach ($node_field as $delta => $item) { + $node_field[$delta]['default node_name'] = db_result(db_query(db_rewrite_sql('SELECT n.title FROM {node} n WHERE n.nid = %d'), $node_field[$delta]['nid'])); + } + break; + + case 'nodereference_autocomplete/form': + $form = array(); + $form[$field['field_name']] = array('#tree' => TRUE); + if ($field['multiple']) { + $form[$field['field_name']]['#type'] = 'fieldset'; + $form[$field['field_name']]['#title'] = t($field['widget']['label']); + $form[$field['field_name']]['#description'] = $field['widget']['description']; + $delta = 0; + foreach ($node_field as $item) { + if ($item['nid']) { $form[$field['field_name']][$delta]['node_name'] = array( '#type' => 'textfield', '#title' => '', '#autocomplete_path' => 'nodereference/autocomplete/'. $field['field_name'], - '#default_value' => '', + '#default_value' => $item['default node_name'], '#required' => ($delta == 0) ? $field['required'] : FALSE, ); + $delta++; } } - else { - $form[$field['field_name']][0]['node_name'] = array( + foreach (range($delta, $delta + 2) as $delta) { + $form[$field['field_name']][$delta]['node_name'] = array( '#type' => 'textfield', - '#title' => t($field['widget']['label']), + '#title' => '', '#autocomplete_path' => 'nodereference/autocomplete/'. $field['field_name'], - '#default_value' => $node_field[0]['default node_name'], - '#required' => $field['required'], - '#description' => $field['widget']['description'], + '#default_value' => '', + '#required' => ($delta == 0) ? $field['required'] : FALSE, ); } - return $form; + } - case 'validate': - foreach ($node_field as $delta => $item) { - if ($item['node_name'] && !in_array($item['node_name'], _nodereference_potential_references($field))) { - form_set_error($field['field_name'], t('No post with that title exists.')); - } + else { + $form[$field['field_name']][0]['node_name'] = array( + '#type' => 'textfield', + '#title' => t($field['widget']['label']), + '#autocomplete_path' => 'nodereference/autocomplete/'. $field['field_name'], + '#default_value' => $node_field[0]['default node_name'], + '#required' => $field['required'], + '#description' => $field['widget']['description'], + ); + } + return $form; + + case 'nodereference_autocomplete/validate': + foreach ($node_field as $delta => $item) { + if ($item['node_name'] && !in_array($item['node_name'], _nodereference_potential_references($field))) { + form_set_error($field['field_name'], t('No post with that title exists.')); } - return; + } + return; - case 'process form values': - foreach ($node_field as $delta => $item) { - $nid = 0; - if ($node_field[$delta]['node_name']) { - $nid = db_result(db_query(db_rewrite_sql("SELECT n.nid FROM {node} n WHERE n.title = '%s'"), $node_field[$delta]['node_name'])); - } - // Remove the widget's data representation so it isn't saved. - unset($node_field[$delta]['node_name']); - if ($nid) { - $node_field[$delta]['nid'] = $nid; - } - else { - unset($node_field[$delta]); - } + + + + case 'nodereference_autocomplete/process form values': + foreach ($node_field as $delta => $item) { + $nid = db_result(db_query(db_rewrite_sql("SELECT n.nid FROM {node} n WHERE n.title = '%s'"), $node_field[$delta]['node_name'])); + + // Remove the widget's data representation so it isn't saved. + unset($node_field[$delta]['node_name']); + if ($nid) { + $node_field[$delta]['nid'] = $nid; } - break; - } + else { + unset($node_field[$delta]); + } + } + break; + + case 'nodereferrers_list/form': + $form = array(); + $form[$field['field_name']] = array('#tree' => TRUE); + $form[$field['field_name']][0]['nid'] = array( + '#type' => 'hidden', + '#value' => $node->nid, + ); + return $form; + + } } - /** * Fetch an array of all candidate referenced nodes, for use in presenting the selection form to the user. */ @@ -281,4 +349,45 @@ print drupal_to_js($matches); exit(); -} \ No newline at end of file +} + +/** + * get an array of referrers by nid and content type. + * @param nid + * referred to nodes nid + * @param content_types + * array of content types to be queried for. empty array == all content types + * @return array + */ +function nodereference_get_referrers($nid, $content_types = array()) { + drupal_set_message('nodereference_get_referrers:
'.print_r($content_types, true) .''); + // Retrieve the fields in order to find the field names of all nodereference fields + $fields = content_fields(); + $values = array(); + foreach($fields as $field) { + if ($field['type'] == 'nodereference') { + $db_info = content_database_info($field); + + // Gather the nodereferences that refer to $nid + //TODO: Should probably collect only nids and call node_load(). + if ($content_types) { + $result = db_query("SELECT n.* FROM {" . $db_info['table'] . "} nr INNER JOIN {node} n ON n.vid = nr.vid + AND n.type IN ('". implode("', '", $content_types) ."') AND n.status = 1 WHERE nr." . $db_info['columns']['nid']['column'] . " = %d + ORDER BY n.created DESC", $nid); + } + else { + $result = db_query("SELECT n.* FROM {" . $db_info['table'] . "} nr INNER JOIN {node} n ON n.vid = nr.vid + AND n.status = 1 WHERE nr." . $db_info['columns']['nid']['column'] . " = %d ORDER BY n.created DESC", $nid); + } + while ($value = db_fetch_object($result)) { + $values[$value->nid] = $value; // Note: Using nid as key to avoid duplicate referrers + } + } + } + return $values; +} + + +function theme_nodereference($field, $node) { + return '