summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--modules/node_reference/node_reference.module94
1 files changed, 53 insertions, 41 deletions
diff --git a/modules/node_reference/node_reference.module b/modules/node_reference/node_reference.module
index 39c6b23..ad6f803 100644
--- a/modules/node_reference/node_reference.module
+++ b/modules/node_reference/node_reference.module
@@ -161,6 +161,9 @@ function node_reference_field_formatter_info() {
function node_reference_field_formatter_view($obj_type, $object, $field, $instance, $langcode, $items, $display) {
$result = array();
+ // @todo Optimisation: use hook_field_formatter_prepare_view() to load
+ // node titles or full nodes in 'multiple' mode.
+
// Collect the list of node ids.
$nids = array();
foreach ($items as $delta => $item) {
@@ -231,7 +234,7 @@ function node_reference_field_formatter_view($obj_type, $object, $field, $instan
$nodes[$nid]->referencing_object = $object;
$nodes[$nid]->referencing_field = $field['field_name'];
}
- $nodes_built = node_build_multiple($nodes, $build_mode);
+ $nodes_built = node_view_multiple($nodes, $build_mode);
}
// Fetch the titles of the other nodes.
@@ -260,7 +263,7 @@ function node_reference_field_formatter_view($obj_type, $object, $field, $instan
}
/**
- * Helper function for formatters.
+ * Helper function for widgets and formatters.
*
* Store node titles collected in the curent request.
*/
@@ -308,7 +311,7 @@ function node_reference_field_widget_info() {
'field types' => array('node_reference'),
'settings' => array(
'autocomplete_match' => 'contains',
- 'size' => 60,
+ 'size' => 60,
'autocomplete_path' => 'node_reference/autocomplete',
),
),
@@ -357,17 +360,16 @@ function node_reference_field_widget_settings_form($field, $instance) {
/**
* Implements hook_field_widget_form().
*/
-function node_reference_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
+function node_reference_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $base) {
switch ($instance['widget']['type']) {
case 'node_reference_autocomplete':
- $element += array(
- '#type' => 'textfield',
- '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL,
+ $element['nid'] = $base + array(
+ '#type' => 'textfield',
+ '#default_value' => isset($items[$delta]['nid']) ? $items[$delta]['nid'] : NULL,
'#autocomplete_path' => $instance['widget']['settings']['autocomplete_path'] . '/' . $field['field_name'],
- '#size' => $instance['widget']['settings']['size'],
- '#element_validate' => array('node_reference_autocomplete_validate'),
- '#input' => TRUE, // allow #value_callback to be invoked
- '#value_callback' => 'node_reference_autocomplete_value',
+ '#size' => $instance['widget']['settings']['size'],
+ '#element_validate' => array('node_reference_autocomplete_validate'),
+ '#value_callback' => 'node_reference_autocomplete_value',
);
break;
}
@@ -376,63 +378,73 @@ function node_reference_field_widget_form(&$form, &$form_state, $field, $instanc
}
/**
- * Value for a node_reference autocomplete element.
+ * Value callback for a node_reference autocomplete element.
*
- * Replace the node title with a node nid.
+ * Replace the node nid with a node title.
*/
-function node_reference_autocomplete_value($element, $edit = FALSE, $form_state) {
- if (!empty($element['#default_value'])) {
+function node_reference_autocomplete_value($element, $input = FALSE, $form_state) {
+ if ($input === FALSE) {
+ // We're building the displayed 'default value': expand the raw nid into
+ // "node title [nid:n]".
$nid = $element['#default_value'];
-
- $q = db_select('node', 'n');
- $node_title_alias = $q->addField('n', 'title');
- $q->addTag('node_access')
- ->condition('n.nid', $nid)
- ->range(0, 1);
- $result = $q->execute();
-
- $value = $result->fetchField();
- $value .= ' [nid:'. $nid .']';
- }
- else {
- $value = NULL;
+ if (!empty($nid)) {
+ $q = db_select('node', 'n');
+ $node_title_alias = $q->addField('n', 'title');
+ $q->addTag('node_access')
+ ->condition('n.nid', $nid)
+ ->range(0, 1);
+ $result = $q->execute();
+ // @todo If no result (node doesn't exist or no access).
+ $value = $result->fetchField();
+ $value .= ' [nid:'. $nid .']';
+ return $value;
+ }
}
- return $value;
}
/**
- * Validate an autocomplete element.
+ * Validation callback for a node_reference autocomplete element.
*/
function node_reference_autocomplete_validate($element, &$form_state, $form) {
+ $field = $form['#fields'][$element['#field_name']]['field'];
+ $instance = $form['#fields'][$element['#field_name']]['instance'];
+
$value = $element['#value'];
$nid = NULL;
+
if (!empty($value)) {
- $field_name = $element['#field_name'];
- $instance = field_info_instance('node', $field_name, $element['#bundle']);
+ // Check whether we have an explicit "[nid:n]" input.
preg_match('/^(?:\s*|(.*) )?\[\s*nid\s*:\s*(\d+)\s*\]$/', $value, $matches);
if (!empty($matches)) {
- // Explicit [nid:n].
+ // Explicit nid. Check that the 'title' part matches the actual title for
+ // the nid.
list(, $title, $nid) = $matches;
- if (!empty($title) && ($n = node_load($nid)) && $title != $n->title[LANGUAGE_NONE][0]['value']) {
- form_error($element, t('%name: title mismatch. Please check your selection.', array('%name' => t($instance['label']))));
+ if (!empty($title)) {
+ $titles = _node_reference_get_node_titles(array($nid));
+ if ($title != $titles[$nid]) {
+ form_error($element, t('%name: title mismatch. Please check your selection.', array('%name' => t($instance['label']))));
+ }
}
}
else {
- // No explicit nid.
- $field = field_info_field($field_name);
+ // No explicit nid (the submitted value was not populated by autocomplete
+ // selection). Get the nid of a referencable node from the entered title.
$reference = _node_reference_potential_references($field, $value, 'equals', NULL, 1);
- if (empty($reference)) {
- form_error($element, t('%name: found no valid post with that title.', array('%name' => t($instance['label']))));
- }
- else {
+ if ($reference) {
// @todo The best thing would be to present the user with an
// additional form, allowing the user to choose between valid
// candidates with the same title. ATM, we pick the first
// matching candidate...
$nid = key($reference);
}
+ else {
+ form_error($element, t('%name: found no valid post with that title.', array('%name' => t($instance['label']))));
+ }
}
}
+
+ // Set the element's value as the node id that was extracted from the entered
+ // input.
form_set_value($element, $nid, $form_state);
}