diff --git a/HEAD_IS_EMPTY_USE_7.x-2.x_BRANCH.txt b/HEAD_IS_EMPTY_USE_7.x-2.x_BRANCH.txt
new file mode 100644
index 0000000000000000000000000000000000000000..485fc70549de58ec776865a2250ddf5bd53f6b35
--- /dev/null
+++ b/HEAD_IS_EMPTY_USE_7.x-2.x_BRANCH.txt
@@ -0,0 +1 @@
+Development takes place in the 7.x-2.x branch
diff --git a/README.txt b/README.txt
deleted file mode 100644
index f5c08ebbf901989f94e233ea253c4e6db419a8e8..0000000000000000000000000000000000000000
--- a/README.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-$Id$
-
--- SUMMARY --
-
-The References project contains straight ports of the node_reference and
-user_reference modules to the Drupal 7 API.
-
-For a full description of the module, visit the project page:
- http://drupal.org/project/references
-
--- REQUIREMENTS --
-
-None.
-
-CCK for Drupal 7 is /not/ a requirement for these modules.
-
--- GOALS AND LIMITATIONS --
-
-It is not envisioned as a final solution, but as a way to actually deploy
-Drupal 7 from release day on sites using node and user references much as on
-Drupal 6, until a native entity relationships Drupal 7 module becomes a usable
-alternative.
-
-As of 2010-11-30, is looks like a candidate for that usable alternative might
-someday be project Relation:
- http://drupal.org/project/relation
-
-In short: use these modules now, but be ready to migrate to a different entity
-referencing solution during the D7 life cycle.
-
--- CONTACT --
-
-Current maintainers:
-
-* References: Frederic G. MARAND (fgm) - http://drupal.org/user/27985
-* CCK D7: Yves CHEDEMOIS (yched) - http://drupal.org/user/39567
-
diff --git a/node_reference/node_reference.info b/node_reference/node_reference.info
deleted file mode 100644
index 7e737977b4a3803207910388d2277e3e83f2ae4b..0000000000000000000000000000000000000000
--- a/node_reference/node_reference.info
+++ /dev/null
@@ -1,6 +0,0 @@
-; $Id$
-name = Node Reference
-description = Defines a field type for referencing one node from another.
-files[]=node_reference.module
-package = CCK
-core = 7.x
diff --git a/node_reference/node_reference.module b/node_reference/node_reference.module
deleted file mode 100644
index 6d0d2f85041f3c4910d24da9e4612d6f4a88503b..0000000000000000000000000000000000000000
--- a/node_reference/node_reference.module
+++ /dev/null
@@ -1,841 +0,0 @@
- 'node_reference autocomplete',
- 'page callback' => 'node_reference_autocomplete',
- 'page arguments' => array(2, 3),
- 'access callback' => 'node_reference_autocomplete_access',
- 'access arguments' => array(2, 3),
- 'type' => MENU_CALLBACK,
- );
- return $items;
-}
-
-/**
- * Implements hook_field_info().
- */
-function node_reference_field_info() {
- return array(
- 'node_reference' => array(
- 'label' => t('Node reference'),
- 'description' => t('This field stores the ID of a related node as an integer value.'),
- 'settings' => array('referenceable_types' => array()),
- // It probably make more sense to have the referenceable types be per-field than per-instance
- // 'instance settings' => array('referenceable_types' => array()),
- 'default_widget' => 'options_select', // node_reference_autocomplete',
- 'default_formatter' => 'node_reference_default',
- ),
- );
-}
-
-/**
- * Implements hook_field_schema().
- */
-function node_reference_field_schema($field) {
- $columns = array(
- 'nid' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => FALSE,
- ),
- );
- return array(
- 'columns' => $columns,
- 'indexes' => array('nid' => array('nid')),
- 'foreign keys' => array(
- 'nid' => array(
- 'table' => 'node',
- 'columns' => array('nid' => 'nid'),
- ),
- ),
- );
-}
-
-/**
- * Implements hook_field_settings_form().
- */
-function node_reference_field_settings_form($field, $instance, $has_data) {
- $settings = $field['settings'];
-
- $form = array();
- $form['referenceable_types'] = array(
- '#type' => 'checkboxes',
- '#title' => t('Content types that can be referenced'),
- '#multiple' => TRUE,
- '#default_value' => is_array($settings['referenceable_types'])
- ? $settings['referenceable_types']
- : array(),
- '#options' => array_map('check_plain', node_type_get_names()),
- '#disabled' => $has_data,
- );
- return $form;
-}
-
-/**
- * Implements hook_field_validate().
- *
- * Possible error codes:
- * - 'invalid_nid': nid is not valid for the field (not a valid node id, or the node is not referenceable).
- */
-function node_reference_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
- // Extract nids to check.
- $ids = array();
-
- // First check non-numeric "nid's to avoid losing time with them.
- foreach ($items as $delta => $item) {
- if (is_array($item) && !empty($item['nid'])) {
- if (is_numeric($item['nid'])) {
- $ids[] = $item['nid'];
- }
- else {
- $errors[$field['field_name']][$langcode][$delta][] = array(
- 'error' => 'invalid_nid',
- 'message' => t("%name: invalid input.",
- array('%name' => $instance['label'])),
- );
- }
- }
- }
- // Prevent performance hog if there are no ids to check.
- if ($ids) {
- $refs = _node_reference_potential_references($field, '', NULL, $ids);
- foreach ($items as $delta => $item) {
- if (is_array($item)) {
- if (!empty($item['nid']) && !isset($refs[$item['nid']])) {
- $errors[$field['field_name']][$langcode][$delta][] = array(
- 'error' => 'invalid_nid',
- 'message' => t("%name: this post can't be referenced.",
- array('%name' => $instance['label'])),
- );
- }
- }
- }
- }
-}
-
-/**
- * Implements hook_field_prepare_view().
- */
-function node_reference_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
- // @todo : do we need the static ?
- $fetched_nodes = &drupal_static(__FUNCTION__, array());
-
- // Extract nids to check.
- $ids = array();
- foreach ($items as $id => $entity_items) {
- foreach ($entity_items as $delta => $item) {
- if (is_array($item)) {
- // Default to 'not accessible'.
- $items[$id][$delta]['access'] = FALSE;
- if (!empty($item['nid']) && is_numeric($item['nid'])) {
- $ids[$item['nid']] = $item['nid'];
- }
- }
- }
- }
-
- if ($ids) {
- // Load information about nids that we haven't already loaded during
- // this page request.
- $missing_ids = array_diff($ids, array_keys($fetched_nodes));
- if (!empty($missing_ids)) {
- $query = db_select('node', 'n')
- ->fields('n')
- ->condition('n.nid', $missing_ids)
- ->addTag('node_access');
- if (!user_access('administer nodes')) {
- $query->condition('status', 1);
- }
- $fetched_nodes = $query->execute()->fetchAllAssoc('nid');
- }
-
- foreach ($items as $id => $entity_items) {
- foreach ($entity_items as $delta => $item) {
- if (is_array($item) && !empty($item['nid']) && isset($fetched_nodes[$item['nid']])) {
- $items[$id][$delta]['node'] = $fetched_nodes[$item['nid']];
- $items[$id][$delta]['access'] = TRUE;
- }
- }
- }
- }
-}
-
-/**
- * Implements hook_field_is_empty().
- */
-function node_reference_field_is_empty($item, $field) {
- // nid = 0 is empty too, which is exactly what we want.
- return empty($item['nid']);
-}
-
-/**
- * Implements hook_field_formatter_info().
- */
-function node_reference_field_formatter_info() {
- $ret = array(
- 'node_reference_default' => array(
- 'label' => t('Title (link)'),
- 'description' => t('Display the title of the referenced node as a link to the node page.'),
- 'field types' => array('node_reference'),
- ),
- 'node_reference_plain' => array(
- 'label' => t('Title (no link)'),
- 'description' => t('Display the title of the referenced node as plain text.'),
- 'field types' => array('node_reference'),
- ),
- 'node_reference_node' => array(
- 'label' => t('Rendered node'),
- 'description' => t('Display the referenced node in a specific view mode'),
- 'field types' => array('node_reference'),
- 'settings' => array('node_reference_view_mode' => 'full'),
- ),
- );
- return $ret;
-}
-
-/**
- * Implements hook_field_formatter_prepare_view().
- *
- * Preload all nodes referenced by items using 'full entity' formatters.
- */
-function node_reference_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {
- // Collect nids to load.
- // @todo : can we make clever use of the recursion queue here ?
- $nids = array();
- foreach ($displays as $id => $display) {
- if ($display['type'] == 'node_reference_node') {
- foreach ($items[$id] as $delta => $item) {
- if ($item['access']) {
- $nids[$item['nid']] = $item['nid'];
- }
- }
- }
- }
- $nodes = node_load_multiple($nids);
-
- // Add the loaded nodes to the items.
- foreach ($displays as $id => $display) {
- if ($display['type'] == 'node_reference_node') {
- foreach ($items[$id] as $delta => $item) {
- if ($item['access']) {
- $items[$id][$delta]['node'] = $nodes[$item['nid']];
- }
- }
- }
- }
-}
-
-/**
- * Implements hook_field_formatter_settings_form().
- */
-function node_reference_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
- $display = $instance['display'][$view_mode];
- $settings = $display['settings'];
-
- // Only build this information for node_reference_node displays
- if ($display['type'] !== 'node_reference_node') {
- return NULL;
- }
-
- $entity_info = entity_get_info('node');
- $modes = $entity_info['view modes'];
- $options = array();
- foreach ($modes as $name => $mode) {
- $options[$name] = $mode['label'];
- }
- $element['node_reference_view_mode'] = array(
- '#title' => t('View mode'),
- '#type' => 'select',
- '#options' => $options,
- '#default_value' => $settings['node_reference_view_mode'],
- // Never empty, so no #empty_option
- );
- return $element;
-}
-
-/**
- * Implements hook_field_formatter_settings_summary().
- */
-function node_reference_field_formatter_settings_summary($field, $instance, $view_mode) {
- $display = $instance['display'][$view_mode];
- $settings = $display['settings'];
-
- if ($display['type'] === 'node_reference_node') {
- $entity_info = entity_get_info('node');
- $modes = $entity_info['view modes'];
- $mode = $modes[$settings['node_reference_view_mode']]['label'];
- $summary = t('View mode: %mode', array('%mode' => $mode));
- }
- else {
- $summary = NULL;
- }
- return $summary;
-}
-
-/**
- * Implements hook_field_formatter_view().
- */
-function node_reference_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
- $result = array();
-
- switch ($display['type']) {
- case 'node_reference_default':
- case 'node_reference_plain':
- foreach ($items as $delta => $item) {
- if ($item['access']) {
- $node = $item['node'];
- if ($display['type'] == 'node_reference_default') {
- $uri = entity_uri('node', $node);
- $result[$delta] = array(
- '#type' => 'link',
- '#title' => $node->title,
- '#href' => $uri['path'],
- '#options' => $uri['options'],
- );
- }
- else {
- $result[$delta] = array(
- '#markup' => check_plain($node->title),
- );
- }
- if (!$node->status) {
- $result[$delta]['#prefix'] = '';
- $result[$delta]['#suffix'] = '';
- }
- }
- }
- break;
-
- case 'node_reference_node':
- $view_mode = $display['settings']['node_reference_view_mode'];
- // To prevent infinite recursion caused by reference cycles, we store
- // diplayed nodes in a recursion queue.
- $recursion_queue = &drupal_static(__FUNCTION__, array());
-
- // If no 'referencing entity' is set, we are starting a new 'reference
- // thread' and need to reset the queue.
- // @todo Bug: $entity->referencing_entity on nodes referenced in a different
- // thread on the page. E.g: 1 references 1+2 / 2 references 1+2 / visit homepage.
- // We'd need a more accurate way...
- if (!isset($entity->referencing_entity)) {
- $recursion_queue = array();
- }
-
- // The recursion queue only needs to track nodes.
- if ($entity_type == 'node') {
- list($id) = entity_extract_ids($entity_type, $entity);
- $recursion_queue[$id] = $id;
- }
-
- // Check the recursion queue to determine which nodes should be fully
- // displayed, and which nodes will only be displayed as a title.
- $nodes_display = array();
- foreach ($items as $delta => $item) {
- if ($item['access'] && !isset($recursion_queue[$item['nid']])) {
- $nodes_display[$item['nid']] = $item['node'];
- }
- }
-
- // Load and build the fully displayed nodes.
- if ($nodes_display) {
- foreach ($nodes_display as $nid => $node) {
- $nodes_display[$nid]->referencing_entity = $entity;
- $nodes_display[$nid]->referencing_field = $field['field_name'];
- }
- $nodes_built = node_view_multiple($nodes_display, $view_mode);
- }
-
- // Assemble the render array.
- foreach ($items as $delta => $item) {
- if ($item['access']) {
- if (isset($nodes_display[$item['nid']])) {
- $result[$delta] = $nodes_built['nodes'][$item['nid']];
- }
- else {
- $node = $item['node'];
- $uri = entity_uri('node', $node);
- $result[$delta] = array(
- '#type' => 'link',
- '#title' => $node->title,
- '#href' => $uri['path'],
- '#options' => $uri['options'],
- );
- if (!$node->status) {
- $result[$delta]['#prefix'] = '';
- $result[$delta]['#suffix'] = '';
- }
- }
- }
- }
- break;
- }
-
- return $result;
-}
-
-/**
- * Implements hook_field_widget_info().
- */
-function node_reference_field_widget_info() {
- return array(
- 'node_reference_autocomplete' => array(
- 'label' => t('Autocomplete text field'),
- 'description' => t('Display the list of referenceable nodes as a textfield with autocomplete behaviour.'),
- 'field types' => array('node_reference'),
- 'settings' => array(
- 'autocomplete_match' => 'contains',
- 'size' => 60,
- 'autocomplete_path' => 'node_reference/autocomplete',
- ),
- ),
- );
-}
-
-/**
- * Implements hook_field_widget_info_alter().
- */
-function node_reference_field_widget_info_alter(&$info) {
- $info['options_select']['field types'][] = 'node_reference';
- $info['options_buttons']['field types'][] = 'node_reference';
-}
-
-/**
- * Implements hook_field_widget_settings_form().
- */
-function node_reference_field_widget_settings_form($field, $instance) {
- $widget = $instance['widget'];
- $defaults = field_info_widget_settings($widget['type']);
- $settings = array_merge($defaults, $widget['settings']);
-
- $form = array();
- if ($widget['type'] == 'node_reference_autocomplete') {
- $form['autocomplete_match'] = array(
- '#type' => 'select',
- '#title' => t('Autocomplete matching'),
- '#default_value' => $settings['autocomplete_match'],
- '#options' => array(
- 'starts_with' => t('Starts with'),
- 'contains' => t('Contains'),
- ),
- '#description' => t('Select the method used to collect autocomplete suggestions. Note that Contains can cause performance issues on sites with thousands of nodes.'),
- );
- $form['size'] = array(
- '#type' => 'textfield',
- '#title' => t('Size of textfield'),
- '#default_value' => $settings['size'],
- '#element_validate' => array('_element_validate_integer_positive'),
- '#required' => TRUE,
- );
- }
- return $form;
-}
-
-/**
- * Implements hook_field_widget_form().
- */
-function node_reference_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
- switch ($instance['widget']['type']) {
- case 'node_reference_autocomplete':
- $element += array(
- '#type' => 'textfield',
- '#default_value' => isset($items[$delta]['nid']) ? $items[$delta]['nid'] : NULL,
- '#autocomplete_path' => $instance['widget']['settings']['autocomplete_path'] . '/' . $instance['entity_type'] . '/' . $field['field_name'],
- '#size' => $instance['widget']['settings']['size'],
- '#element_validate' => array('node_reference_autocomplete_validate'),
- '#value_callback' => 'node_reference_autocomplete_value',
- );
- break;
- }
-
- return array('nid' => $element);
-}
-
-/**
- * Value callback for a node_reference autocomplete element.
- *
- * Replace the node nid with a node title.
- */
-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'];
- 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;
- }
- }
-}
-
-/**
- * Validation callback for a node_reference autocomplete element.
- */
-function node_reference_autocomplete_validate($element, &$form_state, $form) {
- $field = $form_state['field'][$element['#field_name']][$element['#language']]['field'];
- $instance = $form_state['field'][$element['#field_name']][$element['#language']]['instance'];
-
- $value = $element['#value'];
- $nid = NULL;
-
- if (!empty($value)) {
- // 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. Check that the 'title' part matches the actual title for
- // the nid.
- list(, $title, $nid) = $matches;
- if (!empty($title)) {
- $real_title = db_select('node', 'n')
- ->fields('n', array('title'))
- ->condition('n.nid', $nid)
- ->execute()
- ->fetchField();
- if (trim($title) != trim($real_title)) {
- form_error($element, t('%name: title mismatch. Please check your selection.', array('%name' => $instance['label'])));
- }
- }
- }
- else {
- // 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 ($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' => $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);
-}
-
-/**
- * Implements hook_field_widget_error().
- */
-function node_reference_field_widget_error($element, $error, $form, &$form_state) {
- form_error($element['nid'], $error['message']);
-}
-
-/**
- * Fetch an array of all candidate referenced nodes.
- *
- * This info is used in various places (allowed values, autocomplete
- * results, input validation...). Some of them only need the nids,
- * others nid + titles, others yet nid + titles + rendered row (for
- * display in widgets).
- *
- * The array we return contains all the potentially needed information,
- * and lets consumers use the parts they actually need.
- *
- * @param $field
- * The field description.
- * @param $string
- * Optional string to filter titles on (used by autocomplete).
- * @param $match
- * Operator to match filtered name against, can be any of:
- * 'contains', 'equals', 'starts_with'
- * @param $ids
- * Optional node ids to lookup (the $string and $match arguments will be
- * ignored).
- * @param $limit
- * If non-zero, limit the size of the result set.
- *
- * @return
- * An array of valid nodes in the form:
- * array(
- * nid => array(
- * 'title' => The node title,
- * 'rendered' => The text to display in widgets (can be HTML)
- * ),
- * ...
- * )
- * @todo Check whether we still need the 'rendered' value (hook_options_list()
- * does not need it anymore). Should probably be clearer after the 'Views'
- * mode is ported.
- */
-function _node_reference_potential_references($field, $string = '', $match = 'contains', $ids = array(), $limit = NULL) {
- $results = &drupal_static(__FUNCTION__, array());
-
- // Create unique id for static cache.
- $cid = $field['field_name'] . ':' . $match . ':'
- . ($string !== '' ? $string : implode('-', $ids))
- . ':' . $limit;
- if (!isset($results[$cid])) {
- $references = _node_reference_potential_references_standard($field, $string, $match, $ids, $limit);
-
- // Store the results.
- $results[$cid] = !empty($references) ? $references : array();
- }
-
- return $results[$cid];
-}
-
-/**
- * Helper function for _node_reference_potential_references().
- *
- * List of referenceable nodes defined by content types.
- */
-function _node_reference_potential_references_standard($field, $string = '', $match = 'contains', $ids = array(), $limit = NULL) {
- // Avoid useless work
- if (!count($field['settings']['referenceable_types'])) {
- return array();
- }
-
- $query = db_select('node', 'n');
- $node_nid_alias = $query->addField('n', 'nid');
- $node_title_alias = $query->addField('n', 'title', 'node_title');
- $node_type_alias = $query->addField('n', 'type', 'node_type');
- $query->addTag('node_access');
- $query->addMetaData('id', ' _node_reference_potential_references_standard');
-
- if (is_array($field['settings']['referenceable_types'])) {
- $query->condition('n.type', $field['settings']['referenceable_types'], 'IN');
- }
-
- if ($string !== '') {
- switch ($match) {
- case 'contains':
- $query->condition('n.title', '%' . $string . '%', 'LIKE');
- break;
-
- case 'starts_with':
- $query->condition('n.title', $string . '%', 'LIKE');
- break;
-
- case 'equals':
- default: // no match type or incorrect match type: use "="
- $query->condition('n.title', $string);
- break;
- }
- }
- elseif ($ids) {
- $query->condition('n.nid', $ids, 'IN', $ids);
- }
-
- $query
- ->orderBy($node_title_alias)
- ->orderBy($node_type_alias);
-
- if ($limit) {
- $query->range(0, $limit);
- }
-
- $result = $query->execute();
- $references = array();
- foreach ($result->fetchAll() as $node) {
- $references[$node->nid] = array(
- 'title' => $node->node_title,
- 'rendered' => check_plain($node->node_title),
- );
- }
- return $references;
-}
-
-/**
- * Menu access callback for the autocomplete path.
- *
- * Check for both 'edit' and 'view' access in the unlikely event
- * a user has edit but not view access.
- */
-function node_reference_autocomplete_access($entity_type, $field_name) {
- return user_access('access content') && ($field = field_info_field($field_name)) && field_access('view', $field, $entity_type) && field_access('edit', $field, $entity_type);
-}
-
-/**
- * Menu callback for the autocomplete results.
- */
-function node_reference_autocomplete($entity_type, $field_name, $string = '') {
- $field = field_info_field($field_name);
-
- // @todo broken - this is in $field['widget']['settings']['autocomplete_match'] - we'd need the $instance.
- $match = isset($field['widget']['autocomplete_match']) ? $field['widget']['autocomplete_match'] : 'contains';
- $matches = array();
-
- $references = _node_reference_potential_references($field, $string, $match, array(), 10);
- foreach ($references as $id => $row) {
- // Add a class wrapper for a few required CSS overrides.
- $matches[$row['title'] . " [nid:$id]"] = '
' . $row['rendered'] . '
';
- }
- drupal_json_output($matches);
-}
-
-/**
- * Implements hook_node_type_update().
- *
- * Reflect type name changes to the 'referenceable types' settings: when
- * the name of a type changes, the change needs to be reflected in the
- * "referenceable types" setting for any node_reference field
- * referencing it.
- */
-function node_reference_node_type_update($info) {
- if (!empty($info->old_type) && $info->old_type != $info->type) {
- $fields = field_info_fields();
- foreach ($fields as $field_name => $field) {
- if ($field['type'] == 'node_reference' && isset($field['settings']['referenceable_types'][$info->old_type])) {
- $field['settings']['referenceable_types'][$info->type] = empty($field['settings']['referenceable_types'][$info->old_type]) ? 0 : $info->type;
- unset($field['settings']['referenceable_types'][$info->old_type]);
- field_update_field($field);
- }
- }
- }
-}
-
-/**
- * Theme preprocess function.
- *
- * Allows specific node templates for nodes displayed as values of a
- * node_reference field with the 'full node' / 'teaser' formatters.
- */
-function node_reference_preprocess_node(&$vars) {
- // The 'referencing_field' attribute of the node is added by the 'teaser'
- // and 'full node' formatters.
- if (!empty($vars['node']->referencing_field)) {
- $node = $vars['node'];
- $field = $node->referencing_field;
- $vars['theme_hook_suggestions'][] = 'node-reference';
- $vars['theme_hook_suggestions'][] = 'node-reference__' . $field['field_name'];
- $vars['theme_hook_suggestions'][] = 'node-reference__' . $node->type;
- $vars['theme_hook_suggestions'][] = 'node-reference__' . $field['field_name'] . '__' . $node->type;
- }
-}
-
-/**
- * Implements hook_field_prepare_translation().
- *
- * When preparing a translation, load any translations of existing
- * references.
- * @todo Correctly implement after http://drupal.org/node/362021 is fixed.
- */
-function node_reference_field_prepare_translation($entity_type, $entity, $field, $instance, $langcode, &$items) {
- $addition = array();
- $addition[$field['field_name']] = array();
- if (isset($entity->translation_source->$field['field_name'])
- && is_array($entity->translation_source->$field['field_name'])) {
- foreach ($entity->translation_source->$field['field_name'] as $key => $reference) {
- $reference_node = node_load($reference['nid']);
- // Test if the referenced node type is translatable and, if so,
- // load translations if the reference is not for the current language.
- // We can assume the translation module is present because it invokes 'prepare translation'.
- if (translation_supported_type($reference_node->type)
- && !empty($reference_node->language)
- && $reference_node->language != $node->language
- && $translations = translation_node_get_translations($reference_node->tnid)) {
- // If there is a translation for the current language, use it.
- $addition[$field['field_name']][] = array(
- 'nid' => isset($translations[$node->language])
- ? $translations[$node->language]->nid
- : $reference['nid'],
- );
- }
- }
- }
-
- return $addition;
-}
-
-/**
- * Implements hook_options_list().
- */
-function node_reference_options_list($field) {
- $references = _node_reference_potential_references($field);
-
- // @todo Support optgroups ? I think this was added in late CCK D6.
- $options = array();
- foreach ($references as $key => $value) {
- $options[$key] = $value['title'];
- }
-
- return $options;
-}
-
-/**
- * Implements hook_content_migrate_field_alter().
- *
- * Use this to tweak the conversion of field settings from the D6 style to the
- * D7 style for specific situations not handled by basic conversion, as when
- * field types or settings are changed.
- *
- * $field_value['widget_type'] is available to
- * see what widget type was originally used.
- */
-function node_reference_content_migrate_field_alter(&$field_value, $instance_value) {
- switch ($field_value['module']) {
- case 'nodereference':
- $field_value['module'] = 'node_reference';
- $field_value['type'] = 'node_reference';
- break;
- }
-}
-
-/**
- * Implements hook_content_migrate_instance_alter().
- *
- * Use this to tweak the conversion of instance or widget settings from the D6
- * style to the D7 style for specific situations not handled by basic
- * conversion, as when formatter or widget names or settings are changed.
- */
- function node_reference_content_migrate_instance_alter(&$instance_value, $field_value) {
- switch ($field_value['type']) {
- case 'nodereference':
- // Massage formatters.
- foreach ($instance_value['display'] as $context => &$display) {
- switch ($display['type']) {
- case 'full':
- case 'teaser':
- // Those two formatters have been merged into
- // 'node_reference_view_mode', with a formatter setting.
- $display['type'] = 'node_reference_node';
- $display['settings']['node_reference_view_mode'] = $display['type'];
- break;
-
- default:
- // The formatter names changed, all are prefixed with
- // 'node_reference_'.
- $display['type'] = 'node_reference_' . $display['type'];
- break;
- }
- }
- // Massage the widget.
- switch ($instance_value['widget']['type']) {
- case 'nodereference_autocomplete':
- $instance_value['widget']['type'] = 'node_reference_autocomplete';
- $instance_value['widget']['module'] = 'node_reference';
- break;
- case 'nodereference_select':
- $instance_value['widget']['type'] = 'options_select';
- $instance_value['widget']['module'] = 'options';
- break;
- case 'nodereference_buttons':
- $instance_value['widget']['type'] = 'options_buttons';
- $instance_value['widget']['module'] = 'options';
- }
- break;
- }
-}
diff --git a/user_reference/user_reference.info b/user_reference/user_reference.info
deleted file mode 100644
index e5dedd0fc6fea30c9f8c09a19b2274f24bdfc964..0000000000000000000000000000000000000000
--- a/user_reference/user_reference.info
+++ /dev/null
@@ -1,6 +0,0 @@
-; $Id$
-name = User Reference
-description = Defines a field type for referencing a user from a node.
-files[]=user_reference.module
-package = CCK
-core = 7.x
diff --git a/user_reference/user_reference.module b/user_reference/user_reference.module
deleted file mode 100644
index f5c42f0a320268070cebea8d59bf3e81a121de9d..0000000000000000000000000000000000000000
--- a/user_reference/user_reference.module
+++ /dev/null
@@ -1,666 +0,0 @@
- 'user_reference autocomplete',
- 'page callback' => 'user_reference_autocomplete',
- 'access arguments' => array('access content'),
- 'type' => MENU_CALLBACK
- );
- return $items;
-}
-
-/**
- * Implements hook_field_info().
- */
-function user_reference_field_info() {
- return array(
- 'user_reference' => array(
- 'label' => t('User reference'),
- 'description' => t('This field stores the ID of a related user as an integer value.'),
- 'settings' => array('referenceable_roles' => array(), 'referenceable_status' => array()),
- 'default_widget' => 'user_reference_autocomplete',
- 'default_formatter' => 'user_reference_default',
- ),
- );
-}
-
-/**
- * Implements hook_field_schema();
- */
-function user_reference_field_schema($field) {
- $columns = array(
- 'uid' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => FALSE,
- ),
- );
- return array(
- 'columns' => $columns,
- 'indexes' => array('uid' => array('uid')),
- 'foreign keys' => array(
- 'uid' => array(
- 'table' => 'users',
- 'columns' => array('uid' => 'uid'),
- ),
- ),
- );
-}
-
-/**
- * Implements hook_field_settings_form().
- */
-function user_reference_field_settings_form($field, $instance, $has_data) {
- $settings = $field['settings'];
-
- $form = array();
- $form['referenceable_roles'] = array(
- '#type' => 'checkboxes',
- '#title' => t('User roles that can be referenced'),
- '#default_value' => is_array($settings['referenceable_roles'])
- ? array_filter($settings['referenceable_roles'])
- : array(),
- '#options' => user_roles(1),
- '#disabled' => $has_data,
- );
- $form['referenceable_status'] = array(
- '#type' => 'checkboxes',
- '#title' => t('User status that can be referenced'),
- '#default_value' => is_array($settings['referenceable_status'])
- ? array_filter($settings['referenceable_status'])
- : array(1),
- '#options' => array(1 => t('Active'), 0 => t('Blocked')),
- '#disabled' => $has_data,
- );
- return $form;
-}
-
-/**
- * Implements hook_field_validate().
- *
- * Possible error codes:
- * - 'invalid_uid': uid is not valid for the field (not a valid user id, or the user is not referenceable).
- */
-function user_reference_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
- // Extract uids to check.
- $ids = array();
-
- // First check non-numeric uid's to avoid losing time with them.
- foreach ($items as $delta => $item) {
- if (is_array($item) && !empty($item['uid'])) {
- if (is_numeric($item['uid'])) {
- $ids[] = $item['uid'];
- }
- else {
- $errors[$field['field_name']][$langcode][$delta][] = array(
- 'error' => 'invalid_uid',
- 'message' => t('%name: invalid input.',
- array('%name' => $instance['label'])),
- );
- }
- }
- }
- // Prevent performance hog if there are no ids to check.
- if ($ids) {
- $refs = _user_reference_potential_references($field, '', NULL, $ids);
- foreach ($items as $delta => $item) {
- if (is_array($item)) {
- if (!empty($item['uid']) && !isset($refs[$item['uid']])) {
- $errors[$field['field_name']][$langcode][$delta][] = array(
- 'error' => 'invalid_uid',
- 'message' => t("%name: this user can't be referenced.",
- array('%name' => $instance['label'])),
- );
- }
- }
- }
- }
-}
-
-/**
- * Implements hook_field_is_empty().
- */
-function user_reference_field_is_empty($item, $field) {
- return empty($item['uid']);
-}
-
-/**
- * Implements hook_field_formatter_info().
- */
-function user_reference_field_formatter_info() {
- return array(
- 'user_reference_default' => array(
- 'label' => t('Default'),
- 'description' => t("Display the name of the referenced user as a link to the user's profile page."),
- 'field types' => array('user_reference'),
- ),
- 'user_reference_plain' => array(
- 'label' => t('Plain text'),
- 'description' => t('Display the name of the referenced user as plain text.'),
- 'field types' => array('user_reference'),
- ),
- );
-}
-
-/**
- * Implements hook_field_formatter_view().
- */
-function user_reference_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
- $result = array();
-
- // @todo Optimisation: use hook_field_formatter_prepare_view() to load
- // user names or full user entities in 'multiple' mode.
-
- // Collect the list of user ids.
- $uids = array();
- foreach ($items as $delta => $item) {
- $uids[$item['uid']] = $item['uid'];
- }
-
- switch ($display['type']) {
- case 'user_reference_default':
- case 'user_reference_plain':
- $titles = _user_reference_get_user_names($uids);
- foreach ($items as $delta => $item) {
- if ($display['type'] == 'user_reference_default') {
- $result[$delta] = array(
- '#type' => 'link',
- '#title' => $titles[$item['uid']],
- '#href' => 'user/' . $item['uid'],
- );
- }
- else {
- $result[$delta] = array(
- '#markup' => check_plain($titles[$item['uid']]),
- );
- }
- }
- break;
- }
-
- return $result;
-}
-
-/**
- * Helper function for widgets and formatters.
- *
- * Store user names collected in the curent request.
- */
-function _user_reference_get_user_names($uids, $known_titles = array()) {
- $titles = &drupal_static(__FUNCTION__, array());
-
- // Save titles we receive.
- $titles += $known_titles;
-
- // Collect nids to retrieve from database.
- $uids_query = array();
- foreach ($uids as $uid) {
- if (!isset($titles[$uid])) {
- $uids_query[] = $uid;
- }
- }
- if ($uids_query) {
- $query = db_select('users', 'u')
- ->fields('u', array('uid', 'name'))
- ->condition('u.uid', $uids);
- $titles += $query->execute()->fetchAllKeyed();
- }
-
- // Build the results array.
- $return = array();
- foreach ($uids as $uid) {
- $return[$uid] = isset($titles[$uid]) ? $titles[$uid] : '';
- }
-
- return $return;
-}
-
-/**
- * Implements hook_field_widget_info().
- */
-function user_reference_field_widget_info() {
- return array(
- 'user_reference_autocomplete' => array(
- 'label' => t('Autocomplete text field'),
- 'description' => t('Display the list of referenceable users as a textfield with autocomplete behaviour.'),
- 'field types' => array('user_reference'),
- 'settings' => array(
- 'autocomplete_match' => 'contains',
- 'size' => 60,
- 'autocomplete_path' => 'user_reference/autocomplete',
- ),
- ),
- );
-}
-
-/**
- * Implements hook_field_widget_info_alter().
- */
-function user_reference_field_widget_info_alter(&$info) {
- $info['options_select']['field types'][] = 'user_reference';
- $info['options_buttons']['field types'][] = 'user_reference';
-}
-
-/**
- * Implements hook_field_widget_settings_form().
- */
-function user_reference_field_widget_settings_form($field, $instance) {
- $widget = $instance['widget'];
- $defaults = field_info_widget_settings($widget['type']);
- $settings = array_merge($defaults, $widget['settings']);
-
- $form = array();
- if ($widget['type'] == 'user_reference_autocomplete') {
- $form['autocomplete_match'] = array(
- '#type' => 'select',
- '#title' => t('Autocomplete matching'),
- '#default_value' => $settings['autocomplete_match'],
- '#options' => array(
- 'starts_with' => t('Starts with'),
- 'contains' => t('Contains'),
- ),
- '#description' => t('Select the method used to collect autocomplete suggestions. Note that Contains can cause performance issues on sites with thousands of users.'),
- );
- $form['size'] = array(
- '#type' => 'textfield',
- '#title' => t('Size of textfield'),
- '#default_value' => $settings['size'],
- '#element_validate' => array('_element_validate_integer_positive'),
- '#required' => TRUE,
- );
- }
- return $form;
-}
-
-/**
- * Implements hook_field_widget_form().
- */
-function user_reference_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
- switch ($instance['widget']['type']) {
- case 'user_reference_autocomplete':
- $element += array(
- '#type' => 'textfield',
- '#default_value' => isset($items[$delta]['uid']) ? $items[$delta]['uid'] : NULL,
- '#autocomplete_path' => $instance['widget']['settings']['autocomplete_path'] . '/' . $field['field_name'],
- '#size' => $instance['widget']['settings']['size'],
- '#element_validate' => array('user_reference_autocomplete_validate'),
- '#value_callback' => 'user_reference_autocomplete_value',
- );
- break;
- }
- return array('uid' => $element);
-}
-
-/**
- * Value callback for a user_reference autocomplete element.
- *
- * Substitute in the user name for the uid.
- */
-function user_reference_autocomplete_value($element, $input = FALSE, $form_state) {
- if ($input === FALSE) {
- // We're building the displayed 'default value': expand the raw uid into
- // "user name [uid:n]".
- $uid = $element['#default_value'];
- if (!empty($uid)) {
- $q = db_select('users', 'u');
- $q->addField('u', 'name');
-
- $q->condition('u.uid', $uid)
- ->range(0, 1);
- $result = $q->execute();
- // @todo If no result (user doesn't exist).
- $value = $result->fetchField();
- $value .= ' [uid:' . $uid . ']';
- return $value;
- }
- }
-}
-
-/**
- * Validation callback for a user_reference autocomplete element.
- */
-function user_reference_autocomplete_validate($element, &$form_state, $form) {
- $field = $form_state['field'][$element['#field_name']][$element['#language']]['field'];
- $instance = $form_state['field'][$element['#field_name']][$element['#language']]['instance'];
-
- $value = $element['#value'];
- $uid = NULL;
-
- if (!empty($value)) {
- // Check whether we have an explicit "[uid:n]" input.
- preg_match('/^(?:\s*|(.*) )?\[\s*uid\s*:\s*(\d+)\s*\]$/', $value, $matches);
- if (!empty($matches)) {
- // Explicit uid. Check that the 'name' part matches the actual name for
- // the uid.
- list(, $name, $uid) = $matches;
- if (!empty($name)) {
- $names = _user_reference_get_user_names(array($uid));
- if ($name != $names[$uid]) {
- form_error($element, t('%name: name mismatch. Please check your selection.', array('%name' => $instance['label'])));
- }
- }
- }
- else {
- // No explicit uid (the submitted value was not populated by autocomplete
- // selection). Get the uid of a referencable user from the entered name.
- $reference = _user_reference_potential_references($field, $value, 'equals', NULL, 1);
- 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 name. ATM, we pick the first
- // matching candidate...
- $uid = key($reference);
- }
- else {
- form_error($element, t('%name: found no valid user with that name.', array('%name' => $instance['label'])));
- }
- }
- }
-
- // Set the element's value as the user id that was extracted from the entered
- // input.
- form_set_value($element, $uid, $form_state);
-}
-
-/**
- * Implements hook_field_widget_error().
- */
-function user_reference_field_widget_error($element, $error, $form, &$form_state) {
- form_error($element['uid'], $error['message']);
-}
-
-/**
- * Fetch an array of all candidate referenced users.
- *
- * This info is used in various places (aloowed values, autocomplete results,
- * input validation...). Some of them only need the uids, others nid + names,
- * others yet uid + names + rendered row (for display in widgets).
- * The array we return contains all the potentially needed information, and lets
- * consumers use the parts they actually need.
- *
- * @param $field
- * The field description.
- * @param $string
- * Optional string to filter usernames on (used by autocomplete)
- * @param $match
- * Operator to match filtered name against, can be any of:
- * 'contains', 'equals', 'starts_with'
- * @param $ids
- * Optional user ids to lookup (the $string and $match arguments will be
- * ignored).
- * @param $limit
- * If non-zero, limit the size of the result set.
- *
- * @return
- * An array of valid users in the form:
- * array(
- * uid => array(
- * 'title' => The user name,
- * 'rendered' => The text to display in widgets (can be HTML)
- * ),
- * ...
- * )
- */
-function _user_reference_potential_references($field, $string = '', $match = 'contains', $ids = array(), $limit = NULL) {
- $results = &drupal_static(__FUNCTION__, array());
-
- // Create unique id for static cache.
- $cid = $field['field_name'] . ':' . $match . ':'
- . ($string !== '' ? $string : implode('-', $ids))
- . ':' . $limit;
- if (!isset($results[$cid])) {
- $references = _user_reference_potential_references_standard($field, $string, $match, $ids, $limit);
-
- // Store the results.
- $results[$cid] = !empty($references) ? $references : array();
- }
-
- return $results[$cid];
-}
-
-/**
- * Helper function for _user_reference_potential_references().
- *
- * List of referenceable users defined by user role and status.
- */
-function _user_reference_potential_references_standard($field, $string = '', $match = 'contains', $ids = array(), $limit = NULL) {
- // Avoid useless work
- if (!count($field['settings']['referenceable_status']) || !count($field['settings']['referenceable_roles'])) {
- return array();
- }
-
- $query = db_select('users', 'u');
- $user_uid_alias = $query->addField('u', 'uid');
- $user_name_alias = $query->addField('u', 'name');
- $user_status_alias = $query->addField('u', 'status');
- $query->addMetaData('id', ' _user_reference_potential_references_standard');
-
- if (is_array($field['settings']['referenceable_status'])) {
- $query->condition('u.status', $field['settings']['referenceable_status']);
- }
-
- if (is_array($field['settings']['referenceable_roles']) && (!in_array(DRUPAL_AUTHENTICATED_RID, $field['settings']['referenceable_roles']))) {
- $query->join('users_roles', 'r', 'u.uid = r.uid');
- $query->addField('r', 'rid');
- $query->condition('r.rid', $field['settings']['referenceable_roles']);
- }
-
- if ($string !== '') {
- $args = array();
- switch ($match) {
- case 'contains':
- $name_clause = 'u.name LIKE :match';
- $args['match'] = '%' . $string . '%';
- break;
-
- case 'starts_with':
- $name_clause = 'u.name LIKE :match';
- $args['match'] = $string . '%';
- break;
-
- case 'equals':
- default: // no match type or incorrect match type: use "="
- $name_clause = 'u.name = :match';
- $args['match'] = $string;
- break;
- }
- $query->where($name_clause, $args);
- }
- elseif ($ids) {
- $query->condition($user_uid_alias, $ids, 'IN', $ids);
- }
-
- $query
- ->orderBy($user_name_alias);
-
- if ($limit) {
- $query->range(0, $limit);
- }
-
- $result = $query->execute();
- $references = array();
- foreach ($result->fetchAll() as $user) {
- $references[$user->uid] = array(
- 'title' => $user->name,
- 'rendered' => check_plain($user->name),
- );
- }
- return $references;
-}
-
-/**
- * Menu callback; Retrieve a pipe delimited string of autocomplete suggestions for existing users
- */
-function user_reference_autocomplete($field_name, $string = '') {
- $field = field_info_field($field_name);
-
- $match = isset($field['widget']['autocomplete_match']) ? $field['widget']['autocomplete_match'] : 'contains';
- $matches = array();
-
- $references = _user_reference_potential_references($field, $string, $match, array(), 10);
- foreach ($references as $id => $row) {
- // Add a class wrapper for a few required CSS overrides.
- $matches[$row['title'] . " [uid:$id]"] = '' . $row['rendered'] . '
';
- }
- drupal_json_output($matches);
-}
-
-/**
- * Implements hook_options_list().
- */
-function user_reference_options_list($field) {
- $references = _user_reference_potential_references($field);
-
- // @todo Support optgroups ? I think this was added in late CCK D6.
- $options = array();
- foreach ($references as $key => $value) {
- $options[$key] = $value['title'];
- }
-
- return $options;
-}
-
-/**
- * Implementation of hook_user_load().
- */
-/*function user_reference_user_load(&$accounts) {
-
- // Only add links if we are on the user 'view' page.
- if (arg(0) != 'user' || arg(2)) {
- return;
- }
-
- foreach ($accounts as $uid => $account) {
-
- // find CCK user_reference field tables
- // search through them for matching user ids and load those nodes
- $additions = array();
- $fields = field_info_instances('user');
-
- // TODO : replace with field_attach_query() + synchronize with latest D6 code.
-
- // Find the table and columns to search through, if the same
- // table comes up in more than one field type, we only need
- // to search it once.
- $search_tables = array();
- $search_links = array();
- foreach ($fields as $field) {
- if ($field['type'] == 'user_reference' && !empty($field['widget']['reverse_link'])) {
- $db_info = content_database_info($field);
- $search_tables[$db_info['table']] = $db_info['columns']['uid']['column'];
- $search_links[$db_info['table']] = $field['widget']['reverse_link'];
- }
- }
- foreach ($search_tables as $table => $column) {
- $ids = db_query(db_rewrite_sql("SELECT DISTINCT(n.nid) FROM {node} n LEFT JOIN {". $table ."} f ON n.vid = f.vid WHERE f.". $column ."=". $account->uid. " AND n.status = 1"));
- while ($data = db_fetch_object($ids)) {
- // TODO, do we really want a complete node_load() here? We only need the title to create a link.
- $node = node_load($data->nid);
- $node->reverse_link = $search_links[$table];
- $additions[$node->type][] = $node;
- }
- }
- $accounts[$uid]->user_reference = $additions;
- }
- return;
-}*/
-
-/**
- * Implementation of hook_user_view().
- */
-/*function user_reference_user_view(&$account) {
- if (!empty($account->user_reference)) {
- $node_types = content_types();
- $additions = array();
- $values = array();
- foreach ($account->user_reference as $node_type => $nodes) {
- foreach ($nodes as $node) {
- if ($node->reverse_link) {
- $values[$node_type][] = l($node->title, 'node/' . $node->nid);
- }
- }
- if (isset($values[$node_type])) {
- $additions[] = array(
- '#type' => 'user_profile_item',
- '#title' => check_plain($node_types[$node_type]['name']),
- '#value' => theme('item_list', $values[$node_type]),
- );
- }
- }
- if ($additions) {
- $account->content['user_reference'] = $additions + array(
- '#type' => 'user_profile_category',
- '#attributes' => array('class' => array('user-member')),
- '#title' => t('Related content'),
- '#weight' => 10,
- );
- }
- }
-}*/
-
-/**
- * Implements hook_content_migrate_field_alter().
- *
- * Use this to tweak the conversion of field settings
- * from the D6 style to the D7 style for specific
- * situations not handled by basic conversion,
- * as when field types or settings are changed.
- *
- * $field_value['widget_type'] is available to
- * see what widget type was originally used.
- */
-function user_reference_content_migrate_field_alter(&$field_value, $instance_value) {
- switch ($field_value['module']) {
- case 'userreference':
- $field_value['module'] = 'user_reference';
- $field_value['type'] = 'user_reference';
- break;
- }
-}
-
-/**
- * Implements hook_content_migrate_instance_alter().
- *
- * Use this to tweak the conversion of instance or widget settings
- * from the D6 style to the D7 style for specific
- * situations not handled by basic conversion, as when
- * formatter or widget names or settings are changed.
- */
-function user_reference_content_migrate_instance_alter(&$instance_value, $field_value) {
- // The module name for the instance was corrected
- // by the change in user_reference_content_migrate_field_alter().
- switch ($field_value['type']) {
- case 'userreference':
- // The formatter names changed, all are prefixed
- // with 'user_reference_'.
- foreach ($instance_value['display'] as $context => $settings) {
- $instance_value['display'][$context]['type'] = 'user_reference_'. $settings['type'];
- }
- // Massage the widget.
- switch ($instance_value['widget']['type']) {
- case 'userreference_autocomplete':
- $instance_value['widget']['type'] = 'user_reference_autocomplete';
- $instance_value['widget']['module'] = 'user_reference';
- break;
- case 'userreference_select':
- $instance_value['widget']['type'] = 'options_select';
- $instance_value['widget']['module'] = 'options';
- break;
- case 'userreference_buttons':
- $instance_value['widget']['type'] = 'options_buttons';
- $instance_value['widget']['module'] = 'options';
- }
- break;
- }
-}
\ No newline at end of file